MOBILE-2856 data: Fix syncing entries with multiple actions

main
Albert Gasset 2019-04-10 18:06:27 +02:00
parent 6b0f08695f
commit fccf79bbd2
1 changed files with 94 additions and 67 deletions

View File

@ -235,26 +235,32 @@ export class AddonModDataSyncProvider extends CoreSyncBaseProvider {
protected syncEntry(data: any, entryActions: AddonModDataOfflineAction[], result: any, siteId?: string): Promise<any> {
let discardError,
timePromise,
entryId = 0,
entryId = entryActions[0].entryid,
offlineId,
deleted = false;
const promises = [];
// Sort entries by timemodified.
entryActions = entryActions.sort((a: any, b: any) => a.timemodified - b.timemodified);
entryId = entryActions[0].entryid;
const editAction = entryActions.find((action) => action.action == 'add' || action.action == 'edit');
const approveAction = entryActions.find((action) => action.action == 'approve' || action.action == 'disapprove');
const deleteAction = entryActions.find((action) => action.action == 'delete');
if (entryId > 0) {
timePromise = this.dataProvider.getEntry(data.id, entryId, false, siteId).then((entry) => {
timePromise = this.dataProvider.getEntry(data.id, entryId, true, siteId).then((entry) => {
return entry.entry.timemodified;
}).catch(() => {
return -1;
}).catch((error) => {
if (error && this.utils.isWebServiceError(error)) {
// The WebService has thrown an error, this means the entry has been deleted.
return Promise.resolve(-1);
}
return Promise.reject(error);
});
} else {
} else if (editAction) {
// New entry.
offlineId = entryId;
timePromise = Promise.resolve(0);
} else {
// New entry but the add action is missing, discard.
timePromise = Promise.resolve(-1);
}
return timePromise.then((timemodified) => {
@ -266,58 +272,11 @@ export class AddonModDataSyncProvider extends CoreSyncBaseProvider {
return this.dataOffline.deleteAllEntryActions(data.id, entryId, siteId);
}
entryActions.forEach((action) => {
let actionPromise;
const proms = [];
entryId = action.entryid > 0 ? action.entryid : entryId;
if (action.fields) {
action.fields.forEach((field) => {
// Upload Files if asked.
const value = this.textUtils.parseJSON(field.value);
if (value.online || value.offline) {
let files = value.online || [];
const fileProm = value.offline ? this.dataHelper.getStoredFiles(action.dataid, entryId, field.fieldid) :
Promise.resolve([]);
proms.push(fileProm.then((offlineFiles) => {
files = files.concat(offlineFiles);
return this.dataHelper.uploadOrStoreFiles(action.dataid, 0, entryId, field.fieldid, files, false,
siteId).then((filesResult) => {
field.value = JSON.stringify(filesResult);
});
}));
}
});
}
actionPromise = Promise.all(proms).then(() => {
// Perform the action.
switch (action.action) {
case 'add':
return this.dataProvider.addEntryOnline(action.dataid, action.fields, data.groupid, siteId)
.then((result) => {
entryId = result.newentryid;
});
case 'edit':
return this.dataProvider.editEntryOnline(entryId, action.fields, siteId);
case 'approve':
return this.dataProvider.approveEntryOnline(entryId, true, siteId);
case 'disapprove':
return this.dataProvider.approveEntryOnline(entryId, false, siteId);
case 'delete':
return this.dataProvider.deleteEntryOnline(entryId, siteId).then(() => {
deleted = true;
});
default:
break;
}
});
promises.push(actionPromise.catch((error) => {
if (error && error.wserror) {
if (deleteAction) {
return this.dataProvider.deleteEntryOnline(entryId, siteId).then(() => {
deleted = true;
}).catch((error) => {
if (error && this.utils.isWebServiceError(error)) {
// The WebService has thrown an error, this means it cannot be performed. Discard.
discardError = this.textUtils.getErrorMessageFromError(error);
} else {
@ -328,11 +287,79 @@ export class AddonModDataSyncProvider extends CoreSyncBaseProvider {
// Delete the offline data.
result.updated = true;
return this.dataOffline.deleteEntry(action.dataid, action.entryid, action.action, siteId);
}));
});
return this.dataOffline.deleteAllEntryActions(deleteAction.dataid, deleteAction.entryid, siteId);
});
}
let editPromise;
if (editAction) {
editPromise = Promise.all(editAction.fields.map((field) => {
// Upload Files if asked.
const value = this.textUtils.parseJSON(field.value);
if (value.online || value.offline) {
let files = value.online || [];
const fileProm = value.offline ?
this.dataHelper.getStoredFiles(editAction.dataid, entryId, field.fieldid) :
Promise.resolve([]);
return fileProm.then((offlineFiles) => {
files = files.concat(offlineFiles);
return this.dataHelper.uploadOrStoreFiles(editAction.dataid, 0, entryId, field.fieldid, files,
false, siteId).then((filesResult) => {
field.value = JSON.stringify(filesResult);
});
});
}
})).then(() => {
if (editAction.action == 'add') {
return this.dataProvider.addEntryOnline(editAction.dataid, editAction.fields, editAction.groupid, siteId)
.then((result) => {
entryId = result.newentryid;
});
} else {
return this.dataProvider.editEntryOnline(entryId, editAction.fields, siteId);
}
}).catch((error) => {
if (error && this.utils.isWebServiceError(error)) {
// The WebService has thrown an error, this means it cannot be performed. Discard.
discardError = this.textUtils.getErrorMessageFromError(error);
} else {
// Couldn't connect to server, reject.
return Promise.reject(error);
}
}).then(() => {
// Delete the offline data.
result.updated = true;
return this.dataOffline.deleteEntry(editAction.dataid, editAction.entryid, editAction.action, siteId);
});
} else {
editPromise = Promise.resolve();
}
if (approveAction) {
editPromise = editPromise.then(() => {
return this.dataProvider.approveEntryOnline(entryId, approveAction.action == 'approve', siteId);
}).catch((error) => {
if (error && this.utils.isWebServiceError(error)) {
// The WebService has thrown an error, this means it cannot be performed. Discard.
discardError = this.textUtils.getErrorMessageFromError(error);
} else {
// Couldn't connect to server, reject.
return Promise.reject(error);
}
}).then(() => {
// Delete the offline data.
result.updated = true;
return this.dataOffline.deleteEntry(approveAction.dataid, approveAction.entryid, approveAction.action, siteId);
});
}
return editPromise;
return Promise.all(promises);
}).then(() => {
if (discardError) {
// Submission was discarded, add a warning.