+
+
+
+
+ {{ 'core.cancel' | translate }}
+
+
+
+ {{ 'core.done' | translate }}
+
+
+
+
+
diff --git a/src/core/features/reminders/components/set-reminder-custom/set-reminder-custom.ts b/src/core/features/reminders/components/set-reminder-custom/set-reminder-custom.ts
new file mode 100644
index 000000000..617309627
--- /dev/null
+++ b/src/core/features/reminders/components/set-reminder-custom/set-reminder-custom.ts
@@ -0,0 +1,64 @@
+// (C) Copyright 2015 Moodle Pty Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { Component, Input } from '@angular/core';
+import { CoreRemindersUnits } from '@features/reminders/services/reminders';
+import { PopoverController } from '@singletons';
+
+/**
+ * This component is meant to set a custom reminder
+ */
+@Component({
+ templateUrl: 'set-reminder-custom.html',
+})
+export class CoreRemindersSetReminderCustomComponent {
+
+ @Input() customValue = 10;
+ @Input() customUnits = CoreRemindersUnits.MINUTE;
+
+ customUnitsOptions = [
+ {
+ value: CoreRemindersUnits.MINUTE,
+ label: 'core.minutes',
+ },
+ {
+ value: CoreRemindersUnits.HOUR,
+ label: 'core.hours',
+ },
+ {
+ value: CoreRemindersUnits.DAY,
+ label: 'core.days',
+ },
+ {
+ value: CoreRemindersUnits.WEEK,
+ label: 'core.weeks',
+ },
+ ];
+
+ /**
+ * Set custom reminder.
+ */
+ set(): void {
+ // Return it as an object because 0 means undefined if not.
+ PopoverController.dismiss({ value: this.customValue, unit: this.customUnits });
+ }
+
+ /**
+ * Close popup.
+ */
+ cancel(): void {
+ PopoverController.dismiss();
+ }
+
+}
diff --git a/src/core/features/reminders/components/set-reminder-menu/set-reminder-menu.html b/src/core/features/reminders/components/set-reminder-menu/set-reminder-menu.html
new file mode 100644
index 000000000..85c09e03e
--- /dev/null
+++ b/src/core/features/reminders/components/set-reminder-menu/set-reminder-menu.html
@@ -0,0 +1,35 @@
+
+
+
+
{{ 'core.reminders.setareminder' | translate }}
+
+
+
+
+
+
+
+
+
{{ option.label }}
+
+
+
+
+
+
+
+
{{ 'core.reminders.custom' | translate }}
+
{{ customLabel }}
+
+
+
+
+
+
+
{{ noReminderLabel | translate }}
+
+
+
+
+
diff --git a/src/core/features/reminders/components/set-reminder-menu/set-reminder-menu.scss b/src/core/features/reminders/components/set-reminder-menu/set-reminder-menu.scss
new file mode 100644
index 000000000..db4708ab3
--- /dev/null
+++ b/src/core/features/reminders/components/set-reminder-menu/set-reminder-menu.scss
@@ -0,0 +1,3 @@
+ion-item.border-top {
+ border-top: 1px solid var(--stroke);
+}
diff --git a/src/core/features/reminders/components/set-reminder-menu/set-reminder-menu.ts b/src/core/features/reminders/components/set-reminder-menu/set-reminder-menu.ts
new file mode 100644
index 000000000..951886057
--- /dev/null
+++ b/src/core/features/reminders/components/set-reminder-menu/set-reminder-menu.ts
@@ -0,0 +1,152 @@
+// (C) Copyright 2015 Moodle Pty Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { AddonCalendarProvider } from '@addons/calendar/services/calendar';
+import { Component, Input, OnInit } from '@angular/core';
+import { CoreReminders, CoreRemindersUnits, CoreReminderValueAndUnit } from '@features/reminders/services/reminders';
+import { CoreDomUtils } from '@services/utils/dom';
+import { CoreUtils } from '@services/utils/utils';
+import { PopoverController } from '@singletons';
+import { CoreRemindersSetReminderCustomComponent } from '../set-reminder-custom/set-reminder-custom';
+
+/**
+ * This component is meant to display a popover with the reminder options.
+ */
+@Component({
+ templateUrl: 'set-reminder-menu.html',
+ styleUrls: ['set-reminder-menu.scss'],
+})
+export class CoreRemindersSetReminderMenuComponent implements OnInit {
+
+ @Input() initialValue?: CoreReminderValueAndUnit;
+ @Input() noReminderLabel = '';
+
+ currentValue = '0m';
+ customLabel = '';
+
+ protected customValue = 10;
+ protected customUnits = CoreRemindersUnits.MINUTE;
+
+ presetOptions = [
+ {
+ radioValue: '0m',
+ value: 0,
+ unit: CoreRemindersUnits.MINUTE,
+ label: '',
+ },
+ {
+ radioValue: '1h',
+ value: 1,
+ unit: CoreRemindersUnits.HOUR,
+ label: '',
+ },
+ {
+ radioValue: '12h',
+ value: 12,
+ unit: CoreRemindersUnits.HOUR,
+ label: '',
+ },
+ {
+ radioValue: '1d',
+ value: 1,
+ unit: CoreRemindersUnits.DAY,
+ label: '',
+ },
+ ];
+
+ /**
+ * @inheritdoc
+ */
+ async ngOnInit(): Promise {
+ this.presetOptions.forEach((option) => {
+ option.label = CoreReminders.getUnitValueLabel(option.value, option.unit);
+ });
+
+ if (!this.initialValue) {
+ return;
+ }
+
+ if (this.initialValue.value === AddonCalendarProvider.DEFAULT_NOTIFICATION_DISABLED) {
+ this.currentValue = 'disabled';
+ } else {
+ // Search if it's one of the preset options.
+ const option = this.presetOptions.find(option =>
+ option.value === this.initialValue?.value && option.unit === this.initialValue.unit);
+
+ if (option) {
+ this.currentValue = option.radioValue;
+ } else {
+ // It's a custom value.
+ this.currentValue = 'custom';
+ this.customValue = this.initialValue.value;
+ this.customUnits = this.initialValue.unit;
+ this.customLabel = CoreReminders.getUnitValueLabel(this.customValue, this.customUnits);
+ }
+ }
+ }
+
+ /**
+ * Set the reminder.
+ *
+ * @param value Value to set.
+ */
+ setReminder(value: string): void {
+ // Return it as an object because 0 means undefined if not.
+ if (value === 'disabled') {
+ PopoverController.dismiss({ timeBefore: AddonCalendarProvider.DEFAULT_NOTIFICATION_DISABLED });
+
+ return;
+ }
+
+ const option = this.presetOptions.find(option => option.radioValue === value);
+ if (!option) {
+ return;
+ }
+
+ PopoverController.dismiss({ timeBefore: option.unit * option.value });
+ }
+
+ /**
+ * Custom value input clicked.
+ *
+ * @param ev Click event.
+ */
+ async setCustom(ev: Event): Promise {
+ const reminderTime = await CoreDomUtils.openPopover({
+ component: CoreRemindersSetReminderCustomComponent,
+ componentProps: {
+ customValue: this.customValue,
+ customUnits: this.customUnits,
+ },
+ waitForDismissCompleted: true, // To be able to close parent popup.
+ event: ev,
+ });
+
+ if (reminderTime === undefined) {
+ // User canceled.
+ return;
+ }
+
+ this.currentValue = 'custom';
+ this.customValue = reminderTime.value;
+ this.customUnits = reminderTime.unit;
+ this.customLabel = CoreReminders.getUnitValueLabel(this.customValue, this.customUnits);
+
+ // Let the dimissed popover to be removed.
+ await CoreUtils.nextTick();
+
+ PopoverController.dismiss({ timeBefore: Math.abs(this.customValue) * this.customUnits });
+ }
+
+}
diff --git a/src/core/features/reminders/lang.json b/src/core/features/reminders/lang.json
new file mode 100644
index 000000000..d305761ef
--- /dev/null
+++ b/src/core/features/reminders/lang.json
@@ -0,0 +1,11 @@
+{
+ "atthetime": "At the time of the event",
+ "custom": "Custom...",
+ "customreminder": "Custom reminder",
+ "setareminder": "Set a reminder",
+ "daybefore": "{{time}} day before",
+ "daysbefore": "{{time}} days before",
+ "delete": "Delete reminder",
+ "timebefore": "{{value}} {{units}} before",
+ "units": "units"
+}
diff --git a/src/core/features/reminders/reminders.module.ts b/src/core/features/reminders/reminders.module.ts
index 9c010befc..46ddaeee9 100644
--- a/src/core/features/reminders/reminders.module.ts
+++ b/src/core/features/reminders/reminders.module.ts
@@ -14,6 +14,7 @@
import { APP_INITIALIZER, NgModule, Type } from '@angular/core';
import { CORE_SITE_SCHEMAS } from '@services/sites';
+import { CoreRemindersComponentsModule } from './components/components.module';
import { REMINDERS_SITE_SCHEMA } from './services/database/reminders';
import { CoreReminders, CoreRemindersService } from './services/reminders';
@@ -23,6 +24,7 @@ export const CORE_REMINDERS_SERVICES: Type[] = [
@NgModule({
imports: [
+ CoreRemindersComponentsModule,
],
providers: [
{
diff --git a/src/core/features/reminders/services/reminders.ts b/src/core/features/reminders/services/reminders.ts
index a71cf1063..297178a8a 100644
--- a/src/core/features/reminders/services/reminders.ts
+++ b/src/core/features/reminders/services/reminders.ts
@@ -17,10 +17,36 @@ import { Injectable } from '@angular/core';
import { CoreLocalNotifications } from '@services/local-notifications';
import { CoreSites } from '@services/sites';
import { CoreTimeUtils } from '@services/utils/time';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
import { CoreReminderDBRecord, REMINDERS_TABLE } from './database/reminders';
import { ILocalNotification } from '@ionic-native/local-notifications';
import { CorePlatform } from '@services/platform';
+import { CoreConstants } from '@/core/constants';
+
+/**
+ * Units to set a reminder.
+ */
+export enum CoreRemindersUnits {
+ MINUTE = CoreConstants.SECONDS_MINUTE,
+ HOUR = CoreConstants.SECONDS_HOUR,
+ DAY = CoreConstants.SECONDS_DAY,
+ WEEK = CoreConstants.SECONDS_WEEK,
+}
+
+const REMINDER_UNITS_LABELS = {
+ single: {
+ [CoreRemindersUnits.MINUTE]: 'core.minute',
+ [CoreRemindersUnits.HOUR]: 'core.hour',
+ [CoreRemindersUnits.DAY]: 'core.day',
+ [CoreRemindersUnits.WEEK]: 'core.week',
+ },
+ multi: {
+ [CoreRemindersUnits.MINUTE]: 'core.minutes',
+ [CoreRemindersUnits.HOUR]: 'core.hours',
+ [CoreRemindersUnits.DAY]: 'core.days',
+ [CoreRemindersUnits.WEEK]: 'core.weeks',
+ },
+};
/**
* Service to handle reminders.
@@ -274,6 +300,80 @@ export class CoreRemindersService {
}));
}
+ /**
+ * Given a value and a unit, return the translated label.
+ *
+ * @param value Value.
+ * @param unit Unit.
+ * @param addDefaultLabel Whether to add the "Default" text.
+ * @return Translated label.
+ */
+ getUnitValueLabel(value: number, unit: CoreRemindersUnits, addDefaultLabel = false): string {
+ if (value === AddonCalendarProvider.DEFAULT_NOTIFICATION_DISABLED) {
+ // TODO: It will need a migration of date to set 0 to -1 when needed.
+ return Translate.instant('core.settings.disabled');
+ }
+
+ if (value === 0) {
+ return Translate.instant('core.reminders.atthetime');
+ }
+
+ const unitsLabel = value === 1 ?
+ REMINDER_UNITS_LABELS.single[unit] :
+ REMINDER_UNITS_LABELS.multi[unit];
+
+ const label = Translate.instant('core.reminders.timebefore', {
+ units: Translate.instant(unitsLabel),
+ value: value,
+ });
+
+ if (addDefaultLabel) {
+ return Translate.instant('core.defaultvalue', { $a: label });
+ }
+
+ return label;
+ }
+
+ /**
+ * Given a number of seconds, convert it to a unit&value format compatible with reminders.
+ *
+ * @param seconds Number of seconds.
+ * @return Value and unit.
+ */
+ static convertSecondsToValueAndUnit(seconds?: number): CoreReminderValueAndUnit {
+ if (seconds === undefined || seconds < 0) {
+ return {
+ value: AddonCalendarProvider.DEFAULT_NOTIFICATION_DISABLED,
+ unit: CoreRemindersUnits.MINUTE,
+ };
+ } else if (seconds === 0) {
+ return {
+ value: 0,
+ unit: CoreRemindersUnits.MINUTE,
+ };
+ } else if (seconds % CoreRemindersUnits.WEEK === 0) {
+ return {
+ value: seconds / CoreRemindersUnits.WEEK,
+ unit: CoreRemindersUnits.WEEK,
+ };
+ } else if (seconds % CoreRemindersUnits.DAY === 0) {
+ return {
+ value: seconds / CoreRemindersUnits.DAY,
+ unit: CoreRemindersUnits.DAY,
+ };
+ } else if (seconds % CoreRemindersUnits.HOUR === 0) {
+ return {
+ value: seconds / CoreRemindersUnits.HOUR,
+ unit: CoreRemindersUnits.HOUR,
+ };
+ } else {
+ return {
+ value: seconds / CoreRemindersUnits.MINUTE,
+ unit: CoreRemindersUnits.MINUTE,
+ };
+ }
+ }
+
}
export const CoreReminders = makeSingleton(CoreRemindersService);
@@ -293,6 +393,14 @@ export type CoreReminderNotificationOptions = {
title: string;
};
+/**
+ * Value and unit for reminders.
+ */
+export type CoreReminderValueAndUnit = {
+ value: number;
+ unit: CoreRemindersUnits;
+};
+
export type CoreReminderSelector = {
instanceId: number;
component: string;
diff --git a/src/core/services/utils/dom.ts b/src/core/services/utils/dom.ts
index faddf4024..581880eeb 100644
--- a/src/core/services/utils/dom.ts
+++ b/src/core/services/utils/dom.ts
@@ -1138,7 +1138,7 @@ export class CoreDomUtilsProvider {
/**
* Show an alert modal with a button to close it.
*
- * @param title Title to show.
+ * @param header Title to show.
* @param message Message to show.
* @param buttonText Text of the button.
* @param autocloseTime Number of milliseconds to wait to close the modal. If not defined, modal won't be closed.
@@ -1230,7 +1230,7 @@ export class CoreDomUtilsProvider {
/**
* Show an alert modal with a button to close it, translating the values supplied.
*
- * @param title Title to show.
+ * @param header Title to show.
* @param message Message to show.
* @param buttonText Text of the button.
* @param autocloseTime Number of milliseconds to wait to close the modal. If not defined, modal won't be closed.
@@ -1669,7 +1669,6 @@ export class CoreDomUtilsProvider {
* @param needsTranslate Whether the 'text' needs to be translated.
* @param duration Duration in ms of the dimissable toast.
* @param cssClass Class to add to the toast.
- * @param dismissOnPageChange Dismiss the Toast on page change.
* @return Toast instance.
*/
async showToast(