MOBILE-2820 calendar: Manage reminder exact time

main
Pau Ferrer Ocaña 2019-01-23 11:56:35 +01:00
parent 575285077f
commit 9baca2918b
5 changed files with 92 additions and 46 deletions

View File

@ -8,7 +8,8 @@
"eventstarttime": "Start time", "eventstarttime": "Start time",
"gotoactivity": "Go to activity", "gotoactivity": "Go to activity",
"noevents": "There are no events", "noevents": "There are no events",
"notifications": "Notifications", "reminders": "Reminders",
"setnewreminder": "Set a new reminder",
"typeclose": "Close event", "typeclose": "Close event",
"typecourse": "Course event", "typecourse": "Course event",
"typecategory": "Category event", "typecategory": "Category event",

View File

@ -10,10 +10,10 @@
<core-loading [hideUntil]="eventLoaded"> <core-loading [hideUntil]="eventLoaded">
<ion-card> <ion-card>
<ion-card-content *ngIf="event"> <ion-card-content *ngIf="event">
<ion-card-title text-wrap> <ion-item text-wrap>
<core-icon *ngIf="event.icon && !event.moduleIcon" [name]="event.icon" item-start></core-icon> <core-icon *ngIf="event.icon && !event.moduleIcon" [name]="event.icon" item-start></core-icon>
<core-format-text [text]="event.name"></core-format-text> <h2><core-format-text [text]="event.name"></core-format-text></h2>
</ion-card-title> </ion-item>
<ion-item text-wrap> <ion-item text-wrap>
<h2>{{ 'addon.calendar.eventstarttime' | translate}}</h2> <h2>{{ 'addon.calendar.eventstarttime' | translate}}</h2>
<p>{{ event.timestart * 1000 | coreFormatDate }}</p> <p>{{ event.timestart * 1000 | coreFormatDate }}</p>
@ -52,20 +52,24 @@
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
<ion-card list *ngIf="notificationsEnabled && event.timestart - 600 > currentTime"> <ion-card list *ngIf="notificationsEnabled">
<ion-item> <ion-item>
<ion-label>{{ 'addon.calendar.notifications' | translate }}</ion-label> <h2>{{ 'addon.calendar.reminders' | translate }}</h2>
<ion-select [(ngModel)]="notificationTime" (ionChange)="updateNotificationTime($event)" interface="action-sheet"> </ion-item>
<ion-option value="-1" *ngIf="event.timestart - defaultTime > currentTime">{{ 'core.defaultvalue' | translate :{$a: defaultTimeReadable} }}</ion-option> <ion-item [class.item-dimmed]="notificationTime < currentTime" *ngIf="notificationTime > 0">
<ion-option value="0">{{ 'core.settings.disabled' | translate }}</ion-option> <p *ngIf="timeToLoad == -1">{{ 'core.defaultvalue' | translate :{$a: ((event.timestart - defaultTime) * 1000) | coreFormatDate } }}</p>
<ion-option value="10">{{ 600 | coreDuration }}</ion-option> <p *ngIf="timeToLoad > 0">{{ notificationTime * 1000 | coreFormatDate }}</p>
<ion-option value="30" *ngIf="event.timestart - 1800 > currentTime">{{ 1800 | coreDuration }}</ion-option> <button ion-button icon-only clear="true" (click)="cancelNotification($event)" [attr.aria-label]=" 'core.delete' | translate" item-end>
<ion-option value="60" *ngIf="event.timestart - 3600 > currentTime">{{ 3600 | coreDuration }}</ion-option> <ion-icon name="trash" color="danger"></ion-icon>
<ion-option value="120" *ngIf="event.timestart - 7200 > currentTime">{{ 7200 | coreDuration }}</ion-option> </button>
<ion-option value="360" *ngIf="event.timestart - 21600 > currentTime">{{ 21600 | coreDuration }}</ion-option> </ion-item>
<ion-option value="720" *ngIf="event.timestart - 43200 > currentTime">{{ 43200 | coreDuration }}</ion-option>
<ion-option value="1440" *ngIf="event.timestart - 86400 > currentTime">{{ 86400 | coreDuration }}</ion-option> <ion-item *ngIf="event.timestart + event.timeduration > currentTime">
</ion-select> <ion-label stacked>{{ 'addon.calendar.setnewreminder' | translate }}</ion-label>
<ion-datetime [(ngModel)]="notificationTimeText" [placeholder]="'core.choosedots' | translate" [displayFormat]="notificationFormat" [min]="notificationMin" [max]="notificationMax"></ion-datetime>
</ion-item>
<ion-item *ngIf="event.timestart + event.timeduration > currentTime">
<button ion-button block color="primary" (click)="addNotificationTime($event)">{{ 'addon.calendar.setnewreminder' | translate }}</button>
</ion-item> </ion-item>
</ion-card> </ion-card>
</core-loading> </core-loading>

View File

@ -39,8 +39,12 @@ export class AddonCalendarEventPage {
protected eventId; protected eventId;
protected siteHomeId: number; protected siteHomeId: number;
eventLoaded: boolean; eventLoaded: boolean;
notificationFormat: string;
notificationMin: string;
notificationMax: string;
notificationTime: number; notificationTime: number;
defaultTimeReadable: string; notificationTimeText: string;
timeToLoad: number;
event: any = {}; event: any = {};
title: string; title: string;
courseName: string; courseName: string;
@ -58,24 +62,21 @@ export class AddonCalendarEventPage {
private textUtils: CoreTextUtilsProvider, private timeUtils: CoreTimeUtilsProvider) { private textUtils: CoreTextUtilsProvider, private timeUtils: CoreTimeUtilsProvider) {
this.eventId = navParams.get('id'); this.eventId = navParams.get('id');
this.notificationsEnabled = localNotificationsProvider.isAvailable(); this.notificationsEnabled = localNotificationsProvider.isAvailable() || true;
this.siteHomeId = sitesProvider.getCurrentSite().getSiteHomeId(); this.siteHomeId = sitesProvider.getCurrentSite().getSiteHomeId();
if (this.notificationsEnabled) { if (this.notificationsEnabled) {
this.calendarProvider.getEventNotificationTimeOption(this.eventId).then((notificationTime) => { this.calendarProvider.getEventNotificationTimeOption(this.eventId).then((notificationTime) => {
this.notificationTime = notificationTime; this.setNotificationTime(notificationTime);
this.loadNotificationTime();
}); });
this.calendarProvider.getDefaultNotificationTime().then((defaultTime) => { this.calendarProvider.getDefaultNotificationTime().then((defaultTime) => {
this.defaultTime = defaultTime * 60; this.defaultTime = defaultTime * 60;
this.loadNotificationTime(); this.setNotificationTime();
if (defaultTime === 0) {
// Disabled by default.
this.defaultTimeReadable = this.translate.instant('core.settings.disabled');
} else {
this.defaultTimeReadable = timeUtils.formatTime(defaultTime * 60);
}
}); });
// Calculate format to use. ion-datetime doesn't support escaping characters ([]), so we remove them.
this.notificationFormat = this.timeUtils.convertPHPToMoment(this.translate.instant('core.strftimedatetimeshort'))
.replace(/[\[\]]/g, '');
} }
} }
@ -88,12 +89,6 @@ export class AddonCalendarEventPage {
}); });
} }
updateNotificationTime(): void {
if (!isNaN(this.notificationTime) && this.event && this.event.id) {
this.calendarProvider.updateNotificationTime(this.event, this.notificationTime);
}
}
/** /**
* Fetches the event and updates the view. * Fetches the event and updates the view.
* *
@ -117,7 +112,11 @@ export class AddonCalendarEventPage {
this.event = event; this.event = event;
this.currentTime = this.timeUtils.timestamp(); this.currentTime = this.timeUtils.timestamp();
this.loadNotificationTime(); this.notificationMin = this.timeUtils.userDate(this.currentTime * 1000, 'YYYY-MM-DDTHH:mm:ss', false);
this.notificationMax = this.timeUtils.userDate((event.timestart + event.timeduration) * 1000,
'YYYY-MM-DDTHH:mm:ss', false);
this.setNotificationTime();
// Reset some of the calculated data. // Reset some of the calculated data.
this.categoryPath = ''; this.categoryPath = '';
@ -187,15 +186,50 @@ export class AddonCalendarEventPage {
} }
/** /**
* Loads notification time by discarding options not in the list. * Add a notification time for this event.
*
* @param {Event} e Click event.
*/ */
loadNotificationTime(): void { addNotificationTime(e: Event): void {
if (typeof this.notificationTime != 'undefined') { e.preventDefault();
if (this.notificationTime > 0 && this.event.timestart - this.notificationTime * 60 < this.currentTime) { e.stopPropagation();
this.notificationTime = 0;
} else if (this.notificationTime < 0 && this.event.timestart - this.defaultTime < this.currentTime) { if (this.notificationTimeText && this.event && this.event.id) {
this.notificationTime = 0; this.setNotificationTime(new Date(this.notificationTimeText).getTime() / 1000);
this.calendarProvider.updateNotificationTime(this.event, this.notificationTime);
}
}
/**
* Cancel the current notification.
*
* @param {Event} e Click event.
*/
cancelNotification(e: Event): void {
e.preventDefault();
e.stopPropagation();
this.calendarProvider.updateNotificationTime(this.event, 0);
this.notificationTime = 0;
}
/**
* Loads notification time.
*
* @param {number} [timeToLoad] Time to load. If not set, just recalculate.
*/
setNotificationTime(timeToLoad?: number): void {
this.timeToLoad = typeof timeToLoad == 'undefined' ? this.timeToLoad : timeToLoad;
if (typeof this.timeToLoad != 'undefined') {
if (this.timeToLoad < 0) {
this.notificationTime = this.event.timestart - this.defaultTime * 60;
} else if (this.timeToLoad == 0 || this.timeToLoad > 1440) {
this.notificationTime = this.timeToLoad;
} else {
this.notificationTime = this.event.timestart - this.timeToLoad * 60;
} }
this.notificationTimeText = new Date(this.notificationTime * 1000).toString();
} }
} }

View File

@ -305,11 +305,12 @@ export class AddonCalendarProvider {
* *
* @param {number} id Event ID. * @param {number} id Event ID.
* @param {string} [siteId] ID of the site the event belongs to. If not defined, use current site. * @param {string} [siteId] ID of the site the event belongs to. If not defined, use current site.
* @return {Promise<number>} Promise with wvent notification time in minutes. 0 if disabled, -1 if default time. * @return {Promise<number>} Promise with event notification time in minutes. 0 if disabled, -1 if default time.
*/ */
getEventNotificationTimeOption(id: number, siteId?: string): Promise<number> { getEventNotificationTimeOption(id: number, siteId?: string): Promise<number> {
return this.getEventFromLocalDb(id, siteId).then((e) => { return this.getEventFromLocalDb(id, siteId).then((e) => {
return e.notificationtime || -1; console.error(e.notificationtime);
return e.notificationtime || 0;
}).catch(() => { }).catch(() => {
return -1; return -1;
}); });
@ -670,7 +671,12 @@ export class AddonCalendarProvider {
return site.getDb().updateRecords(AddonCalendarProvider.EVENTS_TABLE, {notificationtime: time}, {id: event.id}) return site.getDb().updateRecords(AddonCalendarProvider.EVENTS_TABLE, {notificationtime: time}, {id: event.id})
.then(() => { .then(() => {
return this.scheduleEventNotification(event, time); if (time == 0) {
// No notification, cancel it.
return this.localNotificationsProvider.cancel(event.id, AddonCalendarProvider.COMPONENT, site.getId());
} else {
return this.scheduleEventNotification(event, time);
}
}); });
}); });
} }

View File

@ -65,7 +65,8 @@
"addon.calendar.eventstarttime": "Start time", "addon.calendar.eventstarttime": "Start time",
"addon.calendar.gotoactivity": "Go to activity", "addon.calendar.gotoactivity": "Go to activity",
"addon.calendar.noevents": "There are no events", "addon.calendar.noevents": "There are no events",
"addon.calendar.notifications": "Notifications", "addon.calendar.reminders": "Reminders",
"addon.calendar.setnewreminder": "Set a new reminder",
"addon.calendar.typecategory": "Category event", "addon.calendar.typecategory": "Category event",
"addon.calendar.typeclose": "Close event", "addon.calendar.typeclose": "Close event",
"addon.calendar.typecourse": "Course event", "addon.calendar.typecourse": "Course event",