MOBILE-3936 reminders: Avoid creating reminders in the past
parent
5d910ea5b4
commit
69d2530bb8
|
@ -43,7 +43,6 @@ import { CoreError } from '@classes/errors/error';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CanLeave } from '@guards/can-leave';
|
import { CanLeave } from '@guards/can-leave';
|
||||||
import { CoreForms } from '@singletons/form';
|
import { CoreForms } from '@singletons/form';
|
||||||
import { CoreLocalNotifications } from '@services/local-notifications';
|
|
||||||
import { CoreReminders, CoreRemindersService, CoreRemindersUnits } from '@features/reminders/services/reminders';
|
import { CoreReminders, CoreRemindersService, CoreRemindersUnits } from '@features/reminders/services/reminders';
|
||||||
import { CoreRemindersSetReminderMenuComponent } from '@features/reminders/components/set-reminder-menu/set-reminder-menu';
|
import { CoreRemindersSetReminderMenuComponent } from '@features/reminders/components/set-reminder-menu/set-reminder-menu';
|
||||||
|
|
||||||
|
@ -671,8 +670,14 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
|
||||||
* Add a reminder.
|
* Add a reminder.
|
||||||
*/
|
*/
|
||||||
async addReminder(): Promise<void> {
|
async addReminder(): Promise<void> {
|
||||||
|
const formData = this.form.value;
|
||||||
|
const eventTime = CoreTimeUtils.convertToTimestamp(formData.timestart, true);
|
||||||
|
|
||||||
const reminderTime = await CoreDomUtils.openPopover<{timeBefore: number}>({
|
const reminderTime = await CoreDomUtils.openPopover<{timeBefore: number}>({
|
||||||
component: CoreRemindersSetReminderMenuComponent,
|
component: CoreRemindersSetReminderMenuComponent,
|
||||||
|
componentProps: {
|
||||||
|
eventTime,
|
||||||
|
},
|
||||||
// TODO: Add event to open the popover in place.
|
// TODO: Add event to open the popover in place.
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreDomUtils, ToastDuration } from '@services/utils/dom';
|
import { CoreDomUtils, ToastDuration } from '@services/utils/dom';
|
||||||
import { CoreTextUtils } from '@services/utils/text';
|
import { CoreTextUtils } from '@services/utils/text';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreLocalNotifications } from '@services/local-notifications';
|
|
||||||
import { CoreCourse } from '@features/course/services/course';
|
import { CoreCourse } from '@features/course/services/course';
|
||||||
import { CoreTimeUtils } from '@services/utils/time';
|
import { CoreTimeUtils } from '@services/utils/time';
|
||||||
import { CoreGroups } from '@services/groups';
|
import { CoreGroups } from '@services/groups';
|
||||||
|
@ -389,6 +388,9 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
const reminderTime = await CoreDomUtils.openPopover<{timeBefore: number}>({
|
const reminderTime = await CoreDomUtils.openPopover<{timeBefore: number}>({
|
||||||
component: CoreRemindersSetReminderMenuComponent,
|
component: CoreRemindersSetReminderMenuComponent,
|
||||||
|
componentProps: {
|
||||||
|
eventTime: this.event.timestart,
|
||||||
|
},
|
||||||
// TODO: Add event to open the popover in place.
|
// TODO: Add event to open the popover in place.
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
<ion-button fill="clear" size="small" (click)="setReminder($event)">
|
<ion-button fill="clear" size="small" (click)="setReminder($event)"
|
||||||
<ion-icon name="fas-bell" slot="icon-only" *ngIf="timebefore !== undefined"></ion-icon>
|
[attr.aria-label]="'core.reminders.setareminderfor' | translate : { title: title, label: labelClean }"
|
||||||
<ion-icon name="far-bell-slash" slot="icon-only" *ngIf="timebefore === undefined"></ion-icon>
|
[attr.aria-checked]="timebefore !== undefined">
|
||||||
|
<ion-icon name="fas-bell" slot="icon-only" *ngIf="timebefore !== undefined" aria-hidden="true"></ion-icon>
|
||||||
|
<ion-icon name="far-bell-slash" slot="icon-only" *ngIf="timebefore === undefined" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { CoreReminderData, CoreReminders, CoreRemindersService } from '@features/reminders/services/reminders';
|
import { CoreReminderData, CoreReminders, CoreRemindersService } from '@features/reminders/services/reminders';
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreRemindersSetReminderMenuComponent } from '../set-reminder-menu/set-reminder-menu';
|
import { CoreRemindersSetReminderMenuComponent } from '../set-reminder-menu/set-reminder-menu';
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import { CoreRemindersSetReminderMenuComponent } from '../set-reminder-menu/set-
|
||||||
selector: 'core-reminders-set-button',
|
selector: 'core-reminders-set-button',
|
||||||
templateUrl: 'set-button.html',
|
templateUrl: 'set-button.html',
|
||||||
})
|
})
|
||||||
export class CoreRemindersSetButtonComponent {
|
export class CoreRemindersSetButtonComponent implements OnInit {
|
||||||
|
|
||||||
@Input() component?: string;
|
@Input() component?: string;
|
||||||
@Input() instanceId?: number;
|
@Input() instanceId?: number;
|
||||||
|
@ -35,6 +35,15 @@ export class CoreRemindersSetButtonComponent {
|
||||||
@Input() title = '';
|
@Input() title = '';
|
||||||
@Input() url = '';
|
@Input() url = '';
|
||||||
|
|
||||||
|
labelClean = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.labelClean = this.label.replace(':', '');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set reminder.
|
* Set reminder.
|
||||||
*
|
*
|
||||||
|
@ -60,6 +69,7 @@ export class CoreRemindersSetButtonComponent {
|
||||||
component: CoreRemindersSetReminderMenuComponent,
|
component: CoreRemindersSetReminderMenuComponent,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
initialValue: this.timebefore,
|
initialValue: this.timebefore,
|
||||||
|
eventTime: this.time,
|
||||||
noReminderLabel: 'core.reminders.delete',
|
noReminderLabel: 'core.reminders.delete',
|
||||||
},
|
},
|
||||||
event: ev,
|
event: ev,
|
||||||
|
@ -85,7 +95,7 @@ export class CoreRemindersSetButtonComponent {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timebefore === CoreRemindersService.DISABLED) {
|
if (timebefore === undefined || timebefore === CoreRemindersService.DISABLED) {
|
||||||
// Remove the reminder.
|
// Remove the reminder.
|
||||||
await CoreReminders.removeReminders({
|
await CoreReminders.removeReminders({
|
||||||
instanceId: this.instanceId,
|
instanceId: this.instanceId,
|
||||||
|
|
|
@ -9,13 +9,14 @@
|
||||||
<ion-item class="ion-text-wrap">
|
<ion-item class="ion-text-wrap">
|
||||||
<div class="flex-row">
|
<div class="flex-row">
|
||||||
<!-- Input to enter the value. -->
|
<!-- Input to enter the value. -->
|
||||||
<ion-input type="number" name="customvalue" [(ngModel)]="customValue" placeholder="10">
|
<ion-input id="reminderValue" type="number" name="customvalue" [(ngModel)]="customValue" placeholder="10"
|
||||||
|
[attr.aria-label]="'core.reminders.value' | translate">
|
||||||
</ion-input>
|
</ion-input>
|
||||||
|
|
||||||
<!-- Units. -->
|
<!-- Units. -->
|
||||||
<label class="accesshide" for="reminderUnits">{{ 'core.reminders.units' | translate }}</label>
|
<span class="accesshide" id="reminderUnits_label">{{ 'core.reminders.units' | translate }}</span>
|
||||||
<ion-select id="reminderUnits" name="customunits" [(ngModel)]="customUnits" interface="action-sheet" slot="end"
|
<ion-select aria-labelledby="reminderUnits_label" name="customunits" [(ngModel)]="customUnits" interface="action-sheet"
|
||||||
[interfaceOptions]="{header: 'core.reminders.units' | translate}">
|
slot="end" [interfaceOptions]="{header: 'core.reminders.units' | translate}">
|
||||||
<ion-select-option *ngFor=" let option of customUnitsOptions" [value]="option.value">
|
<ion-select-option *ngFor=" let option of customUnitsOptions" [value]="option.value">
|
||||||
{{ option.label | translate }}
|
{{ option.label | translate }}
|
||||||
</ion-select-option>
|
</ion-select-option>
|
||||||
|
@ -29,7 +30,7 @@
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col>
|
<ion-col>
|
||||||
<ion-button expand="block" (click)="set()">
|
<ion-button expand="block" (click)="set()">
|
||||||
{{ 'core.done' | translate }}
|
{{ 'core.reminders.setreminder' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
</ion-row>
|
</ion-row>
|
||||||
|
|
|
@ -8,27 +8,31 @@
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<!-- Preset options. -->
|
<!-- Preset options. -->
|
||||||
<ion-item button class="ion-text-wrap" (click)="setReminder(option.radioValue)" detail="false" *ngFor="let option of presetOptions">
|
<ng-container *ngFor="let option of presetOptions">
|
||||||
|
<ion-item button class="ion-text-wrap" (click)="setReminder(option.radioValue)" detail="false" *ngIf="option.enabled"
|
||||||
|
[attr.aria-selected]="currentValue === option.radioValue">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ option.label }}</p>
|
<p class="item-heading">{{ option.label }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-icon name="fas-check" *ngIf="currentValue === option.radioValue" slot="end"></ion-icon>
|
<ion-icon name="fas-check" *ngIf="currentValue === option.radioValue" slot="end" aria-hidden="true"></ion-icon>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<!-- Custom value. -->
|
<!-- Custom value. -->
|
||||||
<ion-item button class="ion-text-wrap" (click)="setCustom($event)" detail="false">
|
<ion-item button class="ion-text-wrap" (click)="setCustom($event)" detail="false" [attr.aria-selected]="currentValue === 'custom'">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'core.reminders.custom' | translate }}</p>
|
<p class="item-heading">{{ 'core.reminders.custom' | translate }}</p>
|
||||||
<p>{{ customLabel }}</p>
|
<p>{{ customLabel }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-icon name="fas-check" *ngIf="currentValue === 'custom'" slot="end"></ion-icon>
|
<ion-icon name="fas-check" *ngIf="currentValue === 'custom'" slot="end" aria-hidden="true"></ion-icon>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item *ngIf="noReminderLabel" button class="ion-text-wrap text-danger border-top" (click)="disableReminder()" detail="false">
|
<ion-item *ngIf="noReminderLabel" button class="ion-text-wrap text-danger border-top" (click)="disableReminder()" detail="false"
|
||||||
|
[attr.aria-selected]="currentValue === 'disabled'">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ noReminderLabel | translate }}</p>
|
<p class="item-heading">{{ noReminderLabel | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-icon name="fas-check" *ngIf="currentValue === 'disabled'" slot="end"></ion-icon>
|
<ion-icon name="fas-check" *ngIf="currentValue === 'disabled'" slot="end" aria-hidden="true"></ion-icon>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
|
@ -34,6 +34,7 @@ import { CoreRemindersSetReminderCustomComponent } from '../set-reminder-custom/
|
||||||
export class CoreRemindersSetReminderMenuComponent implements OnInit {
|
export class CoreRemindersSetReminderMenuComponent implements OnInit {
|
||||||
|
|
||||||
@Input() initialValue?: number;
|
@Input() initialValue?: number;
|
||||||
|
@Input() eventTime?: number;
|
||||||
@Input() noReminderLabel = '';
|
@Input() noReminderLabel = '';
|
||||||
|
|
||||||
currentValue = '0m';
|
currentValue = '0m';
|
||||||
|
@ -48,24 +49,28 @@ export class CoreRemindersSetReminderMenuComponent implements OnInit {
|
||||||
value: 0,
|
value: 0,
|
||||||
unit: CoreRemindersUnits.MINUTE,
|
unit: CoreRemindersUnits.MINUTE,
|
||||||
label: '',
|
label: '',
|
||||||
|
enabled: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
radioValue: '1h',
|
radioValue: '1h',
|
||||||
value: 1,
|
value: 1,
|
||||||
unit: CoreRemindersUnits.HOUR,
|
unit: CoreRemindersUnits.HOUR,
|
||||||
label: '',
|
label: '',
|
||||||
|
enabled: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
radioValue: '12h',
|
radioValue: '12h',
|
||||||
value: 12,
|
value: 12,
|
||||||
unit: CoreRemindersUnits.HOUR,
|
unit: CoreRemindersUnits.HOUR,
|
||||||
label: '',
|
label: '',
|
||||||
|
enabled: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
radioValue: '1d',
|
radioValue: '1d',
|
||||||
value: 1,
|
value: 1,
|
||||||
unit: CoreRemindersUnits.DAY,
|
unit: CoreRemindersUnits.DAY,
|
||||||
label: '',
|
label: '',
|
||||||
|
enabled: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -75,6 +80,7 @@ export class CoreRemindersSetReminderMenuComponent implements OnInit {
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
this.presetOptions.forEach((option) => {
|
this.presetOptions.forEach((option) => {
|
||||||
option.label = CoreReminders.getUnitValueLabel(option.value, option.unit);
|
option.label = CoreReminders.getUnitValueLabel(option.value, option.unit);
|
||||||
|
option.enabled = this.isValidTime(option.unit, option.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialValue = CoreRemindersService.convertSecondsToValueAndUnit(this.initialValue);
|
const initialValue = CoreRemindersService.convertSecondsToValueAndUnit(this.initialValue);
|
||||||
|
@ -106,7 +112,10 @@ export class CoreRemindersSetReminderMenuComponent implements OnInit {
|
||||||
*/
|
*/
|
||||||
setReminder(value?: string): void {
|
setReminder(value?: string): void {
|
||||||
const option = this.presetOptions.find(option => option.radioValue === value);
|
const option = this.presetOptions.find(option => option.radioValue === value);
|
||||||
|
|
||||||
if (!option) {
|
if (!option) {
|
||||||
|
PopoverController.dismiss();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +129,23 @@ export class CoreRemindersSetReminderMenuComponent implements OnInit {
|
||||||
PopoverController.dismiss({ timeBefore: undefined });
|
PopoverController.dismiss({ timeBefore: undefined });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the time is on the future.
|
||||||
|
*
|
||||||
|
* @param unit Time unit.
|
||||||
|
* @param value Time value.
|
||||||
|
* @return Wether is a valid time or not.
|
||||||
|
*/
|
||||||
|
protected isValidTime(unit: number, value: number): boolean {
|
||||||
|
if (!this.eventTime) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timebefore = unit * value;
|
||||||
|
|
||||||
|
return (this.eventTime - timebefore) * 1000 > Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom value input clicked.
|
* Custom value input clicked.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue