MOBILE-3090 calendar: Support deleting events
parent
a9d62274c9
commit
1d8f617338
|
@ -87,13 +87,19 @@
|
||||||
"addon.calendar.calendarevent": "local_moodlemobileapp",
|
"addon.calendar.calendarevent": "local_moodlemobileapp",
|
||||||
"addon.calendar.calendarevents": "local_moodlemobileapp",
|
"addon.calendar.calendarevents": "local_moodlemobileapp",
|
||||||
"addon.calendar.calendarreminders": "local_moodlemobileapp",
|
"addon.calendar.calendarreminders": "local_moodlemobileapp",
|
||||||
|
"addon.calendar.confirmeventdelete": "calendar",
|
||||||
|
"addon.calendar.confirmeventseriesdelete": "calendar",
|
||||||
"addon.calendar.defaultnotificationtime": "local_moodlemobileapp",
|
"addon.calendar.defaultnotificationtime": "local_moodlemobileapp",
|
||||||
|
"addon.calendar.deleteallevents": "calendar",
|
||||||
|
"addon.calendar.deleteevent": "calendar",
|
||||||
|
"addon.calendar.deleteoneevent": "calendar",
|
||||||
"addon.calendar.durationminutes": "calendar",
|
"addon.calendar.durationminutes": "calendar",
|
||||||
"addon.calendar.durationnone": "calendar",
|
"addon.calendar.durationnone": "calendar",
|
||||||
"addon.calendar.durationuntil": "calendar",
|
"addon.calendar.durationuntil": "calendar",
|
||||||
"addon.calendar.editevent": "calendar",
|
"addon.calendar.editevent": "calendar",
|
||||||
"addon.calendar.errorloadevent": "local_moodlemobileapp",
|
"addon.calendar.errorloadevent": "local_moodlemobileapp",
|
||||||
"addon.calendar.errorloadevents": "local_moodlemobileapp",
|
"addon.calendar.errorloadevents": "local_moodlemobileapp",
|
||||||
|
"addon.calendar.eventcalendareventdeleted": "calendar",
|
||||||
"addon.calendar.eventduration": "calendar",
|
"addon.calendar.eventduration": "calendar",
|
||||||
"addon.calendar.eventendtime": "calendar",
|
"addon.calendar.eventendtime": "calendar",
|
||||||
"addon.calendar.eventkind": "calendar",
|
"addon.calendar.eventkind": "calendar",
|
||||||
|
|
|
@ -3,13 +3,19 @@
|
||||||
"calendarevent": "Calendar event",
|
"calendarevent": "Calendar event",
|
||||||
"calendarevents": "Calendar events",
|
"calendarevents": "Calendar events",
|
||||||
"calendarreminders": "Calendar reminders",
|
"calendarreminders": "Calendar reminders",
|
||||||
|
"confirmeventdelete": "Are you sure you want to delete the \"{{$a}}\" event?",
|
||||||
|
"confirmeventseriesdelete": "The \"{{$a.name}}\" event is part of a series. Do you want to delete just this event, or all {{$a.count}} events in the series?",
|
||||||
"defaultnotificationtime": "Default notification time",
|
"defaultnotificationtime": "Default notification time",
|
||||||
|
"deleteallevents": "Delete all events",
|
||||||
|
"deleteevent": "Delete event",
|
||||||
|
"deleteoneevent": "Delete this event",
|
||||||
"durationminutes": "Duration in minutes",
|
"durationminutes": "Duration in minutes",
|
||||||
"durationnone": "Without duration",
|
"durationnone": "Without duration",
|
||||||
"durationuntil": "Until",
|
"durationuntil": "Until",
|
||||||
"editevent": "Editing event",
|
"editevent": "Editing event",
|
||||||
"errorloadevent": "Error loading event.",
|
"errorloadevent": "Error loading event.",
|
||||||
"errorloadevents": "Error loading events.",
|
"errorloadevents": "Error loading events.",
|
||||||
|
"eventcalendareventdeleted": "Calendar event deleted",
|
||||||
"eventduration": "Duration",
|
"eventduration": "Duration",
|
||||||
"eventendtime": "End time",
|
"eventendtime": "End time",
|
||||||
"eventkind": "Type of event",
|
"eventkind": "Type of event",
|
||||||
|
|
|
@ -8,8 +8,10 @@
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<core-navbar-buttons end>
|
<core-navbar-buttons end>
|
||||||
<core-context-menu>
|
<core-context-menu>
|
||||||
<core-context-menu-item [hidden]="isSplitViewOn || !eventLoaded || !hasOffline || !isOnline" [priority]="400" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item [hidden]="isSplitViewOn || !eventLoaded || (!hasOffline && !event.deleted) || !isOnline" [priority]="400" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item [hidden]="!canEdit || !event || !event.canedit" [priority]="300" [content]="'core.edit' | translate" (action)="openEdit()" [iconAction]="'create'"></core-context-menu-item>
|
<core-context-menu-item [hidden]="!canEdit || !event || !event.canedit || event.deleted" [priority]="300" [content]="'core.edit' | translate" (action)="openEdit()" [iconAction]="'create'"></core-context-menu-item>
|
||||||
|
<core-context-menu-item [hidden]="!canDelete || !event || !event.candelete || event.deleted" [priority]="200" [content]="'core.delete' | translate" (action)="deleteEvent()" [iconAction]="'trash'"></core-context-menu-item>
|
||||||
|
<core-context-menu-item [hidden]="!event || !event.deleted" [priority]="200" [content]="'core.restore' | translate" (action)="undoDelete()" [iconAction]="'undo'"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
|
@ -18,7 +20,7 @@
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
<core-loading [hideUntil]="eventLoaded">
|
<core-loading [hideUntil]="eventLoaded">
|
||||||
<!-- There is data to be synchronized -->
|
<!-- There is data to be synchronized -->
|
||||||
<ion-card class="core-warning-card" icon-start *ngIf="hasOffline">
|
<ion-card class="core-warning-card" icon-start *ngIf="hasOffline || event.deleted">
|
||||||
<ion-icon name="warning"></ion-icon> {{ 'core.hasdatatosync' | translate:{$a: 'addon.calendar.calendarevent' | translate} }}
|
<ion-icon name="warning"></ion-icon> {{ 'core.hasdatatosync' | translate:{$a: 'addon.calendar.calendarevent' | translate} }}
|
||||||
</ion-card>
|
</ion-card>
|
||||||
|
|
||||||
|
@ -27,6 +29,9 @@
|
||||||
<ion-item 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>
|
||||||
<h2><core-format-text [text]="event.name"></core-format-text></h2>
|
<h2><core-format-text [text]="event.name"></core-format-text></h2>
|
||||||
|
<ion-note item-end *ngIf="event.deleted">
|
||||||
|
<ion-icon name="trash"></ion-icon> {{ 'core.deletedoffline' | translate }}
|
||||||
|
</ion-note>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item text-wrap>
|
<ion-item text-wrap>
|
||||||
<h2>{{ 'addon.calendar.eventstarttime' | translate}}</h2>
|
<h2>{{ 'addon.calendar.eventstarttime' | translate}}</h2>
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
ion-app.app-root page-addon-calendar-event {
|
||||||
|
.card ion-note {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,6 +68,7 @@ export class AddonCalendarEventPage implements OnDestroy {
|
||||||
defaultTime: number;
|
defaultTime: number;
|
||||||
reminders: any[];
|
reminders: any[];
|
||||||
canEdit = false;
|
canEdit = false;
|
||||||
|
canDelete = false;
|
||||||
hasOffline = false;
|
hasOffline = false;
|
||||||
isOnline = false;
|
isOnline = false;
|
||||||
syncIcon: string; // Sync icon.
|
syncIcon: string; // Sync icon.
|
||||||
|
@ -89,8 +90,9 @@ export class AddonCalendarEventPage implements OnDestroy {
|
||||||
this.currentSiteId = sitesProvider.getCurrentSiteId();
|
this.currentSiteId = sitesProvider.getCurrentSiteId();
|
||||||
this.isSplitViewOn = this.svComponent && this.svComponent.isOn();
|
this.isSplitViewOn = this.svComponent && this.svComponent.isOn();
|
||||||
|
|
||||||
// Check if site supports editing. No need to check allowed types, event.canedit already does it.
|
// Check if site supports editing and deleting. No need to check allowed types, event.canedit already does it.
|
||||||
this.canEdit = this.calendarProvider.canEditEventsInSite();
|
this.canEdit = this.calendarProvider.canEditEventsInSite();
|
||||||
|
this.canDelete = this.calendarProvider.canDeleteEventsInSite();
|
||||||
|
|
||||||
if (this.notificationsEnabled) {
|
if (this.notificationsEnabled) {
|
||||||
this.calendarProvider.getEventReminders(this.eventId).then((reminders) => {
|
this.calendarProvider.getEventReminders(this.eventId).then((reminders) => {
|
||||||
|
@ -123,10 +125,10 @@ export class AddonCalendarEventPage implements OnDestroy {
|
||||||
this.currentSiteId);
|
this.currentSiteId);
|
||||||
|
|
||||||
// Refresh online status when changes.
|
// Refresh online status when changes.
|
||||||
this.onlineObserver = network.onchange().subscribe((online) => {
|
this.onlineObserver = network.onchange().subscribe(() => {
|
||||||
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||||
zone.run(() => {
|
zone.run(() => {
|
||||||
this.isOnline = online;
|
this.isOnline = this.appProvider.isOnline();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -150,7 +152,8 @@ export class AddonCalendarEventPage implements OnDestroy {
|
||||||
fetchEvent(sync?: boolean, showErrors?: boolean): Promise<any> {
|
fetchEvent(sync?: boolean, showErrors?: boolean): Promise<any> {
|
||||||
const currentSite = this.sitesProvider.getCurrentSite(),
|
const currentSite = this.sitesProvider.getCurrentSite(),
|
||||||
canGetById = this.calendarProvider.isGetEventByIdAvailable();
|
canGetById = this.calendarProvider.isGetEventByIdAvailable();
|
||||||
let promise;
|
let promise,
|
||||||
|
deleted = false;
|
||||||
|
|
||||||
this.isOnline = this.appProvider.isOnline();
|
this.isOnline = this.appProvider.isOnline();
|
||||||
|
|
||||||
|
@ -161,6 +164,11 @@ export class AddonCalendarEventPage implements OnDestroy {
|
||||||
this.domUtils.showErrorModal(result.warnings[0]);
|
this.domUtils.showErrorModal(result.warnings[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.deleted && result.deleted.indexOf(this.eventId) != -1) {
|
||||||
|
// This event was deleted during the sync.
|
||||||
|
deleted = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (result.updated) {
|
if (result.updated) {
|
||||||
// Trigger a manual sync event.
|
// Trigger a manual sync event.
|
||||||
result.source = 'event';
|
result.source = 'event';
|
||||||
|
@ -177,6 +185,10 @@ export class AddonCalendarEventPage implements OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise.then(() => {
|
return promise.then(() => {
|
||||||
|
if (deleted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
// Get the event data.
|
// Get the event data.
|
||||||
|
@ -204,6 +216,10 @@ export class AddonCalendarEventPage implements OnDestroy {
|
||||||
});
|
});
|
||||||
|
|
||||||
}).then((event) => {
|
}).then((event) => {
|
||||||
|
if (deleted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
this.calendarHelper.formatEventData(event);
|
this.calendarHelper.formatEventData(event);
|
||||||
|
@ -251,7 +267,7 @@ export class AddonCalendarEventPage implements OnDestroy {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
|
||||||
// If the event belongs to a course, get the course name and the URL to view it.
|
// If the event belongs to a course, get the course name and the URL to view it.
|
||||||
if (canGetById && event.course) {
|
if (canGetById && event.course && event.course.id != this.siteHomeId) {
|
||||||
this.courseName = event.course.fullname;
|
this.courseName = event.course.fullname;
|
||||||
this.courseUrl = event.course.viewurl;
|
this.courseUrl = event.course.viewurl;
|
||||||
} else if (event.courseid && event.courseid != this.siteHomeId) {
|
} else if (event.courseid && event.courseid != this.siteHomeId) {
|
||||||
|
@ -290,6 +306,11 @@ export class AddonCalendarEventPage implements OnDestroy {
|
||||||
event.encodedLocation = this.textUtils.buildAddressURL(event.location);
|
event.encodedLocation = this.textUtils.buildAddressURL(event.location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if event was deleted in offine.
|
||||||
|
promises.push(this.calendarOffline.isEventDeleted(this.eventId).then((deleted) => {
|
||||||
|
event.deleted = deleted;
|
||||||
|
}));
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
this.domUtils.showErrorModalDefault(error, 'addon.calendar.errorloadevent', true);
|
this.domUtils.showErrorModalDefault(error, 'addon.calendar.errorloadevent', true);
|
||||||
|
@ -391,6 +412,97 @@ export class AddonCalendarEventPage implements OnDestroy {
|
||||||
navCtrl.push('AddonCalendarEditEventPage', {eventId: this.eventId});
|
navCtrl.push('AddonCalendarEditEventPage', {eventId: this.eventId});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the event.
|
||||||
|
*/
|
||||||
|
deleteEvent(): void {
|
||||||
|
const title = this.translate.instant('addon.calendar.deleteevent'),
|
||||||
|
options: any = {};
|
||||||
|
let message: string;
|
||||||
|
|
||||||
|
if (this.event.eventcount > 1) {
|
||||||
|
// It's a repeated event.
|
||||||
|
message = this.translate.instant('addon.calendar.confirmeventseriesdelete',
|
||||||
|
{$a: {name: this.event.name, count: this.event.eventcount}});
|
||||||
|
|
||||||
|
options.inputs = [
|
||||||
|
{
|
||||||
|
type: 'radio',
|
||||||
|
name: 'deleteall',
|
||||||
|
checked: true,
|
||||||
|
value: false,
|
||||||
|
label: this.translate.instant('addon.calendar.deleteoneevent')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'radio',
|
||||||
|
name: 'deleteall',
|
||||||
|
checked: false,
|
||||||
|
value: true,
|
||||||
|
label: this.translate.instant('addon.calendar.deleteallevents')
|
||||||
|
}
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// Not repeated, display a simple confirm.
|
||||||
|
message = this.translate.instant('addon.calendar.confirmeventdelete', {$a: this.event.name});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.domUtils.showConfirm(message, title, undefined, undefined, options).then((deleteAll) => {
|
||||||
|
|
||||||
|
const modal = this.domUtils.showModalLoading('core.sending', true);
|
||||||
|
|
||||||
|
this.calendarProvider.deleteEvent(this.event.id, this.event.name, deleteAll).then((sent) => {
|
||||||
|
|
||||||
|
// Trigger an event.
|
||||||
|
this.eventsProvider.trigger(AddonCalendarProvider.DELETED_EVENT_EVENT, {
|
||||||
|
eventId: this.eventId,
|
||||||
|
sent: sent
|
||||||
|
}, this.sitesProvider.getCurrentSiteId());
|
||||||
|
|
||||||
|
if (sent) {
|
||||||
|
this.domUtils.showToast('addon.calendar.eventcalendareventdeleted', true, 3000, undefined, false);
|
||||||
|
|
||||||
|
// Event deleted, close the view.
|
||||||
|
if (!this.svComponent || !this.svComponent.isOn()) {
|
||||||
|
this.navCtrl.pop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Event deleted in offline, just mark it as deleted.
|
||||||
|
this.event.deleted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
this.domUtils.showErrorModalDefault(error, 'Error deleting event.');
|
||||||
|
}).finally(() => {
|
||||||
|
modal.dismiss();
|
||||||
|
});
|
||||||
|
}, () => {
|
||||||
|
// User canceled.
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo delete the event.
|
||||||
|
*/
|
||||||
|
undoDelete(): void {
|
||||||
|
const modal = this.domUtils.showModalLoading('core.sending', true);
|
||||||
|
|
||||||
|
this.calendarOffline.unmarkDeleted(this.event.id).then(() => {
|
||||||
|
|
||||||
|
// Trigger an event.
|
||||||
|
this.eventsProvider.trigger(AddonCalendarProvider.UNDELETED_EVENT_EVENT, {
|
||||||
|
eventId: this.eventId
|
||||||
|
}, this.sitesProvider.getCurrentSiteId());
|
||||||
|
|
||||||
|
this.domUtils.showToast('addon.calendar.eventcalendareventdeleted', true, 3000, undefined, false);
|
||||||
|
this.event.deleted = false;
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
this.domUtils.showErrorModalDefault(error, 'Error undeleting event.');
|
||||||
|
}).finally(() => {
|
||||||
|
modal.dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the result of an automatic sync or a manual sync not done by this page.
|
* Check the result of an automatic sync or a manual sync not done by this page.
|
||||||
*
|
*
|
||||||
|
@ -398,7 +510,18 @@ export class AddonCalendarEventPage implements OnDestroy {
|
||||||
* @param {any} data Sync result.
|
* @param {any} data Sync result.
|
||||||
*/
|
*/
|
||||||
protected checkSyncResult(isManual: boolean, data: any): void {
|
protected checkSyncResult(isManual: boolean, data: any): void {
|
||||||
if (data && data.events && (!isManual || data.source != 'event')) {
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.deleted && data.deleted.indexOf(this.eventId) != -1) {
|
||||||
|
this.domUtils.showToast('addon.calendar.eventcalendareventdeleted', true, 3000, undefined, false);
|
||||||
|
|
||||||
|
// Event was deleted, close the view.
|
||||||
|
if (!this.svComponent || !this.svComponent.isOn()) {
|
||||||
|
this.navCtrl.pop();
|
||||||
|
}
|
||||||
|
} else if (data.events && (!isManual || data.source != 'event')) {
|
||||||
const event = data.events.find((ev) => {
|
const event = data.events.find((ev) => {
|
||||||
return ev.id == this.eventId;
|
return ev.id == this.eventId;
|
||||||
});
|
});
|
||||||
|
|
|
@ -40,9 +40,13 @@
|
||||||
<span *ngIf="event.timeduration && event.endsSameDay"> - {{ (event.timestart + event.timeduration) * 1000 | coreFormatDate: "strftimetime" }}</span>
|
<span *ngIf="event.timeduration && event.endsSameDay"> - {{ (event.timestart + event.timeduration) * 1000 | coreFormatDate: "strftimetime" }}</span>
|
||||||
<span *ngIf="event.timeduration && !event.endsSameDay"> - {{ (event.timestart + event.timeduration) * 1000 | coreFormatDate: "strftimedatetimeshort" }}</span>
|
<span *ngIf="event.timeduration && !event.endsSameDay"> - {{ (event.timestart + event.timeduration) * 1000 | coreFormatDate: "strftimedatetimeshort" }}</span>
|
||||||
</p>
|
</p>
|
||||||
<ion-note *ngIf="event.offline" item-end>
|
<ion-note *ngIf="event.offline && !event.deleted" item-end>
|
||||||
<ion-icon name="time"></ion-icon>
|
<ion-icon name="time"></ion-icon>
|
||||||
{{ 'core.notsent' | translate }}
|
<span text-wrap>{{ 'core.notsent' | translate }}</span>
|
||||||
|
</ion-note>
|
||||||
|
<ion-note *ngIf="event.deleted" item-end>
|
||||||
|
<ion-icon name="trash"></ion-icon>
|
||||||
|
<span text-wrap>{{ 'core.deletedoffline' | translate }}</span>
|
||||||
</ion-note>
|
</ion-note>
|
||||||
</a>
|
</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
ion-app.app-root page-addon-calendar-list {
|
||||||
|
ion-note {
|
||||||
|
max-width: 30%;
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,16 +63,19 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
protected newEventObserver: any;
|
protected newEventObserver: any;
|
||||||
protected discardedObserver: any;
|
protected discardedObserver: any;
|
||||||
protected editEventObserver: any;
|
protected editEventObserver: any;
|
||||||
|
protected deleteEventObserver: any;
|
||||||
|
protected undeleteEventObserver: any;
|
||||||
protected syncObserver: any;
|
protected syncObserver: any;
|
||||||
protected manualSyncObserver: any;
|
protected manualSyncObserver: any;
|
||||||
protected onlineObserver: any;
|
protected onlineObserver: any;
|
||||||
protected currentSiteId: string;
|
protected currentSiteId: string;
|
||||||
|
protected onlineEvents = [];
|
||||||
|
protected offlineEvents = [];
|
||||||
|
protected deletedEvents = [];
|
||||||
|
|
||||||
courses: any[];
|
courses: any[];
|
||||||
eventsLoaded = false;
|
eventsLoaded = false;
|
||||||
events = []; // Events (both online and offline).
|
events = []; // Events (both online and offline).
|
||||||
onlineEvents = [];
|
|
||||||
offlineEvents = [];
|
|
||||||
notificationsEnabled = false;
|
notificationsEnabled = false;
|
||||||
filteredEvents = [];
|
filteredEvents = [];
|
||||||
canLoadMore = false;
|
canLoadMore = false;
|
||||||
|
@ -149,6 +152,11 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
this.syncObserver = eventsProvider.on(AddonCalendarSyncProvider.AUTO_SYNCED, (data) => {
|
this.syncObserver = eventsProvider.on(AddonCalendarSyncProvider.AUTO_SYNCED, (data) => {
|
||||||
this.eventsLoaded = false;
|
this.eventsLoaded = false;
|
||||||
this.refreshEvents();
|
this.refreshEvents();
|
||||||
|
|
||||||
|
if (this.splitviewCtrl.isOn() && this.eventId && data && data.deleted && data.deleted.indexOf(this.eventId) != -1) {
|
||||||
|
// Current selected event was deleted. Clear details.
|
||||||
|
this.splitviewCtrl.emptyDetails();
|
||||||
|
}
|
||||||
}, this.currentSiteId);
|
}, this.currentSiteId);
|
||||||
|
|
||||||
// Refresh data if calendar events are synchronized manually but not by this page.
|
// Refresh data if calendar events are synchronized manually but not by this page.
|
||||||
|
@ -157,13 +165,51 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
this.eventsLoaded = false;
|
this.eventsLoaded = false;
|
||||||
this.refreshEvents();
|
this.refreshEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.splitviewCtrl.isOn() && this.eventId && data && data.deleted && data.deleted.indexOf(this.eventId) != -1) {
|
||||||
|
// Current selected event was deleted. Clear details.
|
||||||
|
this.splitviewCtrl.emptyDetails();
|
||||||
|
}
|
||||||
|
}, this.currentSiteId);
|
||||||
|
|
||||||
|
// Update the list when an event is deleted.
|
||||||
|
this.deleteEventObserver = eventsProvider.on(AddonCalendarProvider.DELETED_EVENT_EVENT, (data) => {
|
||||||
|
if (data && !data.sent) {
|
||||||
|
// Event was deleted in offline. Just mark it as deleted, no need to refresh.
|
||||||
|
this.markAsDeleted(data.eventId, true);
|
||||||
|
this.hasOffline = true;
|
||||||
|
} else {
|
||||||
|
// Event deleted, clear the details if needed and refresh the view.
|
||||||
|
if (this.splitviewCtrl.isOn()) {
|
||||||
|
this.splitviewCtrl.emptyDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.eventsLoaded = false;
|
||||||
|
this.refreshEvents();
|
||||||
|
}
|
||||||
|
}, this.currentSiteId);
|
||||||
|
|
||||||
|
// Listen for events "undeleted" (offline).
|
||||||
|
this.undeleteEventObserver = eventsProvider.on(AddonCalendarProvider.UNDELETED_EVENT_EVENT, (data) => {
|
||||||
|
if (data && data.eventId) {
|
||||||
|
// Mark it as undeleted, no need to refresh.
|
||||||
|
this.markAsDeleted(data.eventId, false);
|
||||||
|
|
||||||
|
// Remove it from the list of deleted events if it's there.
|
||||||
|
const index = this.deletedEvents.indexOf(data.eventId);
|
||||||
|
if (index != -1) {
|
||||||
|
this.deletedEvents.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hasOffline = !!this.offlineEvents.length || !!this.deletedEvents.length;
|
||||||
|
}
|
||||||
}, this.currentSiteId);
|
}, this.currentSiteId);
|
||||||
|
|
||||||
// Refresh online status when changes.
|
// Refresh online status when changes.
|
||||||
this.onlineObserver = network.onchange().subscribe((online) => {
|
this.onlineObserver = network.onchange().subscribe(() => {
|
||||||
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||||
zone.run(() => {
|
zone.run(() => {
|
||||||
this.isOnline = online;
|
this.isOnline = this.appProvider.isOnline();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -234,6 +280,8 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
const courseId = this.filter.course.id != this.allCourses.id ? this.filter.course.id : undefined;
|
const courseId = this.filter.course.id != this.allCourses.id ? this.filter.course.id : undefined;
|
||||||
|
|
||||||
|
this.hasOffline = false;
|
||||||
|
|
||||||
promises.push(this.calendarHelper.canEditEvents(courseId).then((canEdit) => {
|
promises.push(this.calendarHelper.canEditEvents(courseId).then((canEdit) => {
|
||||||
this.canCreate = canEdit;
|
this.canCreate = canEdit;
|
||||||
}));
|
}));
|
||||||
|
@ -254,8 +302,8 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Get offline events.
|
// Get offline events.
|
||||||
promises.push(this.calendarOffline.getAllEvents().then((events) => {
|
promises.push(this.calendarOffline.getAllEditedEvents().then((events) => {
|
||||||
this.hasOffline = !!events.length;
|
this.hasOffline = this.hasOffline || !!events.length;
|
||||||
|
|
||||||
// Format data and sort by timestart.
|
// Format data and sort by timestart.
|
||||||
events.forEach((event) => {
|
events.forEach((event) => {
|
||||||
|
@ -265,6 +313,12 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
this.offlineEvents = this.sortEvents(events);
|
this.offlineEvents = this.sortEvents(events);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Get events deleted in offline.
|
||||||
|
promises.push(this.calendarOffline.getAllDeletedEventsIds().then((ids) => {
|
||||||
|
this.hasOffline = this.hasOffline || !!ids.length;
|
||||||
|
this.deletedEvents = ids;
|
||||||
|
}));
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.eventsLoaded = true;
|
this.eventsLoaded = true;
|
||||||
|
@ -457,22 +511,32 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
* @return {any[]} Merged events.
|
* @return {any[]} Merged events.
|
||||||
*/
|
*/
|
||||||
protected mergeEvents(onlineEvents: any[]): any[] {
|
protected mergeEvents(onlineEvents: any[]): any[] {
|
||||||
if (!this.offlineEvents || !this.offlineEvents.length) {
|
if (!this.offlineEvents.length && !this.deletedEvents.length) {
|
||||||
// No offline events, nothing to merge.
|
// No offline events, nothing to merge.
|
||||||
return onlineEvents;
|
return onlineEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
const start = this.initialTime + (CoreConstants.SECONDS_DAY * this.daysLoaded),
|
const start = this.initialTime + (CoreConstants.SECONDS_DAY * this.daysLoaded),
|
||||||
end = start + (CoreConstants.SECONDS_DAY * AddonCalendarProvider.DAYS_INTERVAL) - 1;
|
end = start + (CoreConstants.SECONDS_DAY * AddonCalendarProvider.DAYS_INTERVAL) - 1;
|
||||||
|
let result = onlineEvents;
|
||||||
|
|
||||||
// First of all, remove the online events that were modified in offline.
|
if (this.deletedEvents.length) {
|
||||||
let result = onlineEvents.filter((event) => {
|
// Mark as deleted the events that were deleted in offline.
|
||||||
|
result.forEach((event) => {
|
||||||
|
event.deleted = this.deletedEvents.indexOf(event.id) != -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.offlineEvents.length) {
|
||||||
|
// Remove the online events that were modified in offline.
|
||||||
|
result = result.filter((event) => {
|
||||||
const offlineEvent = this.offlineEvents.find((ev) => {
|
const offlineEvent = this.offlineEvents.find((ev) => {
|
||||||
return ev.id == event.id;
|
return ev.id == event.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
return !offlineEvent;
|
return !offlineEvent;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Now get the offline events that belong to this period.
|
// Now get the offline events that belong to this period.
|
||||||
const periodOfflineEvents = this.offlineEvents.filter((event) => {
|
const periodOfflineEvents = this.offlineEvents.filter((event) => {
|
||||||
|
@ -658,6 +722,22 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an event and mark it as deleted.
|
||||||
|
*
|
||||||
|
* @param {number} eventId Event ID.
|
||||||
|
* @param {boolean} deleted Whether to mark it as deleted or not.
|
||||||
|
*/
|
||||||
|
protected markAsDeleted(eventId: number, deleted: boolean): void {
|
||||||
|
const event = this.onlineEvents.find((event) => {
|
||||||
|
return event.id == eventId;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (event) {
|
||||||
|
event.deleted = deleted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page destroyed.
|
* Page destroyed.
|
||||||
*/
|
*/
|
||||||
|
@ -666,6 +746,8 @@ export class AddonCalendarListPage implements OnDestroy {
|
||||||
this.newEventObserver && this.newEventObserver.off();
|
this.newEventObserver && this.newEventObserver.off();
|
||||||
this.discardedObserver && this.discardedObserver.off();
|
this.discardedObserver && this.discardedObserver.off();
|
||||||
this.editEventObserver && this.editEventObserver.off();
|
this.editEventObserver && this.editEventObserver.off();
|
||||||
|
this.deleteEventObserver && this.deleteEventObserver.off();
|
||||||
|
this.undeleteEventObserver && this.undeleteEventObserver.off();
|
||||||
this.syncObserver && this.syncObserver.off();
|
this.syncObserver && this.syncObserver.off();
|
||||||
this.manualSyncObserver && this.manualSyncObserver.off();
|
this.manualSyncObserver && this.manualSyncObserver.off();
|
||||||
this.onlineObserver && this.onlineObserver.unsubscribe();
|
this.onlineObserver && this.onlineObserver.unsubscribe();
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { CoreSitesProvider, CoreSiteSchema } from '@providers/sites';
|
import { CoreSitesProvider, CoreSiteSchema } from '@providers/sites';
|
||||||
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to handle offline calendar events.
|
* Service to handle offline calendar events.
|
||||||
|
@ -23,6 +24,7 @@ export class AddonCalendarOfflineProvider {
|
||||||
|
|
||||||
// Variables for database.
|
// Variables for database.
|
||||||
static EVENTS_TABLE = 'addon_calendar_offline_events';
|
static EVENTS_TABLE = 'addon_calendar_offline_events';
|
||||||
|
static DELETED_EVENTS_TABLE = 'addon_calendar_deleted_events';
|
||||||
|
|
||||||
protected siteSchema: CoreSiteSchema = {
|
protected siteSchema: CoreSiteSchema = {
|
||||||
name: 'AddonCalendarOfflineProvider',
|
name: 'AddonCalendarOfflineProvider',
|
||||||
|
@ -34,6 +36,7 @@ export class AddonCalendarOfflineProvider {
|
||||||
{
|
{
|
||||||
name: 'id', // Negative for offline entries.
|
name: 'id', // Negative for offline entries.
|
||||||
type: 'INTEGER',
|
type: 'INTEGER',
|
||||||
|
primaryKey: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
|
@ -110,13 +113,35 @@ export class AddonCalendarOfflineProvider {
|
||||||
name: 'timecreated',
|
name: 'timecreated',
|
||||||
type: 'INTEGER',
|
type: 'INTEGER',
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
primaryKeys: ['id']
|
},
|
||||||
|
{
|
||||||
|
name: AddonCalendarOfflineProvider.DELETED_EVENTS_TABLE,
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
type: 'INTEGER',
|
||||||
|
primaryKey: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'name', // Save the name to be able to notify the user.
|
||||||
|
type: 'TEXT',
|
||||||
|
notNull: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'repeat',
|
||||||
|
type: 'INTEGER'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'timemodified',
|
||||||
|
type: 'INTEGER',
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(private sitesProvider: CoreSitesProvider) {
|
constructor(private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider) {
|
||||||
this.sitesProvider.registerSiteSchema(this.siteSchema);
|
this.sitesProvider.registerSiteSchema(this.siteSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,17 +163,91 @@ export class AddonCalendarOfflineProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all offline events.
|
* Get the IDs of all the events created/edited/deleted in offline.
|
||||||
|
*
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<number[]>} Promise resolved with the IDs.
|
||||||
|
*/
|
||||||
|
getAllEventsIds(siteId?: string): Promise<number[]> {
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
promises.push(this.getAllDeletedEventsIds(siteId));
|
||||||
|
promises.push(this.getAllEditedEventsIds(siteId));
|
||||||
|
|
||||||
|
return Promise.all(promises).then((result) => {
|
||||||
|
return this.utils.mergeArraysWithoutDuplicates(result[0], result[1]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the events deleted in offline.
|
||||||
|
*
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any[]>} Promise resolved with all the events deleted in offline.
|
||||||
|
*/
|
||||||
|
getAllDeletedEvents(siteId?: string): Promise<any[]> {
|
||||||
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
return site.getDb().getRecords(AddonCalendarOfflineProvider.DELETED_EVENTS_TABLE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the IDs of all the events deleted in offline.
|
||||||
|
*
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<number[]>} Promise resolved with the IDs of all the events deleted in offline.
|
||||||
|
*/
|
||||||
|
getAllDeletedEventsIds(siteId?: string): Promise<number[]> {
|
||||||
|
return this.getAllDeletedEvents(siteId).then((events) => {
|
||||||
|
return events.map((event) => {
|
||||||
|
return event.id;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the events created/edited in offline.
|
||||||
*
|
*
|
||||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
* @return {Promise<any[]>} Promise resolved with events.
|
* @return {Promise<any[]>} Promise resolved with events.
|
||||||
*/
|
*/
|
||||||
getAllEvents(siteId?: string): Promise<any[]> {
|
getAllEditedEvents(siteId?: string): Promise<any[]> {
|
||||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
return site.getDb().getRecords(AddonCalendarOfflineProvider.EVENTS_TABLE);
|
return site.getDb().getRecords(AddonCalendarOfflineProvider.EVENTS_TABLE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the IDs of all the events created/edited in offline.
|
||||||
|
*
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<number[]>} Promise resolved with events IDs.
|
||||||
|
*/
|
||||||
|
getAllEditedEventsIds(siteId?: string): Promise<number[]> {
|
||||||
|
return this.getAllEditedEvents(siteId).then((events) => {
|
||||||
|
return events.map((event) => {
|
||||||
|
return event.id;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an event deleted in offline.
|
||||||
|
*
|
||||||
|
* @param {number} eventId Event ID.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any>} Promise resolved with the deleted event.
|
||||||
|
*/
|
||||||
|
getDeletedEvent(eventId: number, siteId?: string): Promise<any> {
|
||||||
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
const conditions: any = {
|
||||||
|
id: eventId
|
||||||
|
};
|
||||||
|
|
||||||
|
return site.getDb().getRecord(AddonCalendarOfflineProvider.DELETED_EVENTS_TABLE, conditions);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an offline event.
|
* Get an offline event.
|
||||||
*
|
*
|
||||||
|
@ -172,8 +271,8 @@ export class AddonCalendarOfflineProvider {
|
||||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
* @return {Promise<boolean>} Promise resolved with boolean: true if has offline events, false otherwise.
|
* @return {Promise<boolean>} Promise resolved with boolean: true if has offline events, false otherwise.
|
||||||
*/
|
*/
|
||||||
hasEvents(siteId?: string): Promise<boolean> {
|
hasEditedEvents(siteId?: string): Promise<boolean> {
|
||||||
return this.getAllEvents(siteId).then((events) => {
|
return this.getAllEditedEvents(siteId).then((events) => {
|
||||||
return !!events.length;
|
return !!events.length;
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
// No offline data found, return false.
|
// No offline data found, return false.
|
||||||
|
@ -181,6 +280,43 @@ export class AddonCalendarOfflineProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an event is deleted.
|
||||||
|
*
|
||||||
|
* @param {number} eventId Event ID.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<boolean>} Promise resolved with boolean: whether the event is deleted.
|
||||||
|
*/
|
||||||
|
isEventDeleted(eventId: number, siteId?: string): Promise<boolean> {
|
||||||
|
return this.getDeletedEvent(eventId, siteId).then((event) => {
|
||||||
|
return !!event;
|
||||||
|
}).catch(() => {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark an event as deleted.
|
||||||
|
*
|
||||||
|
* @param {number} eventId Event ID to delete.
|
||||||
|
* @param {number} name Name of the event to delete.
|
||||||
|
* @param {boolean} [deleteAll] If it's a repeated event. whether to delete all events of the series.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
|
*/
|
||||||
|
markDeleted(eventId: number, name: string, deleteAll?: boolean, siteId?: string): Promise<any> {
|
||||||
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
const event = {
|
||||||
|
id: eventId,
|
||||||
|
name: name || '',
|
||||||
|
repeat: deleteAll ? 1 : 0,
|
||||||
|
timemodified: Date.now()
|
||||||
|
};
|
||||||
|
|
||||||
|
return site.getDb().insertRecord(AddonCalendarOfflineProvider.DELETED_EVENTS_TABLE, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offline version for adding a new discussion to a forum.
|
* Offline version for adding a new discussion to a forum.
|
||||||
*
|
*
|
||||||
|
@ -221,4 +357,21 @@ export class AddonCalendarOfflineProvider {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmark an event as deleted.
|
||||||
|
*
|
||||||
|
* @param {number} eventId Event ID.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any>} Promise resolved if deleted, rejected if failure.
|
||||||
|
*/
|
||||||
|
unmarkDeleted(eventId: number, siteId?: string): Promise<any> {
|
||||||
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
const conditions: any = {
|
||||||
|
id: eventId
|
||||||
|
};
|
||||||
|
|
||||||
|
return site.getDb().deleteRecords(AddonCalendarOfflineProvider.DELETED_EVENTS_TABLE, conditions);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,8 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
// Sync successful, send event.
|
// Sync successful, send event.
|
||||||
this.eventsProvider.trigger(AddonCalendarSyncProvider.AUTO_SYNCED, {
|
this.eventsProvider.trigger(AddonCalendarSyncProvider.AUTO_SYNCED, {
|
||||||
warnings: result.warnings,
|
warnings: result.warnings,
|
||||||
events: result.events
|
events: result.events,
|
||||||
|
deleted: result.deleted
|
||||||
}, siteId);
|
}, siteId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -122,18 +123,19 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
const result = {
|
const result = {
|
||||||
warnings: [],
|
warnings: [],
|
||||||
events: [],
|
events: [],
|
||||||
|
deleted: [],
|
||||||
updated: false
|
updated: false
|
||||||
};
|
};
|
||||||
let offlineEvents;
|
let offlineEventIds: number[];
|
||||||
|
|
||||||
// Get offline events.
|
// Get offline events.
|
||||||
const syncPromise = this.calendarOffline.getAllEvents(siteId).catch(() => {
|
const syncPromise = this.calendarOffline.getAllEventsIds(siteId).catch(() => {
|
||||||
// No offline data found, return empty list.
|
// No offline data found, return empty list.
|
||||||
return [];
|
return [];
|
||||||
}).then((events) => {
|
}).then((eventIds) => {
|
||||||
offlineEvents = events;
|
offlineEventIds = eventIds;
|
||||||
|
|
||||||
if (!events.length) {
|
if (!eventIds.length) {
|
||||||
// Nothing to sync.
|
// Nothing to sync.
|
||||||
return;
|
return;
|
||||||
} else if (!this.appProvider.isOnline()) {
|
} else if (!this.appProvider.isOnline()) {
|
||||||
|
@ -143,8 +145,8 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
events.forEach((event) => {
|
offlineEventIds.forEach((eventId) => {
|
||||||
promises.push(this.syncOfflineEvent(event, result, siteId));
|
promises.push(this.syncOfflineEvent(eventId, result, siteId));
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.utils.allPromises(promises);
|
return this.utils.allPromises(promises);
|
||||||
|
@ -155,10 +157,10 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
this.calendarProvider.invalidateEventsList(siteId),
|
this.calendarProvider.invalidateEventsList(siteId),
|
||||||
];
|
];
|
||||||
|
|
||||||
offlineEvents.forEach((event) => {
|
offlineEventIds.forEach((eventId) => {
|
||||||
if (event.id > 0) {
|
if (eventId > 0) {
|
||||||
// An event was edited, invalidate its data too.
|
// An event was edited, invalidate its data too.
|
||||||
promises.push(this.calendarProvider.invalidateEvent(event.id, siteId));
|
promises.push(this.calendarProvider.invalidateEvent(eventId, siteId));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -182,25 +184,71 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
/**
|
/**
|
||||||
* Synchronize an offline event.
|
* Synchronize an offline event.
|
||||||
*
|
*
|
||||||
* @param {any} event The event to sync.
|
* @param {number} eventId The event ID to sync.
|
||||||
* @param {any} result Object where to store the result of the sync.
|
* @param {any} result Object where to store the result of the sync.
|
||||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
* @return {Promise<any>} Promise resolved if sync is successful, rejected otherwise.
|
* @return {Promise<any>} Promise resolved if sync is successful, rejected otherwise.
|
||||||
*/
|
*/
|
||||||
protected syncOfflineEvent(event: any, result: any, siteId?: string): Promise<any> {
|
protected syncOfflineEvent(eventId: number, result: any, siteId?: string): Promise<any> {
|
||||||
|
|
||||||
// Verify that event isn't blocked.
|
// Verify that event isn't blocked.
|
||||||
if (this.syncProvider.isBlocked(AddonCalendarProvider.COMPONENT, event.id, siteId)) {
|
if (this.syncProvider.isBlocked(AddonCalendarProvider.COMPONENT, eventId, siteId)) {
|
||||||
this.logger.debug('Cannot sync event ' + event.name + ' because it is blocked.');
|
this.logger.debug('Cannot sync event ' + eventId + ' because it is blocked.');
|
||||||
|
|
||||||
return Promise.reject(this.translate.instant('core.errorsyncblocked',
|
return Promise.reject(this.translate.instant('core.errorsyncblocked',
|
||||||
{$a: this.translate.instant('addon.calendar.calendarevent')}));
|
{$a: this.translate.instant('addon.calendar.calendarevent')}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// First of all, check if the event has been deleted.
|
||||||
|
return this.calendarOffline.getDeletedEvent(eventId, siteId).then((data) => {
|
||||||
|
// Delete the event.
|
||||||
|
return this.calendarProvider.deleteEventOnline(data.id, data.repeat, siteId).then(() => {
|
||||||
|
result.updated = true;
|
||||||
|
result.deleted.push(eventId);
|
||||||
|
|
||||||
|
// Event sent, delete the offline data.
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
promises.push(this.calendarOffline.unmarkDeleted(eventId, siteId));
|
||||||
|
promises.push(this.calendarOffline.deleteEvent(eventId, siteId).catch(() => {
|
||||||
|
// Ignore errors, maybe there was no edit data.
|
||||||
|
}));
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
|
}).catch((error) => {
|
||||||
|
|
||||||
|
if (this.utils.isWebServiceError(error)) {
|
||||||
|
// The WebService has thrown an error, this means that the event cannot be created. Delete it.
|
||||||
|
result.updated = true;
|
||||||
|
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
promises.push(this.calendarOffline.unmarkDeleted(eventId, siteId));
|
||||||
|
promises.push(this.calendarOffline.deleteEvent(eventId, siteId).catch(() => {
|
||||||
|
// Ignore errors, maybe there was no edit data.
|
||||||
|
}));
|
||||||
|
|
||||||
|
return Promise.all(promises).then(() => {
|
||||||
|
// Event deleted, add a warning.
|
||||||
|
result.warnings.push(this.translate.instant('core.warningofflinedatadeleted', {
|
||||||
|
component: this.translate.instant('addon.calendar.calendarevent'),
|
||||||
|
name: data.name,
|
||||||
|
error: this.textUtils.getErrorMessageFromError(error)
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local error, reject.
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
}, () => {
|
||||||
|
|
||||||
|
// Not deleted. Now get the event data.
|
||||||
|
return this.calendarOffline.getEvent(eventId, siteId).then((event) => {
|
||||||
// Try to send the data.
|
// Try to send the data.
|
||||||
const data = this.utils.clone(event); // Clone the object because it will be modified in the submit function.
|
const data = this.utils.clone(event); // Clone the object because it will be modified in the submit function.
|
||||||
|
|
||||||
return this.calendarProvider.submitEventOnline(event.id > 0 ? event.id : undefined, data, siteId).then((newEvent) => {
|
return this.calendarProvider.submitEventOnline(eventId > 0 ? eventId : undefined, data, siteId).then((newEvent) => {
|
||||||
result.updated = true;
|
result.updated = true;
|
||||||
result.events.push(newEvent);
|
result.events.push(newEvent);
|
||||||
|
|
||||||
|
@ -224,5 +272,7 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
|
||||||
// Local error, reject.
|
// Local error, reject.
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ export class AddonCalendarProvider {
|
||||||
static NEW_EVENT_EVENT = 'addon_calendar_new_event';
|
static NEW_EVENT_EVENT = 'addon_calendar_new_event';
|
||||||
static NEW_EVENT_DISCARDED_EVENT = 'addon_calendar_new_event_discarded';
|
static NEW_EVENT_DISCARDED_EVENT = 'addon_calendar_new_event_discarded';
|
||||||
static EDIT_EVENT_EVENT = 'addon_calendar_edit_event';
|
static EDIT_EVENT_EVENT = 'addon_calendar_edit_event';
|
||||||
|
static DELETED_EVENT_EVENT = 'addon_calendar_deleted_event';
|
||||||
|
static UNDELETED_EVENT_EVENT = 'addon_calendar_undeleted_event';
|
||||||
static TYPE_CATEGORY = 'category';
|
static TYPE_CATEGORY = 'category';
|
||||||
static TYPE_COURSE = 'course';
|
static TYPE_COURSE = 'course';
|
||||||
static TYPE_GROUP = 'group';
|
static TYPE_GROUP = 'group';
|
||||||
|
@ -225,11 +227,38 @@ export class AddonCalendarProvider {
|
||||||
this.sitesProvider.registerSiteSchema(this.siteSchema);
|
this.sitesProvider.registerSiteSchema(this.siteSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a certain site allows deleting events.
|
||||||
|
*
|
||||||
|
* @param {string} [siteId] Site Id. If not defined, use current site.
|
||||||
|
* @return {Promise<boolean>} Promise resolved with true if can delete.
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
canDeleteEvents(siteId?: string): Promise<boolean> {
|
||||||
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
return this.canDeleteEventsInSite(site);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a certain site allows deleting events.
|
||||||
|
*
|
||||||
|
* @param {CoreSite} [site] Site. If not defined, use current site.
|
||||||
|
* @return {boolean} Whether events can be deleted.
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
canDeleteEventsInSite(site?: CoreSite): boolean {
|
||||||
|
site = site || this.sitesProvider.getCurrentSite();
|
||||||
|
|
||||||
|
return site.wsAvailable('core_calendar_delete_calendar_events');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a certain site allows creating and editing events.
|
* Check if a certain site allows creating and editing events.
|
||||||
*
|
*
|
||||||
* @param {string} [siteId] Site Id. If not defined, use current site.
|
* @param {string} [siteId] Site Id. If not defined, use current site.
|
||||||
* @return {Promise<boolean>} Promise resolved with true if can create/edit.
|
* @return {Promise<boolean>} Promise resolved with true if can create/edit.
|
||||||
|
* @since 3.7.1
|
||||||
*/
|
*/
|
||||||
canEditEvents(siteId?: string): Promise<boolean> {
|
canEditEvents(siteId?: string): Promise<boolean> {
|
||||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
@ -242,6 +271,7 @@ export class AddonCalendarProvider {
|
||||||
*
|
*
|
||||||
* @param {CoreSite} [site] Site. If not defined, use current site.
|
* @param {CoreSite} [site] Site. If not defined, use current site.
|
||||||
* @return {boolean} Whether events can be created and edited.
|
* @return {boolean} Whether events can be created and edited.
|
||||||
|
* @since 3.7.1
|
||||||
*/
|
*/
|
||||||
canEditEventsInSite(site?: CoreSite): boolean {
|
canEditEventsInSite(site?: CoreSite): boolean {
|
||||||
site = site || this.sitesProvider.getCurrentSite();
|
site = site || this.sitesProvider.getCurrentSite();
|
||||||
|
@ -261,20 +291,89 @@ export class AddonCalendarProvider {
|
||||||
return site.getDb().getRecordsSelect(AddonCalendarProvider.EVENTS_TABLE, 'timestart + timeduration < ?',
|
return site.getDb().getRecordsSelect(AddonCalendarProvider.EVENTS_TABLE, 'timestart + timeduration < ?',
|
||||||
[this.timeUtils.timestamp()]).then((events) => {
|
[this.timeUtils.timestamp()]).then((events) => {
|
||||||
return Promise.all(events.map((event) => {
|
return Promise.all(events.map((event) => {
|
||||||
return this.deleteEvent(event.id, siteId);
|
return this.deleteLocalEvent(event.id, siteId);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete event cancelling all the reminders and notifications.
|
* Delete an event.
|
||||||
|
*
|
||||||
|
* @param {number} eventId Event ID to delete.
|
||||||
|
* @param {string} name Name of the event to delete.
|
||||||
|
* @param {boolean} [deleteAll] If it's a repeated event. whether to delete all events of the series.
|
||||||
|
* @param {boolean} [forceOffline] True to always save it in offline.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
|
*/
|
||||||
|
deleteEvent(eventId: number, name: string, deleteAll?: boolean, forceOffline?: boolean, siteId?: string): Promise<boolean> {
|
||||||
|
|
||||||
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
|
// Function to store the submission to be synchronized later.
|
||||||
|
const storeOffline = (): Promise<boolean> => {
|
||||||
|
return this.calendarOffline.markDeleted(eventId, name, deleteAll, siteId).then(() => {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (forceOffline || !this.appProvider.isOnline()) {
|
||||||
|
// App is offline, store the action.
|
||||||
|
return storeOffline();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the event is already stored, discard it first.
|
||||||
|
return this.calendarOffline.unmarkDeleted(eventId, siteId).then(() => {
|
||||||
|
return this.deleteEventOnline(eventId, deleteAll, siteId).then(() => {
|
||||||
|
return true;
|
||||||
|
}).catch((error) => {
|
||||||
|
if (error && !this.utils.isWebServiceError(error)) {
|
||||||
|
// Couldn't connect to server, store in offline.
|
||||||
|
return storeOffline();
|
||||||
|
} else {
|
||||||
|
// The WebService has thrown an error, reject.
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete an event. It will fail if offline or cannot connect.
|
||||||
|
*
|
||||||
|
* @param {number} eventId Event ID to delete.
|
||||||
|
* @param {boolean} [deleteAll] If it's a repeated event. whether to delete all events of the series.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
|
*/
|
||||||
|
deleteEventOnline(eventId: number, deleteAll?: boolean, siteId?: string): Promise<any> {
|
||||||
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
eventid: eventId,
|
||||||
|
repeat: deleteAll ? 1 : 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
preSets = {
|
||||||
|
responseExpected: false
|
||||||
|
};
|
||||||
|
|
||||||
|
return site.write('core_calendar_delete_calendar_events', params, preSets);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a locally stored event cancelling all the reminders and notifications.
|
||||||
*
|
*
|
||||||
* @param {number} eventId Event ID.
|
* @param {number} eventId 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<any>} Resolved when done.
|
* @return {Promise<any>} Resolved when done.
|
||||||
*/
|
*/
|
||||||
protected deleteEvent(eventId: number, siteId?: string): Promise<any> {
|
protected deleteLocalEvent(eventId: number, siteId?: string): Promise<any> {
|
||||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
siteId = site.getId();
|
siteId = site.getId();
|
||||||
|
|
||||||
|
@ -833,7 +932,7 @@ export class AddonCalendarProvider {
|
||||||
|
|
||||||
if (timeEnd <= new Date().getTime()) {
|
if (timeEnd <= new Date().getTime()) {
|
||||||
// The event has finished already, don't schedule it.
|
// The event has finished already, don't schedule it.
|
||||||
return this.deleteEvent(event.id, siteId);
|
return this.deleteLocalEvent(event.id, siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getEventReminders(event.id, siteId).then((reminders) => {
|
return this.getEventReminders(event.id, siteId).then((reminders) => {
|
||||||
|
|
|
@ -65,7 +65,7 @@ export class AddonModChatChatPage {
|
||||||
this.logger = logger.getInstance('AddonModChoiceChoicePage');
|
this.logger = logger.getInstance('AddonModChoiceChoicePage');
|
||||||
this.currentUserBeep = 'beep ' + sitesProvider.getCurrentSiteUserId();
|
this.currentUserBeep = 'beep ' + sitesProvider.getCurrentSiteUserId();
|
||||||
this.isOnline = this.appProvider.isOnline();
|
this.isOnline = this.appProvider.isOnline();
|
||||||
this.onlineObserver = network.onchange().subscribe((online) => {
|
this.onlineObserver = network.onchange().subscribe(() => {
|
||||||
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||||
zone.run(() => {
|
zone.run(() => {
|
||||||
this.isOnline = this.appProvider.isOnline();
|
this.isOnline = this.appProvider.isOnline();
|
||||||
|
|
|
@ -44,7 +44,7 @@ export class AddonModChatUsersPage {
|
||||||
this.sessionId = navParams.get('sessionId');
|
this.sessionId = navParams.get('sessionId');
|
||||||
this.isOnline = this.appProvider.isOnline();
|
this.isOnline = this.appProvider.isOnline();
|
||||||
this.currentUserId = this.sitesProvider.getCurrentSiteUserId();
|
this.currentUserId = this.sitesProvider.getCurrentSiteUserId();
|
||||||
this.onlineObserver = network.onchange().subscribe((online) => {
|
this.onlineObserver = network.onchange().subscribe(() => {
|
||||||
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||||
zone.run(() => {
|
zone.run(() => {
|
||||||
this.isOnline = this.appProvider.isOnline();
|
this.isOnline = this.appProvider.isOnline();
|
||||||
|
|
|
@ -82,10 +82,10 @@ export class AddonModFeedbackFormPage implements OnDestroy {
|
||||||
this.currentSite = sitesProvider.getCurrentSite();
|
this.currentSite = sitesProvider.getCurrentSite();
|
||||||
|
|
||||||
// Refresh online status when changes.
|
// Refresh online status when changes.
|
||||||
this.onlineObserver = network.onchange().subscribe((online) => {
|
this.onlineObserver = network.onchange().subscribe(() => {
|
||||||
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||||
zone.run(() => {
|
zone.run(() => {
|
||||||
this.offline = !online;
|
this.offline = !this.appProvider.isOnline();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
||||||
this.postId = navParams.get('postId');
|
this.postId = navParams.get('postId');
|
||||||
|
|
||||||
this.isOnline = this.appProvider.isOnline();
|
this.isOnline = this.appProvider.isOnline();
|
||||||
this.onlineObserver = network.onchange().subscribe((online) => {
|
this.onlineObserver = network.onchange().subscribe(() => {
|
||||||
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||||
zone.run(() => {
|
zone.run(() => {
|
||||||
this.isOnline = this.appProvider.isOnline();
|
this.isOnline = this.appProvider.isOnline();
|
||||||
|
|
|
@ -87,13 +87,19 @@
|
||||||
"addon.calendar.calendarevent": "Calendar event",
|
"addon.calendar.calendarevent": "Calendar event",
|
||||||
"addon.calendar.calendarevents": "Calendar events",
|
"addon.calendar.calendarevents": "Calendar events",
|
||||||
"addon.calendar.calendarreminders": "Calendar reminders",
|
"addon.calendar.calendarreminders": "Calendar reminders",
|
||||||
|
"addon.calendar.confirmeventdelete": "Are you sure you want to delete the \"{{$a}}\" event?",
|
||||||
|
"addon.calendar.confirmeventseriesdelete": "The \"{{$a.name}}\" event is part of a series. Do you want to delete just this event, or all {{$a.count}} events in the series?",
|
||||||
"addon.calendar.defaultnotificationtime": "Default notification time",
|
"addon.calendar.defaultnotificationtime": "Default notification time",
|
||||||
|
"addon.calendar.deleteallevents": "Delete all events",
|
||||||
|
"addon.calendar.deleteevent": "Delete event",
|
||||||
|
"addon.calendar.deleteoneevent": "Delete this event",
|
||||||
"addon.calendar.durationminutes": "Duration in minutes",
|
"addon.calendar.durationminutes": "Duration in minutes",
|
||||||
"addon.calendar.durationnone": "Without duration",
|
"addon.calendar.durationnone": "Without duration",
|
||||||
"addon.calendar.durationuntil": "Until",
|
"addon.calendar.durationuntil": "Until",
|
||||||
"addon.calendar.editevent": "Editing event",
|
"addon.calendar.editevent": "Editing event",
|
||||||
"addon.calendar.errorloadevent": "Error loading event.",
|
"addon.calendar.errorloadevent": "Error loading event.",
|
||||||
"addon.calendar.errorloadevents": "Error loading events.",
|
"addon.calendar.errorloadevents": "Error loading events.",
|
||||||
|
"addon.calendar.eventcalendareventdeleted": "Calendar event deleted",
|
||||||
"addon.calendar.eventduration": "Duration",
|
"addon.calendar.eventduration": "Duration",
|
||||||
"addon.calendar.eventendtime": "End time",
|
"addon.calendar.eventendtime": "End time",
|
||||||
"addon.calendar.eventkind": "Type of event",
|
"addon.calendar.eventkind": "Type of event",
|
||||||
|
|
|
@ -63,10 +63,10 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
|
||||||
const zone = injector.get(NgZone);
|
const zone = injector.get(NgZone);
|
||||||
|
|
||||||
// Refresh online status when changes.
|
// Refresh online status when changes.
|
||||||
this.onlineObserver = network.onchange().subscribe((online) => {
|
this.onlineObserver = network.onchange().subscribe(() => {
|
||||||
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||||
zone.run(() => {
|
zone.run(() => {
|
||||||
this.isOnline = online;
|
this.isOnline = this.appProvider.isOnline();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1344,9 +1344,12 @@ export class CoreDomUtilsProvider {
|
||||||
* @param {boolean} [needsTranslate] Whether the 'text' needs to be translated.
|
* @param {boolean} [needsTranslate] Whether the 'text' needs to be translated.
|
||||||
* @param {number} [duration=2000] Duration in ms of the dimissable toast.
|
* @param {number} [duration=2000] Duration in ms of the dimissable toast.
|
||||||
* @param {string} [cssClass=""] Class to add to the toast.
|
* @param {string} [cssClass=""] Class to add to the toast.
|
||||||
|
* @param {boolean} [dismissOnPageChange=true] Dismiss the Toast on page change.
|
||||||
* @return {Toast} Toast instance.
|
* @return {Toast} Toast instance.
|
||||||
*/
|
*/
|
||||||
showToast(text: string, needsTranslate?: boolean, duration: number = 2000, cssClass: string = ''): Toast {
|
showToast(text: string, needsTranslate?: boolean, duration: number = 2000, cssClass: string = '',
|
||||||
|
dismissOnPageChange: boolean = true): Toast {
|
||||||
|
|
||||||
if (needsTranslate) {
|
if (needsTranslate) {
|
||||||
text = this.translate.instant(text);
|
text = this.translate.instant(text);
|
||||||
}
|
}
|
||||||
|
@ -1356,7 +1359,7 @@ export class CoreDomUtilsProvider {
|
||||||
duration: duration,
|
duration: duration,
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
cssClass: cssClass,
|
cssClass: cssClass,
|
||||||
dismissOnPageChange: true
|
dismissOnPageChange: dismissOnPageChange
|
||||||
});
|
});
|
||||||
|
|
||||||
loader.present();
|
loader.present();
|
||||||
|
|
Loading…
Reference in New Issue