diff --git a/src/addons/mod/glossary/pages/edit/edit.ts b/src/addons/mod/glossary/pages/edit/edit.ts index 950751961..4c2aa09fe 100644 --- a/src/addons/mod/glossary/pages/edit/edit.ts +++ b/src/addons/mod/glossary/pages/edit/edit.ts @@ -286,9 +286,9 @@ abstract class AddonModGlossaryFormHandler { * Upload attachments online. * * @param glossary Glossary. - * @returns Uploaded attachments item id. + * @returns Uploaded attachments item id, undefined if nothing to upload or change. */ - protected async uploadAttachments(glossary: AddonModGlossaryGlossary): Promise { + protected async uploadAttachments(glossary: AddonModGlossaryGlossary): Promise { const data = this.page.data; const itemId = await CoreFileUploader.uploadOrReuploadFiles( data.attachments, @@ -643,10 +643,7 @@ class AddonModGlossaryOnlineFormHandler extends AddonModGlossaryFormHandler { data.fullmatch = this.entry.fullmatch; } - // Treat offline attachments if any. - if (this.entry.attachments) { - data.attachments = this.entry.attachments; - } + data.attachments = (this.entry.attachments ?? []).slice(); this.page.originalData = { concept: data.concept, @@ -677,11 +674,7 @@ class AddonModGlossaryOnlineFormHandler extends AddonModGlossaryFormHandler { const definition = CoreText.formatHtmlLines(data.definition); // Upload attachments, if any. - let attachmentsId: number | undefined = undefined; - - if (data.attachments.length) { - attachmentsId = await this.uploadAttachments(glossary); - } + const attachmentsId = await this.uploadAttachments(); // Save entry data. await AddonModGlossary.updateEntry(glossary.id, this.entry.id, data.concept, definition, options, attachmentsId); @@ -694,6 +687,31 @@ class AddonModGlossaryOnlineFormHandler extends AddonModGlossaryFormHandler { return true; } + /** + * Upload attachments online. + * + * @returns Uploaded attachments item id, undefined if nothing to upload or change. + */ + protected async uploadAttachments(): Promise { + const data = this.page.data; + + if (!CoreFileUploader.areFileListDifferent(data.attachments, this.entry.attachments ?? [])) { + return; + } + + const { attachmentsid: attachmentsId } = await AddonModGlossary.prepareEntryForEdition(this.entry.id); + + const removedFiles = CoreFileUploader.getFilesToDelete(this.entry.attachments ?? [], data.attachments); + + if (removedFiles.length) { + await CoreFileUploader.deleteDraftFiles(attachmentsId, removedFiles); + } + + await CoreFileUploader.uploadFiles(attachmentsId, data.attachments); + + return attachmentsId; + } + } /** diff --git a/src/addons/mod/glossary/services/glossary.ts b/src/addons/mod/glossary/services/glossary.ts index a9c12cf1a..715ee9575 100644 --- a/src/addons/mod/glossary/services/glossary.ts +++ b/src/addons/mod/glossary/services/glossary.ts @@ -626,6 +626,7 @@ export class AddonModGlossaryProvider { * * @param siteId Site id. * @returns Whether the site can update entries. + * @since 3.10 */ async canUpdateEntries(siteId?: string): Promise { const site = await CoreSites.getSite(siteId); @@ -1097,6 +1098,26 @@ export class AddonModGlossaryProvider { await site.getDb().insertRecord(ENTRIES_TABLE_NAME, entry); } + /** + * Prepare entry for edition. + * + * @param entryId Entry ID. + * @param siteId Site ID. + * @returns Data of prepared area. + */ + async prepareEntryForEdition( + entryId: number, + siteId?: string, + ): Promise { + const site = await CoreSites.getSite(siteId); + + const params: AddonModGlossaryPrepareEntryForEditionWSParams = { + entryid: entryId, + }; + + return await site.write('mod_glossary_prepare_entry_for_edition', params); + } + } export const AddonModGlossary = makeSingleton(AddonModGlossaryProvider); @@ -1435,6 +1456,31 @@ export type AddonModGlossaryViewEntryWSParams = { id: number; // Glossary entry ID. }; +/** + * Params of mod_glossary_prepare_entry_for_edition WS. + */ +type AddonModGlossaryPrepareEntryForEditionWSParams = { + entryid: number; // Glossary entry id to update. +}; + +/** + * Data returned by mod_glossary_prepare_entry_for_edition WS. + */ +export type AddonModGlossaryPrepareEntryForEditionWSResponse = { + inlineattachmentsid: number; // Draft item id for the text editor. + attachmentsid: number; // Draft item id for the file manager. + areas: { // File areas including options. + area: string; // File area name. + options: { // Draft file area options. + name: string; // Name of option. + value: string; // Value of option. + }[]; + }[]; + aliases: string[]; + categories: number[]; + warnings?: CoreWSExternalWarning[]; +}; + /** * Options to pass to add entry. */