diff --git a/src/addon/calendar/pages/edit-event/edit-event.ts b/src/addon/calendar/pages/edit-event/edit-event.ts index 0296859a5..fe80b521b 100644 --- a/src/addon/calendar/pages/edit-event/edit-event.ts +++ b/src/addon/calendar/pages/edit-event/edit-event.ts @@ -497,10 +497,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy { this.calendarProvider.submitEvent(this.eventId, data).then((result) => { event = result.event; - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: result.sent, - }, this.currentSite.getId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, result.sent, this.currentSite.getId()); if (result.sent) { // Event created or edited, invalidate right days & months. @@ -563,6 +560,9 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy { discard(): void { this.domUtils.showConfirm(this.translate.instant('core.areyousure')).then(() => { this.calendarOffline.deleteEvent(this.eventId).then(() => { + + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.currentSite.getId()); + this.returnToList(); }).catch(() => { // Shouldn't happen. @@ -578,16 +578,18 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy { * * @return Resolved if we can leave it, rejected if not. */ - ionViewCanLeave(): boolean | Promise { - + async ionViewCanLeave(): Promise { if (this.calendarHelper.hasEventDataChanged(this.eventForm.value, this.originalData)) { // Show confirmation if some data has been modified. - return this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); - } else { - return Promise.resolve(); + await this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); } + + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.currentSite.getId()); } + /** + * Unblock sync. + */ protected unblockSync(): void { if (this.eventId) { this.syncProvider.unblockOperation(AddonCalendarProvider.COMPONENT, this.eventId); diff --git a/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.ts b/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.ts index 599f8aa86..5ea771319 100644 --- a/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.ts +++ b/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.ts @@ -61,16 +61,17 @@ export class AddonModAssignEditFeedbackModalPage { * * @return Resolved if we can leave it, rejected if not. */ - ionViewCanLeave(): boolean | Promise { + async ionViewCanLeave(): Promise { if (this.forceLeave) { - return true; + return; } - return this.hasDataChanged().then((changed) => { - if (changed) { - return this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); - } - }); + const changed = await this.hasDataChanged(); + if (changed) { + await this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); + } + + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.sitesProvider.getCurrentSiteId()); } /** @@ -91,10 +92,7 @@ export class AddonModAssignEditFeedbackModalPage { e.preventDefault(); e.stopPropagation(); - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: false, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, this.sitesProvider.getCurrentSiteId()); // Close the modal, sending the input data. this.forceLeave = true; diff --git a/src/addon/mod/assign/pages/edit/edit.ts b/src/addon/mod/assign/pages/edit/edit.ts index 901cc2baa..4ec6fe6d2 100644 --- a/src/addon/mod/assign/pages/edit/edit.ts +++ b/src/addon/mod/assign/pages/edit/edit.ts @@ -85,20 +85,21 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy { * * @return Resolved if we can leave it, rejected if not. */ - ionViewCanLeave(): boolean | Promise { + async ionViewCanLeave(): Promise { if (this.forceLeave) { - return true; + return; } // Check if data has changed. - return this.hasDataChanged().then((changed) => { - if (changed) { - return this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); - } - }).then(() => { - // Nothing has changed or user confirmed to leave. Clear temporary data from plugins. - this.assignHelper.clearSubmissionPluginTmpData(this.assign, this.userSubmission, this.getInputData()); - }); + const changed = await this.hasDataChanged(); + if (changed) { + await this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); + } + + // Nothing has changed or user confirmed to leave. Clear temporary data from plugins. + this.assignHelper.clearSubmissionPluginTmpData(this.assign, this.userSubmission, this.getInputData()); + + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.sitesProvider.getCurrentSiteId()); } /** @@ -317,10 +318,7 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy { await this.assignHelper.clearSubmissionPluginTmpData(this.assign, this.userSubmission, inputData); // Submission saved, trigger events. - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: sent, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, sent, this.sitesProvider.getCurrentSiteId()); const params = { assignmentId: this.assign.id, diff --git a/src/addon/mod/data/pages/edit/edit.ts b/src/addon/mod/data/pages/edit/edit.ts index 6bc8c66ff..20a58c60c 100644 --- a/src/addon/mod/data/pages/edit/edit.ts +++ b/src/addon/mod/data/pages/edit/edit.ts @@ -96,28 +96,25 @@ export class AddonModDataEditPage { * * @return Resolved if we can leave it, rejected if not. */ - ionViewCanLeave(): boolean | Promise { + async ionViewCanLeave(): Promise { if (this.forceLeave || !this.entry) { - return true; + return; } const inputData = this.editForm.value; - return this.dataHelper.hasEditDataChanged(inputData, this.fieldsArray, this.data.id, - this.entry.contents).then((changed) => { - if (!changed) { - return Promise.resolve(); - } + const changed = await this.dataHelper.hasEditDataChanged(inputData, this.fieldsArray, this.data.id, this.entry.contents); + if (changed) { // Show confirmation if some data has been modified. - return this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); - }).then(() => { - // Delete the local files from the tmp folder. - return this.dataHelper.getEditTmpFiles(inputData, this.fieldsArray, this.data.id, - this.entry.contents).then((files) => { - this.fileUploaderProvider.clearTmpFiles(files); - }); - }); + await this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); + } + + // Delete the local files from the tmp folder. + const files = await this.dataHelper.getEditTmpFiles(inputData, this.fieldsArray, this.data.id, this.entry.contents); + this.fileUploaderProvider.clearTmpFiles(files); + + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.siteId); } /** @@ -218,10 +215,7 @@ export class AddonModDataEditPage { // This is done if entry is updated when editing or creating if not. if ((this.entryId && result.updated) || (!this.entryId && result.newentryid)) { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: result.sent, - }, this.siteId); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, result.sent, this.siteId); const promises = []; diff --git a/src/addon/mod/data/pages/search/search.ts b/src/addon/mod/data/pages/search/search.ts index 5834e6ccc..4d2263630 100644 --- a/src/addon/mod/data/pages/search/search.ts +++ b/src/addon/mod/data/pages/search/search.ts @@ -186,6 +186,12 @@ export class AddonModDataSearchPage { * @param data Data to return to the page. */ closeModal(data?: any): void { + if (typeof data == 'undefined') { + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.sitesProvider.getCurrentSiteId()); + } else { + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, this.sitesProvider.getCurrentSiteId()); + } + this.viewCtrl.dismiss(data); } @@ -220,11 +226,6 @@ export class AddonModDataSearchPage { this.search.sortBy = searchedData.sortBy; this.search.sortDirection = searchedData.sortDirection; - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: false, - }, this.sitesProvider.getCurrentSiteId()); - this.closeModal(this.search); } } diff --git a/src/addon/mod/lesson/components/index/index.ts b/src/addon/mod/lesson/components/index/index.ts index b3b4b95a7..23ad87ae6 100644 --- a/src/addon/mod/lesson/components/index/index.ts +++ b/src/addon/mod/lesson/components/index/index.ts @@ -14,7 +14,6 @@ import { Component, Optional, Injector, Input, ViewChild, ElementRef } from '@angular/core'; import { Content, NavController } from 'ionic-angular'; -import { CoreEventsProvider } from '@providers/events'; import { CoreGroupsProvider, CoreGroupInfo } from '@providers/groups'; import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreUtilsProvider } from '@providers/utils/utils'; @@ -587,10 +586,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo this.refreshIcon = 'refresh'; this.syncIcon = 'sync'; - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: true, - }, this.siteId); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true, this.siteId); }); } diff --git a/src/addon/mod/lesson/pages/password-modal/password-modal.ts b/src/addon/mod/lesson/pages/password-modal/password-modal.ts index d72df1ca4..2446bb266 100644 --- a/src/addon/mod/lesson/pages/password-modal/password-modal.ts +++ b/src/addon/mod/lesson/pages/password-modal/password-modal.ts @@ -16,6 +16,7 @@ import { Component, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, ViewController } from 'ionic-angular'; import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider } from '@providers/sites'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; /** * Modal that asks the password for a lesson. @@ -30,7 +31,8 @@ export class AddonModLessonPasswordModalPage { constructor(protected viewCtrl: ViewController, protected eventsProvider: CoreEventsProvider, - protected sitesProvider: CoreSitesProvider) { } + protected sitesProvider: CoreSitesProvider, + protected domUtils: CoreDomUtilsProvider) { } /** * Send the password back. @@ -42,10 +44,7 @@ export class AddonModLessonPasswordModalPage { e.preventDefault(); e.stopPropagation(); - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: false, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, this.sitesProvider.getCurrentSiteId()); this.viewCtrl.dismiss(password.value); } @@ -54,6 +53,8 @@ export class AddonModLessonPasswordModalPage { * Close modal. */ closeModal(): void { + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.sitesProvider.getCurrentSiteId()); + this.viewCtrl.dismiss(); } } diff --git a/src/addon/mod/lesson/pages/player/player.ts b/src/addon/mod/lesson/pages/player/player.ts index 7ab23e96f..44d2a87ca 100644 --- a/src/addon/mod/lesson/pages/player/player.ts +++ b/src/addon/mod/lesson/pages/player/player.ts @@ -137,19 +137,19 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy { * * @return Resolved if we can leave it, rejected if not. */ - ionViewCanLeave(): boolean | Promise { + async ionViewCanLeave(): Promise { if (this.forceLeave) { - return true; + return; } if (this.question && !this.eolData && !this.processData && this.originalData) { // Question shown. Check if there is any change. if (!this.utils.basicLeftCompare(this.questionForm.getRawValue(), this.originalData, 3)) { - return this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); + await this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); } } - return Promise.resolve(); + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.sitesProvider.getCurrentSiteId()); } /** @@ -552,10 +552,8 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy { return this.callFunction(this.lessonProvider.processPage.bind(this.lessonProvider), args, 6, 8).then((result) => { if (formSubmitted) { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: result.sent, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, result.sent, + this.sitesProvider.getCurrentSiteId()); } if (!this.offline && !this.review && this.lessonProvider.isLessonOffline(this.lesson)) { diff --git a/src/addon/mod/quiz/pages/player/player.ts b/src/addon/mod/quiz/pages/player/player.ts index 31acddaa4..92d9a04ac 100644 --- a/src/addon/mod/quiz/pages/player/player.ts +++ b/src/addon/mod/quiz/pages/player/player.ts @@ -137,26 +137,28 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy { * * @return Resolved if we can leave it, rejected if not. */ - ionViewCanLeave(): boolean | Promise { + async ionViewCanLeave(): Promise { if (this.forceLeave) { - return true; + return; } if (this.questions && this.questions.length && !this.showSummary) { // Save answers. const modal = this.domUtils.showModalLoading('core.sending', true); - return this.processAttempt(false, false).catch(() => { + try { + await this.processAttempt(false, false); + } catch (error) { // Save attempt failed. Show confirmation. modal.dismiss(); - return this.domUtils.showConfirm(this.translate.instant('addon.mod_quiz.confirmleavequizonerror')); - }).finally(() => { - modal.dismiss(); - }); - } + await this.domUtils.showConfirm(this.translate.instant('addon.mod_quiz.confirmleavequizonerror')); - return Promise.resolve(); + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.sitesProvider.getCurrentSiteId()); + } finally { + modal.dismiss(); + } + } } /** @@ -587,10 +589,8 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy { this.autoSave.cancelAutoSave(); this.autoSave.hideAutoSaveError(); - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: !this.offline, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, !this.offline, + this.sitesProvider.getCurrentSiteId()); }); } diff --git a/src/addon/mod/quiz/pages/preflight-modal/preflight-modal.ts b/src/addon/mod/quiz/pages/preflight-modal/preflight-modal.ts index 28681c8a5..fa149c30f 100644 --- a/src/addon/mod/quiz/pages/preflight-modal/preflight-modal.ts +++ b/src/addon/mod/quiz/pages/preflight-modal/preflight-modal.ts @@ -120,10 +120,7 @@ export class AddonModQuizPreflightModalPage implements OnInit { this.domUtils.showErrorModal('core.errorinvalidform', true); } } else { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: false, - }, this.siteId); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, this.siteId); this.viewCtrl.dismiss(this.preflightForm.value); } @@ -133,6 +130,8 @@ export class AddonModQuizPreflightModalPage implements OnInit { * Close modal. */ closeModal(): void { + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.siteId); + this.viewCtrl.dismiss(); } } diff --git a/src/addon/mod/wiki/pages/edit/edit.ts b/src/addon/mod/wiki/pages/edit/edit.ts index 7df9ad26a..7cd65dccb 100644 --- a/src/addon/mod/wiki/pages/edit/edit.ts +++ b/src/addon/mod/wiki/pages/edit/edit.ts @@ -346,17 +346,17 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy { * * @return Resolved if we can leave it, rejected if not. */ - ionViewCanLeave(): boolean | Promise { + async ionViewCanLeave(): Promise { if (this.forceLeave) { - return true; + return; } // Check if data has changed. if (this.hasDataChanged()) { - return this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); + await this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); } - return true; + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.sitesProvider.getCurrentSiteId()); } /** @@ -426,10 +426,8 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy { // Edit existing page. promise = this.wikiProvider.editPage(this.pageId, text, this.section).then(() => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: true, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true, + this.sitesProvider.getCurrentSiteId()); // Invalidate page since it changed. return this.wikiProvider.invalidatePage(this.pageId).then(() => { @@ -465,10 +463,8 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy { return this.wikiProvider.newPage(title, text, this.subwikiId, wikiId, this.userId, this.groupId).then((id) => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: id > 0, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, id > 0, + this.sitesProvider.getCurrentSiteId()); if (id > 0) { // Page was created, get its data and go to the page. diff --git a/src/addon/mod/workshop/components/assessment-strategy/assessment-strategy.ts b/src/addon/mod/workshop/components/assessment-strategy/assessment-strategy.ts index 9b239ddac..a0121dee6 100644 --- a/src/addon/mod/workshop/components/assessment-strategy/assessment-strategy.ts +++ b/src/addon/mod/workshop/components/assessment-strategy/assessment-strategy.ts @@ -304,10 +304,7 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit { assessmentData, false, allowOffline); }).then((grade) => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: !!grade, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, !!grade, this.sitesProvider.getCurrentSiteId()); const promises = []; diff --git a/src/addon/mod/workshop/pages/assessment/assessment.ts b/src/addon/mod/workshop/pages/assessment/assessment.ts index ae9a53d62..09be157c7 100644 --- a/src/addon/mod/workshop/pages/assessment/assessment.ts +++ b/src/addon/mod/workshop/pages/assessment/assessment.ts @@ -120,17 +120,19 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { * * @return Resolved if we can leave it, rejected if not. */ - ionViewCanLeave(): boolean | Promise { + async ionViewCanLeave(): Promise { if (this.forceLeave || !this.evaluating) { - return true; + return; } if (!this.hasEvaluationChanged()) { - return Promise.resolve(); + return; } // Show confirmation if some data has been modified. - return this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); + await this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); + + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.siteId); } /** @@ -344,10 +346,7 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { return this.workshopProvider.evaluateAssessment(this.workshopId, this.assessmentId, this.courseId, inputData.text, inputData.weight, inputData.grade).then((result) => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: !!result, - }, this.siteId); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, !!result, this.siteId); const data = { workshopId: this.workshopId, diff --git a/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts b/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts index 121d11ed8..0911dc7d0 100644 --- a/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts +++ b/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts @@ -112,27 +112,23 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { * * @return Resolved if we can leave it, rejected if not. */ - ionViewCanLeave(): boolean | Promise { + async ionViewCanLeave(): Promise { if (this.forceLeave) { - return true; + return; } - let promise; - // Check if data has changed. - if (!this.hasDataChanged()) { - promise = Promise.resolve(); - } else { + if (this.hasDataChanged()) { // Show confirmation if some data has been modified. - promise = this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); + await this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); } - return promise.then(() => { - if (this.submission.attachmentfiles) { - // Delete the local files from the tmp folder. - this.fileUploaderProvider.clearTmpFiles(this.submission.attachmentfiles); - } - }); + if (this.submission.attachmentfiles) { + // Delete the local files from the tmp folder. + this.fileUploaderProvider.clearTmpFiles(this.submission.attachmentfiles); + } + + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.siteId); } /** @@ -378,10 +374,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { attachmentsId, undefined, submissionId, allowOffline); }).then((newSubmissionId) => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: !!newSubmissionId, - }, this.siteId); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, !!newSubmissionId, this.siteId); const data = { workshopId: this.workshopId, diff --git a/src/addon/mod/workshop/pages/submission/submission.ts b/src/addon/mod/workshop/pages/submission/submission.ts index a1c3b6d50..947aec803 100644 --- a/src/addon/mod/workshop/pages/submission/submission.ts +++ b/src/addon/mod/workshop/pages/submission/submission.ts @@ -144,14 +144,16 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { * * @return Resolved if we can leave it, rejected if not. */ - ionViewCanLeave(): boolean | Promise { + async ionViewCanLeave(): Promise { const assessmentHasChanged = this.assessmentStrategy && this.assessmentStrategy.hasDataChanged(); if (this.forceLeave || (!this.hasEvaluationChanged() && !assessmentHasChanged)) { - return true; + return; } // Show confirmation if some data has been modified. - return this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); + await this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); + + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.siteId); } /** @@ -447,10 +449,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { return this.workshopProvider.evaluateSubmission(this.workshopId, this.submissionId, this.courseId, inputData.text, inputData.published, inputData.grade).then((result) => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: !!result, - }, this.siteId); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, !!result, this.siteId); const data = { workshopId: this.workshopId, diff --git a/src/addon/notes/pages/add/add.ts b/src/addon/notes/pages/add/add.ts index d00e95aa2..64459dd0a 100644 --- a/src/addon/notes/pages/add/add.ts +++ b/src/addon/notes/pages/add/add.ts @@ -65,10 +65,7 @@ export class AddonNotesAddPage { this.processing = true; this.notesProvider.addNote(this.userId, this.courseId, this.type, this.text).then((sent) => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: sent, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, sent, this.sitesProvider.getCurrentSiteId()); this.viewCtrl.dismiss({type: this.type, sent: true}).finally(() => { this.domUtils.showToast(sent ? 'addon.notes.eventnotecreated' : 'core.datastoredoffline', true, 3000); @@ -85,6 +82,8 @@ export class AddonNotesAddPage { * Close modal. */ closeModal(): void { + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.sitesProvider.getCurrentSiteId()); + this.viewCtrl.dismiss({type: this.type}); } } diff --git a/src/components/local-file/local-file.ts b/src/components/local-file/local-file.ts index 31fd41bf0..d430af3f4 100644 --- a/src/components/local-file/local-file.ts +++ b/src/components/local-file/local-file.ts @@ -143,6 +143,7 @@ export class CoreLocalFileComponent implements OnInit { if (newName == this.file.name) { // Name hasn't changed, stop. this.editMode = false; + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.sitesProvider.getCurrentSiteId()); return; } @@ -159,10 +160,8 @@ export class CoreLocalFileComponent implements OnInit { // File doesn't exist, move it. return this.fileProvider.moveFile(this.relativePath, newPath).then((fileEntry) => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: false, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, + this.sitesProvider.getCurrentSiteId()); this.editMode = false; this.file = fileEntry; diff --git a/src/components/search-box/search-box.ts b/src/components/search-box/search-box.ts index 4698e4584..8d313b71b 100644 --- a/src/components/search-box/search-box.ts +++ b/src/components/search-box/search-box.ts @@ -16,6 +16,7 @@ import { Component, Input, Output, EventEmitter, OnInit, ViewChild, ElementRef } import { TranslateService } from '@ngx-translate/core'; import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider } from '@providers/sites'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreUtilsProvider } from '@providers/utils/utils'; /** @@ -53,7 +54,8 @@ export class CoreSearchBoxComponent implements OnInit { constructor(protected translate: TranslateService, protected utils: CoreUtilsProvider, protected eventsProvider: CoreEventsProvider, - protected sitesProvider: CoreSitesProvider) { + protected sitesProvider: CoreSitesProvider, + protected domUtils: CoreDomUtilsProvider) { this.onSubmit = new EventEmitter(); this.onClear = new EventEmitter(); } @@ -80,10 +82,7 @@ export class CoreSearchBoxComponent implements OnInit { return; } - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: false, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, this.sitesProvider.getCurrentSiteId()); this.searched = true; this.onSubmit.emit(this.searchText); diff --git a/src/components/send-message-form/send-message-form.ts b/src/components/send-message-form/send-message-form.ts index 147118f7c..05a3de17f 100644 --- a/src/components/send-message-form/send-message-form.ts +++ b/src/components/send-message-form/send-message-form.ts @@ -19,6 +19,7 @@ import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreTextUtilsProvider } from '@providers/utils/text'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreConstants } from '@core/constants'; /** @@ -52,7 +53,8 @@ export class CoreSendMessageFormComponent implements OnInit { configProvider: CoreConfigProvider, protected eventsProvider: CoreEventsProvider, protected sitesProvider: CoreSitesProvider, - protected appProvider: CoreAppProvider) { + protected appProvider: CoreAppProvider, + protected domUtils: CoreDomUtilsProvider) { this.onSubmit = new EventEmitter(); this.onResize = new EventEmitter(); @@ -88,10 +90,7 @@ export class CoreSendMessageFormComponent implements OnInit { this.message = ''; // Reset the form. - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: false, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, this.sitesProvider.getCurrentSiteId()); value = this.textUtils.replaceNewLines(value, '
'); this.onSubmit.emit(value); diff --git a/src/core/comments/pages/add/add.ts b/src/core/comments/pages/add/add.ts index 583cb0300..826d642fc 100644 --- a/src/core/comments/pages/add/add.ts +++ b/src/core/comments/pages/add/add.ts @@ -71,10 +71,8 @@ export class CoreCommentsAddPage { this.commentsProvider.addComment(this.content, this.contextLevel, this.instanceId, this.componentName, this.itemId, this.area).then((commentsResponse) => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: !!commentsResponse, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, !!commentsResponse, + this.sitesProvider.getCurrentSiteId()); this.viewCtrl.dismiss({comments: commentsResponse}).finally(() => { this.domUtils.showToast(commentsResponse ? 'core.comments.eventcommentcreated' : 'core.datastoredoffline', true, @@ -92,6 +90,7 @@ export class CoreCommentsAddPage { * Close modal. */ closeModal(): void { + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.sitesProvider.getCurrentSiteId()); this.viewCtrl.dismiss(); } } diff --git a/src/core/courses/pages/self-enrol-password/self-enrol-password.ts b/src/core/courses/pages/self-enrol-password/self-enrol-password.ts index c95c5ec83..7e0080248 100644 --- a/src/core/courses/pages/self-enrol-password/self-enrol-password.ts +++ b/src/core/courses/pages/self-enrol-password/self-enrol-password.ts @@ -16,6 +16,7 @@ import { Component, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, ViewController } from 'ionic-angular'; import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider } from '@providers/sites'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; /** * Page that displays a form to enter a password to self enrol in a course. @@ -31,12 +32,14 @@ export class CoreCoursesSelfEnrolPasswordPage { constructor(protected viewCtrl: ViewController, protected eventsProvider: CoreEventsProvider, - protected sitesProvider: CoreSitesProvider) { } + protected sitesProvider: CoreSitesProvider, + protected domUtils: CoreDomUtilsProvider) { } /** * Close help modal. */ close(): void { + this.domUtils.triggerFormCancelledEvent(this.formElement.nativeElement, this.sitesProvider.getCurrentSiteId()); this.viewCtrl.dismiss(); } @@ -50,10 +53,7 @@ export class CoreCoursesSelfEnrolPasswordPage { e.preventDefault(); e.stopPropagation(); - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: false, - }, this.sitesProvider.getCurrentSiteId()); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, this.sitesProvider.getCurrentSiteId()); this.viewCtrl.dismiss(password); } diff --git a/src/core/editor/components/rich-text-editor/rich-text-editor.ts b/src/core/editor/components/rich-text-editor/rich-text-editor.ts index 2fa0bc613..b28969ebe 100644 --- a/src/core/editor/components/rich-text-editor/rich-text-editor.ts +++ b/src/core/editor/components/rich-text-editor/rich-text-editor.ts @@ -194,7 +194,7 @@ export class CoreEditorRichTextEditorComponent implements AfterContentInit, OnDe this.autoSaveDrafts(); - this.deleteDraftOnSubmit(); + this.deleteDraftOnSubmitOrCancel(); } } @@ -814,11 +814,11 @@ export class CoreEditorRichTextEditorComponent implements AfterContentInit, OnDe } /** - * Delete the draft when the form is submitted. + * Delete the draft when the form is submitted or cancelled. */ - protected deleteDraftOnSubmit(): void { + protected deleteDraftOnSubmitOrCancel(): void { - this.resetObs = this.events.on(CoreEventsProvider.FORM_SUBMITTED, async (data) => { + this.resetObs = this.events.on(CoreEventsProvider.FORM_ACTION, async (data) => { const form = this.element.closest('form'); if (data.form && form && data.form == form) { diff --git a/src/core/login/pages/credentials/credentials.ts b/src/core/login/pages/credentials/credentials.ts index 3d3f6f5e4..0aaccaa12 100644 --- a/src/core/login/pages/credentials/credentials.ts +++ b/src/core/login/pages/credentials/credentials.ts @@ -246,10 +246,7 @@ export class CoreLoginCredentialsPage { }).finally(() => { modal.dismiss(); - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: true, - }); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true); }); } diff --git a/src/core/login/pages/email-signup/email-signup.ts b/src/core/login/pages/email-signup/email-signup.ts index e9563da59..f4cc08996 100644 --- a/src/core/login/pages/email-signup/email-signup.ts +++ b/src/core/login/pages/email-signup/email-signup.ts @@ -277,10 +277,7 @@ export class CoreLoginEmailSignupPage { }).then((result) => { if (result.success) { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.signupFormElement.nativeElement, - online: true, - }); + this.domUtils.triggerFormSubmittedEvent(this.signupFormElement.nativeElement, true); // Show alert and ho back. const message = this.translate.instant('core.login.emailconfirmsent', { $a: params.email }); @@ -352,10 +349,7 @@ export class CoreLoginEmailSignupPage { this.wsProvider.callAjax('core_auth_is_minor', params, {siteUrl: this.siteUrl}).then((result) => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.ageFormElement.nativeElement, - online: true, - }); + this.domUtils.triggerFormSubmittedEvent(this.ageFormElement.nativeElement, true); if (!result.status) { if (this.countryControl.value) { diff --git a/src/core/login/pages/forgotten-password/forgotten-password.ts b/src/core/login/pages/forgotten-password/forgotten-password.ts index 1187d903a..9b975e958 100644 --- a/src/core/login/pages/forgotten-password/forgotten-password.ts +++ b/src/core/login/pages/forgotten-password/forgotten-password.ts @@ -82,10 +82,7 @@ export class CoreLoginForgottenPasswordPage { this.domUtils.showErrorModal(response.notice); } else { // Success. - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: true, - }); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true); this.domUtils.showAlert(this.translate.instant('core.success'), response.notice); this.navCtrl.pop(); diff --git a/src/core/login/pages/reconnect/reconnect.ts b/src/core/login/pages/reconnect/reconnect.ts index 73b551574..59918eab7 100644 --- a/src/core/login/pages/reconnect/reconnect.ts +++ b/src/core/login/pages/reconnect/reconnect.ts @@ -181,10 +181,7 @@ export class CoreLoginReconnectPage { this.sitesProvider.getUserToken(siteUrl, username, password).then((data) => { return this.sitesProvider.updateSiteToken(this.infoSiteUrl, username, data.token, data.privateToken).then(() => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: true, - }); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true); // Update site info too because functions might have changed (e.g. unisntall local_mobile). return this.sitesProvider.updateSiteInfoByUrl(this.infoSiteUrl, username).then(() => { diff --git a/src/core/login/pages/site/site.ts b/src/core/login/pages/site/site.ts index d20b510f7..92193fd92 100644 --- a/src/core/login/pages/site/site.ts +++ b/src/core/login/pages/site/site.ts @@ -107,10 +107,7 @@ export class CoreLoginSitePage { this.sitesProvider.getUserToken(siteData.url, siteData.username, siteData.password).then((data) => { return this.sitesProvider.newSite(data.siteUrl, data.token, data.privateToken).then(() => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: true, - }); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true); return this.loginHelper.goToSiteInitialPage(); }, (error) => { @@ -192,10 +189,7 @@ export class CoreLoginSitePage { protected async login(response: CoreSiteCheckResponse): Promise { return this.sitesProvider.checkRequiredMinimumVersion(response.config).then(() => { - this.eventsProvider.trigger(CoreEventsProvider.FORM_SUBMITTED, { - form: this.formElement.nativeElement, - online: true, - }); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true); if (response.warning) { this.domUtils.showErrorModal(response.warning, true, 4000); diff --git a/src/providers/events.ts b/src/providers/events.ts index d20103e88..abed87a95 100644 --- a/src/providers/events.ts +++ b/src/providers/events.ts @@ -64,7 +64,7 @@ export class CoreEventsProvider { static SELECT_COURSE_TAB = 'select_course_tab'; static WS_CACHE_INVALIDATED = 'ws_cache_invalidated'; static SITE_STORAGE_DELETED = 'site_storage_deleted'; - static FORM_SUBMITTED = 'form_submitted'; + static FORM_ACTION = 'form_action'; protected logger; protected observables: { [s: string]: Subject } = {}; diff --git a/src/providers/utils/dom.ts b/src/providers/utils/dom.ts index 91e4b7ad1..748e73923 100644 --- a/src/providers/utils/dom.ts +++ b/src/providers/utils/dom.ts @@ -22,6 +22,7 @@ import { TranslateService } from '@ngx-translate/core'; import { CoreTextUtilsProvider } from './text'; import { CoreAppProvider } from '../app'; import { CoreConfigProvider } from '../config'; +import { CoreEventsProvider } from '../events'; import { CoreLoggerProvider } from '../logger'; import { CoreUrlUtilsProvider } from './url'; import { CoreFileProvider } from '@providers/file'; @@ -64,20 +65,21 @@ export class CoreDomUtilsProvider { protected displayedAlerts = {}; // To prevent duplicated alerts. protected logger; - constructor(private translate: TranslateService, - private loadingCtrl: LoadingController, - private toastCtrl: ToastController, - private alertCtrl: AlertController, - private textUtils: CoreTextUtilsProvider, - private appProvider: CoreAppProvider, - private platform: Platform, - private configProvider: CoreConfigProvider, - private urlUtils: CoreUrlUtilsProvider, - private modalCtrl: ModalController, - private sanitizer: DomSanitizer, - private popoverCtrl: PopoverController, - private fileProvider: CoreFileProvider, - loggerProvider: CoreLoggerProvider) { + constructor(protected translate: TranslateService, + protected loadingCtrl: LoadingController, + protected toastCtrl: ToastController, + protected alertCtrl: AlertController, + protected textUtils: CoreTextUtilsProvider, + protected appProvider: CoreAppProvider, + protected platform: Platform, + protected configProvider: CoreConfigProvider, + protected urlUtils: CoreUrlUtilsProvider, + protected modalCtrl: ModalController, + protected sanitizer: DomSanitizer, + protected popoverCtrl: PopoverController, + protected fileProvider: CoreFileProvider, + loggerProvider: CoreLoggerProvider, + protected eventsProvider: CoreEventsProvider) { this.logger = loggerProvider.getInstance('CoreDomUtilsProvider'); @@ -1625,4 +1627,32 @@ export class CoreDomUtilsProvider { // Now move the element into the wrapper. wrapper.appendChild(el); } + + /** + * Trigger form cancelled event. + * + * @param form Form element. + * @param siteId The site affected. If not provided, no site affected. + */ + triggerFormCancelledEvent(form: HTMLElement, siteId?: string): void { + this.eventsProvider.trigger(CoreEventsProvider.FORM_ACTION, { + action: 'cancel', + form: form, + }, siteId); + } + + /** + * Trigger form submitted event. + * + * @param form Form element. + * @param online Whether the action was done in offline or not. + * @param siteId The site affected. If not provided, no site affected. + */ + triggerFormSubmittedEvent(form: HTMLElement, online?: boolean, siteId?: string): void { + this.eventsProvider.trigger(CoreEventsProvider.FORM_ACTION, { + action: 'submit', + form: form, + online: !!online, + }, siteId); + } }