diff --git a/src/addon/mod/assign/providers/default-feedback-handler.ts b/src/addon/mod/assign/providers/default-feedback-handler.ts index 05466f140..0c3d03852 100644 --- a/src/addon/mod/assign/providers/default-feedback-handler.ts +++ b/src/addon/mod/assign/providers/default-feedback-handler.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Injectable } from '@angular/core'; +import { Injectable, Injector } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { AddonModAssignFeedbackHandler } from './feedback-delegate'; @@ -24,7 +24,43 @@ export class AddonModAssignDefaultFeedbackHandler implements AddonModAssignFeedb name = 'AddonModAssignDefaultFeedbackHandler'; type = 'default'; - constructor(private translate: TranslateService) { } + constructor(protected translate: TranslateService) { } + + /** + * 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 { + // Nothing to do. + } + + /** + * Return the Component to use to display the plugin data. + * 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 { + // Nothing to do. + } + + /** + * 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 { + // Nothing to do. + } /** * Get files used by this plugin. @@ -95,4 +131,46 @@ export class AddonModAssignDefaultFeedbackHandler implements AddonModAssignFeedb isEnabled(): boolean | Promise { return true; } + + /** + * Prefetch any required data for the plugin. + * This should NOT prefetch files. Files to be prefetched should be returned by the getPluginFiles function. + * + * @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 {Promise} Promise resolved when done. + */ + prefetch(assign: any, submission: any, plugin: any, siteId?: string): Promise { + return Promise.resolve(); + } + + /** + * 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 { + // Nothing to do. + } + + /** + * 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 { + // Nothing to do. + } } diff --git a/src/addon/mod/assign/providers/default-submission-handler.ts b/src/addon/mod/assign/providers/default-submission-handler.ts index e473ad898..aa1f84056 100644 --- a/src/addon/mod/assign/providers/default-submission-handler.ts +++ b/src/addon/mod/assign/providers/default-submission-handler.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Injectable } from '@angular/core'; +import { Injectable, Injector } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { AddonModAssignSubmissionHandler } from './submission-delegate'; @@ -24,7 +24,7 @@ export class AddonModAssignDefaultSubmissionHandler implements AddonModAssignSub name = 'AddonModAssignDefaultSubmissionHandler'; type = 'default'; - constructor(private translate: TranslateService) { } + constructor(protected translate: TranslateService) { } /** * Whether the plugin can be edited in offline for existing submissions. In general, this should return false if the @@ -40,6 +40,60 @@ export class AddonModAssignDefaultSubmissionHandler implements AddonModAssignSub return false; } + /** + * Should clear temporary data for a cancelled submission. + * + * @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 submission. + */ + clearTmpData(assign: any, submission: any, plugin: any, inputData: any): void { + // Nothing to do. + } + + /** + * This function will be called when the user wants to create a new submission based on the previous one. + * It should add to pluginData the data to send to server based in the data in plugin (previous attempt). + * + * @param {any} assign The assignment. + * @param {any} plugin The plugin object. + * @param {any} pluginData Object where to store the data to send. + * @param {number} [userId] User ID. If not defined, site's current user. + * @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. + */ + copySubmissionData(assign: any, plugin: any, pluginData: any, userId?: number, siteId?: string): void | Promise { + // Nothing to do. + } + + /** + * Delete any stored data for the plugin and submission. + * + * @param {any} assign The assignment. + * @param {any} submission The submission. + * @param {any} plugin The plugin object. + * @param {any} offlineData Offline data stored. + * @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. + */ + deleteOfflineData(assign: any, submission: any, plugin: any, offlineData: any, siteId?: string): void | Promise { + // Nothing to do. + } + + /** + * 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. + * @param {boolean} [edit] Whether the user is editing. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getComponent(injector: Injector, plugin: any, edit?: boolean): any | Promise { + // Nothing to do. + } + /** * Get files used by this plugin. * The files returned by this function will be prefetched when the user prefetches the assign. @@ -127,4 +181,53 @@ export class AddonModAssignDefaultSubmissionHandler implements AddonModAssignSub isEnabledForEdit(): boolean | Promise { return false; } + + /** + * Prefetch any required data for the plugin. + * This should NOT prefetch files. Files to be prefetched should be returned by the getPluginFiles function. + * + * @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 {Promise} Promise resolved when done. + */ + prefetch(assign: any, submission: any, plugin: any, siteId?: string): Promise { + return Promise.resolve(); + } + + /** + * Prepare and add to pluginData the data to send to the server based on the input data. + * + * @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 submission. + * @param {any} pluginData Object where to store the data to send. + * @param {boolean} [offline] Whether the user is editing in offline. + * @param {number} [userId] User ID. If not defined, site's current user. + * @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. + */ + prepareSubmissionData?(assign: any, submission: any, plugin: any, inputData: any, pluginData: any, offline?: boolean, + userId?: number, siteId?: string): void | Promise { + // Nothing to do. + } + + /** + * Prepare and add to pluginData the data to send to the server based on the offline data stored. + * This will be used when performing a synchronization. + * + * @param {any} assign The assignment. + * @param {any} submission The submission. + * @param {any} plugin The plugin object. + * @param {any} offlineData Offline data stored. + * @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. + */ + prepareSyncData?(assign: any, submission: any, plugin: any, offlineData: any, pluginData: any, siteId?: string) + : void | Promise { + // Nothing to do. + } } diff --git a/src/core/compile/providers/compile.ts b/src/core/compile/providers/compile.ts index 68c67cc42..828238d0f 100644 --- a/src/core/compile/providers/compile.ts +++ b/src/core/compile/providers/compile.ts @@ -79,6 +79,8 @@ import { CoreSitePluginsQuestionComponent } from '@core/siteplugins/components/q import { CoreSitePluginsQuestionBehaviourComponent } from '@core/siteplugins/components/question-behaviour/question-behaviour'; import { CoreSitePluginsUserProfileFieldComponent } from '@core/siteplugins/components/user-profile-field/user-profile-field'; import { CoreSitePluginsQuizAccessRuleComponent } from '@core/siteplugins/components/quiz-access-rule/quiz-access-rule'; +import { CoreSitePluginsAssignFeedbackComponent } from '@core/siteplugins/components/assign-feedback/assign-feedback'; +import { CoreSitePluginsAssignSubmissionComponent } from '@core/siteplugins/components/assign-submission/assign-submission'; /** * Service to provide functionalities regarding compiling dynamic HTML and Javascript. @@ -211,6 +213,8 @@ export class CoreCompileProvider { instance['CoreSitePluginsQuestionBehaviourComponent'] = CoreSitePluginsQuestionBehaviourComponent; instance['CoreSitePluginsUserProfileFieldComponent'] = CoreSitePluginsUserProfileFieldComponent; instance['CoreSitePluginsQuizAccessRuleComponent'] = CoreSitePluginsQuizAccessRuleComponent; + instance['CoreSitePluginsAssignFeedbackComponent'] = CoreSitePluginsAssignFeedbackComponent; + instance['CoreSitePluginsAssignSubmissionComponent'] = CoreSitePluginsAssignSubmissionComponent; } /** diff --git a/src/core/siteplugins/classes/handlers/assign-feedback-handler.ts b/src/core/siteplugins/classes/handlers/assign-feedback-handler.ts new file mode 100644 index 000000000..04b64049f --- /dev/null +++ b/src/core/siteplugins/classes/handlers/assign-feedback-handler.ts @@ -0,0 +1,63 @@ +// (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 { Injector } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { AddonModAssignDefaultFeedbackHandler } from '@addon/mod/assign/providers/default-feedback-handler'; +import { CoreSitePluginsAssignFeedbackComponent } from '../../components/assign-feedback/assign-feedback'; + +/** + * Handler to display an assign feedback site plugin. + */ +export class CoreSitePluginsAssignFeedbackHandler extends AddonModAssignDefaultFeedbackHandler { + + constructor(translate: TranslateService, public name: string, public type: string, protected prefix: string) { + super(translate); + } + + /** + * 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. + * @param {boolean} [edit] Whether the user is editing. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getComponent(injector: Injector, plugin: any, edit?: boolean): any | Promise { + return CoreSitePluginsAssignFeedbackComponent; + } + + /** + * Get a readable name to use for the plugin. + * + * @param {any} plugin The plugin object. + * @return {string} The plugin name. + */ + getPluginName(plugin: any): string { + // Check if there's a translated string for the plugin. + const translationId = this.prefix + 'pluginname', + translation = this.translate.instant(translationId); + + if (translationId != translation) { + // Translation found, use it. + return translation; + } + + // Fallback to WS string. + if (plugin.name) { + return plugin.name; + } + } +} diff --git a/src/core/siteplugins/classes/handlers/assign-submission-handler.ts b/src/core/siteplugins/classes/handlers/assign-submission-handler.ts new file mode 100644 index 000000000..c02a3cd7d --- /dev/null +++ b/src/core/siteplugins/classes/handlers/assign-submission-handler.ts @@ -0,0 +1,72 @@ +// (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 { Injector } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { AddonModAssignDefaultSubmissionHandler } from '@addon/mod/assign/providers/default-submission-handler'; +import { CoreSitePluginsAssignSubmissionComponent } from '../../components/assign-submission/assign-submission'; + +/** + * Handler to display an assign submission site plugin. + */ +export class CoreSitePluginsAssignSubmissionHandler extends AddonModAssignDefaultSubmissionHandler { + + constructor(translate: TranslateService, public name: string, public type: string, protected prefix: string) { + super(translate); + } + + /** + * 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. + * @param {boolean} [edit] Whether the user is editing. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getComponent(injector: Injector, plugin: any, edit?: boolean): any | Promise { + return CoreSitePluginsAssignSubmissionComponent; + } + + /** + * Get a readable name to use for the plugin. + * + * @param {any} plugin The plugin object. + * @return {string} The plugin name. + */ + getPluginName(plugin: any): string { + // Check if there's a translated string for the plugin. + const translationId = this.prefix + 'pluginname', + translation = this.translate.instant(translationId); + + if (translationId != translation) { + // Translation found, use it. + return translation; + } + + // Fallback to WS string. + if (plugin.name) { + return plugin.name; + } + } + + /** + * 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; + } +} diff --git a/src/core/siteplugins/components/assign-feedback/assign-feedback.html b/src/core/siteplugins/components/assign-feedback/assign-feedback.html new file mode 100644 index 000000000..f58bcd913 --- /dev/null +++ b/src/core/siteplugins/components/assign-feedback/assign-feedback.html @@ -0,0 +1 @@ + diff --git a/src/core/siteplugins/components/assign-feedback/assign-feedback.ts b/src/core/siteplugins/components/assign-feedback/assign-feedback.ts new file mode 100644 index 000000000..870ddc30b --- /dev/null +++ b/src/core/siteplugins/components/assign-feedback/assign-feedback.ts @@ -0,0 +1,67 @@ +// (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, Input } from '@angular/core'; +import { CoreSitePluginsProvider } from '../../providers/siteplugins'; +import { CoreSitePluginsCompileInitComponent } from '../../classes/compile-init-component'; + +/** + * Component that displays an assign feedback plugin created using a site plugin. + */ +@Component({ + selector: 'core-site-plugins-assign-feedback', + templateUrl: 'assign-feedback.html', +}) +export class CoreSitePluginsAssignFeedbackComponent extends CoreSitePluginsCompileInitComponent implements OnInit { + @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(sitePluginsProvider: CoreSitePluginsProvider) { + super(sitePluginsProvider); + } + + /** + * Component being initialized. + */ + ngOnInit(): void { + // Pass the input and output data to the component. + this.jsData = { + assign: this.assign, + submission: this.submission, + plugin: this.plugin, + userId: this.userId, + configs: this.configs, + edit: this.edit, + canEdit: this.canEdit + }; + + if (this.plugin) { + this.getHandlerData('assignfeedback_' + this.plugin.type); + } + } + + /** + * Invalidate the data. + * + * @return {Promise} Promise resolved when done. + */ + invalidate(): Promise { + return Promise.resolve(); + } +} diff --git a/src/core/siteplugins/components/assign-submission/assign-submission.html b/src/core/siteplugins/components/assign-submission/assign-submission.html new file mode 100644 index 000000000..f58bcd913 --- /dev/null +++ b/src/core/siteplugins/components/assign-submission/assign-submission.html @@ -0,0 +1 @@ + diff --git a/src/core/siteplugins/components/assign-submission/assign-submission.ts b/src/core/siteplugins/components/assign-submission/assign-submission.ts new file mode 100644 index 000000000..f01644488 --- /dev/null +++ b/src/core/siteplugins/components/assign-submission/assign-submission.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 { Component, OnInit, Input } from '@angular/core'; +import { CoreSitePluginsProvider } from '../../providers/siteplugins'; +import { CoreSitePluginsCompileInitComponent } from '../../classes/compile-init-component'; + +/** + * Component that displays an assign submission plugin created using a site plugin. + */ +@Component({ + selector: 'core-site-plugins-assign-submission', + templateUrl: 'assign-submission.html', +}) +export class CoreSitePluginsAssignSubmissionComponent extends CoreSitePluginsCompileInitComponent implements OnInit { + @Input() assign: any; // The assignment. + @Input() submission: any; // The submission. + @Input() plugin: any; // The plugin object. + @Input() configs: any; // The configs for the plugin. + @Input() edit: boolean; // Whether the user is editing. + @Input() allowOffline: boolean; // Whether to allow offline. + + constructor(sitePluginsProvider: CoreSitePluginsProvider) { + super(sitePluginsProvider); + } + + /** + * Component being initialized. + */ + ngOnInit(): void { + // Pass the input and output data to the component. + this.jsData = { + assign: this.assign, + submission: this.submission, + plugin: this.plugin, + configs: this.configs, + edit: this.edit, + allowOffline: this.allowOffline + }; + + if (this.plugin) { + this.getHandlerData('assignsubmission_' + this.plugin.type); + } + } + + /** + * Invalidate the data. + * + * @return {Promise} Promise resolved when done. + */ + invalidate(): Promise { + return Promise.resolve(); + } +} diff --git a/src/core/siteplugins/components/components.module.ts b/src/core/siteplugins/components/components.module.ts index c83d80db8..a5e5b75a7 100644 --- a/src/core/siteplugins/components/components.module.ts +++ b/src/core/siteplugins/components/components.module.ts @@ -26,6 +26,8 @@ import { CoreSitePluginsUserProfileFieldComponent } from './user-profile-field/u import { CoreSitePluginsQuestionComponent } from './question/question'; import { CoreSitePluginsQuestionBehaviourComponent } from './question-behaviour/question-behaviour'; import { CoreSitePluginsQuizAccessRuleComponent } from './quiz-access-rule/quiz-access-rule'; +import { CoreSitePluginsAssignFeedbackComponent } from './assign-feedback/assign-feedback'; +import { CoreSitePluginsAssignSubmissionComponent } from './assign-submission/assign-submission'; @NgModule({ declarations: [ @@ -36,7 +38,9 @@ import { CoreSitePluginsQuizAccessRuleComponent } from './quiz-access-rule/quiz- CoreSitePluginsUserProfileFieldComponent, CoreSitePluginsQuestionComponent, CoreSitePluginsQuestionBehaviourComponent, - CoreSitePluginsQuizAccessRuleComponent + CoreSitePluginsQuizAccessRuleComponent, + CoreSitePluginsAssignFeedbackComponent, + CoreSitePluginsAssignSubmissionComponent ], imports: [ CommonModule, @@ -55,7 +59,9 @@ import { CoreSitePluginsQuizAccessRuleComponent } from './quiz-access-rule/quiz- CoreSitePluginsUserProfileFieldComponent, CoreSitePluginsQuestionComponent, CoreSitePluginsQuestionBehaviourComponent, - CoreSitePluginsQuizAccessRuleComponent + CoreSitePluginsQuizAccessRuleComponent, + CoreSitePluginsAssignFeedbackComponent, + CoreSitePluginsAssignSubmissionComponent ], entryComponents: [ CoreSitePluginsModuleIndexComponent, @@ -64,7 +70,9 @@ import { CoreSitePluginsQuizAccessRuleComponent } from './quiz-access-rule/quiz- CoreSitePluginsUserProfileFieldComponent, CoreSitePluginsQuestionComponent, CoreSitePluginsQuestionBehaviourComponent, - CoreSitePluginsQuizAccessRuleComponent + CoreSitePluginsQuizAccessRuleComponent, + CoreSitePluginsAssignFeedbackComponent, + CoreSitePluginsAssignSubmissionComponent ] }) export class CoreSitePluginsComponentsModule {} diff --git a/src/core/siteplugins/providers/helper.ts b/src/core/siteplugins/providers/helper.ts index 5a05e7363..da08de28c 100644 --- a/src/core/siteplugins/providers/helper.ts +++ b/src/core/siteplugins/providers/helper.ts @@ -14,6 +14,7 @@ import { Injectable, Injector } from '@angular/core'; import { Http } from '@angular/http'; +import { TranslateService } from '@ngx-translate/core'; import { CoreEventsProvider } from '@providers/events'; import { CoreFilepoolProvider } from '@providers/filepool'; import { CoreLangProvider } from '@providers/lang'; @@ -40,6 +41,8 @@ import { CoreQuestionDelegate } from '@core/question/providers/delegate'; import { CoreQuestionBehaviourDelegate } from '@core/question/providers/behaviour-delegate'; import { AddonMessageOutputDelegate } from '@addon/messageoutput/providers/delegate'; import { AddonModQuizAccessRuleDelegate } from '@addon/mod/quiz/providers/access-rules-delegate'; +import { AddonModAssignFeedbackDelegate } from '@addon/mod/assign/providers/feedback-delegate'; +import { AddonModAssignSubmissionDelegate } from '@addon/mod/assign/providers/submission-delegate'; // Handler classes. import { CoreSitePluginsCourseFormatHandler } from '../classes/handlers/course-format-handler'; @@ -54,6 +57,8 @@ import { CoreSitePluginsQuestionHandler } from '../classes/handlers/question-han import { CoreSitePluginsQuestionBehaviourHandler } from '../classes/handlers/question-behaviour-handler'; import { CoreSitePluginsMessageOutputHandler } from '../classes/handlers/message-output-handler'; import { CoreSitePluginsQuizAccessRuleHandler } from '../classes/handlers/quiz-access-rule-handler'; +import { CoreSitePluginsAssignFeedbackHandler } from '../classes/handlers/assign-feedback-handler'; +import { CoreSitePluginsAssignSubmissionHandler } from '../classes/handlers/assign-submission-handler'; /** * Helper service to provide functionalities regarding site plugins. It basically has the features to load and register site @@ -78,8 +83,9 @@ export class CoreSitePluginsHelperProvider { private textUtils: CoreTextUtilsProvider, private filepoolProvider: CoreFilepoolProvider, private settingsDelegate: CoreSettingsDelegate, private questionDelegate: CoreQuestionDelegate, private questionBehaviourDelegate: CoreQuestionBehaviourDelegate, private questionProvider: CoreQuestionProvider, - private messageOutputDelegate: AddonMessageOutputDelegate, - private accessRulesDelegate: AddonModQuizAccessRuleDelegate) { + private messageOutputDelegate: AddonMessageOutputDelegate, private accessRulesDelegate: AddonModQuizAccessRuleDelegate, + private assignSubmissionDelegate: AddonModAssignSubmissionDelegate, private translate: TranslateService, + private assignFeedbackDelegate: AddonModAssignFeedbackDelegate) { this.logger = logger.getInstance('CoreSitePluginsHelperProvider'); @@ -469,6 +475,14 @@ export class CoreSitePluginsHelperProvider { promise = Promise.resolve(this.registerQuizAccessRuleHandler(plugin, handlerName, handlerSchema, result)); break; + case 'AddonModAssignFeedbackDelegate': + promise = Promise.resolve(this.registerAssignFeedbackHandler(plugin, handlerName, handlerSchema, result)); + break; + + case 'AddonModAssignSubmissionDelegate': + promise = Promise.resolve(this.registerAssignSubmissionHandler(plugin, handlerName, handlerSchema, result)); + break; + default: // Nothing to do. promise = Promise.resolve(); @@ -490,6 +504,108 @@ export class CoreSitePluginsHelperProvider { }); } + /** + * Given a handler in a plugin, register it in the assign feedback delegate. + * + * @param {any} plugin Data of the plugin. + * @param {string} handlerName Name of the handler in the plugin. + * @param {any} handlerSchema Data about the handler. + * @param {any} initResult Result of the init WS call. + * @return {string|Promise} A string (or a promise resolved with a string) to identify the handler. + */ + protected registerAssignFeedbackHandler(plugin: any, handlerName: string, handlerSchema: any, initResult: any) + : string | Promise { + if (!handlerSchema.method) { + // Required data not provided, stop. + this.logger.warn('Ignore site plugin because it doesn\'t provide method', plugin, handlerSchema); + + return; + } + + this.logger.debug('Register site plugin in assign feedback delegate:', plugin, handlerSchema, initResult); + + // Execute the main method and its JS. The template returned will be used in the feedback component. + return this.executeMethodAndJS(plugin, handlerSchema.method).then((result) => { + + // Create and register the handler. + const uniqueName = this.sitePluginsProvider.getHandlerUniqueName(plugin, handlerName), + type = plugin.component.replace('assignfeedback_', ''), + prefix = this.getPrefixForStrings(plugin.addon), + feedbackHandler = new CoreSitePluginsAssignFeedbackHandler(this.translate, uniqueName, type, prefix); + + // Store in handlerSchema some data required by the component. + handlerSchema.methodTemplates = result.templates; + handlerSchema.methodJSResult = result.jsResult; + + if (result && result.jsResult) { + // Override default handler functions with the result of the method JS. + for (const property in feedbackHandler) { + if (property != 'constructor' && typeof feedbackHandler[property] == 'function' && + typeof result.jsResult[property] == 'function') { + feedbackHandler[property] = result.jsResult[property].bind(feedbackHandler); + } + } + } + + this.assignFeedbackDelegate.registerHandler(feedbackHandler); + + return plugin.component; + }).catch((err) => { + this.logger.error('Error executing main method for assign feedback', handlerSchema.method, err); + }); + } + + /** + * Given a handler in a plugin, register it in the assign submission delegate. + * + * @param {any} plugin Data of the plugin. + * @param {string} handlerName Name of the handler in the plugin. + * @param {any} handlerSchema Data about the handler. + * @param {any} initResult Result of the init WS call. + * @return {string|Promise} A string (or a promise resolved with a string) to identify the handler. + */ + protected registerAssignSubmissionHandler(plugin: any, handlerName: string, handlerSchema: any, initResult: any) + : string | Promise { + if (!handlerSchema.method) { + // Required data not provided, stop. + this.logger.warn('Ignore site plugin because it doesn\'t provide method', plugin, handlerSchema); + + return; + } + + this.logger.debug('Register site plugin in assign submission delegate:', plugin, handlerSchema, initResult); + + // Execute the main method and its JS. The template returned will be used in the submission component. + return this.executeMethodAndJS(plugin, handlerSchema.method).then((result) => { + + // Create and register the handler. + const uniqueName = this.sitePluginsProvider.getHandlerUniqueName(plugin, handlerName), + type = plugin.component.replace('assignsubmission_', ''), + prefix = this.getPrefixForStrings(plugin.addon), + submissionHandler = new CoreSitePluginsAssignSubmissionHandler(this.translate, uniqueName, type, prefix); + + // Store in handlerSchema some data required by the component. + handlerSchema.methodTemplates = result.templates; + handlerSchema.methodJSResult = result.jsResult; + + if (result && result.jsResult) { + // Override default handler functions with the result of the method JS. + for (const property in submissionHandler) { + if (property != 'constructor' && typeof submissionHandler[property] == 'function' && + typeof result.jsResult[property] == 'function') { + submissionHandler[property] = result.jsResult[property].bind(submissionHandler); + } + } + } + + this.assignSubmissionDelegate.registerHandler(submissionHandler); + + return plugin.component; + }).catch((err) => { + this.logger.error('Error executing main method for assign submission', handlerSchema.method, err); + }); + } + /** * Given a handler in a plugin, register it in the course format delegate. *