diff --git a/scripts/langindex.json b/scripts/langindex.json index 344e7460d..339c56c5a 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1482,6 +1482,8 @@ "core.downloaded": "local_moodlemobileapp", "core.downloading": "local_moodlemobileapp", "core.edit": "moodle", + "core.editor.autosavesucceeded": "editor_atto", + "core.editor.textrecovered": "editor_atto", "core.emptysplit": "local_moodlemobileapp", "core.error": "moodle", "core.errorchangecompletion": "local_moodlemobileapp", diff --git a/src/addon/calendar/pages/edit-event/edit-event.html b/src/addon/calendar/pages/edit-event/edit-event.html index 9eae210f8..49c0bb32f 100644 --- a/src/addon/calendar/pages/edit-event/edit-event.html +++ b/src/addon/calendar/pages/edit-event/edit-event.html @@ -9,7 +9,7 @@ -
+

{{ 'addon.calendar.eventname' | translate }}

@@ -86,7 +86,7 @@

{{ 'core.description' | translate }}

- +
diff --git a/src/addon/calendar/pages/edit-event/edit-event.module.ts b/src/addon/calendar/pages/edit-event/edit-event.module.ts index 32a1ac65a..5821de8a0 100644 --- a/src/addon/calendar/pages/edit-event/edit-event.module.ts +++ b/src/addon/calendar/pages/edit-event/edit-event.module.ts @@ -17,6 +17,7 @@ import { IonicPageModule } from 'ionic-angular'; import { TranslateModule } from '@ngx-translate/core'; import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; import { AddonCalendarEditEventPage } from './edit-event'; @NgModule({ @@ -26,6 +27,7 @@ import { AddonCalendarEditEventPage } from './edit-event'; imports: [ CoreComponentsModule, CoreDirectivesModule, + CoreEditorComponentsModule, IonicPageModule.forChild(AddonCalendarEditEventPage), TranslateModule.forChild() ], diff --git a/src/addon/calendar/pages/edit-event/edit-event.ts b/src/addon/calendar/pages/edit-event/edit-event.ts index 293d1fd62..fe80b521b 100644 --- a/src/addon/calendar/pages/edit-event/edit-event.ts +++ b/src/addon/calendar/pages/edit-event/edit-event.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, OnDestroy, Optional, ViewChild } from '@angular/core'; +import { Component, OnInit, OnDestroy, Optional, ViewChild, ElementRef } from '@angular/core'; import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms'; import { IonicPage, NavController, NavParams } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; @@ -25,7 +25,7 @@ import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCoursesProvider } from '@core/courses/providers/courses'; import { CoreSplitViewComponent } from '@components/split-view/split-view'; -import { CoreRichTextEditorComponent } from '@components/rich-text-editor/rich-text-editor.ts'; +import { CoreEditorRichTextEditorComponent } from '@core/editor/components/rich-text-editor/rich-text-editor.ts'; import { AddonCalendarProvider, AddonCalendarGetAccessInfoResult, AddonCalendarEvent } from '../../providers/calendar'; import { AddonCalendarOfflineProvider } from '../../providers/calendar-offline'; import { AddonCalendarHelperProvider } from '../../providers/helper'; @@ -43,7 +43,8 @@ import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; }) export class AddonCalendarEditEventPage implements OnInit, OnDestroy { - @ViewChild(CoreRichTextEditorComponent) descriptionEditor: CoreRichTextEditorComponent; + @ViewChild(CoreEditorRichTextEditorComponent) descriptionEditor: CoreEditorRichTextEditorComponent; + @ViewChild('editEventForm') formElement: ElementRef; title: string; dateFormat: string; @@ -496,6 +497,8 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy { this.calendarProvider.submitEvent(this.eventId, data).then((result) => { event = result.event; + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, result.sent, this.currentSite.getId()); + if (result.sent) { // Event created or edited, invalidate right days & months. const numberOfRepetitions = formData.repeat ? formData.repeats : @@ -557,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. @@ -572,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/feedback/comments/comments.module.ts b/src/addon/mod/assign/feedback/comments/comments.module.ts index 491a88fde..cb23c6983 100644 --- a/src/addon/mod/assign/feedback/comments/comments.module.ts +++ b/src/addon/mod/assign/feedback/comments/comments.module.ts @@ -21,6 +21,7 @@ import { AddonModAssignFeedbackCommentsComponent } from './component/comments'; import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegate'; import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -31,7 +32,8 @@ import { CoreDirectivesModule } from '@directives/directives.module'; IonicModule, TranslateModule.forChild(), CoreComponentsModule, - CoreDirectivesModule + CoreDirectivesModule, + CoreEditorComponentsModule, ], providers: [ AddonModAssignFeedbackCommentsHandler diff --git a/src/addon/mod/assign/feedback/comments/component/addon-mod-assign-feedback-comments.html b/src/addon/mod/assign/feedback/comments/component/addon-mod-assign-feedback-comments.html index 6a2fff370..75892386b 100644 --- a/src/addon/mod/assign/feedback/comments/component/addon-mod-assign-feedback-comments.html +++ b/src/addon/mod/assign/feedback/comments/component/addon-mod-assign-feedback-comments.html @@ -19,5 +19,6 @@ - + + diff --git a/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.html b/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.html index a51daa3fd..381d0ff43 100644 --- a/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.html +++ b/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.html @@ -9,7 +9,7 @@ - + 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 41c02baaf..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 @@ -12,9 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, Input } from '@angular/core'; +import { Component, Input, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, ViewController, NavParams } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; +import { CoreEventsProvider } from '@providers/events'; +import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegate'; import { @@ -36,10 +38,17 @@ export class AddonModAssignEditFeedbackModalPage { @Input() plugin: AddonModAssignPlugin; // The plugin object. @Input() userId: number; // The user ID of the submission. + @ViewChild('editFeedbackForm') formElement: ElementRef; + protected forceLeave = false; // To allow leaving the page without checking for changes. - constructor(params: NavParams, protected viewCtrl: ViewController, protected domUtils: CoreDomUtilsProvider, - protected translate: TranslateService, protected feedbackDelegate: AddonModAssignFeedbackDelegate) { + constructor(params: NavParams, + protected viewCtrl: ViewController, + protected domUtils: CoreDomUtilsProvider, + protected translate: TranslateService, + protected feedbackDelegate: AddonModAssignFeedbackDelegate, + protected eventsProvider: CoreEventsProvider, + protected sitesProvider: CoreSitesProvider) { this.assign = params.get('assign'); this.submission = params.get('submission'); @@ -52,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()); } /** @@ -82,6 +92,8 @@ export class AddonModAssignEditFeedbackModalPage { e.preventDefault(); e.stopPropagation(); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, this.sitesProvider.getCurrentSiteId()); + // Close the modal, sending the input data. this.forceLeave = true; this.closeModal(this.getInputData()); diff --git a/src/addon/mod/assign/pages/edit/edit.html b/src/addon/mod/assign/pages/edit/edit.html index c85acfcf9..f849d0390 100644 --- a/src/addon/mod/assign/pages/edit/edit.html +++ b/src/addon/mod/assign/pages/edit/edit.html @@ -13,7 +13,7 @@ -
+ diff --git a/src/addon/mod/assign/pages/edit/edit.ts b/src/addon/mod/assign/pages/edit/edit.ts index 7eccd3c20..4ec6fe6d2 100644 --- a/src/addon/mod/assign/pages/edit/edit.ts +++ b/src/addon/mod/assign/pages/edit/edit.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, OnDestroy } from '@angular/core'; +import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, NavController, NavParams } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; import { CoreEventsProvider } from '@providers/events'; @@ -34,6 +34,9 @@ import { AddonModAssignHelperProvider } from '../../providers/helper'; templateUrl: 'edit.html', }) export class AddonModAssignEditPage implements OnInit, OnDestroy { + + @ViewChild('editSubmissionForm') formElement: ElementRef; + title: string; // Title to display. assign: AddonModAssignAssign; // Assignment. courseId: number; // Course ID the assignment belongs to. @@ -82,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()); } /** @@ -265,69 +269,74 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy { * * @return Promise resolved when done. */ - protected saveSubmission(): Promise { + protected async saveSubmission(): Promise { const inputData = this.getInputData(); if (this.submissionStatement && (!inputData.submissionstatement || inputData.submissionstatement === 'false')) { - return Promise.reject(this.translate.instant('addon.mod_assign.acceptsubmissionstatement')); + throw this.translate.instant('addon.mod_assign.acceptsubmissionstatement'); } let modal = this.domUtils.showModalLoading(); + let size; // Get size to ask for confirmation. - return this.assignHelper.getSubmissionSizeForEdit(this.assign, this.userSubmission, inputData).catch(() => { + try { + size = await this.assignHelper.getSubmissionSizeForEdit(this.assign, this.userSubmission, inputData); + } catch (error) { // Error calculating size, return -1. - return -1; - }).then((size) => { - modal.dismiss(); + size = -1; + } + modal.dismiss(); + + try { // Confirm action. - return this.fileUploaderHelper.confirmUploadFile(size, true, this.allowOffline); - }).then(() => { + await this.fileUploaderHelper.confirmUploadFile(size, true, this.allowOffline); + modal = this.domUtils.showModalLoading('core.sending', true); - return this.prepareSubmissionData(inputData).then((pluginData) => { - if (!Object.keys(pluginData).length) { - // Nothing to save. - return; - } + const pluginData = await this.prepareSubmissionData(inputData); + if (!Object.keys(pluginData).length) { + // Nothing to save. + return; + } - let promise; + let sent: boolean; - if (this.saveOffline) { - // Save submission in offline. - promise = this.assignOfflineProvider.saveSubmission(this.assign.id, this.courseId, pluginData, - this.userSubmission.timemodified, !this.assign.submissiondrafts, this.userId); - } else { - // Try to send it to server. - promise = this.assignProvider.saveSubmission(this.assign.id, this.courseId, pluginData, this.allowOffline, - this.userSubmission.timemodified, !!this.assign.submissiondrafts, this.userId); - } + if (this.saveOffline) { + // Save submission in offline. + sent = false; + await this.assignOfflineProvider.saveSubmission(this.assign.id, this.courseId, pluginData, + this.userSubmission.timemodified, !this.assign.submissiondrafts, this.userId); + } else { + // Try to send it to server. + sent = await this.assignProvider.saveSubmission(this.assign.id, this.courseId, pluginData, this.allowOffline, + this.userSubmission.timemodified, !!this.assign.submissiondrafts, this.userId); + } - return promise.then(() => { - // Clear temporary data from plugins. - return this.assignHelper.clearSubmissionPluginTmpData(this.assign, this.userSubmission, inputData); - }).then(() => { - // Submission saved, trigger event. - const params = { - assignmentId: this.assign.id, - submissionId: this.userSubmission.id, - userId: this.userId, - }; + // Clear temporary data from plugins. + await this.assignHelper.clearSubmissionPluginTmpData(this.assign, this.userSubmission, inputData); - this.eventsProvider.trigger(AddonModAssignProvider.SUBMISSION_SAVED_EVENT, params, - this.sitesProvider.getCurrentSiteId()); + // Submission saved, trigger events. + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, sent, this.sitesProvider.getCurrentSiteId()); - if (!this.assign.submissiondrafts) { - // No drafts allowed, so it was submitted. Trigger event. - this.eventsProvider.trigger(AddonModAssignProvider.SUBMITTED_FOR_GRADING_EVENT, params, - this.sitesProvider.getCurrentSiteId()); - } - }); - }); - }).finally(() => { + const params = { + assignmentId: this.assign.id, + submissionId: this.userSubmission.id, + userId: this.userId, + }; + + this.eventsProvider.trigger(AddonModAssignProvider.SUBMISSION_SAVED_EVENT, params, + this.sitesProvider.getCurrentSiteId()); + + if (!this.assign.submissiondrafts) { + // No drafts allowed, so it was submitted. Trigger event. + this.eventsProvider.trigger(AddonModAssignProvider.SUBMITTED_FOR_GRADING_EVENT, params, + this.sitesProvider.getCurrentSiteId()); + } + } finally { modal.dismiss(); - }); + } } /** diff --git a/src/addon/mod/assign/submission/onlinetext/component/addon-mod-assign-submission-onlinetext.html b/src/addon/mod/assign/submission/onlinetext/component/addon-mod-assign-submission-onlinetext.html index a629ab325..a659af7a9 100644 --- a/src/addon/mod/assign/submission/onlinetext/component/addon-mod-assign-submission-onlinetext.html +++ b/src/addon/mod/assign/submission/onlinetext/component/addon-mod-assign-submission-onlinetext.html @@ -15,6 +15,6 @@

{{ 'core.numwords' | translate: {'$a': words + ' / ' + configs.wordlimit} }}

- + diff --git a/src/addon/mod/assign/submission/onlinetext/component/onlinetext.ts b/src/addon/mod/assign/submission/onlinetext/component/onlinetext.ts index 70ee9d183..a788de667 100644 --- a/src/addon/mod/assign/submission/onlinetext/component/onlinetext.ts +++ b/src/addon/mod/assign/submission/onlinetext/component/onlinetext.ts @@ -14,6 +14,7 @@ import { Component, OnInit, ElementRef } from '@angular/core'; import { FormBuilder, FormControl } from '@angular/forms'; +import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { AddonModAssignProvider } from '../../../providers/assign'; @@ -35,16 +36,23 @@ export class AddonModAssignSubmissionOnlineTextComponent extends AddonModAssignS text: string; loaded: boolean; wordLimitEnabled: boolean; + currentUserId: number; protected wordCountTimeout: any; protected element: HTMLElement; - constructor(protected fb: FormBuilder, protected domUtils: CoreDomUtilsProvider, protected textUtils: CoreTextUtilsProvider, - protected assignProvider: AddonModAssignProvider, protected assignOfflineProvider: AddonModAssignOfflineProvider, - element: ElementRef) { + constructor( + protected fb: FormBuilder, + protected domUtils: CoreDomUtilsProvider, + protected textUtils: CoreTextUtilsProvider, + protected assignProvider: AddonModAssignProvider, + protected assignOfflineProvider: AddonModAssignOfflineProvider, + element: ElementRef, + sitesProvider: CoreSitesProvider) { super(); this.element = element.nativeElement; + this.currentUserId = sitesProvider.getCurrentSiteUserId(); } /** diff --git a/src/addon/mod/assign/submission/onlinetext/onlinetext.module.ts b/src/addon/mod/assign/submission/onlinetext/onlinetext.module.ts index 88de4de1d..5ac1e16f8 100644 --- a/src/addon/mod/assign/submission/onlinetext/onlinetext.module.ts +++ b/src/addon/mod/assign/submission/onlinetext/onlinetext.module.ts @@ -21,6 +21,7 @@ import { AddonModAssignSubmissionOnlineTextComponent } from './component/onlinet import { AddonModAssignSubmissionDelegate } from '../../providers/submission-delegate'; import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -31,7 +32,8 @@ import { CoreDirectivesModule } from '@directives/directives.module'; IonicModule, TranslateModule.forChild(), CoreComponentsModule, - CoreDirectivesModule + CoreDirectivesModule, + CoreEditorComponentsModule, ], providers: [ AddonModAssignSubmissionOnlineTextHandler diff --git a/src/addon/mod/data/fields/field.module.ts b/src/addon/mod/data/fields/field.module.ts index 0e0467799..9a850d4f6 100644 --- a/src/addon/mod/data/fields/field.module.ts +++ b/src/addon/mod/data/fields/field.module.ts @@ -40,7 +40,7 @@ import { AddonModDataFieldUrlModule } from './url/url.module'; AddonModDataFieldRadiobuttonModule, AddonModDataFieldTextModule, AddonModDataFieldTextareaModule, - AddonModDataFieldUrlModule + AddonModDataFieldUrlModule, ], providers: [ ], diff --git a/src/addon/mod/data/fields/textarea/component/addon-mod-data-field-textarea.html b/src/addon/mod/data/fields/textarea/component/addon-mod-data-field-textarea.html index 02ce6f367..680b92f89 100644 --- a/src/addon/mod/data/fields/textarea/component/addon-mod-data-field-textarea.html +++ b/src/addon/mod/data/fields/textarea/component/addon-mod-data-field-textarea.html @@ -2,7 +2,7 @@ - + diff --git a/src/addon/mod/data/fields/textarea/component/textarea.ts b/src/addon/mod/data/fields/textarea/component/textarea.ts index ba54212d7..d0d03359a 100644 --- a/src/addon/mod/data/fields/textarea/component/textarea.ts +++ b/src/addon/mod/data/fields/textarea/component/textarea.ts @@ -49,10 +49,10 @@ export class AddonModDataFieldTextareaComponent extends AddonModDataFieldPluginC * Initialize field. */ protected init(): void { - if (this.isShowOrListMode()) { - this.component = AddonModDataProvider.COMPONENT; - this.componentId = this.database.coursemodule; + this.component = AddonModDataProvider.COMPONENT; + this.componentId = this.database.coursemodule; + if (this.isShowOrListMode()) { return; } diff --git a/src/addon/mod/data/fields/textarea/textarea.module.ts b/src/addon/mod/data/fields/textarea/textarea.module.ts index 3f7070ef7..ead1184b6 100644 --- a/src/addon/mod/data/fields/textarea/textarea.module.ts +++ b/src/addon/mod/data/fields/textarea/textarea.module.ts @@ -20,6 +20,7 @@ import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate'; import { AddonModDataFieldTextareaComponent } from './component/textarea'; import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -30,7 +31,8 @@ import { CoreDirectivesModule } from '@directives/directives.module'; IonicModule, TranslateModule.forChild(), CoreComponentsModule, - CoreDirectivesModule + CoreDirectivesModule, + CoreEditorComponentsModule, ], providers: [ AddonModDataFieldTextareaHandler diff --git a/src/addon/mod/data/pages/edit/edit.html b/src/addon/mod/data/pages/edit/edit.html index d5865e7e3..7b5418da5 100644 --- a/src/addon/mod/data/pages/edit/edit.html +++ b/src/addon/mod/data/pages/edit/edit.html @@ -21,7 +21,7 @@
- +
diff --git a/src/addon/mod/data/pages/edit/edit.ts b/src/addon/mod/data/pages/edit/edit.ts index 38a1bc2e8..20a58c60c 100644 --- a/src/addon/mod/data/pages/edit/edit.ts +++ b/src/addon/mod/data/pages/edit/edit.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, ViewChild } from '@angular/core'; +import { Component, ViewChild, ElementRef } from '@angular/core'; import { Content, IonicPage, NavParams, NavController } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; import { FormGroup } from '@angular/forms'; @@ -40,6 +40,7 @@ import { CoreTagProvider } from '@core/tag/providers/tag'; }) export class AddonModDataEditPage { @ViewChild(Content) content: Content; + @ViewChild('editFormEl') formElement: ElementRef; protected module: any; protected courseId: number; @@ -95,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); } /** @@ -216,6 +214,9 @@ 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.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, result.sent, this.siteId); + const promises = []; this.entryId = this.entryId || result.newentryid; diff --git a/src/addon/mod/data/pages/search/search.html b/src/addon/mod/data/pages/search/search.html index 000181e40..6dc36d529 100644 --- a/src/addon/mod/data/pages/search/search.html +++ b/src/addon/mod/data/pages/search/search.html @@ -13,7 +13,7 @@ {{ 'addon.mod_data.search' | translate}} {{ 'addon.mod_data.advancedsearch' | translate }} -
+ diff --git a/src/addon/mod/data/pages/search/search.ts b/src/addon/mod/data/pages/search/search.ts index 5aff12b6b..4d2263630 100644 --- a/src/addon/mod/data/pages/search/search.ts +++ b/src/addon/mod/data/pages/search/search.ts @@ -12,9 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component } from '@angular/core'; +import { Component, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, NavParams, ViewController } from 'ionic-angular'; import { FormBuilder, FormGroup } from '@angular/forms'; +import { CoreEventsProvider } from '@providers/events'; +import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider } from '@providers/utils/text'; @@ -32,6 +34,8 @@ import { CoreTagProvider } from '@core/tag/providers/tag'; templateUrl: 'search.html', }) export class AddonModDataSearchPage { + @ViewChild('searchFormEl') formElement: ElementRef; + search: any; fields: any; data: any; @@ -41,10 +45,17 @@ export class AddonModDataSearchPage { jsData: any; fieldsArray: any; - constructor(params: NavParams, private viewCtrl: ViewController, fb: FormBuilder, protected utils: CoreUtilsProvider, - protected domUtils: CoreDomUtilsProvider, protected fieldsDelegate: AddonModDataFieldsDelegate, - protected textUtils: CoreTextUtilsProvider, protected dataHelper: AddonModDataHelperProvider, - private tagProvider: CoreTagProvider) { + constructor(params: NavParams, + protected viewCtrl: ViewController, + fb: FormBuilder, + protected utils: CoreUtilsProvider, + protected domUtils: CoreDomUtilsProvider, + protected fieldsDelegate: AddonModDataFieldsDelegate, + protected textUtils: CoreTextUtilsProvider, + protected dataHelper: AddonModDataHelperProvider, + protected tagProvider: CoreTagProvider, + protected eventsProvider: CoreEventsProvider, + protected sitesProvider: CoreSitesProvider) { this.search = params.get('search'); this.fields = params.get('fields'); this.data = params.get('data'); @@ -175,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); } diff --git a/src/addon/mod/data/providers/data.ts b/src/addon/mod/data/providers/data.ts index 0e70b084c..481896b28 100644 --- a/src/addon/mod/data/providers/data.ts +++ b/src/addon/mod/data/providers/data.ts @@ -126,7 +126,8 @@ export class AddonModDataProvider { .then((entry) => { return { // Return provissional entry Id. - newentryid: entry + newentryid: entry, + sent: false, }; }); }; @@ -142,7 +143,11 @@ export class AddonModDataProvider { return storeOffline(); } - return this.addEntryOnline(dataId, contents, groupId, siteId).catch((error) => { + return this.addEntryOnline(dataId, contents, groupId, siteId).then((result) => { + result.sent = true; + + return result; + }).catch((error) => { if (this.utils.isWebServiceError(error)) { // The WebService has thrown an error, this means that responses cannot be submitted. return Promise.reject(error); @@ -194,7 +199,12 @@ export class AddonModDataProvider { const storeOffline = (): Promise => { const action = approve ? 'approve' : 'disapprove'; - return this.dataOffline.saveEntry(dataId, entryId, action, courseId, undefined, undefined, undefined, siteId); + return this.dataOffline.saveEntry(dataId, entryId, action, courseId, undefined, undefined, undefined, siteId) + .then(() => { + return { + sent: false, + }; + }); }; // Get if the opposite action is not synced. @@ -210,7 +220,11 @@ export class AddonModDataProvider { return storeOffline(); } - return this.approveEntryOnline(entryId, approve, siteId).catch((error) => { + return this.approveEntryOnline(entryId, approve, siteId).then(() => { + return { + sent: true, + }; + }).catch((error) => { if (this.utils.isWebServiceError(error)) { // The WebService has thrown an error, this means that responses cannot be submitted. return Promise.reject(error); @@ -288,7 +302,12 @@ export class AddonModDataProvider { // Convenience function to store a data to be synchronized later. const storeOffline = (): Promise => { - return this.dataOffline.saveEntry(dataId, entryId, 'delete', courseId, undefined, undefined, undefined, siteId); + return this.dataOffline.saveEntry(dataId, entryId, 'delete', courseId, undefined, undefined, undefined, siteId) + .then(() => { + return { + sent: false, + }; + }); }; let justAdded = false; @@ -318,7 +337,11 @@ export class AddonModDataProvider { return storeOffline(); } - return this.deleteEntryOnline(entryId, siteId).catch((error) => { + return this.deleteEntryOnline(entryId, siteId).then(() => { + return { + sent: true, + }; + }).catch((error) => { if (this.utils.isWebServiceError(error)) { // The WebService has thrown an error, this means that responses cannot be submitted. return Promise.reject(error); @@ -368,7 +391,8 @@ export class AddonModDataProvider { return this.dataOffline.saveEntry(dataId, entryId, 'edit', courseId, undefined, contents, undefined, siteId) .then(() => { return { - updated: true + updated: true, + sent: false, }; }); }; @@ -408,6 +432,7 @@ export class AddonModDataProvider { return this.addEntry(dataId, entryId, courseId, contents, groupId, fields, siteId, forceOffline) .then((result) => { result.updated = true; + result.sent = true; return result; }); @@ -418,7 +443,11 @@ export class AddonModDataProvider { return storeOffline(); } - return this.editEntryOnline(entryId, contents, siteId).catch((error) => { + return this.editEntryOnline(entryId, contents, siteId).then((result) => { + result.sent = true; + + return result; + }).catch((error) => { if (this.utils.isWebServiceError(error)) { // The WebService has thrown an error, this means that responses cannot be submitted. return Promise.reject(error); diff --git a/src/addon/mod/forum/components/components.module.ts b/src/addon/mod/forum/components/components.module.ts index 5a3180af3..e9cdcba14 100644 --- a/src/addon/mod/forum/components/components.module.ts +++ b/src/addon/mod/forum/components/components.module.ts @@ -26,6 +26,7 @@ import { AddonModForumIndexComponent } from './index/index'; import { AddonModForumPostComponent } from './post/post'; import { AddonForumDiscussionOptionsMenuComponent } from './discussion-options-menu/discussion-options-menu'; import { AddonForumPostOptionsMenuComponent } from './post-options-menu/post-options-menu'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -43,7 +44,8 @@ import { AddonForumPostOptionsMenuComponent } from './post-options-menu/post-opt CorePipesModule, CoreCourseComponentsModule, CoreRatingComponentsModule, - CoreTagComponentsModule + CoreTagComponentsModule, + CoreEditorComponentsModule, ], providers: [ ], diff --git a/src/addon/mod/forum/components/post/addon-mod-forum-post.html b/src/addon/mod/forum/components/post/addon-mod-forum-post.html index 02a3bbe42..cafe72514 100644 --- a/src/addon/mod/forum/components/post/addon-mod-forum-post.html +++ b/src/addon/mod/forum/components/post/addon-mod-forum-post.html @@ -64,7 +64,7 @@ {{ 'addon.mod_forum.message' | translate }} - + {{ 'addon.mod_forum.privatereply' | translate }} diff --git a/src/addon/mod/forum/pages/edit-post/addon-mod-forum-edit-post.html b/src/addon/mod/forum/pages/edit-post/addon-mod-forum-edit-post.html index 0a934fa27..3fd8d6e4a 100644 --- a/src/addon/mod/forum/pages/edit-post/addon-mod-forum-edit-post.html +++ b/src/addon/mod/forum/pages/edit-post/addon-mod-forum-edit-post.html @@ -16,7 +16,7 @@ {{ 'addon.mod_forum.message' | translate }} - + diff --git a/src/addon/mod/forum/pages/edit-post/edit-post.module.ts b/src/addon/mod/forum/pages/edit-post/edit-post.module.ts index 07f409742..89cf9ad4d 100644 --- a/src/addon/mod/forum/pages/edit-post/edit-post.module.ts +++ b/src/addon/mod/forum/pages/edit-post/edit-post.module.ts @@ -19,6 +19,7 @@ import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; import { AddonModForumComponentsModule } from '../../components/components.module'; import { AddonModForumEditPostPage } from './edit-post'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -28,6 +29,7 @@ import { AddonModForumEditPostPage } from './edit-post'; CoreComponentsModule, CoreDirectivesModule, AddonModForumComponentsModule, + CoreEditorComponentsModule, IonicPageModule.forChild(AddonModForumEditPostPage), TranslateModule.forChild() ], diff --git a/src/addon/mod/forum/pages/new-discussion/new-discussion.html b/src/addon/mod/forum/pages/new-discussion/new-discussion.html index 95bb6e5ce..6cfeb39f8 100644 --- a/src/addon/mod/forum/pages/new-discussion/new-discussion.html +++ b/src/addon/mod/forum/pages/new-discussion/new-discussion.html @@ -19,7 +19,7 @@ {{ 'addon.mod_forum.message' | translate }} - + diff --git a/src/addon/mod/forum/pages/new-discussion/new-discussion.module.ts b/src/addon/mod/forum/pages/new-discussion/new-discussion.module.ts index c0add2f4c..0bb9e4038 100644 --- a/src/addon/mod/forum/pages/new-discussion/new-discussion.module.ts +++ b/src/addon/mod/forum/pages/new-discussion/new-discussion.module.ts @@ -18,6 +18,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; import { AddonModForumNewDiscussionPage } from './new-discussion'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -26,6 +27,7 @@ import { AddonModForumNewDiscussionPage } from './new-discussion'; imports: [ CoreComponentsModule, CoreDirectivesModule, + CoreEditorComponentsModule, IonicPageModule.forChild(AddonModForumNewDiscussionPage), TranslateModule.forChild() ], diff --git a/src/addon/mod/forum/pages/new-discussion/new-discussion.ts b/src/addon/mod/forum/pages/new-discussion/new-discussion.ts index 091753865..68b44837b 100644 --- a/src/addon/mod/forum/pages/new-discussion/new-discussion.ts +++ b/src/addon/mod/forum/pages/new-discussion/new-discussion.ts @@ -25,7 +25,7 @@ import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader'; import { CoreSplitViewComponent } from '@components/split-view/split-view'; -import { CoreRichTextEditorComponent } from '@components/rich-text-editor/rich-text-editor.ts'; +import { CoreEditorRichTextEditorComponent } from '@core/editor/components/rich-text-editor/rich-text-editor.ts'; import { AddonModForumProvider } from '../../providers/forum'; import { AddonModForumOfflineProvider } from '../../providers/offline'; import { AddonModForumHelperProvider } from '../../providers/helper'; @@ -41,7 +41,7 @@ import { AddonModForumSyncProvider } from '../../providers/sync'; }) export class AddonModForumNewDiscussionPage implements OnDestroy { - @ViewChild(CoreRichTextEditorComponent) messageEditor: CoreRichTextEditorComponent; + @ViewChild(CoreEditorRichTextEditorComponent) messageEditor: CoreEditorRichTextEditorComponent; component = AddonModForumProvider.COMPONENT; messageControl = new FormControl(); diff --git a/src/addon/mod/glossary/pages/edit/edit.html b/src/addon/mod/glossary/pages/edit/edit.html index 3c3bfa0d7..0bf02b458 100644 --- a/src/addon/mod/glossary/pages/edit/edit.html +++ b/src/addon/mod/glossary/pages/edit/edit.html @@ -15,7 +15,7 @@ {{ 'addon.mod_glossary.definition' | translate }} - + {{ 'addon.mod_glossary.categories' | translate }} diff --git a/src/addon/mod/glossary/pages/edit/edit.module.ts b/src/addon/mod/glossary/pages/edit/edit.module.ts index 0f606e93e..926f32ad6 100644 --- a/src/addon/mod/glossary/pages/edit/edit.module.ts +++ b/src/addon/mod/glossary/pages/edit/edit.module.ts @@ -18,6 +18,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; import { AddonModGlossaryEditPage } from './edit'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -26,6 +27,7 @@ import { AddonModGlossaryEditPage } from './edit'; imports: [ CoreComponentsModule, CoreDirectivesModule, + CoreEditorComponentsModule, IonicPageModule.forChild(AddonModGlossaryEditPage), TranslateModule.forChild() ], diff --git a/src/addon/mod/glossary/pages/edit/edit.ts b/src/addon/mod/glossary/pages/edit/edit.ts index 7bb9e60eb..9cf8b4355 100644 --- a/src/addon/mod/glossary/pages/edit/edit.ts +++ b/src/addon/mod/glossary/pages/edit/edit.ts @@ -51,6 +51,7 @@ export class AddonModGlossaryEditPage implements OnInit { attachments = []; definitionControl = new FormControl(); categories = []; + editorExtraParams: {[name: string]: any} = {}; protected courseId: number; protected module: any; @@ -113,6 +114,10 @@ export class AddonModGlossaryEditPage implements OnInit { this.originalData.files = files.slice(); }); } + + if (entry.id) { + this.editorExtraParams.id = entry.id; + } } this.definitionControl.setValue(this.entry.definition); diff --git a/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html b/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html index 440d7f383..f7ac672e0 100644 --- a/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html +++ b/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html @@ -34,7 +34,7 @@ - + {{ 'addon.mod_lesson.enterpassword' | translate }} diff --git a/src/addon/mod/lesson/components/index/index.ts b/src/addon/mod/lesson/components/index/index.ts index 17dec12ee..23ad87ae6 100644 --- a/src/addon/mod/lesson/components/index/index.ts +++ b/src/addon/mod/lesson/components/index/index.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, Optional, Injector, Input, ViewChild } from '@angular/core'; +import { Component, Optional, Injector, Input, ViewChild, ElementRef } from '@angular/core'; import { Content, NavController } from 'ionic-angular'; import { CoreGroupsProvider, CoreGroupInfo } from '@providers/groups'; import { CoreTimeUtilsProvider } from '@providers/utils/time'; @@ -35,6 +35,7 @@ import { CoreTabsComponent } from '@components/tabs/tabs'; }) export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityComponent { @ViewChild(CoreTabsComponent) tabsComponent: CoreTabsComponent; + @ViewChild('passwordForm') formElement: ElementRef; @Input() group: number; // The group to display. @Input() action: string; // The "action" to display first. @@ -584,6 +585,8 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo this.loaded = true; this.refreshIcon = 'refresh'; this.syncIcon = 'sync'; + + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true, this.siteId); }); } diff --git a/src/addon/mod/lesson/pages/password-modal/password-modal.html b/src/addon/mod/lesson/pages/password-modal/password-modal.html index b673d540c..3c35a3dcc 100644 --- a/src/addon/mod/lesson/pages/password-modal/password-modal.html +++ b/src/addon/mod/lesson/pages/password-modal/password-modal.html @@ -9,7 +9,7 @@ - + {{ 'addon.mod_lesson.enterpassword' | translate }} 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 13fbfcdb1..2446bb266 100644 --- a/src/addon/mod/lesson/pages/password-modal/password-modal.ts +++ b/src/addon/mod/lesson/pages/password-modal/password-modal.ts @@ -12,8 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component } from '@angular/core'; +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. @@ -24,8 +27,12 @@ import { IonicPage, ViewController } from 'ionic-angular'; templateUrl: 'password-modal.html', }) export class AddonModLessonPasswordModalPage { + @ViewChild('passwordForm') formElement: ElementRef; - constructor(protected viewCtrl: ViewController) { } + constructor(protected viewCtrl: ViewController, + protected eventsProvider: CoreEventsProvider, + protected sitesProvider: CoreSitesProvider, + protected domUtils: CoreDomUtilsProvider) { } /** * Send the password back. @@ -37,6 +44,8 @@ export class AddonModLessonPasswordModalPage { e.preventDefault(); e.stopPropagation(); + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, this.sitesProvider.getCurrentSiteId()); + this.viewCtrl.dismiss(password.value); } @@ -44,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.html b/src/addon/mod/lesson/pages/player/player.html index 13c7e7f0b..dfe4c3e86 100644 --- a/src/addon/mod/lesson/pages/player/player.html +++ b/src/addon/mod/lesson/pages/player/player.html @@ -38,7 +38,7 @@ - + @@ -57,7 +57,7 @@ - +

{{ 'addon.mod_lesson.youranswer' | translate }}

diff --git a/src/addon/mod/lesson/pages/player/player.module.ts b/src/addon/mod/lesson/pages/player/player.module.ts index 361ae19ab..c6dd35097 100644 --- a/src/addon/mod/lesson/pages/player/player.module.ts +++ b/src/addon/mod/lesson/pages/player/player.module.ts @@ -18,6 +18,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; import { AddonModLessonPlayerPage } from './player'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -26,6 +27,7 @@ import { AddonModLessonPlayerPage } from './player'; imports: [ CoreComponentsModule, CoreDirectivesModule, + CoreEditorComponentsModule, IonicPageModule.forChild(AddonModLessonPlayerPage), TranslateModule.forChild() ], diff --git a/src/addon/mod/lesson/pages/player/player.ts b/src/addon/mod/lesson/pages/player/player.ts index c29ad99b5..44d2a87ca 100644 --- a/src/addon/mod/lesson/pages/player/player.ts +++ b/src/addon/mod/lesson/pages/player/player.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core'; +import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef, ElementRef } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { IonicPage, NavParams, Content, PopoverController, ModalController, Modal, NavController } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; @@ -41,6 +41,7 @@ import { AddonModLessonHelperProvider } from '../../providers/helper'; }) export class AddonModLessonPlayerPage implements OnInit, OnDestroy { @ViewChild(Content) content: Content; + @ViewChild('questionFormEl') formElement: ElementRef; component = AddonModLessonProvider.COMPONENT; LESSON_EOL = AddonModLessonProvider.LESSON_EOL; @@ -136,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()); } /** @@ -540,15 +541,21 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy { * Process a page, sending some data. * * @param data The data to send. + * @param formSubmitted Whether a form was submitted. * @return Promise resolved when done. */ - protected processPage(data: any): Promise { + protected processPage(data: any, formSubmitted?: boolean): Promise { this.loaded = false; const args = [this.lesson, this.courseId, this.pageData, data, this.password, this.review, this.offline, this.accessInfo, this.jumps]; return this.callFunction(this.lessonProvider.processPage.bind(this.lessonProvider), args, 6, 8).then((result) => { + if (formSubmitted) { + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, result.sent, + this.sitesProvider.getCurrentSiteId()); + } + if (!this.offline && !this.review && this.lessonProvider.isLessonOffline(this.lesson)) { // Lesson allows offline and the user changed some data in server. Update cached data. const retake = this.accessInfo.attemptscount; @@ -637,7 +644,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy { // Use getRawValue to include disabled values. const data = this.lessonHelper.prepareQuestionData(this.question, this.questionForm.getRawValue()); - this.processPage(data).finally(() => { + this.processPage(data, true).finally(() => { this.loaded = true; }); } diff --git a/src/addon/mod/lesson/providers/lesson.ts b/src/addon/mod/lesson/providers/lesson.ts index b7fabe1f1..a4db30c6f 100644 --- a/src/addon/mod/lesson/providers/lesson.ts +++ b/src/addon/mod/lesson/providers/lesson.ts @@ -3089,6 +3089,7 @@ export class AddonModLessonProvider { result.warnings = []; result.displaymenu = pageData.displaymenu; // Keep the same value since we can't calculate it in offline. result.messages = this.getPageProcessMessages(lesson, accessInfo, result, review, jumps); + result.sent = false; Object.assign(result, calculatedData); return result; @@ -3104,6 +3105,8 @@ export class AddonModLessonProvider { review: review }, this.sitesProvider.getCurrentSiteId()); + response.sent = true; + return response; }); } diff --git a/src/addon/mod/quiz/pages/player/player.html b/src/addon/mod/quiz/pages/player/player.html index e632829c1..81d271d7d 100644 --- a/src/addon/mod/quiz/pages/player/player.html +++ b/src/addon/mod/quiz/pages/player/player.html @@ -45,7 +45,7 @@ - +
diff --git a/src/addon/mod/quiz/pages/player/player.ts b/src/addon/mod/quiz/pages/player/player.ts index 81f7989d5..92d9a04ac 100644 --- a/src/addon/mod/quiz/pages/player/player.ts +++ b/src/addon/mod/quiz/pages/player/player.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef, ViewChildren, QueryList } from '@angular/core'; +import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef, ViewChildren, QueryList, ElementRef } from '@angular/core'; import { IonicPage, NavParams, Content, PopoverController, ModalController, Modal, NavController } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; import { CoreEventsProvider } from '@providers/events'; @@ -41,6 +41,7 @@ import { Subscription } from 'rxjs'; export class AddonModQuizPlayerPage implements OnInit, OnDestroy { @ViewChild(Content) content: Content; @ViewChildren(CoreQuestionComponent) questionComponents: QueryList; + @ViewChild('quizForm') formElement: ElementRef; quiz: any; // The quiz the attempt belongs to. attempt: any; // The attempt being attempted. @@ -136,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(); + } + } } /** @@ -585,6 +588,9 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy { // Answers saved, cancel auto save. this.autoSave.cancelAutoSave(); this.autoSave.hideAutoSaveError(); + + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, !this.offline, + this.sitesProvider.getCurrentSiteId()); }); } diff --git a/src/addon/mod/quiz/pages/preflight-modal/preflight-modal.html b/src/addon/mod/quiz/pages/preflight-modal/preflight-modal.html index c00c08277..69d32d7ab 100644 --- a/src/addon/mod/quiz/pages/preflight-modal/preflight-modal.html +++ b/src/addon/mod/quiz/pages/preflight-modal/preflight-modal.html @@ -10,7 +10,7 @@ - + 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 590d03137..fa149c30f 100644 --- a/src/addon/mod/quiz/pages/preflight-modal/preflight-modal.ts +++ b/src/addon/mod/quiz/pages/preflight-modal/preflight-modal.ts @@ -12,10 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, Injector, ViewChild } from '@angular/core'; +import { Component, OnInit, Injector, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, ViewController, NavParams, Content } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; import { FormBuilder, FormGroup } from '@angular/forms'; +import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate'; @@ -31,6 +32,7 @@ import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-del export class AddonModQuizPreflightModalPage implements OnInit { @ViewChild(Content) content: Content; + @ViewChild('preflightFormEl') formElement: ElementRef; preflightForm: FormGroup; title: string; @@ -43,9 +45,15 @@ export class AddonModQuizPreflightModalPage implements OnInit { protected siteId: string; protected rules: string[]; - constructor(params: NavParams, fb: FormBuilder, translate: TranslateService, sitesProvider: CoreSitesProvider, - protected viewCtrl: ViewController, protected accessRuleDelegate: AddonModQuizAccessRuleDelegate, - protected injector: Injector, protected domUtils: CoreDomUtilsProvider) { + constructor(params: NavParams, + fb: FormBuilder, + translate: TranslateService, + sitesProvider: CoreSitesProvider, + protected viewCtrl: ViewController, + protected accessRuleDelegate: AddonModQuizAccessRuleDelegate, + protected injector: Injector, + protected domUtils: CoreDomUtilsProvider, + protected eventsProvider: CoreEventsProvider) { this.title = params.get('title') || translate.instant('addon.mod_quiz.startattempt'); this.quiz = params.get('quiz'); @@ -112,6 +120,8 @@ export class AddonModQuizPreflightModalPage implements OnInit { this.domUtils.showErrorModal('core.errorinvalidform', true); } } else { + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, this.siteId); + this.viewCtrl.dismiss(this.preflightForm.value); } } @@ -120,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.html b/src/addon/mod/wiki/pages/edit/edit.html index c9f61f896..aa2491c90 100644 --- a/src/addon/mod/wiki/pages/edit/edit.html +++ b/src/addon/mod/wiki/pages/edit/edit.html @@ -11,13 +11,13 @@ - + - + diff --git a/src/addon/mod/wiki/pages/edit/edit.module.ts b/src/addon/mod/wiki/pages/edit/edit.module.ts index 20b25f6bc..ecf4b0fa4 100644 --- a/src/addon/mod/wiki/pages/edit/edit.module.ts +++ b/src/addon/mod/wiki/pages/edit/edit.module.ts @@ -18,6 +18,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; import { AddonModWikiEditPage } from './edit'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -26,6 +27,7 @@ import { AddonModWikiEditPage } from './edit'; imports: [ CoreComponentsModule, CoreDirectivesModule, + CoreEditorComponentsModule, IonicPageModule.forChild(AddonModWikiEditPage), TranslateModule.forChild() ], diff --git a/src/addon/mod/wiki/pages/edit/edit.ts b/src/addon/mod/wiki/pages/edit/edit.ts index 160bfeeb2..7cd65dccb 100644 --- a/src/addon/mod/wiki/pages/edit/edit.ts +++ b/src/addon/mod/wiki/pages/edit/edit.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, OnDestroy } from '@angular/core'; +import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, NavController, NavParams } from 'ionic-angular'; import { FormControl, FormGroup, FormBuilder } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; @@ -37,6 +37,8 @@ import { AddonModWikiSyncProvider, AddonModWikiSyncSubwikiResult } from '../../p }) export class AddonModWikiEditPage implements OnInit, OnDestroy { + @ViewChild('editPageForm') formElement: ElementRef; + title: string; // Title to display. pageForm: FormGroup; // The form group. contentControl: FormControl; // The FormControl for the page content. @@ -45,6 +47,7 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy { component = AddonModWikiProvider.COMPONENT; // Component to link the files to. componentId: number; // Component ID to link the files to. wrongVersionLock: boolean; // Whether the page lock doesn't match the initial one. + editorExtraParams: {[name: string]: any} = {}; protected module: any; // Wiki module instance. protected courseId: number; // Course the wiki belongs to. @@ -101,6 +104,20 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy { // Block the wiki so it cannot be synced. this.syncProvider.blockOperation(this.component, this.blockId); + + if (!this.module.id) { + this.editorExtraParams.type = 'wiki'; + } + + if (this.pageId) { + this.editorExtraParams.pageid = this.pageId; + + if (this.section) { + this.editorExtraParams.section = this.section; + } + } else if (pageTitle) { + this.editorExtraParams.pagetitle = pageTitle; + } } /** @@ -329,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()); } /** @@ -408,6 +425,10 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy { if (this.editing) { // Edit existing page. promise = this.wikiProvider.editPage(this.pageId, text, this.section).then(() => { + + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true, + this.sitesProvider.getCurrentSiteId()); + // Invalidate page since it changed. return this.wikiProvider.invalidatePage(this.pageId).then(() => { return this.gotoPage(title); @@ -441,6 +462,10 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy { let wikiId = this.wikiId || (this.module && this.module.instance); return this.wikiProvider.newPage(title, text, this.subwikiId, wikiId, this.userId, this.groupId).then((id) => { + + 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. this.pageId = id; diff --git a/src/addon/mod/workshop/components/assessment-strategy/addon-mod-workshop-assessment-strategy.html b/src/addon/mod/workshop/components/assessment-strategy/addon-mod-workshop-assessment-strategy.html index 7f3b2bba7..c3bb1fd41 100644 --- a/src/addon/mod/workshop/components/assessment-strategy/addon-mod-workshop-assessment-strategy.html +++ b/src/addon/mod/workshop/components/assessment-strategy/addon-mod-workshop-assessment-strategy.html @@ -1,6 +1,6 @@

{{ 'addon.mod_workshop.assessmentform' | translate }}

- + @@ -16,7 +16,7 @@
{{ 'addon.mod_workshop.feedbackauthor' | translate }} - + { - // Don't return anything. + return false; }); } @@ -301,6 +303,9 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit { return this.workshopProvider.updateAssessment(this.workshop.id, this.assessmentId, this.workshop.course, assessmentData, false, allowOffline); }).then((grade) => { + + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, !!grade, this.sitesProvider.getCurrentSiteId()); + const promises = []; // If sent to the server, invalidate and clean. diff --git a/src/addon/mod/workshop/components/components.module.ts b/src/addon/mod/workshop/components/components.module.ts index 775490396..279484ef6 100644 --- a/src/addon/mod/workshop/components/components.module.ts +++ b/src/addon/mod/workshop/components/components.module.ts @@ -24,6 +24,7 @@ import { AddonModWorkshopIndexComponent } from './index/index'; import { AddonModWorkshopSubmissionComponent } from './submission/submission'; import { AddonModWorkshopAssessmentComponent } from './assessment/assessment'; import { AddonModWorkshopAssessmentStrategyComponent } from './assessment-strategy/assessment-strategy'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -39,7 +40,8 @@ import { AddonModWorkshopAssessmentStrategyComponent } from './assessment-strate CoreComponentsModule, CoreDirectivesModule, CorePipesModule, - CoreCourseComponentsModule + CoreCourseComponentsModule, + CoreEditorComponentsModule, ], providers: [ ], diff --git a/src/addon/mod/workshop/pages/assessment/assessment.html b/src/addon/mod/workshop/pages/assessment/assessment.html index 76229b26a..cfb72fa00 100644 --- a/src/addon/mod/workshop/pages/assessment/assessment.html +++ b/src/addon/mod/workshop/pages/assessment/assessment.html @@ -38,7 +38,7 @@ - +

{{ 'addon.mod_workshop.assessmentsettings' | translate }}

@@ -60,7 +60,7 @@ {{ 'addon.mod_workshop.feedbackreviewer' | translate }} - + diff --git a/src/addon/mod/workshop/pages/assessment/assessment.module.ts b/src/addon/mod/workshop/pages/assessment/assessment.module.ts index 21415631e..8a2314b34 100644 --- a/src/addon/mod/workshop/pages/assessment/assessment.module.ts +++ b/src/addon/mod/workshop/pages/assessment/assessment.module.ts @@ -19,6 +19,7 @@ import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; import { AddonModWorkshopComponentsModule } from '../../components/components.module'; import { AddonModWorkshopAssessmentPage } from './assessment'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -28,6 +29,7 @@ import { AddonModWorkshopAssessmentPage } from './assessment'; CoreDirectivesModule, CoreComponentsModule, AddonModWorkshopComponentsModule, + CoreEditorComponentsModule, IonicPageModule.forChild(AddonModWorkshopAssessmentPage), TranslateModule.forChild() ], diff --git a/src/addon/mod/workshop/pages/assessment/assessment.ts b/src/addon/mod/workshop/pages/assessment/assessment.ts index 1fe9fe5aa..09be157c7 100644 --- a/src/addon/mod/workshop/pages/assessment/assessment.ts +++ b/src/addon/mod/workshop/pages/assessment/assessment.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, OnDestroy } from '@angular/core'; +import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, NavParams, NavController } from 'ionic-angular'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; @@ -39,6 +39,8 @@ import { AddonModWorkshopSyncProvider } from '../../providers/sync'; }) export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { + @ViewChild('evaluateFormEl') formElement: ElementRef; + assessment: any; submission: any; profile: any; @@ -118,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); } /** @@ -340,7 +344,10 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { // Try to send it to server. return this.workshopProvider.evaluateAssessment(this.workshopId, this.assessmentId, this.courseId, inputData.text, - inputData.weight, inputData.grade).then(() => { + inputData.weight, inputData.grade).then((result) => { + + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, !!result, this.siteId); + const data = { workshopId: this.workshopId, assessmentId: this.assessmentId, diff --git a/src/addon/mod/workshop/pages/edit-submission/edit-submission.html b/src/addon/mod/workshop/pages/edit-submission/edit-submission.html index 71b1e535d..99e4d0bf3 100644 --- a/src/addon/mod/workshop/pages/edit-submission/edit-submission.html +++ b/src/addon/mod/workshop/pages/edit-submission/edit-submission.html @@ -10,7 +10,7 @@ -
+ {{ 'addon.mod_workshop.submissiontitle' | translate }} @@ -18,7 +18,7 @@ {{ 'addon.mod_workshop.submissioncontent' | translate }} - + diff --git a/src/addon/mod/workshop/pages/edit-submission/edit-submission.module.ts b/src/addon/mod/workshop/pages/edit-submission/edit-submission.module.ts index 25e5e4073..d3b216c60 100644 --- a/src/addon/mod/workshop/pages/edit-submission/edit-submission.module.ts +++ b/src/addon/mod/workshop/pages/edit-submission/edit-submission.module.ts @@ -18,6 +18,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; import { AddonModWorkshopEditSubmissionPage } from './edit-submission'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -26,6 +27,7 @@ import { AddonModWorkshopEditSubmissionPage } from './edit-submission'; imports: [ CoreDirectivesModule, CoreComponentsModule, + CoreEditorComponentsModule, IonicPageModule.forChild(AddonModWorkshopEditSubmissionPage), TranslateModule.forChild() ], 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 816a29b46..0911dc7d0 100644 --- a/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts +++ b/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, OnDestroy } from '@angular/core'; +import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, NavParams, NavController } from 'ionic-angular'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; @@ -37,6 +37,8 @@ import { AddonModWorkshopOfflineProvider } from '../../providers/offline'; }) export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { + @ViewChild('editFormEl') formElement: ElementRef; + module: any; courseId: number; access: any; @@ -51,6 +53,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { component = AddonModWorkshopProvider.COMPONENT; componentId: number; editForm: FormGroup; // The form group. + editorExtraParams: {[name: string]: any} = {}; protected workshopId: number; protected submissionId: number; @@ -86,6 +89,10 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { this.editForm = new FormGroup({}); this.editForm.addControl('title', this.fb.control('', Validators.required)); this.editForm.addControl('content', this.fb.control('')); + + if (this.submissionId) { + this.editorExtraParams.id = this.submissionId; + } } /** @@ -105,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); } /** @@ -347,7 +350,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { // Save submission in offline. return this.workshopOffline.saveSubmission(this.workshopId, this.courseId, inputData.title, inputData.content, attachmentsId, submissionId, 'update').then(() => { - // Don't return anything. + return false; }); } @@ -360,8 +363,8 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { if (saveOffline) { // Save submission in offline. return this.workshopOffline.saveSubmission(this.workshopId, this.courseId, inputData.title, inputData.content, - attachmentsId, submissionId, 'add').then(() => { - // Don't return anything. + attachmentsId, submissionId, 'add').then(() => { + return false; }); } @@ -370,6 +373,9 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { return this.workshopProvider.addSubmission(this.workshopId, this.courseId, inputData.title, inputData.content, attachmentsId, undefined, submissionId, allowOffline); }).then((newSubmissionId) => { + + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, !!newSubmissionId, this.siteId); + const data = { workshopId: this.workshopId, cmId: this.module.cmid diff --git a/src/addon/mod/workshop/pages/submission/submission.html b/src/addon/mod/workshop/pages/submission/submission.html index 41fbecd1d..5bff46089 100644 --- a/src/addon/mod/workshop/pages/submission/submission.html +++ b/src/addon/mod/workshop/pages/submission/submission.html @@ -65,7 +65,7 @@ - +

{{ 'addon.mod_workshop.feedbackauthor' | translate }}

@@ -87,7 +87,7 @@
{{ 'addon.mod_workshop.feedbackauthor' | translate }} - +
diff --git a/src/addon/mod/workshop/pages/submission/submission.module.ts b/src/addon/mod/workshop/pages/submission/submission.module.ts index b393b059b..6484fdc06 100644 --- a/src/addon/mod/workshop/pages/submission/submission.module.ts +++ b/src/addon/mod/workshop/pages/submission/submission.module.ts @@ -19,6 +19,7 @@ import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; import { AddonModWorkshopComponentsModule } from '../../components/components.module'; import { AddonModWorkshopSubmissionPage } from './submission'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -28,6 +29,7 @@ import { AddonModWorkshopSubmissionPage } from './submission'; CoreDirectivesModule, CoreComponentsModule, AddonModWorkshopComponentsModule, + CoreEditorComponentsModule, IonicPageModule.forChild(AddonModWorkshopSubmissionPage), TranslateModule.forChild() ], diff --git a/src/addon/mod/workshop/pages/submission/submission.ts b/src/addon/mod/workshop/pages/submission/submission.ts index 3fb884e5f..947aec803 100644 --- a/src/addon/mod/workshop/pages/submission/submission.ts +++ b/src/addon/mod/workshop/pages/submission/submission.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, OnDestroy, Optional, ViewChild } from '@angular/core'; +import { Component, OnInit, OnDestroy, Optional, ViewChild, ElementRef } from '@angular/core'; import { Content, IonicPage, NavParams, NavController } from 'ionic-angular'; import { FormGroup, FormBuilder } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; @@ -41,6 +41,7 @@ import { AddonModWorkshopSyncProvider } from '../../providers/sync'; export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { @ViewChild(AddonModWorkshopAssessmentStrategyComponent) assessmentStrategy: AddonModWorkshopAssessmentStrategyComponent; + @ViewChild('feedbackFormEl') formElement: ElementRef; module: any; workshop: any; @@ -143,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); } /** @@ -444,7 +447,10 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { // Try to send it to server. return this.workshopProvider.evaluateSubmission(this.workshopId, this.submissionId, this.courseId, inputData.text, - inputData.published, inputData.grade).then(() => { + inputData.published, inputData.grade).then((result) => { + + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, !!result, this.siteId); + const data = { workshopId: this.workshopId, cmId: this.module.cmid, diff --git a/src/addon/notes/pages/add/add.html b/src/addon/notes/pages/add/add.html index b6df1d660..93f2a04a4 100644 --- a/src/addon/notes/pages/add/add.html +++ b/src/addon/notes/pages/add/add.html @@ -9,7 +9,7 @@ -
+ {{ 'addon.notes.publishstate' | translate }} diff --git a/src/addon/notes/pages/add/add.ts b/src/addon/notes/pages/add/add.ts index 15fd9da0a..64459dd0a 100644 --- a/src/addon/notes/pages/add/add.ts +++ b/src/addon/notes/pages/add/add.ts @@ -12,9 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component } from '@angular/core'; +import { Component, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, ViewController, NavParams } from 'ionic-angular'; import { CoreAppProvider } from '@providers/app'; +import { CoreEventsProvider } from '@providers/events'; +import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { AddonNotesProvider } from '../../providers/notes'; @@ -27,14 +29,22 @@ import { AddonNotesProvider } from '../../providers/notes'; templateUrl: 'add.html', }) export class AddonNotesAddPage { + + @ViewChild('itemEdit') formElement: ElementRef; + userId: number; courseId: number; type = 'personal'; text = ''; processing = false; - constructor(params: NavParams, private viewCtrl: ViewController, private appProvider: CoreAppProvider, - private domUtils: CoreDomUtilsProvider, private notesProvider: AddonNotesProvider) { + constructor(params: NavParams, + protected viewCtrl: ViewController, + protected appProvider: CoreAppProvider, + protected domUtils: CoreDomUtilsProvider, + protected notesProvider: AddonNotesProvider, + protected eventsProvider: CoreEventsProvider, + protected sitesProvider: CoreSitesProvider) { this.userId = params.get('userId'); this.courseId = params.get('courseId'); this.type = params.get('type') || 'personal'; @@ -54,6 +64,9 @@ export class AddonNotesAddPage { // Freeze the add note button. this.processing = true; this.notesProvider.addNote(this.userId, this.courseId, this.type, this.text).then((sent) => { + + 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); }); @@ -69,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/addon/qtype/essay/component/addon-qtype-essay.html b/src/addon/qtype/essay/component/addon-qtype-essay.html index 5c171fedc..13462423b 100644 --- a/src/addon/qtype/essay/component/addon-qtype-essay.html +++ b/src/addon/qtype/essay/component/addon-qtype-essay.html @@ -11,7 +11,7 @@ - + diff --git a/src/addon/qtype/essay/essay.module.ts b/src/addon/qtype/essay/essay.module.ts index da95a1363..d259137cc 100644 --- a/src/addon/qtype/essay/essay.module.ts +++ b/src/addon/qtype/essay/essay.module.ts @@ -20,6 +20,7 @@ import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; import { AddonQtypeEssayHandler } from './providers/handler'; import { AddonQtypeEssayComponent } from './component/essay'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -29,7 +30,8 @@ import { AddonQtypeEssayComponent } from './component/essay'; IonicModule, TranslateModule.forChild(), CoreComponentsModule, - CoreDirectivesModule + CoreDirectivesModule, + CoreEditorComponentsModule, ], providers: [ AddonQtypeEssayHandler diff --git a/src/addon/userprofilefield/textarea/component/addon-user-profile-field-textarea.html b/src/addon/userprofilefield/textarea/component/addon-user-profile-field-textarea.html index 1d149a8ed..8908db521 100644 --- a/src/addon/userprofilefield/textarea/component/addon-user-profile-field-textarea.html +++ b/src/addon/userprofilefield/textarea/component/addon-user-profile-field-textarea.html @@ -9,5 +9,5 @@ {{ field.name }} - + \ No newline at end of file diff --git a/src/addon/userprofilefield/textarea/textarea.module.ts b/src/addon/userprofilefield/textarea/textarea.module.ts index f64fc285d..68ad0e678 100644 --- a/src/addon/userprofilefield/textarea/textarea.module.ts +++ b/src/addon/userprofilefield/textarea/textarea.module.ts @@ -20,6 +20,7 @@ import { CoreUserProfileFieldDelegate } from '@core/user/providers/user-profile- import { AddonUserProfileFieldTextareaComponent } from './component/textarea'; import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; @NgModule({ declarations: [ @@ -29,7 +30,8 @@ import { CoreDirectivesModule } from '@directives/directives.module'; IonicModule, TranslateModule.forChild(), CoreComponentsModule, - CoreDirectivesModule + CoreDirectivesModule, + CoreEditorComponentsModule, ], providers: [ AddonUserProfileFieldTextareaHandler diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 38fff7b5d..81fdb84a7 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -87,6 +87,7 @@ import { CoreTagModule } from '@core/tag/tag.module'; import { CoreFilterModule } from '@core/filter/filter.module'; import { CoreH5PModule } from '@core/h5p/h5p.module'; import { CoreSearchModule } from '@core/search/search.module'; +import { CoreEditorModule } from '@core/editor/editor.module'; // Addon modules. import { AddonBadgesModule } from '@addon/badges/badges.module'; @@ -235,6 +236,7 @@ export const WP_PROVIDER: any = null; CoreFilterModule, CoreH5PModule, CoreSearchModule, + CoreEditorModule, AddonBadgesModule, AddonBlogModule, AddonCalendarModule, diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index e9673f525..d3f4ff056 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1482,6 +1482,8 @@ "core.downloaded": "Downloaded", "core.downloading": "Downloading", "core.edit": "Edit", + "core.editor.autosavesucceeded": "Draft saved.", + "core.editor.textrecovered": "A draft version of this text was automatically restored.", "core.emptysplit": "This page will appear blank if the left panel is empty or is loading.", "core.error": "Error", "core.errorchangecompletion": "An error occurred while changing the completion status. Please try again.", diff --git a/src/components/components.module.ts b/src/components/components.module.ts index bdd2f6d4c..e48f29dd6 100644 --- a/src/components/components.module.ts +++ b/src/components/components.module.ts @@ -39,7 +39,6 @@ import { CoreLocalFileComponent } from './local-file/local-file'; import { CoreSitePickerComponent } from './site-picker/site-picker'; import { CoreTabsComponent } from './tabs/tabs'; import { CoreTabComponent } from './tabs/tab'; -import { CoreRichTextEditorComponent } from './rich-text-editor/rich-text-editor'; import { CoreNavBarButtonsComponent } from './navbar-buttons/navbar-buttons'; import { CoreDynamicComponent } from './dynamic-component/dynamic-component'; import { CoreSendMessageFormComponent } from './send-message-form/send-message-form'; @@ -79,7 +78,6 @@ import { CoreBSTooltipComponent } from './bs-tooltip/bs-tooltip'; CoreSitePickerComponent, CoreTabsComponent, CoreTabComponent, - CoreRichTextEditorComponent, CoreNavBarButtonsComponent, CoreDynamicComponent, CoreSendMessageFormComponent, @@ -128,7 +126,6 @@ import { CoreBSTooltipComponent } from './bs-tooltip/bs-tooltip'; CoreSitePickerComponent, CoreTabsComponent, CoreTabComponent, - CoreRichTextEditorComponent, CoreNavBarButtonsComponent, CoreDynamicComponent, CoreSendMessageFormComponent, diff --git a/src/components/local-file/core-local-file.html b/src/components/local-file/core-local-file.html index a988397a9..ffec36361 100644 --- a/src/components/local-file/core-local-file.html +++ b/src/components/local-file/core-local-file.html @@ -1,4 +1,4 @@ - + {{fileExtension}} diff --git a/src/components/local-file/local-file.ts b/src/components/local-file/local-file.ts index e1c46b1c2..d430af3f4 100644 --- a/src/components/local-file/local-file.ts +++ b/src/components/local-file/local-file.ts @@ -12,8 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, Input, Output, OnInit, EventEmitter } from '@angular/core'; +import { Component, Input, Output, OnInit, EventEmitter, ViewChild, ElementRef } from '@angular/core'; +import { CoreEventsProvider } from '@providers/events'; import { CoreFileProvider } from '@providers/file'; +import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype'; import { CoreTextUtilsProvider } from '@providers/utils/text'; @@ -38,6 +40,8 @@ export class CoreLocalFileComponent implements OnInit { @Output() onRename?: EventEmitter; // Will notify when the file is renamed. Receives the FileEntry as the param. @Output() onClick?: EventEmitter; // Will notify when the file is clicked. Only if overrideClick is true. + @ViewChild('nameForm') formElement: ElementRef; + fileName: string; fileIcon: string; fileExtension: string; @@ -47,12 +51,14 @@ export class CoreLocalFileComponent implements OnInit { editMode: boolean; relativePath: string; - constructor(private mimeUtils: CoreMimetypeUtilsProvider, - private utils: CoreUtilsProvider, - private textUtils: CoreTextUtilsProvider, - private fileProvider: CoreFileProvider, - private domUtils: CoreDomUtilsProvider, - private timeUtils: CoreTimeUtilsProvider) { + constructor(protected mimeUtils: CoreMimetypeUtilsProvider, + protected utils: CoreUtilsProvider, + protected textUtils: CoreTextUtilsProvider, + protected fileProvider: CoreFileProvider, + protected domUtils: CoreDomUtilsProvider, + protected timeUtils: CoreTimeUtilsProvider, + protected sitesProvider: CoreSitesProvider, + protected eventsProvider: CoreEventsProvider) { this.onDelete = new EventEmitter(); this.onRename = new EventEmitter(); this.onClick = new EventEmitter(); @@ -137,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; } @@ -152,6 +159,10 @@ export class CoreLocalFileComponent implements OnInit { }).catch(() => { // File doesn't exist, move it. return this.fileProvider.moveFile(this.relativePath, newPath).then((fileEntry) => { + + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, false, + this.sitesProvider.getCurrentSiteId()); + this.editMode = false; this.file = fileEntry; this.loadFileBasicData(); diff --git a/src/components/send-message-form/core-send-message-form.html b/src/components/send-message-form/core-send-message-form.html index 8caa886c3..bed8756ce 100644 --- a/src/components/send-message-form/core-send-message-form.html +++ b/src/components/send-message-form/core-send-message-form.html @@ -1,4 +1,4 @@ - +
- + diff --git a/src/core/login/pages/credentials/credentials.ts b/src/core/login/pages/credentials/credentials.ts index 13b81d12c..0aaccaa12 100644 --- a/src/core/login/pages/credentials/credentials.ts +++ b/src/core/login/pages/credentials/credentials.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component } from '@angular/core'; +import { Component, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, NavController, NavParams } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from '@providers/app'; @@ -32,6 +32,9 @@ import { CoreConfigConstants } from '../../../../configconstants'; templateUrl: 'credentials.html', }) export class CoreLoginCredentialsPage { + + @ViewChild('credentialsForm') formElement: ElementRef; + credForm: FormGroup; siteUrl: string; siteChecked = false; @@ -242,6 +245,8 @@ export class CoreLoginCredentialsPage { } }).finally(() => { modal.dismiss(); + + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true); }); } diff --git a/src/core/login/pages/email-signup/email-signup.html b/src/core/login/pages/email-signup/email-signup.html index 2e49ea822..3e52b4b6c 100644 --- a/src/core/login/pages/email-signup/email-signup.html +++ b/src/core/login/pages/email-signup/email-signup.html @@ -17,7 +17,7 @@ - +

{{ 'core.agelocationverification' | translate }}

@@ -47,7 +47,7 @@ -
+

{{siteUrl}}

diff --git a/src/core/login/pages/email-signup/email-signup.ts b/src/core/login/pages/email-signup/email-signup.ts index ffb8a6f42..f4cc08996 100644 --- a/src/core/login/pages/email-signup/email-signup.ts +++ b/src/core/login/pages/email-signup/email-signup.ts @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, ViewChild } from '@angular/core'; +import { Component, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, NavController, NavParams, Content } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; +import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider } from '@providers/utils/text'; @@ -35,6 +36,8 @@ import { CoreConfigConstants } from '../../../../configconstants'; }) export class CoreLoginEmailSignupPage { @ViewChild(Content) content: Content; + @ViewChild('ageForm') ageFormElement: ElementRef; + @ViewChild('signupFormEl') signupFormElement: ElementRef; signupForm: FormGroup; siteUrl: string; @@ -66,10 +69,18 @@ export class CoreLoginEmailSignupPage { policyErrors: any; namefieldsErrors: any; - constructor(private navCtrl: NavController, navParams: NavParams, private fb: FormBuilder, private wsProvider: CoreWSProvider, - private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider, - private domUtils: CoreDomUtilsProvider, private translate: TranslateService, private utils: CoreUtilsProvider, - private textUtils: CoreTextUtilsProvider, private userProfileFieldDelegate: CoreUserProfileFieldDelegate) { + constructor(protected navCtrl: NavController, + navParams: NavParams, + protected fb: FormBuilder, + protected wsProvider: CoreWSProvider, + protected sitesProvider: CoreSitesProvider, + protected loginHelper: CoreLoginHelperProvider, + protected domUtils: CoreDomUtilsProvider, + protected translate: TranslateService, + protected utils: CoreUtilsProvider, + protected textUtils: CoreTextUtilsProvider, + protected userProfileFieldDelegate: CoreUserProfileFieldDelegate, + protected eventsProvider: CoreEventsProvider) { this.siteUrl = navParams.get('siteUrl'); @@ -265,6 +276,9 @@ export class CoreLoginEmailSignupPage { return this.wsProvider.callAjax('auth_email_signup_user', params, { siteUrl: this.siteUrl }); }).then((result) => { if (result.success) { + + this.domUtils.triggerFormSubmittedEvent(this.signupFormElement.nativeElement, true); + // Show alert and ho back. const message = this.translate.instant('core.login.emailconfirmsent', { $a: params.email }); this.domUtils.showAlert(this.translate.instant('core.success'), message); @@ -334,6 +348,9 @@ export class CoreLoginEmailSignupPage { params.age = parseInt(params.age, 10); // Use just the integer part. this.wsProvider.callAjax('core_auth_is_minor', params, {siteUrl: this.siteUrl}).then((result) => { + + this.domUtils.triggerFormSubmittedEvent(this.ageFormElement.nativeElement, true); + if (!result.status) { if (this.countryControl.value) { this.signUpCountryControl.setValue(this.countryControl.value); diff --git a/src/core/login/pages/forgotten-password/forgotten-password.html b/src/core/login/pages/forgotten-password/forgotten-password.html index 182ef2312..81905e4d4 100644 --- a/src/core/login/pages/forgotten-password/forgotten-password.html +++ b/src/core/login/pages/forgotten-password/forgotten-password.html @@ -10,7 +10,7 @@
- + {{ 'core.login.searchby' | translate }} diff --git a/src/core/login/pages/forgotten-password/forgotten-password.ts b/src/core/login/pages/forgotten-password/forgotten-password.ts index b1d5d6785..9b975e958 100644 --- a/src/core/login/pages/forgotten-password/forgotten-password.ts +++ b/src/core/login/pages/forgotten-password/forgotten-password.ts @@ -12,9 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component } from '@angular/core'; +import { Component, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, NavController, NavParams } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; +import { CoreEventsProvider } from '@providers/events'; +import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreLoginHelperProvider } from '../../providers/helper'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @@ -28,11 +30,20 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; templateUrl: 'forgotten-password.html', }) export class CoreLoginForgottenPasswordPage { + + @ViewChild('resetPasswordForm') formElement: ElementRef; + myForm: FormGroup; siteUrl: string; - constructor(private navCtrl: NavController, navParams: NavParams, fb: FormBuilder, private translate: TranslateService, - private loginHelper: CoreLoginHelperProvider, private domUtils: CoreDomUtilsProvider) { + constructor(protected navCtrl: NavController, + navParams: NavParams, + fb: FormBuilder, + protected translate: TranslateService, + protected loginHelper: CoreLoginHelperProvider, + protected domUtils: CoreDomUtilsProvider, + protected eventsProvider: CoreEventsProvider, + protected sitesProvider: CoreSitesProvider) { this.siteUrl = navParams.get('siteUrl'); this.myForm = fb.group({ @@ -71,6 +82,8 @@ export class CoreLoginForgottenPasswordPage { this.domUtils.showErrorModal(response.notice); } else { // Success. + 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.html b/src/core/login/pages/reconnect/reconnect.html index bfb460784..1b87186ee 100644 --- a/src/core/login/pages/reconnect/reconnect.html +++ b/src/core/login/pages/reconnect/reconnect.html @@ -29,7 +29,7 @@ {{ 'core.login.reconnectdescription' | translate }}

- +

{{username}}

diff --git a/src/core/login/pages/reconnect/reconnect.ts b/src/core/login/pages/reconnect/reconnect.ts index 9372ed2b7..59918eab7 100644 --- a/src/core/login/pages/reconnect/reconnect.ts +++ b/src/core/login/pages/reconnect/reconnect.ts @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component } from '@angular/core'; +import { Component, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, NavController, NavParams } from 'ionic-angular'; import { CoreAppProvider } from '@providers/app'; +import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreLoginHelperProvider } from '../../providers/helper'; @@ -29,6 +30,9 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; templateUrl: 'reconnect.html', }) export class CoreLoginReconnectPage { + + @ViewChild('reconnectForm') formElement: ElementRef; + credForm: FormGroup; siteUrl: string; username: string; @@ -47,13 +51,14 @@ export class CoreLoginReconnectPage { protected isLoggedOut: boolean; protected siteId: string; - constructor(private navCtrl: NavController, + constructor(protected navCtrl: NavController, navParams: NavParams, fb: FormBuilder, - private appProvider: CoreAppProvider, - private sitesProvider: CoreSitesProvider, - private loginHelper: CoreLoginHelperProvider, - private domUtils: CoreDomUtilsProvider) { + protected appProvider: CoreAppProvider, + protected sitesProvider: CoreSitesProvider, + protected loginHelper: CoreLoginHelperProvider, + protected domUtils: CoreDomUtilsProvider, + protected eventsProvider: CoreEventsProvider) { const currentSite = this.sitesProvider.getCurrentSite(); @@ -175,6 +180,9 @@ export class CoreLoginReconnectPage { // Start the authentication process. this.sitesProvider.getUserToken(siteUrl, username, password).then((data) => { return this.sitesProvider.updateSiteToken(this.infoSiteUrl, username, data.token, data.privateToken).then(() => { + + 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(() => { // Reset fields so the data is not in the view anymore. diff --git a/src/core/login/pages/site/site.html b/src/core/login/pages/site/site.html index 6a4b40f36..8da75c237 100644 --- a/src/core/login/pages/site/site.html +++ b/src/core/login/pages/site/site.html @@ -17,7 +17,7 @@
- +

{{ 'core.login.newsitedescription' | translate }}

diff --git a/src/core/login/pages/site/site.ts b/src/core/login/pages/site/site.ts index 5a231d27c..92193fd92 100644 --- a/src/core/login/pages/site/site.ts +++ b/src/core/login/pages/site/site.ts @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component } from '@angular/core'; +import { Component, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, NavController, ModalController, NavParams } from 'ionic-angular'; import { CoreAppProvider } from '@providers/app'; +import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider, CoreSiteCheckResponse } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreConfigConstants } from '../../../../configconstants'; @@ -31,6 +32,9 @@ import { CoreUrl } from '@classes/utils/url'; templateUrl: 'site.html', }) export class CoreLoginSitePage { + + @ViewChild('siteFormEl') formElement: ElementRef; + siteForm: FormGroup; fixedSites: any[]; filteredSites: any[]; @@ -38,9 +42,15 @@ export class CoreLoginSitePage { showKeyboard = false; filter = ''; - constructor(navParams: NavParams, private navCtrl: NavController, fb: FormBuilder, private appProvider: CoreAppProvider, - private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider, - private modalCtrl: ModalController, private domUtils: CoreDomUtilsProvider) { + constructor(navParams: NavParams, + protected navCtrl: NavController, + fb: FormBuilder, + protected appProvider: CoreAppProvider, + protected sitesProvider: CoreSitesProvider, + protected loginHelper: CoreLoginHelperProvider, + protected modalCtrl: ModalController, + protected domUtils: CoreDomUtilsProvider, + protected eventsProvider: CoreEventsProvider) { this.showKeyboard = !!navParams.get('showKeyboard'); @@ -96,6 +106,9 @@ export class CoreLoginSitePage { // It's a demo site. this.sitesProvider.getUserToken(siteData.url, siteData.username, siteData.password).then((data) => { return this.sitesProvider.newSite(data.siteUrl, data.token, data.privateToken).then(() => { + + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true); + return this.loginHelper.goToSiteInitialPage(); }, (error) => { this.loginHelper.treatUserTokenError(siteData.url, error, siteData.username, siteData.password); @@ -175,6 +188,9 @@ export class CoreLoginSitePage { */ protected async login(response: CoreSiteCheckResponse): Promise { return this.sitesProvider.checkRequiredMinimumVersion(response.config).then(() => { + + this.domUtils.triggerFormSubmittedEvent(this.formElement.nativeElement, true); + if (response.warning) { this.domUtils.showErrorModal(response.warning, true, 4000); } diff --git a/src/core/search/components/search-box/core-search-box.html b/src/core/search/components/search-box/core-search-box.html index adc00c50b..be186a40b 100644 --- a/src/core/search/components/search-box/core-search-box.html +++ b/src/core/search/components/search-box/core-search-box.html @@ -1,5 +1,5 @@ - +