From dc74546f3d965fc126bc52ac16a2ad0373b3cc54 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 18 Apr 2018 13:00:29 +0200 Subject: [PATCH] MOBILE-2334 assign: Implement feedback plugins --- src/addon/mod/assign/assign.module.ts | 4 +- .../classes/feedback-plugin-component.ts | 70 ++++++ .../assign/components/components.module.ts | 7 +- .../feedback-plugin/feedback-plugin.html | 16 ++ .../feedback-plugin/feedback-plugin.ts | 104 ++++++++ .../components/submission/submission.html | 2 +- .../feedback/comments/comments.module.ts | 50 ++++ .../feedback/comments/component/comments.html | 24 ++ .../feedback/comments/component/comments.ts | 148 ++++++++++++ .../mod/assign/feedback/comments/lang/en.json | 3 + .../feedback/comments/providers/handler.ts | 224 ++++++++++++++++++ .../feedback/editpdf/component/editpdf.html | 7 + .../feedback/editpdf/component/editpdf.ts | 44 ++++ .../assign/feedback/editpdf/editpdf.module.ts | 50 ++++ .../mod/assign/feedback/editpdf/lang/en.json | 3 + .../feedback/editpdf/providers/handler.ts | 65 +++++ .../mod/assign/feedback/feedback.module.ts | 31 +++ .../assign/feedback/file/component/file.html | 7 + .../assign/feedback/file/component/file.ts | 44 ++++ .../mod/assign/feedback/file/file.module.ts | 50 ++++ .../mod/assign/feedback/file/lang/en.json | 3 + .../assign/feedback/file/providers/handler.ts | 65 +++++ .../edit-feedback-modal.html | 16 ++ .../edit-feedback-modal.module.ts | 35 +++ .../edit-feedback-modal.ts | 103 ++++++++ 25 files changed, 1171 insertions(+), 4 deletions(-) create mode 100644 src/addon/mod/assign/classes/feedback-plugin-component.ts create mode 100644 src/addon/mod/assign/components/feedback-plugin/feedback-plugin.html create mode 100644 src/addon/mod/assign/components/feedback-plugin/feedback-plugin.ts create mode 100644 src/addon/mod/assign/feedback/comments/comments.module.ts create mode 100644 src/addon/mod/assign/feedback/comments/component/comments.html create mode 100644 src/addon/mod/assign/feedback/comments/component/comments.ts create mode 100644 src/addon/mod/assign/feedback/comments/lang/en.json create mode 100644 src/addon/mod/assign/feedback/comments/providers/handler.ts create mode 100644 src/addon/mod/assign/feedback/editpdf/component/editpdf.html create mode 100644 src/addon/mod/assign/feedback/editpdf/component/editpdf.ts create mode 100644 src/addon/mod/assign/feedback/editpdf/editpdf.module.ts create mode 100644 src/addon/mod/assign/feedback/editpdf/lang/en.json create mode 100644 src/addon/mod/assign/feedback/editpdf/providers/handler.ts create mode 100644 src/addon/mod/assign/feedback/feedback.module.ts create mode 100644 src/addon/mod/assign/feedback/file/component/file.html create mode 100644 src/addon/mod/assign/feedback/file/component/file.ts create mode 100644 src/addon/mod/assign/feedback/file/file.module.ts create mode 100644 src/addon/mod/assign/feedback/file/lang/en.json create mode 100644 src/addon/mod/assign/feedback/file/providers/handler.ts create mode 100644 src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.html create mode 100644 src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.module.ts create mode 100644 src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.ts diff --git a/src/addon/mod/assign/assign.module.ts b/src/addon/mod/assign/assign.module.ts index d623ec3fb..145356eae 100644 --- a/src/addon/mod/assign/assign.module.ts +++ b/src/addon/mod/assign/assign.module.ts @@ -28,12 +28,14 @@ import { AddonModAssignModuleHandler } from './providers/module-handler'; import { AddonModAssignPrefetchHandler } from './providers/prefetch-handler'; import { AddonModAssignSyncCronHandler } from './providers/sync-cron-handler'; import { AddonModAssignSubmissionModule } from './submission/submission.module'; +import { AddonModAssignFeedbackModule } from './feedback/feedback.module'; @NgModule({ declarations: [ ], imports: [ - AddonModAssignSubmissionModule + AddonModAssignSubmissionModule, + AddonModAssignFeedbackModule ], providers: [ AddonModAssignProvider, diff --git a/src/addon/mod/assign/classes/feedback-plugin-component.ts b/src/addon/mod/assign/classes/feedback-plugin-component.ts new file mode 100644 index 000000000..847e7fe5a --- /dev/null +++ b/src/addon/mod/assign/classes/feedback-plugin-component.ts @@ -0,0 +1,70 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Input } from '@angular/core'; +import { ModalController } from 'ionic-angular'; + +/** + * Base class for component to render a feedback plugin. + */ +export class AddonModAssignFeedbackPluginComponent { + @Input() assign: any; // The assignment. + @Input() submission: any; // The submission. + @Input() plugin: any; // The plugin object. + @Input() userId: number; // The user ID of the submission. + @Input() configs: any; // The configs for the plugin. + @Input() canEdit: boolean; // Whether the user can edit. + @Input() edit: boolean; // Whether the user is editing. + + constructor(protected modalCtrl: ModalController) { } + + /** + * Open a modal to edit the feedback plugin. + * + * @return {Promise} Promise resolved with the input data, rejected if cancelled. + */ + editFeedback(): Promise { + if (this.canEdit) { + return new Promise((resolve, reject): void => { + // Create the navigation modal. + const modal = this.modalCtrl.create('AddonModAssignEditFeedbackModalPage', { + assign: this.assign, + submission: this.submission, + plugin: this.plugin, + userId: this.userId + }); + + modal.present(); + modal.onDidDismiss((data) => { + if (typeof data == 'undefined') { + reject(); + } else { + resolve(data); + } + }); + }); + } else { + return Promise.reject(null); + } + } + + /** + * Invalidate the data. + * + * @return {Promise} Promise resolved when done. + */ + invalidate(): Promise { + return Promise.resolve(); + } +} diff --git a/src/addon/mod/assign/components/components.module.ts b/src/addon/mod/assign/components/components.module.ts index 94e81c86e..b794ebe49 100644 --- a/src/addon/mod/assign/components/components.module.ts +++ b/src/addon/mod/assign/components/components.module.ts @@ -23,12 +23,14 @@ import { CoreCourseComponentsModule } from '@core/course/components/components.m import { AddonModAssignIndexComponent } from './index/index'; import { AddonModAssignSubmissionComponent } from './submission/submission'; import { AddonModAssignSubmissionPluginComponent } from './submission-plugin/submission-plugin'; +import { AddonModAssignFeedbackPluginComponent } from './feedback-plugin/feedback-plugin'; @NgModule({ declarations: [ AddonModAssignIndexComponent, AddonModAssignSubmissionComponent, - AddonModAssignSubmissionPluginComponent + AddonModAssignSubmissionPluginComponent, + AddonModAssignFeedbackPluginComponent ], imports: [ CommonModule, @@ -44,7 +46,8 @@ import { AddonModAssignSubmissionPluginComponent } from './submission-plugin/sub exports: [ AddonModAssignIndexComponent, AddonModAssignSubmissionComponent, - AddonModAssignSubmissionPluginComponent + AddonModAssignSubmissionPluginComponent, + AddonModAssignFeedbackPluginComponent ], entryComponents: [ AddonModAssignIndexComponent diff --git a/src/addon/mod/assign/components/feedback-plugin/feedback-plugin.html b/src/addon/mod/assign/components/feedback-plugin/feedback-plugin.html new file mode 100644 index 000000000..fd814742c --- /dev/null +++ b/src/addon/mod/assign/components/feedback-plugin/feedback-plugin.html @@ -0,0 +1,16 @@ + + + + + +

{{ plugin.name }}

+ + {{ 'addon.mod_assign.feedbacknotsupported' | translate }} + +

+ +

+ +
+
+
diff --git a/src/addon/mod/assign/components/feedback-plugin/feedback-plugin.ts b/src/addon/mod/assign/components/feedback-plugin/feedback-plugin.ts new file mode 100644 index 000000000..efc561c4b --- /dev/null +++ b/src/addon/mod/assign/components/feedback-plugin/feedback-plugin.ts @@ -0,0 +1,104 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component, Input, OnInit, Injector, ViewChild } from '@angular/core'; +import { AddonModAssignProvider } from '../../providers/assign'; +import { AddonModAssignHelperProvider } from '../../providers/helper'; +import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegate'; +import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-component'; + +/** + * Component that displays an assignment feedback plugin. + */ +@Component({ + selector: 'addon-mod-assign-feedback-plugin', + templateUrl: 'feedback-plugin.html', +}) +export class AddonModAssignFeedbackPluginComponent implements OnInit { + @ViewChild(CoreDynamicComponent) dynamicComponent: CoreDynamicComponent; + + @Input() assign: any; // The assignment. + @Input() submission: any; // The submission. + @Input() plugin: any; // The plugin object. + @Input() userId: number; // The user ID of the submission. + @Input() canEdit: boolean | string; // Whether the user can edit. + @Input() edit: boolean | string; // Whether the user is editing. + + pluginComponent: any; // Component to render the plugin. + data: any; // Data to pass to the component. + + // Data to render the plugin if it isn't supported. + component = AddonModAssignProvider.COMPONENT; + text = ''; + files = []; + notSupported: boolean; + pluginLoaded: boolean; + + constructor(protected injector: Injector, protected feedbackDelegate: AddonModAssignFeedbackDelegate, + protected assignProvider: AddonModAssignProvider, protected assignHelper: AddonModAssignHelperProvider) { } + + /** + * Component being initialized. + */ + ngOnInit(): void { + if (!this.plugin) { + this.pluginLoaded = true; + + return; + } + + this.plugin.name = this.feedbackDelegate.getPluginName(this.plugin); + if (!this.plugin.name) { + this.pluginLoaded = true; + + return; + } + + this.edit = this.edit && this.edit !== 'false'; + this.canEdit = this.canEdit && this.canEdit !== 'false'; + + // Check if the plugin has defined its own component to render itself. + this.feedbackDelegate.getComponentForPlugin(this.injector, this.plugin).then((component) => { + this.pluginComponent = component; + + if (component) { + // Prepare the data to pass to the component. + this.data = { + assign: this.assign, + submission: this.submission, + plugin: this.plugin, + userId: this.userId, + configs: this.assignHelper.getPluginConfig(this.assign, 'assignfeedback', this.plugin.type), + edit: this.edit, + canEdit: this.canEdit + }; + } else { + // Data to render the plugin. + this.text = this.assignProvider.getSubmissionPluginText(this.plugin); + this.files = this.assignProvider.getSubmissionPluginAttachments(this.plugin); + this.notSupported = this.feedbackDelegate.isPluginSupported(this.plugin.type); + this.pluginLoaded = true; + } + }); + } + + /** + * Invalidate the plugin data. + * + * @return {Promise} Promise resolved when done. + */ + invalidate(): Promise { + return Promise.resolve(this.dynamicComponent && this.dynamicComponent.callComponentFunction('invalidate', [])); + } +} diff --git a/src/addon/mod/assign/components/submission/submission.html b/src/addon/mod/assign/components/submission/submission.html index 33d75d8b6..f9cf275bc 100644 --- a/src/addon/mod/assign/components/submission/submission.html +++ b/src/addon/mod/assign/components/submission/submission.html @@ -176,7 +176,7 @@

{{ outcome.selected }}

- + diff --git a/src/addon/mod/assign/feedback/comments/comments.module.ts b/src/addon/mod/assign/feedback/comments/comments.module.ts new file mode 100644 index 000000000..c5905c452 --- /dev/null +++ b/src/addon/mod/assign/feedback/comments/comments.module.ts @@ -0,0 +1,50 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { IonicModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { AddonModAssignFeedbackCommentsHandler } from './providers/handler'; +import { AddonModAssignFeedbackCommentsComponent } from './component/comments'; +import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegate'; +import { CoreComponentsModule } from '@components/components.module'; +import { CoreDirectivesModule } from '@directives/directives.module'; + +@NgModule({ + declarations: [ + AddonModAssignFeedbackCommentsComponent + ], + imports: [ + CommonModule, + IonicModule, + TranslateModule.forChild(), + CoreComponentsModule, + CoreDirectivesModule + ], + providers: [ + AddonModAssignFeedbackCommentsHandler + ], + exports: [ + AddonModAssignFeedbackCommentsComponent + ], + entryComponents: [ + AddonModAssignFeedbackCommentsComponent + ] +}) +export class AddonModAssignFeedbackCommentsModule { + constructor(feedbackDelegate: AddonModAssignFeedbackDelegate, handler: AddonModAssignFeedbackCommentsHandler) { + feedbackDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/assign/feedback/comments/component/comments.html b/src/addon/mod/assign/feedback/comments/component/comments.html new file mode 100644 index 000000000..8c68abdb8 --- /dev/null +++ b/src/addon/mod/assign/feedback/comments/component/comments.html @@ -0,0 +1,24 @@ + + +

{{ plugin.name }}

+

+ +

+
+
+ + + +
+ + + {{ 'core.notsent' | translate }} + +
+
+ + + + + + diff --git a/src/addon/mod/assign/feedback/comments/component/comments.ts b/src/addon/mod/assign/feedback/comments/component/comments.ts new file mode 100644 index 000000000..23ddedaf8 --- /dev/null +++ b/src/addon/mod/assign/feedback/comments/component/comments.ts @@ -0,0 +1,148 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component, OnInit, ElementRef } from '@angular/core'; +import { ModalController } from 'ionic-angular'; +import { FormBuilder, FormControl } from '@angular/forms'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { CoreTextUtilsProvider } from '@providers/utils/text'; +import { AddonModAssignProvider } from '../../../providers/assign'; +import { AddonModAssignOfflineProvider } from '../../../providers/assign-offline'; +import { AddonModAssignFeedbackDelegate } from '../../../providers/feedback-delegate'; +import { AddonModAssignFeedbackPluginComponent } from '../../../classes/feedback-plugin-component'; +import { AddonModAssignFeedbackCommentsHandler } from '../providers/handler'; + +/** + * Component to render a comments feedback plugin. + */ +@Component({ + selector: 'addon-mod-assign-feedback-comments', + templateUrl: 'comments.html' +}) +export class AddonModAssignFeedbackCommentsComponent extends AddonModAssignFeedbackPluginComponent implements OnInit { + + control: FormControl; + component = AddonModAssignProvider.COMPONENT; + text: string; + isSent: boolean; + loaded: boolean; + + protected element: HTMLElement; + + constructor(modalCtrl: ModalController, element: ElementRef, protected domUtils: CoreDomUtilsProvider, + protected textUtils: CoreTextUtilsProvider, protected assignOfflineProvider: AddonModAssignOfflineProvider, + protected assignProvider: AddonModAssignProvider, protected fb: FormBuilder, + protected feedbackDelegate: AddonModAssignFeedbackDelegate) { + super(modalCtrl); + + this.element = element.nativeElement; + } + + /** + * Component being initialized. + */ + ngOnInit(): void { + let promise, + rteEnabled; + + // Check if rich text editor is enabled. + if (this.edit) { + promise = this.domUtils.isRichTextEditorEnabled(); + } else { + // We aren't editing, so no rich text editor. + promise = Promise.resolve(false); + } + + promise.then((enabled) => { + rteEnabled = enabled; + + return this.getText(rteEnabled); + }).then((text) => { + + this.text = text; + + if (!this.canEdit && !this.edit) { + // User cannot edit the comment. Show it full when clicked. + this.element.addEventListener('click', (e) => { + e.preventDefault(); + e.stopPropagation(); + + if (this.text) { + // Open a new state with the text. + this.textUtils.expandText(this.plugin.name, this.text, this.component, this.assign.cmid); + } + }); + } else if (this.edit) { + this.control = this.fb.control(text); + } + }).finally(() => { + this.loaded = true; + }); + } + + /** + * Edit the comment. + */ + editComment(): void { + this.editFeedback().then((inputData) => { + const text = AddonModAssignFeedbackCommentsHandler.getTextFromInputData(this.textUtils, this.plugin, inputData); + + // Update the text and save it as draft. + this.isSent = false; + this.text = text; + this.feedbackDelegate.saveFeedbackDraft(this.assign.id, this.userId, this.plugin, { + text: text, + format: 1 + }); + }).catch(() => { + // User cancelled, nothing to do. + }); + } + + /** + * Get the text for the plugin. + * + * @param {boolean} rteEnabled Whether Rich Text Editor is enabled. + * @return {Promise} Promise resolved with the text. + */ + protected getText(rteEnabled: boolean): Promise { + // Check if the user already modified the comment. + return this.feedbackDelegate.getPluginDraftData(this.assign.id, this.userId, this.plugin).then((draft) => { + if (draft) { + this.isSent = false; + + return draft.text; + } else { + // There is no draft saved. Check if we have anything offline. + return this.assignOfflineProvider.getSubmissionGrade(this.assign.id, this.userId).catch(() => { + // No offline data found. + }).then((offlineData) => { + if (offlineData && offlineData.plugindata && offlineData.plugindata.assignfeedbackcomments_editor) { + // Save offline as draft. + this.isSent = false; + this.feedbackDelegate.saveFeedbackDraft(this.assign.id, this.userId, this.plugin, + offlineData.plugindata.assignfeedbackcomments_editor); + + return offlineData.plugindata.assignfeedbackcomments_editor.text; + } + + // No offline data found, return online text. + this.isSent = true; + + return this.assignProvider.getSubmissionPluginText(this.plugin, this.edit && !rteEnabled); + }); + } + }); + } +} diff --git a/src/addon/mod/assign/feedback/comments/lang/en.json b/src/addon/mod/assign/feedback/comments/lang/en.json new file mode 100644 index 000000000..637363859 --- /dev/null +++ b/src/addon/mod/assign/feedback/comments/lang/en.json @@ -0,0 +1,3 @@ +{ + "pluginname": "Feedback comments" +} \ No newline at end of file diff --git a/src/addon/mod/assign/feedback/comments/providers/handler.ts b/src/addon/mod/assign/feedback/comments/providers/handler.ts new file mode 100644 index 000000000..d6c3f6bd3 --- /dev/null +++ b/src/addon/mod/assign/feedback/comments/providers/handler.ts @@ -0,0 +1,224 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injectable, Injector } from '@angular/core'; +import { CoreSitesProvider } from '@providers/sites'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { CoreTextUtilsProvider } from '@providers/utils/text'; +import { AddonModAssignProvider } from '../../../providers/assign'; +import { AddonModAssignOfflineProvider } from '../../../providers/assign-offline'; +import { AddonModAssignFeedbackHandler } from '../../../providers/feedback-delegate'; +import { AddonModAssignFeedbackCommentsComponent } from '../component/comments'; + +/** + * Handler for comments feedback plugin. + */ +@Injectable() +export class AddonModAssignFeedbackCommentsHandler implements AddonModAssignFeedbackHandler { + name = 'AddonModAssignFeedbackCommentsHandler'; + type = 'comments'; + + protected drafts = {}; // Store the data in this service so it isn't lost if the user performs a PTR in the page. + + constructor(private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider, + private textUtils: CoreTextUtilsProvider, private assignProvider: AddonModAssignProvider, + private assignOfflineProvider: AddonModAssignOfflineProvider) { } + + /** + * Discard the draft data of the feedback plugin. + * + * @param {number} assignId The assignment ID. + * @param {number} userId User ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {void|Promise} If the function is async, it should return a Promise resolved when done. + */ + discardDraft(assignId: number, userId: number, siteId?: string): void | Promise { + const id = this.getDraftId(assignId, userId, siteId); + + if (typeof this.drafts[id] != 'undefined') { + delete this.drafts[id]; + } + } + + /** + * Return the Component to use to display the plugin data, either in read or in edit mode. + * It's recommended to return the class of the component, but you can also return an instance of the component. + * + * @param {Injector} injector Injector. + * @param {any} plugin The plugin object. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getComponent(injector: Injector, plugin: any): any | Promise { + return AddonModAssignFeedbackCommentsComponent; + } + + /** + * Return the draft saved data of the feedback plugin. + * + * @param {number} assignId The assignment ID. + * @param {number} userId User ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {any|Promise} Data (or promise resolved with the data). + */ + getDraft(assignId: number, userId: number, siteId?: string): any | Promise { + const id = this.getDraftId(assignId, userId, siteId); + + if (typeof this.drafts[id] != 'undefined') { + return this.drafts[id]; + } + } + + /** + * Get a draft ID. + * + * @param {number} assignId The assignment ID. + * @param {number} userId User ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {string} Draft ID. + */ + protected getDraftId(assignId: number, userId: number, siteId?: string): string { + siteId = siteId || this.sitesProvider.getCurrentSiteId(); + + return siteId + '#' + assignId + '#' + userId; + } + + /** + * Get the text to submit. + * + * @param {CoreTextUtilsProvider} textUtils Text utils instance. + * @param {any} plugin Plugin. + * @param {any} inputData Data entered in the feedback edit form. + * @return {string} Text to submit. + */ + static getTextFromInputData(textUtils: CoreTextUtilsProvider, plugin: any, inputData: any): string { + const files = plugin.fileareas && plugin.fileareas[0] ? plugin.fileareas[0].files : []; + let text = inputData.assignfeedbackcomments_editor; + + // The input data can have a string or an object with text and format. Get the text. + if (text && text.text) { + text = text.text; + } + + return textUtils.restorePluginfileUrls(text, files); + } + + /** + * Check if the feedback data has changed for this plugin. + * + * @param {any} assign The assignment. + * @param {any} submission The submission. + * @param {any} plugin The plugin object. + * @param {any} inputData Data entered by the user for the feedback. + * @param {number} userId User ID of the submission. + * @return {boolean|Promise} Boolean (or promise resolved with boolean): whether the data has changed. + */ + hasDataChanged(assign: any, submission: any, plugin: any, inputData: any, userId: number): boolean | Promise { + // Get it from plugin or offline. + return this.assignOfflineProvider.getSubmissionGrade(assign.id, userId).catch(() => { + // No offline data found. + }).then((data) => { + if (data && data.plugindata && data.plugindata.assignfeedbackcomments_editor) { + return data.plugindata.assignfeedbackcomments_editor.text; + } + + // No offline data found, get text from plugin. + return this.domUtils.isRichTextEditorEnabled().then((enabled) => { + return this.assignProvider.getSubmissionPluginText(plugin, !enabled); + }); + }).then((initialText) => { + const newText = AddonModAssignFeedbackCommentsHandler.getTextFromInputData(this.textUtils, plugin, inputData); + + if (typeof newText == 'undefined') { + return false; + } + + // Check if text has changed. + return initialText != newText; + }); + } + + /** + * Check whether the plugin has draft data stored. + * + * @param {number} assignId The assignment ID. + * @param {number} userId User ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {boolean|Promise} Boolean or promise resolved with boolean: whether the plugin has draft data. + */ + hasDraftData(assignId: number, userId: number, siteId?: string): boolean | Promise { + const draft = this.getDraft(assignId, userId, siteId); + + return !!draft; + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } + + /** + * Whether or not the handler is enabled for edit on a site level. + * + * @return {boolean|Promise} Whether or not the handler is enabled for edit on a site level. + */ + isEnabledForEdit(): boolean | Promise { + return true; + } + + /** + * Prepare and add to pluginData the data to send to the server based on the draft data saved. + * + * @param {number} assignId The assignment ID. + * @param {number} userId User ID. + * @param {any} plugin The plugin object. + * @param {any} pluginData Object where to store the data to send. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {void|Promise} If the function is async, it should return a Promise resolved when done. + */ + prepareFeedbackData(assignId: number, userId: number, plugin: any, pluginData: any, siteId?: string): void | Promise { + const draft = this.getDraft(assignId, userId, siteId); + + if (draft) { + return this.domUtils.isRichTextEditorEnabled().then((enabled) => { + if (!enabled) { + // Rich text editor not enabled, add some HTML to the text if needed. + draft.text = this.textUtils.formatHtmlLines(draft.text); + } + + pluginData.assignfeedbackcomments_editor = draft; + }); + } + } + + /** + * Save draft data of the feedback plugin. + * + * @param {number} assignId The assignment ID. + * @param {number} userId User ID. + * @param {any} plugin The plugin object. + * @param {any} data The data to save. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {void|Promise} If the function is async, it should return a Promise resolved when done. + */ + saveDraft(assignId: number, userId: number, plugin: any, data: any, siteId?: string): void | Promise { + if (data) { + this.drafts[this.getDraftId(assignId, userId, siteId)] = data; + } + } +} diff --git a/src/addon/mod/assign/feedback/editpdf/component/editpdf.html b/src/addon/mod/assign/feedback/editpdf/component/editpdf.html new file mode 100644 index 000000000..fc9633296 --- /dev/null +++ b/src/addon/mod/assign/feedback/editpdf/component/editpdf.html @@ -0,0 +1,7 @@ + + +

{{plugin.name}}

+
+ +
+
diff --git a/src/addon/mod/assign/feedback/editpdf/component/editpdf.ts b/src/addon/mod/assign/feedback/editpdf/component/editpdf.ts new file mode 100644 index 000000000..4ccf24e5b --- /dev/null +++ b/src/addon/mod/assign/feedback/editpdf/component/editpdf.ts @@ -0,0 +1,44 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component, OnInit } from '@angular/core'; +import { ModalController } from 'ionic-angular'; +import { AddonModAssignProvider } from '../../../providers/assign'; +import { AddonModAssignFeedbackPluginComponent } from '../../../classes/feedback-plugin-component'; + +/** + * Component to render a edit pdf feedback plugin. + */ +@Component({ + selector: 'addon-mod-assign-feedback-edit-pdf', + templateUrl: 'editpdf.html' +}) +export class AddonModAssignFeedbackEditPdfComponent extends AddonModAssignFeedbackPluginComponent implements OnInit { + + component = AddonModAssignProvider.COMPONENT; + files: any[]; + + constructor(modalCtrl: ModalController, protected assignProvider: AddonModAssignProvider) { + super(modalCtrl); + } + + /** + * Component being initialized. + */ + ngOnInit(): void { + if (this.plugin) { + this.files = this.assignProvider.getSubmissionPluginAttachments(this.plugin); + } + } +} diff --git a/src/addon/mod/assign/feedback/editpdf/editpdf.module.ts b/src/addon/mod/assign/feedback/editpdf/editpdf.module.ts new file mode 100644 index 000000000..defcb5e86 --- /dev/null +++ b/src/addon/mod/assign/feedback/editpdf/editpdf.module.ts @@ -0,0 +1,50 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { IonicModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { AddonModAssignFeedbackEditPdfHandler } from './providers/handler'; +import { AddonModAssignFeedbackEditPdfComponent } from './component/editpdf'; +import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegate'; +import { CoreComponentsModule } from '@components/components.module'; +import { CoreDirectivesModule } from '@directives/directives.module'; + +@NgModule({ + declarations: [ + AddonModAssignFeedbackEditPdfComponent + ], + imports: [ + CommonModule, + IonicModule, + TranslateModule.forChild(), + CoreComponentsModule, + CoreDirectivesModule + ], + providers: [ + AddonModAssignFeedbackEditPdfHandler + ], + exports: [ + AddonModAssignFeedbackEditPdfComponent + ], + entryComponents: [ + AddonModAssignFeedbackEditPdfComponent + ] +}) +export class AddonModAssignFeedbackEditPdfModule { + constructor(feedbackDelegate: AddonModAssignFeedbackDelegate, handler: AddonModAssignFeedbackEditPdfHandler) { + feedbackDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/assign/feedback/editpdf/lang/en.json b/src/addon/mod/assign/feedback/editpdf/lang/en.json new file mode 100644 index 000000000..a98c70fd9 --- /dev/null +++ b/src/addon/mod/assign/feedback/editpdf/lang/en.json @@ -0,0 +1,3 @@ +{ + "pluginname": "Annotate PDF" +} \ No newline at end of file diff --git a/src/addon/mod/assign/feedback/editpdf/providers/handler.ts b/src/addon/mod/assign/feedback/editpdf/providers/handler.ts new file mode 100644 index 000000000..1758fb8fe --- /dev/null +++ b/src/addon/mod/assign/feedback/editpdf/providers/handler.ts @@ -0,0 +1,65 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injectable, Injector } from '@angular/core'; +import { AddonModAssignProvider } from '../../../providers/assign'; +import { AddonModAssignFeedbackHandler } from '../../../providers/feedback-delegate'; +import { AddonModAssignFeedbackEditPdfComponent } from '../component/editpdf'; + +/** + * Handler for edit pdf feedback plugin. + */ +@Injectable() +export class AddonModAssignFeedbackEditPdfHandler implements AddonModAssignFeedbackHandler { + name = 'AddonModAssignFeedbackEditPdfHandler'; + type = 'editpdf'; + + constructor(private assignProvider: AddonModAssignProvider) { } + + /** + * Return the Component to use to display the plugin data, either in read or in edit mode. + * It's recommended to return the class of the component, but you can also return an instance of the component. + * + * @param {Injector} injector Injector. + * @param {any} plugin The plugin object. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getComponent(injector: Injector, plugin: any): any | Promise { + return AddonModAssignFeedbackEditPdfComponent; + } + + /** + * Get files used by this plugin. + * The files returned by this function will be prefetched when the user prefetches the assign. + * + * @param {any} assign The assignment. + * @param {any} submission The submission. + * @param {any} plugin The plugin object. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {any[]|Promise} The files (or promise resolved with the files). + */ + getPluginFiles(assign: any, submission: any, plugin: any, siteId?: string): any[] | Promise { + return this.assignProvider.getSubmissionPluginAttachments(plugin); + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } +} diff --git a/src/addon/mod/assign/feedback/feedback.module.ts b/src/addon/mod/assign/feedback/feedback.module.ts new file mode 100644 index 000000000..ef504bc2a --- /dev/null +++ b/src/addon/mod/assign/feedback/feedback.module.ts @@ -0,0 +1,31 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { AddonModAssignFeedbackCommentsModule } from './comments/comments.module'; +import { AddonModAssignFeedbackEditPdfModule } from './editpdf/editpdf.module'; +import { AddonModAssignFeedbackFileModule } from './file/file.module'; + +@NgModule({ + declarations: [], + imports: [ + AddonModAssignFeedbackCommentsModule, + AddonModAssignFeedbackEditPdfModule, + AddonModAssignFeedbackFileModule + ], + providers: [ + ], + exports: [] +}) +export class AddonModAssignFeedbackModule { } diff --git a/src/addon/mod/assign/feedback/file/component/file.html b/src/addon/mod/assign/feedback/file/component/file.html new file mode 100644 index 000000000..fc9633296 --- /dev/null +++ b/src/addon/mod/assign/feedback/file/component/file.html @@ -0,0 +1,7 @@ + + +

{{plugin.name}}

+
+ +
+
diff --git a/src/addon/mod/assign/feedback/file/component/file.ts b/src/addon/mod/assign/feedback/file/component/file.ts new file mode 100644 index 000000000..6074bc2f2 --- /dev/null +++ b/src/addon/mod/assign/feedback/file/component/file.ts @@ -0,0 +1,44 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component, OnInit } from '@angular/core'; +import { ModalController } from 'ionic-angular'; +import { AddonModAssignProvider } from '../../../providers/assign'; +import { AddonModAssignFeedbackPluginComponent } from '../../../classes/feedback-plugin-component'; + +/** + * Component to render a file feedback plugin. + */ +@Component({ + selector: 'addon-mod-assign-feedback-file', + templateUrl: 'file.html' +}) +export class AddonModAssignFeedbackFileComponent extends AddonModAssignFeedbackPluginComponent implements OnInit { + + component = AddonModAssignProvider.COMPONENT; + files: any[]; + + constructor(modalCtrl: ModalController, protected assignProvider: AddonModAssignProvider) { + super(modalCtrl); + } + + /** + * Component being initialized. + */ + ngOnInit(): void { + if (this.plugin) { + this.files = this.assignProvider.getSubmissionPluginAttachments(this.plugin); + } + } +} diff --git a/src/addon/mod/assign/feedback/file/file.module.ts b/src/addon/mod/assign/feedback/file/file.module.ts new file mode 100644 index 000000000..3ce4230db --- /dev/null +++ b/src/addon/mod/assign/feedback/file/file.module.ts @@ -0,0 +1,50 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { IonicModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { AddonModAssignFeedbackFileHandler } from './providers/handler'; +import { AddonModAssignFeedbackFileComponent } from './component/file'; +import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegate'; +import { CoreComponentsModule } from '@components/components.module'; +import { CoreDirectivesModule } from '@directives/directives.module'; + +@NgModule({ + declarations: [ + AddonModAssignFeedbackFileComponent + ], + imports: [ + CommonModule, + IonicModule, + TranslateModule.forChild(), + CoreComponentsModule, + CoreDirectivesModule + ], + providers: [ + AddonModAssignFeedbackFileHandler + ], + exports: [ + AddonModAssignFeedbackFileComponent + ], + entryComponents: [ + AddonModAssignFeedbackFileComponent + ] +}) +export class AddonModAssignFeedbackFileModule { + constructor(feedbackDelegate: AddonModAssignFeedbackDelegate, handler: AddonModAssignFeedbackFileHandler) { + feedbackDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/assign/feedback/file/lang/en.json b/src/addon/mod/assign/feedback/file/lang/en.json new file mode 100644 index 000000000..e5e6aeb98 --- /dev/null +++ b/src/addon/mod/assign/feedback/file/lang/en.json @@ -0,0 +1,3 @@ +{ + "pluginname": "File feedback" +} \ No newline at end of file diff --git a/src/addon/mod/assign/feedback/file/providers/handler.ts b/src/addon/mod/assign/feedback/file/providers/handler.ts new file mode 100644 index 000000000..fb3936a26 --- /dev/null +++ b/src/addon/mod/assign/feedback/file/providers/handler.ts @@ -0,0 +1,65 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injectable, Injector } from '@angular/core'; +import { AddonModAssignProvider } from '../../../providers/assign'; +import { AddonModAssignFeedbackHandler } from '../../../providers/feedback-delegate'; +import { AddonModAssignFeedbackFileComponent } from '../component/file'; + +/** + * Handler for file feedback plugin. + */ +@Injectable() +export class AddonModAssignFeedbackFileHandler implements AddonModAssignFeedbackHandler { + name = 'AddonModAssignFeedbackFileHandler'; + type = 'file'; + + constructor(private assignProvider: AddonModAssignProvider) { } + + /** + * Return the Component to use to display the plugin data, either in read or in edit mode. + * It's recommended to return the class of the component, but you can also return an instance of the component. + * + * @param {Injector} injector Injector. + * @param {any} plugin The plugin object. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getComponent(injector: Injector, plugin: any): any | Promise { + return AddonModAssignFeedbackFileComponent; + } + + /** + * Get files used by this plugin. + * The files returned by this function will be prefetched when the user prefetches the assign. + * + * @param {any} assign The assignment. + * @param {any} submission The submission. + * @param {any} plugin The plugin object. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {any[]|Promise} The files (or promise resolved with the files). + */ + getPluginFiles(assign: any, submission: any, plugin: any, siteId?: string): any[] | Promise { + return this.assignProvider.getSubmissionPluginAttachments(plugin); + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } +} 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 new file mode 100644 index 000000000..649bd289e --- /dev/null +++ b/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.html @@ -0,0 +1,16 @@ + + + + + + + + + +
+ + +
+
diff --git a/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.module.ts b/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.module.ts new file mode 100644 index 000000000..f7e67463d --- /dev/null +++ b/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.module.ts @@ -0,0 +1,35 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { AddonModAssignEditFeedbackModalPage } from './edit-feedback-modal'; +import { TranslateModule } from '@ngx-translate/core'; +import { CoreComponentsModule } from '@components/components.module'; +import { CoreDirectivesModule } from '@directives/directives.module'; +import { AddonModAssignComponentsModule } from '../../components/components.module'; + +@NgModule({ + declarations: [ + AddonModAssignEditFeedbackModalPage + ], + imports: [ + CoreComponentsModule, + CoreDirectivesModule, + AddonModAssignComponentsModule, + IonicPageModule.forChild(AddonModAssignEditFeedbackModalPage), + TranslateModule.forChild() + ] +}) +export class AddonModAssignEditFeedbackModalPageModule {} 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 new file mode 100644 index 000000000..01b24e5de --- /dev/null +++ b/src/addon/mod/assign/pages/edit-feedback-modal/edit-feedback-modal.ts @@ -0,0 +1,103 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component, Input } from '@angular/core'; +import { IonicPage, ViewController, NavParams } from 'ionic-angular'; +import { TranslateService } from '@ngx-translate/core'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegate'; + +/** + * Modal that allows editing a feedback plugin. + */ +@IonicPage({ segment: 'addon-mod-assign-edit-feedback-modal' }) +@Component({ + selector: 'page-addon-mod-assign-edit-feedback-modal', + templateUrl: 'edit-feedback-modal.html', +}) +export class AddonModAssignEditFeedbackModalPage { + + @Input() assign: any; // The assignment. + @Input() submission: any; // The submission. + @Input() plugin: any; // The plugin object. + @Input() userId: number; // The user ID of the submission. + + 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) { + + this.assign = params.get('assign'); + this.submission = params.get('submission'); + this.plugin = params.get('plugin'); + this.userId = params.get('userId'); + } + + /** + * Check if we can leave the page or not. + * + * @return {boolean|Promise} Resolved if we can leave it, rejected if not. + */ + ionViewCanLeave(): boolean | Promise { + if (this.forceLeave) { + return true; + } + + return this.hasDataChanged().then((changed) => { + if (changed) { + return this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); + } + }); + } + + /** + * Close modal. + * + * @param {any} data Data to return to the page. + */ + closeModal(data: any): void { + this.viewCtrl.dismiss(data); + } + + /** + * Done editing. + */ + done(): void { + // Close the modal, sending the input data. + this.forceLeave = true; + this.closeModal(this.getInputData()); + } + + /** + * Get the input data. + * + * @return {any} Object with the data. + */ + protected getInputData(): any { + return this.domUtils.getDataFromForm(document.forms['addon-mod_assign-edit-feedback-form']); + } + + /** + * Check if data has changed. + * + * @return {Promise} Promise resolved with boolean: whether the data has changed. + */ + protected hasDataChanged(): Promise { + return this.feedbackDelegate.hasPluginDataChanged(this.assign, this.userId, this.plugin, this.getInputData(), this.userId) + .catch(() => { + // Ignore errors. + return true; + }); + } +}