Merge pull request #2059 from dpalou/MOBILE-3090

MOBILE-3090 calendar: Improve invalidate data after sync
main
Juan Leyva 2019-08-20 08:46:42 +01:00 committed by GitHub
commit 373a4d0cc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 126 additions and 66 deletions

View File

@ -479,7 +479,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
}
if (formData.repeat) {
data.repeats = formData.repeats;
data.repeats = Number(formData.repeats);
}
if (this.event && this.event.repeatid) {
@ -489,15 +489,22 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
// Send the data.
const modal = this.domUtils.showModalLoading('core.sending', true);
let event;
this.calendarProvider.submitEvent(this.eventId, data).then((result) => {
const numberOfRepetitions = formData.repeat ? formData.repeats :
(data.repeateditall && this.event.othereventscount ? this.event.othereventscount + 1 : 1);
this.calendarHelper.invalidateRepeatedEventsOnCalendar(result.event, numberOfRepetitions).catch(() => {
// Ignore errors.
}).then(() => {
this.returnToList(result.event);
});
event = result.event;
if (result.sent) {
// Event created or edited, invalidate right days & months.
const numberOfRepetitions = formData.repeat ? formData.repeats :
(data.repeateditall && this.event.othereventscount ? this.event.othereventscount + 1 : 1);
this.calendarHelper.invalidateRepeatedEventsOnCalendarForEvent(result.event, numberOfRepetitions).catch(() => {
// Ignore errors.
});
}
}).then(() => {
this.returnToList(event);
}).catch((error) => {
this.domUtils.showErrorModalDefault(error, 'Error sending data.');
}).finally(() => {

View File

@ -445,10 +445,19 @@ export class AddonCalendarEventPage implements OnDestroy {
const modal = this.domUtils.showModalLoading('core.sending', true);
this.calendarProvider.deleteEvent(this.event.id, this.event.name, deleteAll).then((sent) => {
this.calendarHelper.invalidateRepeatedEventsOnCalendar(this.event, deleteAll ? this.event.eventcount : 1)
.catch(() => {
// Ignore errors.
}).then(() => {
let promise;
if (sent) {
// Event deleted, invalidate right days & months.
promise = this.calendarHelper.invalidateRepeatedEventsOnCalendarForEvent(this.event,
deleteAll ? this.event.eventcount : 1).catch(() => {
// Ignore errors.
});
} else {
promise = Promise.resolve();
}
return promise.then(() => {
// Trigger an event.
this.eventsProvider.trigger(AddonCalendarProvider.DELETED_EVENT_EVENT, {
eventId: this.eventId,

View File

@ -95,7 +95,7 @@ export class AddonCalendarOfflineProvider {
},
{
name: 'repeats',
type: 'TEXT',
type: 'INTEGER',
},
{
name: 'repeatid',

View File

@ -26,6 +26,7 @@ import { CoreTimeUtilsProvider } from '@providers/utils/time';
import { CoreUtilsProvider } from '@providers/utils/utils';
import { AddonCalendarProvider } from './calendar';
import { AddonCalendarOfflineProvider } from './calendar-offline';
import { AddonCalendarHelperProvider } from './helper';
/**
* Service to sync calendar.
@ -48,7 +49,8 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
timeUtils: CoreTimeUtilsProvider,
private utils: CoreUtilsProvider,
private calendarProvider: AddonCalendarProvider,
private calendarOffline: AddonCalendarOfflineProvider) {
private calendarOffline: AddonCalendarOfflineProvider,
private calendarHelper: AddonCalendarHelperProvider) {
super('AddonCalendarSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate,
timeUtils);
@ -124,6 +126,7 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
warnings: [],
events: [],
deleted: [],
toinvalidate: [],
updated: false
};
let offlineEventIds: number[];
@ -152,18 +155,13 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
return this.utils.allPromises(promises);
}).then(() => {
if (result.updated) {
// Data has been sent to server. Now invalidate the WS calls.
const promises = [
this.calendarProvider.invalidateEventsList(siteId),
this.calendarHelper.invalidateRepeatedEventsOnCalendar(result.toinvalidate, siteId)
];
offlineEventIds.forEach((eventId) => {
if (eventId > 0) {
// An event was edited, invalidate its data too.
promises.push(this.calendarProvider.invalidateEvent(eventId, siteId));
}
});
return Promise.all(promises).catch(() => {
// Ignore errors.
});
@ -214,6 +212,16 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
// Ignore errors, maybe there was no edit data.
}));
// We need the event data to invalidate it. Get it from local DB.
promises.push(this.calendarProvider.getEventFromLocalDb(eventId, siteId).then((event) => {
result.toinvalidate.push({
event: event,
repeated: data.repeat ? event.eventcount : 1
});
}).catch(() => {
// Ignore errors.
}));
return Promise.all(promises);
}).catch((error) => {
@ -257,6 +265,15 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider {
result.updated = true;
result.events.push(newEvent);
// Add data to invalidate.
const numberOfRepetitions = data.repeat ? data.repeats :
(data.repeateditall && newEvent.repeatid ? newEvent.eventcount : 1);
result.toinvalidate.push({
event: newEvent,
repeated: numberOfRepetitions
});
// Event sent, delete the offline data.
return this.calendarOffline.deleteEvent(event.id, siteId);
}).catch((error) => {

View File

@ -344,73 +344,100 @@ export class AddonCalendarHelperProvider {
/**
* Invalidate all calls from calendar WS calls.
*
* @param {any} event Event that has been touched.
* @param {number} repeated Number of times the event is repeated.
* @param {{event: any, repeated: number}[]} events Events that have been touched and number of times each event is repeated.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} REsolved when done.
* @return {Promise<any>} Resolved when done.
*/
invalidateRepeatedEventsOnCalendar(event: any, repeated: number, siteId?: string): Promise<any> {
invalidateRepeatedEventsOnCalendar(events: {event: any, repeated: number}[], siteId?: string): Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => {
let invalidatePromise;
const timestarts = [];
if (repeated > 1) {
if (event.repeatid) {
// Being edited or deleted.
invalidatePromise = this.calendarProvider.getLocalEventsByRepeatIdFromLocalDb(event.repeatid, site.id)
.then((events) => {
return this.utils.allPromises(events.map((event) => {
timestarts.push(event.timestart);
// Invalidate the events and get the timestarts so we can invalidate months & days.
return this.utils.allPromises(events.map((eventData) => {
return this.calendarProvider.invalidateEvent(event.id);
}));
});
} else {
// Being added.
let time = event.timestart;
while (repeated > 0) {
timestarts.push(time);
time += CoreConstants.SECONDS_DAY * 7;
repeated--;
if (eventData.repeated > 1) {
if (eventData.event.repeatid) {
// Being edited or deleted.
// We need to calculate the days to invalidate because the event date could have changed.
// We don't know if the repeated events are before or after this one, invalidate them all.
timestarts.push(eventData.event.timestart);
for (let i = 1; i < eventData.repeated; i++) {
timestarts.push(eventData.event.timestart + CoreConstants.SECONDS_DAY * 7 * i);
timestarts.push(eventData.event.timestart - CoreConstants.SECONDS_DAY * 7 * i);
}
// Get the repeated events to invalidate them.
return this.calendarProvider.getLocalEventsByRepeatIdFromLocalDb(eventData.event.repeatid, site.id)
.then((events) => {
return this.utils.allPromises(events.map((event) => {
return this.calendarProvider.invalidateEvent(event.id);
}));
});
} else {
// Being added.
let time = eventData.event.timestart;
while (eventData.repeated > 0) {
timestarts.push(time);
time += CoreConstants.SECONDS_DAY * 7;
eventData.repeated--;
}
return Promise.resolve();
}
} else {
// Not repeated.
timestarts.push(eventData.event.timestart);
invalidatePromise = Promise.resolve();
return this.calendarProvider.invalidateEvent(eventData.event.id);
}
} else {
// Not repeated.
timestarts.push(event.timestart);
invalidatePromise = this.calendarProvider.invalidateEvent(event.id);
}
return invalidatePromise.finally(() => {
let lastMonth, lastYear;
})).finally(() => {
const invalidatedMonths = {},
invalidatedDays = {};
return this.utils.allPromises([
this.calendarProvider.invalidateAllUpcomingEvents(),
// Invalidate months.
// Invalidate months and days.
this.utils.allPromises(timestarts.map((time) => {
const day = moment(new Date(time * 1000));
const promises = [],
day = moment(new Date(time * 1000)),
monthId = this.getMonthId(day.year(), day.month() + 1),
dayId = monthId + '#' + day.date();
if (lastMonth && (lastMonth == day.month() + 1 && lastYear == day.year())) {
return Promise.resolve();
if (!invalidatedMonths[monthId]) {
// Month not invalidated already, do it now.
invalidatedMonths[monthId] = monthId;
promises.push(this.calendarProvider.invalidateMonthlyEvents(day.year(), day.month() + 1, site.id));
}
// Invalidate once.
lastMonth = day.month() + 1;
lastYear = day.year();
if (!invalidatedDays[dayId]) {
// Day not invalidated already, do it now.
invalidatedDays[dayId] = dayId;
return this.calendarProvider.invalidateMonthlyEvents(lastYear, lastMonth, site.id);
})),
promises.push(this.calendarProvider.invalidateDayEvents(day.year(), day.month() + 1, day.date(),
site.id));
}
// Invalidate days.
this.utils.allPromises(timestarts.map((time) => {
const day = moment(new Date(time * 1000));
return this.calendarProvider.invalidateDayEvents(day.year(), day.month() + 1, day.date(), site.id);
})),
return this.utils.allPromises(promises);
}))
]);
});
});
}
/**
* Invalidate all calls from calendar WS calls.
*
* @param {any} event Event that has been touched.
* @param {number} repeated Number of times the event is repeated.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Resolved when done.
*/
invalidateRepeatedEventsOnCalendarForEvent(event: any, repeated: number, siteId?: string): Promise<any> {
return this.invalidateRepeatedEventsOnCalendar([{event: event, repeated: repeated}], siteId);
}
}