MOBILE-3936 reminders: Avoid creating reminders in the past

main
Pau Ferrer Ocaña 2022-11-08 17:33:50 +01:00
parent 5d910ea5b4
commit 69d2530bb8
7 changed files with 74 additions and 24 deletions

View File

@ -43,7 +43,6 @@ import { CoreError } from '@classes/errors/error';
import { CoreNavigator } from '@services/navigator';
import { CanLeave } from '@guards/can-leave';
import { CoreForms } from '@singletons/form';
import { CoreLocalNotifications } from '@services/local-notifications';
import { CoreReminders, CoreRemindersService, CoreRemindersUnits } from '@features/reminders/services/reminders';
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.
*/
async addReminder(): Promise<void> {
const formData = this.form.value;
const eventTime = CoreTimeUtils.convertToTimestamp(formData.timestart, true);
const reminderTime = await CoreDomUtils.openPopover<{timeBefore: number}>({
component: CoreRemindersSetReminderMenuComponent,
componentProps: {
eventTime,
},
// TODO: Add event to open the popover in place.
});

View File

@ -28,7 +28,6 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreDomUtils, ToastDuration } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text';
import { CoreSites } from '@services/sites';
import { CoreLocalNotifications } from '@services/local-notifications';
import { CoreCourse } from '@features/course/services/course';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreGroups } from '@services/groups';
@ -389,6 +388,9 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy {
const reminderTime = await CoreDomUtils.openPopover<{timeBefore: number}>({
component: CoreRemindersSetReminderMenuComponent,
componentProps: {
eventTime: this.event.timestart,
},
// TODO: Add event to open the popover in place.
});

View File

@ -1,4 +1,6 @@
<ion-button fill="clear" size="small" (click)="setReminder($event)">
<ion-icon name="fas-bell" slot="icon-only" *ngIf="timebefore !== undefined"></ion-icon>
<ion-icon name="far-bell-slash" slot="icon-only" *ngIf="timebefore === undefined"></ion-icon>
<ion-button fill="clear" size="small" (click)="setReminder($event)"
[attr.aria-label]="'core.reminders.setareminderfor' | translate : { title: title, label: labelClean }"
[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>

View File

@ -13,7 +13,7 @@
// limitations under the License.
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 { CoreRemindersSetReminderMenuComponent } from '../set-reminder-menu/set-reminder-menu';
@ -24,7 +24,7 @@ import { CoreRemindersSetReminderMenuComponent } from '../set-reminder-menu/set-
selector: 'core-reminders-set-button',
templateUrl: 'set-button.html',
})
export class CoreRemindersSetButtonComponent {
export class CoreRemindersSetButtonComponent implements OnInit {
@Input() component?: string;
@Input() instanceId?: number;
@ -35,6 +35,15 @@ export class CoreRemindersSetButtonComponent {
@Input() title = '';
@Input() url = '';
labelClean = '';
/**
* @inheritdoc
*/
ngOnInit(): void {
this.labelClean = this.label.replace(':', '');
}
/**
* Set reminder.
*
@ -60,6 +69,7 @@ export class CoreRemindersSetButtonComponent {
component: CoreRemindersSetReminderMenuComponent,
componentProps: {
initialValue: this.timebefore,
eventTime: this.time,
noReminderLabel: 'core.reminders.delete',
},
event: ev,
@ -85,7 +95,7 @@ export class CoreRemindersSetButtonComponent {
return;
}
if (timebefore === CoreRemindersService.DISABLED) {
if (timebefore === undefined || timebefore === CoreRemindersService.DISABLED) {
// Remove the reminder.
await CoreReminders.removeReminders({
instanceId: this.instanceId,

View File

@ -9,14 +9,15 @@
<ion-item class="ion-text-wrap">
<div class="flex-row">
<!-- 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>
<!-- Units. -->
<label class="accesshide" for="reminderUnits">{{ 'core.reminders.units' | translate }}</label>
<ion-select id="reminderUnits" name="customunits" [(ngModel)]="customUnits" interface="action-sheet" slot="end"
[interfaceOptions]="{header: 'core.reminders.units' | translate}">
<ion-select-option *ngFor="let option of customUnitsOptions" [value]="option.value">
<span class="accesshide" id="reminderUnits_label">{{ 'core.reminders.units' | translate }}</span>
<ion-select aria-labelledby="reminderUnits_label" name="customunits" [(ngModel)]="customUnits" interface="action-sheet"
slot="end" [interfaceOptions]="{header: 'core.reminders.units' | translate}">
<ion-select-option *ngFor=" let option of customUnitsOptions" [value]="option.value">
{{ option.label | translate }}
</ion-select-option>
</ion-select>
@ -29,7 +30,7 @@
</ion-col>
<ion-col>
<ion-button expand="block" (click)="set()">
{{ 'core.done' | translate }}
{{ 'core.reminders.setreminder' | translate }}
</ion-button>
</ion-col>
</ion-row>

View File

@ -8,27 +8,31 @@
<ion-content>
<ion-content>
<!-- Preset options. -->
<ion-item button class="ion-text-wrap" (click)="setReminder(option.radioValue)" detail="false" *ngFor="let option of presetOptions">
<ion-label>
<p class="item-heading">{{ option.label }}</p>
</ion-label>
<ion-icon name="fas-check" *ngIf="currentValue === option.radioValue" slot="end"></ion-icon>
</ion-item>
<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>
<p class="item-heading">{{ option.label }}</p>
</ion-label>
<ion-icon name="fas-check" *ngIf="currentValue === option.radioValue" slot="end" aria-hidden="true"></ion-icon>
</ion-item>
</ng-container>
<!-- 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>
<p class="item-heading">{{ 'core.reminders.custom' | translate }}</p>
<p>{{ customLabel }}</p>
</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 *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>
<p class="item-heading">{{ noReminderLabel | translate }}</p>
</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-content>

View File

@ -34,6 +34,7 @@ import { CoreRemindersSetReminderCustomComponent } from '../set-reminder-custom/
export class CoreRemindersSetReminderMenuComponent implements OnInit {
@Input() initialValue?: number;
@Input() eventTime?: number;
@Input() noReminderLabel = '';
currentValue = '0m';
@ -48,24 +49,28 @@ export class CoreRemindersSetReminderMenuComponent implements OnInit {
value: 0,
unit: CoreRemindersUnits.MINUTE,
label: '',
enabled: true,
},
{
radioValue: '1h',
value: 1,
unit: CoreRemindersUnits.HOUR,
label: '',
enabled: true,
},
{
radioValue: '12h',
value: 12,
unit: CoreRemindersUnits.HOUR,
label: '',
enabled: true,
},
{
radioValue: '1d',
value: 1,
unit: CoreRemindersUnits.DAY,
label: '',
enabled: true,
},
];
@ -75,6 +80,7 @@ export class CoreRemindersSetReminderMenuComponent implements OnInit {
async ngOnInit(): Promise<void> {
this.presetOptions.forEach((option) => {
option.label = CoreReminders.getUnitValueLabel(option.value, option.unit);
option.enabled = this.isValidTime(option.unit, option.value);
});
const initialValue = CoreRemindersService.convertSecondsToValueAndUnit(this.initialValue);
@ -106,7 +112,10 @@ export class CoreRemindersSetReminderMenuComponent implements OnInit {
*/
setReminder(value?: string): void {
const option = this.presetOptions.find(option => option.radioValue === value);
if (!option) {
PopoverController.dismiss();
return;
}
@ -120,6 +129,23 @@ export class CoreRemindersSetReminderMenuComponent implements OnInit {
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.
*