commit
6c518d55fa
|
@ -11,49 +11,52 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-radio-group [(ngModel)]="radioValue" class="ion-text-wrap">
|
||||
<!-- Preset options. -->
|
||||
<ion-item *ngIf="allowDisable">
|
||||
<ion-label>
|
||||
<p>{{ 'core.settings.disabled' | translate }}</p>
|
||||
</ion-label>
|
||||
<ion-radio slot="end" value="disabled"></ion-radio>
|
||||
</ion-item>
|
||||
<ion-item *ngFor="let option of presetOptions">
|
||||
<ion-label>
|
||||
<p>{{ option.label }}</p>
|
||||
</ion-label>
|
||||
<ion-radio slot="end" [value]="option.radioValue"></ion-radio>
|
||||
</ion-item>
|
||||
<form (ngSubmit)="saveReminder()">
|
||||
<ion-radio-group name="radiovalue" [(ngModel)]="radioValue" class="ion-text-wrap">
|
||||
<!-- Preset options. -->
|
||||
<ion-item *ngIf="allowDisable">
|
||||
<ion-label>
|
||||
<p>{{ 'core.settings.disabled' | translate }}</p>
|
||||
</ion-label>
|
||||
<ion-radio slot="end" value="disabled"></ion-radio>
|
||||
</ion-item>
|
||||
<ion-item *ngFor="let option of presetOptions">
|
||||
<ion-label>
|
||||
<p>{{ option.label }}</p>
|
||||
</ion-label>
|
||||
<ion-radio slot="end" [value]="option.radioValue"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<!-- Custom value. -->
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<p>{{ 'core.custom' | translate }}</p>
|
||||
</ion-label>
|
||||
<ion-radio slot="end" value="custom"></ion-radio>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label></ion-label>
|
||||
<!-- Custom value. -->
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<p>{{ 'core.custom' | translate }}</p>
|
||||
</ion-label>
|
||||
<ion-radio slot="end" value="custom"></ion-radio>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label></ion-label>
|
||||
|
||||
<div class="flex-row">
|
||||
<!-- Input to enter the value. -->
|
||||
<ion-input type="number" name="customvalue" [(ngModel)]="customValue" [disabled]="radioValue != 'custom'" placeholder="10">
|
||||
</ion-input>
|
||||
<div class="flex-row">
|
||||
<!-- Input to enter the value. -->
|
||||
<ion-input type="number" name="customvalue" [(ngModel)]="customValue" [disabled]="radioValue != 'custom'"
|
||||
placeholder="10" (click)="customInputClicked($event)">
|
||||
</ion-input>
|
||||
|
||||
<!-- Units. -->
|
||||
<label class="accesshide" for="reminderUnits">{{ 'addon.calendar.units' | translate }}</label>
|
||||
<ion-select id="reminderUnits" name="customunits" [(ngModel)]="customUnits" interface="action-sheet"
|
||||
[disabled]="radioValue != 'custom'" slot="end" [interfaceOptions]="{header: 'addon.calendar.units' | translate}">
|
||||
<ion-select-option *ngFor="let option of customUnitsOptions" [value]="option.value">
|
||||
{{ option.label | translate }}
|
||||
</ion-select-option>
|
||||
</ion-select>
|
||||
</div>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
<!-- Units. -->
|
||||
<label class="accesshide" for="reminderUnits">{{ 'addon.calendar.units' | translate }}</label>
|
||||
<ion-select id="reminderUnits" name="customunits" [(ngModel)]="customUnits" interface="action-sheet"
|
||||
[disabled]="radioValue != 'custom'" slot="end" [interfaceOptions]="{header: 'addon.calendar.units' | translate}">
|
||||
<ion-select-option *ngFor="let option of customUnitsOptions" [value]="option.value">
|
||||
{{ option.label | translate }}
|
||||
</ion-select-option>
|
||||
</ion-select>
|
||||
</div>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
|
||||
<ion-button class="ion-margin" expand="block" (click)="saveReminder()" [disabled]="radioValue == 'custom' && !customValue">
|
||||
{{ 'core.done' | translate }}
|
||||
</ion-button>
|
||||
<ion-button type="submit" class="ion-margin" expand="block" [disabled]="radioValue == 'custom' && !customValue">
|
||||
{{ 'core.done' | translate }}
|
||||
</ion-button>
|
||||
</form>
|
||||
</ion-content>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import { AddonCalendar, AddonCalendarReminderUnits, AddonCalendarValueAndUnit } from '@addons/calendar/services/calendar';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { ModalController } from '@singletons';
|
||||
|
||||
/**
|
||||
|
@ -153,4 +154,24 @@ export class AddonCalendarReminderTimeModalComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom value input clicked.
|
||||
*
|
||||
* @param ev Click event.
|
||||
*/
|
||||
async customInputClicked(ev: Event): Promise<void> {
|
||||
if (this.radioValue === 'custom') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.radioValue = 'custom';
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
|
||||
const target = <HTMLInputElement | Element | null> ev.target;
|
||||
if (target && 'focus' in target) {
|
||||
target.focus();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -374,7 +374,9 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
|||
|
||||
const selectedDay = this.manager?.getSelectedItem();
|
||||
if (selectedDay) {
|
||||
params.timestamp = selectedDay.moment.unix() * 1000;
|
||||
// Use current time but in the specified day.
|
||||
const now = moment();
|
||||
params.timestamp = selectedDay.moment.clone().set({ hour: now.hour(), minute: now.minute() }).unix() * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -520,7 +520,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
|
|||
|
||||
try {
|
||||
const result = await AddonCalendar.submitEvent(this.eventId, data, {
|
||||
reminders: this.reminders,
|
||||
reminders: this.eventId ? [] : this.reminders, // Only allow adding reminders for new events.
|
||||
});
|
||||
event = result.event;
|
||||
|
||||
|
@ -638,7 +638,8 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
|
|||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async initReminders(): Promise<void> {
|
||||
if (!this.notificationsEnabled) {
|
||||
// Don't init reminders when editing an event. Right now, only allow adding reminders for new events.
|
||||
if (!this.notificationsEnabled || this.eventId) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,8 @@
|
|||
<ng-container *ngFor="let reminder of reminders">
|
||||
<ion-item *ngIf="reminder.timestamp > 0" class="ion-text-wrap" [class.item-dimmed]="reminder.timestamp <= currentTime">
|
||||
<ion-label>
|
||||
<p>{{ reminder.label }}</p>
|
||||
<p class="item-heading">{{ reminder.label }}</p>
|
||||
<p *ngIf="reminder.sublabel">{{ reminder.sublabel }}</p>
|
||||
</ion-label>
|
||||
<ion-button fill="clear" (click)="cancelNotification(reminder.id, $event)" [attr.aria-label]="'core.delete' | translate"
|
||||
slot="end">
|
||||
|
|
|
@ -37,6 +37,7 @@ import { AddonCalendarSyncInvalidateEvent } from './calendar-sync';
|
|||
import { AddonCalendarOfflineEventDBRecord } from './database/calendar-offline';
|
||||
import { CoreCategoryData } from '@features/courses/services/courses';
|
||||
import { AddonCalendarReminderDBRecord } from './database/calendar';
|
||||
import { CoreTimeUtils } from '@services/utils/time';
|
||||
|
||||
/**
|
||||
* Context levels enumeration.
|
||||
|
@ -329,6 +330,9 @@ export class AddonCalendarHelperProvider {
|
|||
|
||||
if (reminder.value && reminder.unit) {
|
||||
reminder.label = AddonCalendar.getUnitValueLabel(reminder.value, reminder.unit, reminder.time === null);
|
||||
if (reminder.timestamp) {
|
||||
reminder.sublabel = CoreTimeUtils.userDate(reminder.timestamp * 1000, 'core.strftimedatetime');
|
||||
}
|
||||
}
|
||||
|
||||
return reminder;
|
||||
|
@ -796,4 +800,5 @@ export type AddonCalendarEventReminder = AddonCalendarReminderDBRecord & {
|
|||
unit?: AddonCalendarReminderUnits; // Units.
|
||||
timestamp?: number; // Timestamp (in seconds).
|
||||
label?: string; // Label to represent the reminder.
|
||||
sublabel?: string; // Sub label.
|
||||
};
|
||||
|
|
|
@ -777,6 +777,7 @@ export class AddonCalendarProvider {
|
|||
const reminder: Partial<AddonCalendarReminderDBRecord> = {
|
||||
eventid: event.id,
|
||||
time: time ?? null,
|
||||
timecreated: Date.now(),
|
||||
};
|
||||
|
||||
const reminderId = await site.getDb().insertRecord(REMINDERS_TABLE, reminder);
|
||||
|
@ -913,7 +914,7 @@ export class AddonCalendarProvider {
|
|||
async getEventReminders(id: number, siteId?: string): Promise<AddonCalendarReminderDBRecord[]> {
|
||||
const site = await CoreSites.getSite(siteId);
|
||||
|
||||
return await site.getDb().getRecords(REMINDERS_TABLE, { eventid: id }, 'time ASC');
|
||||
return await site.getDb().getRecords(REMINDERS_TABLE, { eventid: id }, 'timecreated ASC, time ASC');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1696,7 +1697,7 @@ export class AddonCalendarProvider {
|
|||
const event = await AddonCalendarOffline.saveEvent(eventId, formData, siteId);
|
||||
|
||||
// Now save the reminders if any.
|
||||
if (options.reminders) {
|
||||
if (options.reminders?.length) {
|
||||
await CoreUtils.ignoreErrors(
|
||||
Promise.all(options.reminders.map((reminder) => this.addEventReminder(event, reminder.time, siteId))),
|
||||
);
|
||||
|
@ -1718,7 +1719,7 @@ export class AddonCalendarProvider {
|
|||
const event = await this.submitEventOnline(eventId, formData, siteId);
|
||||
|
||||
// Now save the reminders if any.
|
||||
if (options.reminders) {
|
||||
if (options.reminders?.length) {
|
||||
await CoreUtils.ignoreErrors(
|
||||
Promise.all(options.reminders.map((reminder) => this.addEventReminder(event, reminder.time, siteId))),
|
||||
);
|
||||
|
|
|
@ -22,7 +22,7 @@ import { AddonCalendar, AddonCalendarEventType, AddonCalendarProvider } from '..
|
|||
* Database variables for AddonCalendarProvider service.
|
||||
*/
|
||||
export const EVENTS_TABLE = 'addon_calendar_events_3';
|
||||
export const REMINDERS_TABLE = 'addon_calendar_reminders';
|
||||
export const REMINDERS_TABLE = 'addon_calendar_reminders_2';
|
||||
export const CALENDAR_SITE_SCHEMA: CoreSiteSchema = {
|
||||
name: 'AddonCalendarProvider',
|
||||
version: 4,
|
||||
|
@ -195,6 +195,10 @@ export const CALENDAR_SITE_SCHEMA: CoreSiteSchema = {
|
|||
name: 'time',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'timecreated',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
uniqueKeys: [
|
||||
['eventid', 'time'],
|
||||
|
@ -228,7 +232,16 @@ export const CALENDAR_SITE_SCHEMA: CoreSiteSchema = {
|
|||
}
|
||||
|
||||
// Migrate reminders. New format @since 4.0.
|
||||
const records = await db.getAllRecords<AddonCalendarReminderDBRecord>(REMINDERS_TABLE);
|
||||
const oldTable = 'addon_calendar_reminders';
|
||||
|
||||
try {
|
||||
await db.tableExists(oldTable);
|
||||
} catch (error) {
|
||||
// Old table does not exist, ignore.
|
||||
return;
|
||||
}
|
||||
|
||||
const records = await db.getAllRecords<AddonCalendarReminderDBRecord>(oldTable);
|
||||
const events: Record<number, AddonCalendarEventDBRecord> = {};
|
||||
|
||||
await Promise.all(records.map(async (record) => {
|
||||
|
@ -237,9 +250,7 @@ export const CALENDAR_SITE_SCHEMA: CoreSiteSchema = {
|
|||
try {
|
||||
events[record.eventid] = await db.getRecord(EVENTS_TABLE, { id: record.eventid });
|
||||
} catch {
|
||||
// Event not found in local DB, shouldn't happen. Delete the reminder.
|
||||
await db.deleteRecords(REMINDERS_TABLE, { id: record.id });
|
||||
|
||||
// Event not found in local DB, shouldn't happen. Ignore the reminder.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -248,9 +259,7 @@ export const CALENDAR_SITE_SCHEMA: CoreSiteSchema = {
|
|||
// Default reminder. Use null now.
|
||||
record.time = null;
|
||||
} else if (record.time > events[record.eventid].timestart) {
|
||||
// Reminder is after the event, delete it.
|
||||
await db.deleteRecords(REMINDERS_TABLE, { id: record.id });
|
||||
|
||||
// Reminder is after the event, ignore it.
|
||||
return;
|
||||
} else {
|
||||
// Remove seconds from the old reminder, it could include seconds by mistake.
|
||||
|
@ -259,6 +268,12 @@ export const CALENDAR_SITE_SCHEMA: CoreSiteSchema = {
|
|||
|
||||
return db.insertRecord(REMINDERS_TABLE, record);
|
||||
}));
|
||||
|
||||
try {
|
||||
await db.dropTable(oldTable);
|
||||
} catch (error) {
|
||||
// Error deleting old table, ignore.
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -308,4 +323,5 @@ export type AddonCalendarReminderDBRecord = {
|
|||
id: number;
|
||||
eventid: number;
|
||||
time: number | null; // Number of seconds before the event, null for default time.
|
||||
timecreated?: number | null;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue