MOBILE-2272 quiz: Support deleting attachments

main
Dani Palou 2020-10-01 14:39:42 +02:00
parent 5b0059a617
commit 65909073fa
2 changed files with 97 additions and 1 deletions

View File

@ -278,6 +278,15 @@ export class AddonQtypeEssayHandler implements CoreQuestionHandler {
// Store the files in the answers. // Store the files in the answers.
answers[attachmentsInput.name + '_offline'] = JSON.stringify(result); answers[attachmentsInput.name + '_offline'] = JSON.stringify(result);
} else { } else {
// Check if any attachment was deleted.
const originalAttachments = this.questionHelper.getResponseFileAreaFiles(question, 'attachments');
const filesToDelete = CoreFileUploader.instance.getFilesToDelete(originalAttachments, attachments);
if (filesToDelete.length > 0) {
// Delete files.
await CoreFileUploader.instance.deleteDraftFiles(draftId, filesToDelete, siteId);
}
await CoreFileUploader.instance.uploadFiles(draftId, attachments, siteId); await CoreFileUploader.instance.uploadFiles(draftId, attachments, siteId);
} }
} }
@ -304,9 +313,17 @@ export class AddonQtypeEssayHandler implements CoreQuestionHandler {
} }
if (answers && answers.attachments_offline) { if (answers && answers.attachments_offline) {
// Check if it has new attachments to upload.
const attachmentsData = this.textUtils.parseJSON(answers.attachments_offline, {}); const attachmentsData = this.textUtils.parseJSON(answers.attachments_offline, {});
// Check if any attachment was deleted.
const originalAttachments = this.questionHelper.getResponseFileAreaFiles(question, 'attachments');
const filesToDelete = CoreFileUploader.instance.getFilesToDelete(originalAttachments, attachmentsData.online);
if (filesToDelete.length > 0) {
// Delete files.
await CoreFileUploader.instance.deleteDraftFiles(answers.attachments, filesToDelete, siteId);
}
if (attachmentsData.offline) { if (attachmentsData.offline) {
// Upload the offline files. // Upload the offline files.
const offlineFiles = await this.questionHelper.getStoredQuestionFiles(question, component, componentId, siteId); const offlineFiles = await this.questionHelper.getStoredQuestionFiles(question, component, componentId, siteId);

View File

@ -29,6 +29,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreWSFileUploadOptions, CoreWSExternalFile } from '@providers/ws'; import { CoreWSFileUploadOptions, CoreWSExternalFile } from '@providers/ws';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { CoreApp } from '@providers/app'; import { CoreApp } from '@providers/app';
import { CoreSite } from '@classes/site';
import { makeSingleton } from '@singletons/core.singletons'; import { makeSingleton } from '@singletons/core.singletons';
/** /**
@ -106,6 +107,36 @@ export class CoreFileUploaderProvider {
return false; return false;
} }
/**
* Check if a certain site allows deleting draft files.
*
* @param siteId Site Id. If not defined, use current site.
* @return Promise resolved with true if can delete.
* @since 3.10
*/
async canDeleteDraftFiles(siteId?: string): Promise<boolean> {
try {
const site = await this.sitesProvider.getSite(siteId);
return this.canDeleteDraftFilesInSite(site);
} catch (error) {
return false;
}
}
/**
* Check if a certain site allows deleting draft files.
*
* @param site Site. If not defined, use current site.
* @return Whether draft files can be deleted.
* @since 3.10
*/
canDeleteDraftFilesInSite(site?: CoreSite): boolean {
site = site || this.sitesProvider.getCurrentSite();
return site.wsAvailable('core_files_delete_draft_files');
}
/** /**
* Start the audio recorder application and return information about captured audio clip files. * Start the audio recorder application and return information about captured audio clip files.
* *
@ -175,6 +206,25 @@ export class CoreFileUploaderProvider {
}); });
} }
/**
* Delete draft files.
*
* @param draftId Draft ID.
* @param files Files to delete.
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
async deleteDraftFiles(draftId: number, files: {filepath: string, filename: string}[], siteId?: string): Promise<void> {
const site = await this.sitesProvider.getSite(siteId);
const params = {
draftitemid: draftId,
files: files,
};
return site.write('core_files_delete_draft_files', params);
}
/** /**
* Get the upload options for a file taken with the Camera Cordova plugin. * Get the upload options for a file taken with the Camera Cordova plugin.
* *
@ -217,6 +267,35 @@ export class CoreFileUploaderProvider {
return options; return options;
} }
/**
* Given a list of original files and a list of current files, return the list of files to delete.
*
* @param originalFiles Original files.
* @param currentFiles Current files.
* @return List of files to delete.
*/
getFilesToDelete(originalFiles: CoreWSExternalFile[], currentFiles: (CoreWSExternalFile | FileEntry)[])
: {filepath: string, filename: string}[] {
const filesToDelete: {filepath: string, filename: string}[] = [];
currentFiles = currentFiles || [];
originalFiles.forEach((file) => {
const stillInList = currentFiles.some((currentFile) => {
return (<CoreWSExternalFile> currentFile).fileurl == file.fileurl;
});
if (!stillInList) {
filesToDelete.push({
filepath: file.filepath,
filename: file.filename,
});
}
});
return filesToDelete;
}
/** /**
* Get the upload options for a file of any type. * Get the upload options for a file of any type.
* *