MOBILE-2376 siteplugins: Support question behaviours
parent
02fd27d3d4
commit
bf658df6b4
|
@ -13,7 +13,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
||||||
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
||||||
|
|
||||||
|
@ -34,11 +34,12 @@ export class AddonQbehaviourAdaptiveHandler implements CoreQuestionBehaviourHand
|
||||||
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
* If the behaviour requires to show some extra data, it should return the components to render it.
|
* If the behaviour requires to show some extra data, it should return the components to render it.
|
||||||
*
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
* @param {any} question The question.
|
* @param {any} question The question.
|
||||||
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
||||||
* (e.g. certainty options). Don't return anything if no extra data is required.
|
* (e.g. certainty options). Don't return anything if no extra data is required.
|
||||||
*/
|
*/
|
||||||
handleQuestion(question: any): any[] | Promise<any[]> {
|
handleQuestion(injector: Injector, question: any): any[] | Promise<any[]> {
|
||||||
// Just extract the button, it doesn't need any specific component.
|
// Just extract the button, it doesn't need any specific component.
|
||||||
this.questionHelper.extractQbehaviourButtons(question);
|
this.questionHelper.extractQbehaviourButtons(question);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
||||||
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
||||||
|
|
||||||
|
@ -34,11 +34,12 @@ export class AddonQbehaviourAdaptiveNoPenaltyHandler implements CoreQuestionBeha
|
||||||
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
* If the behaviour requires to show some extra data, it should return the components to render it.
|
* If the behaviour requires to show some extra data, it should return the components to render it.
|
||||||
*
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
* @param {any} question The question.
|
* @param {any} question The question.
|
||||||
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
||||||
* (e.g. certainty options). Don't return anything if no extra data is required.
|
* (e.g. certainty options). Don't return anything if no extra data is required.
|
||||||
*/
|
*/
|
||||||
handleQuestion(question: any): any[] | Promise<any[]> {
|
handleQuestion(injector: Injector, question: any): any[] | Promise<any[]> {
|
||||||
// Just extract the button, it doesn't need any specific component.
|
// Just extract the button, it doesn't need any specific component.
|
||||||
this.questionHelper.extractQbehaviourButtons(question);
|
this.questionHelper.extractQbehaviourButtons(question);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
||||||
import { CoreQuestionDelegate } from '@core/question/providers/delegate';
|
import { CoreQuestionDelegate } from '@core/question/providers/delegate';
|
||||||
import { CoreQuestionState } from '@core/question/providers/question';
|
import { CoreQuestionState } from '@core/question/providers/question';
|
||||||
|
@ -55,11 +55,12 @@ export class AddonQbehaviourDeferredCBMHandler implements CoreQuestionBehaviourH
|
||||||
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
* If the behaviour requires to show some extra data, it should return the components to render it.
|
* If the behaviour requires to show some extra data, it should return the components to render it.
|
||||||
*
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
* @param {any} question The question.
|
* @param {any} question The question.
|
||||||
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
||||||
* (e.g. certainty options). Don't return anything if no extra data is required.
|
* (e.g. certainty options). Don't return anything if no extra data is required.
|
||||||
*/
|
*/
|
||||||
handleQuestion(question: any): any[] | Promise<any[]> {
|
handleQuestion(injector: Injector, question: any): any[] | Promise<any[]> {
|
||||||
if (this.questionHelper.extractQbehaviourCBM(question)) {
|
if (this.questionHelper.extractQbehaviourCBM(question)) {
|
||||||
return [AddonQbehaviourDeferredCBMComponent];
|
return [AddonQbehaviourDeferredCBMComponent];
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
||||||
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
||||||
import { AddonQbehaviourDeferredCBMComponent } from '@addon/qbehaviour/deferredcbm/component/deferredcbm';
|
import { AddonQbehaviourDeferredCBMComponent } from '@addon/qbehaviour/deferredcbm/component/deferredcbm';
|
||||||
|
@ -35,11 +35,12 @@ export class AddonQbehaviourImmediateCBMHandler implements CoreQuestionBehaviour
|
||||||
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
* If the behaviour requires to show some extra data, it should return the components to render it.
|
* If the behaviour requires to show some extra data, it should return the components to render it.
|
||||||
*
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
* @param {any} question The question.
|
* @param {any} question The question.
|
||||||
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
||||||
* (e.g. certainty options). Don't return anything if no extra data is required.
|
* (e.g. certainty options). Don't return anything if no extra data is required.
|
||||||
*/
|
*/
|
||||||
handleQuestion(question: any): any[] | Promise<any[]> {
|
handleQuestion(injector: Injector, question: any): any[] | Promise<any[]> {
|
||||||
// Just extract the button, it doesn't need any specific component.
|
// Just extract the button, it doesn't need any specific component.
|
||||||
this.questionHelper.extractQbehaviourButtons(question);
|
this.questionHelper.extractQbehaviourButtons(question);
|
||||||
if (this.questionHelper.extractQbehaviourCBM(question)) {
|
if (this.questionHelper.extractQbehaviourCBM(question)) {
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
||||||
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
||||||
|
|
||||||
|
@ -34,11 +34,12 @@ export class AddonQbehaviourImmediateFeedbackHandler implements CoreQuestionBeha
|
||||||
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
* If the behaviour requires to show some extra data, it should return the components to render it.
|
* If the behaviour requires to show some extra data, it should return the components to render it.
|
||||||
*
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
* @param {any} question The question.
|
* @param {any} question The question.
|
||||||
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
||||||
* (e.g. certainty options). Don't return anything if no extra data is required.
|
* (e.g. certainty options). Don't return anything if no extra data is required.
|
||||||
*/
|
*/
|
||||||
handleQuestion(question: any): any[] | Promise<any[]> {
|
handleQuestion(injector: Injector, question: any): any[] | Promise<any[]> {
|
||||||
// Just extract the button, it doesn't need any specific component.
|
// Just extract the button, it doesn't need any specific component.
|
||||||
this.questionHelper.extractQbehaviourButtons(question);
|
this.questionHelper.extractQbehaviourButtons(question);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
||||||
import { CoreQuestionProvider, CoreQuestionState } from '@core/question/providers/question';
|
import { CoreQuestionProvider, CoreQuestionState } from '@core/question/providers/question';
|
||||||
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
||||||
|
@ -52,11 +52,12 @@ export class AddonQbehaviourInformationItemHandler implements CoreQuestionBehavi
|
||||||
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
* If the behaviour requires to show some extra data, it should return the components to render it.
|
* If the behaviour requires to show some extra data, it should return the components to render it.
|
||||||
*
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
* @param {any} question The question.
|
* @param {any} question The question.
|
||||||
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
||||||
* (e.g. certainty options). Don't return anything if no extra data is required.
|
* (e.g. certainty options). Don't return anything if no extra data is required.
|
||||||
*/
|
*/
|
||||||
handleQuestion(question: any): any[] | Promise<any[]> {
|
handleQuestion(injector: Injector, question: any): any[] | Promise<any[]> {
|
||||||
if (this.questionHelper.extractQbehaviourSeenInput(question)) {
|
if (this.questionHelper.extractQbehaviourSeenInput(question)) {
|
||||||
return [AddonQbehaviourInformationItemComponent];
|
return [AddonQbehaviourInformationItemComponent];
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
||||||
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
||||||
|
|
||||||
|
@ -34,11 +34,12 @@ export class AddonQbehaviourInteractiveHandler implements CoreQuestionBehaviourH
|
||||||
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
* If the behaviour requires to show some extra data, it should return the components to render it.
|
* If the behaviour requires to show some extra data, it should return the components to render it.
|
||||||
*
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
* @param {any} question The question.
|
* @param {any} question The question.
|
||||||
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
||||||
* (e.g. certainty options). Don't return anything if no extra data is required.
|
* (e.g. certainty options). Don't return anything if no extra data is required.
|
||||||
*/
|
*/
|
||||||
handleQuestion(question: any): any[] | Promise<any[]> {
|
handleQuestion(injector: Injector, question: any): any[] | Promise<any[]> {
|
||||||
// Just extract the button, it doesn't need any specific component.
|
// Just extract the button, it doesn't need any specific component.
|
||||||
this.questionHelper.extractQbehaviourButtons(question);
|
this.questionHelper.extractQbehaviourButtons(question);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
import { CoreQuestionBehaviourHandler } from '@core/question/providers/behaviour-delegate';
|
||||||
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
||||||
|
|
||||||
|
@ -34,11 +34,12 @@ export class AddonQbehaviourInteractiveCountbackHandler implements CoreQuestionB
|
||||||
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
* If the behaviour requires to show some extra data, it should return the components to render it.
|
* If the behaviour requires to show some extra data, it should return the components to render it.
|
||||||
*
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
* @param {any} question The question.
|
* @param {any} question The question.
|
||||||
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
||||||
* (e.g. certainty options). Don't return anything if no extra data is required.
|
* (e.g. certainty options). Don't return anything if no extra data is required.
|
||||||
*/
|
*/
|
||||||
handleQuestion(question: any): any[] | Promise<any[]> {
|
handleQuestion(injector: Injector, question: any): any[] | Promise<any[]> {
|
||||||
// Just extract the button, it doesn't need any specific component.
|
// Just extract the button, it doesn't need any specific component.
|
||||||
this.questionHelper.extractQbehaviourButtons(question);
|
this.questionHelper.extractQbehaviourButtons(question);
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,10 @@
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Component, Input, OnInit, OnChanges, OnDestroy, ViewContainerRef, ViewChild, ComponentRef, SimpleChange, ChangeDetectorRef,
|
Component, Input, OnInit, OnChanges, OnDestroy, ViewContainerRef, ViewChild, ComponentRef, SimpleChange, ChangeDetectorRef,
|
||||||
ElementRef, Optional
|
ElementRef, Optional, Output, EventEmitter
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { NavController } from 'ionic-angular';
|
import { NavController } from 'ionic-angular';
|
||||||
import { CoreCompileProvider } from '../../providers/compile';
|
import { CoreCompileProvider } from '../../providers/compile';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component has a behaviour similar to $compile for AngularJS. Given an HTML code, it will compile it so all its
|
* This component has a behaviour similar to $compile for AngularJS. Given an HTML code, it will compile it so all its
|
||||||
|
@ -43,18 +42,17 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
||||||
@Input() text: string; // The HTML text to display.
|
@Input() text: string; // The HTML text to display.
|
||||||
@Input() javascript: string; // The Javascript to execute in the component.
|
@Input() javascript: string; // The Javascript to execute in the component.
|
||||||
@Input() jsData: any; // Data to pass to the fake component.
|
@Input() jsData: any; // Data to pass to the fake component.
|
||||||
|
@Output() created: EventEmitter<any> = new EventEmitter(); // Will emit an event when the component is instantiated.
|
||||||
|
|
||||||
// Get the container where to put the content.
|
// Get the container where to put the content.
|
||||||
@ViewChild('dynamicComponent', { read: ViewContainerRef }) container: ViewContainerRef;
|
@ViewChild('dynamicComponent', { read: ViewContainerRef }) container: ViewContainerRef;
|
||||||
|
|
||||||
protected componentRef: ComponentRef<any>;
|
protected componentRef: ComponentRef<any>;
|
||||||
protected element;
|
protected element;
|
||||||
componentObservable: BehaviorSubject<any>; // An observable to notify observers when the component is instantiated.
|
|
||||||
|
|
||||||
constructor(protected compileProvider: CoreCompileProvider, protected cdr: ChangeDetectorRef, element: ElementRef,
|
constructor(protected compileProvider: CoreCompileProvider, protected cdr: ChangeDetectorRef, element: ElementRef,
|
||||||
@Optional() protected navCtrl: NavController) {
|
@Optional() protected navCtrl: NavController) {
|
||||||
this.element = element.nativeElement;
|
this.element = element.nativeElement;
|
||||||
this.componentObservable = new BehaviorSubject<any>(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,7 +68,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
||||||
if (factory) {
|
if (factory) {
|
||||||
// Create the component.
|
// Create the component.
|
||||||
this.componentRef = this.container.createComponent(factory);
|
this.componentRef = this.container.createComponent(factory);
|
||||||
this.componentObservable.next(this.componentRef.instance);
|
this.created.emit(this.componentRef.instance);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,9 @@ import { CoreCourseFormatSingleActivityComponent } from '@core/course/formats/si
|
||||||
import { CoreSitePluginsModuleIndexComponent } from '@core/siteplugins/components/module-index/module-index';
|
import { CoreSitePluginsModuleIndexComponent } from '@core/siteplugins/components/module-index/module-index';
|
||||||
import { CoreSitePluginsCourseOptionComponent } from '@core/siteplugins/components/course-option/course-option';
|
import { CoreSitePluginsCourseOptionComponent } from '@core/siteplugins/components/course-option/course-option';
|
||||||
import { CoreSitePluginsCourseFormatComponent } from '@core/siteplugins/components/course-format/course-format';
|
import { CoreSitePluginsCourseFormatComponent } from '@core/siteplugins/components/course-format/course-format';
|
||||||
|
import { CoreSitePluginsQuestionComponent } from '@core/siteplugins/components/question/question';
|
||||||
|
import { CoreSitePluginsQuestionBehaviourComponent } from '@core/siteplugins/components/question-behaviour/question-behaviour';
|
||||||
|
import { CoreSitePluginsUserProfileFieldComponent } from '@core/siteplugins/components/user-profile-field/user-profile-field';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to provide functionalities regarding compiling dynamic HTML and Javascript.
|
* Service to provide functionalities regarding compiling dynamic HTML and Javascript.
|
||||||
|
@ -203,6 +206,9 @@ export class CoreCompileProvider {
|
||||||
instance['CoreSitePluginsModuleIndexComponent'] = CoreSitePluginsModuleIndexComponent;
|
instance['CoreSitePluginsModuleIndexComponent'] = CoreSitePluginsModuleIndexComponent;
|
||||||
instance['CoreSitePluginsCourseOptionComponent'] = CoreSitePluginsCourseOptionComponent;
|
instance['CoreSitePluginsCourseOptionComponent'] = CoreSitePluginsCourseOptionComponent;
|
||||||
instance['CoreSitePluginsCourseFormatComponent'] = CoreSitePluginsCourseFormatComponent;
|
instance['CoreSitePluginsCourseFormatComponent'] = CoreSitePluginsCourseFormatComponent;
|
||||||
|
instance['CoreSitePluginsQuestionComponent'] = CoreSitePluginsQuestionComponent;
|
||||||
|
instance['CoreSitePluginsQuestionBehaviourComponent'] = CoreSitePluginsQuestionBehaviourComponent;
|
||||||
|
instance['CoreSitePluginsUserProfileFieldComponent'] = CoreSitePluginsUserProfileFieldComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -123,11 +123,15 @@ export class CoreQuestionComponent implements OnInit {
|
||||||
|
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
// Handle behaviour.
|
// Handle behaviour.
|
||||||
this.behaviourDelegate.handleQuestion(this.question.preferredBehaviour, this.question).then((comps) => {
|
this.behaviourDelegate.handleQuestion(this.injector, this.question.preferredBehaviour, this.question)
|
||||||
|
.then((comps) => {
|
||||||
this.behaviourComponents = comps;
|
this.behaviourComponents = comps;
|
||||||
|
}).finally(() => {
|
||||||
|
this.question.html = this.domUtils.removeElementFromHtml(this.question.html, '.im-controls');
|
||||||
|
this.loaded = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.questionHelper.extractQbehaviourRedoButton(this.question);
|
this.questionHelper.extractQbehaviourRedoButton(this.question);
|
||||||
this.question.html = this.domUtils.removeElementFromHtml(this.question.html, '.im-controls');
|
|
||||||
|
|
||||||
// Extract the validation error of the question.
|
// Extract the validation error of the question.
|
||||||
this.question.validationError = this.questionHelper.getValidationErrorFromHtml(this.question.html);
|
this.question.validationError = this.questionHelper.getValidationErrorFromHtml(this.question.html);
|
||||||
|
@ -138,8 +142,6 @@ export class CoreQuestionComponent implements OnInit {
|
||||||
// Try to extract the feedback and comment for the question.
|
// Try to extract the feedback and comment for the question.
|
||||||
this.questionHelper.extractQuestionFeedback(this.question);
|
this.questionHelper.extractQuestionFeedback(this.question);
|
||||||
this.questionHelper.extractQuestionComment(this.question);
|
this.questionHelper.extractQuestionComment(this.question);
|
||||||
|
|
||||||
this.loaded = true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { CoreLoggerProvider } from '@providers/logger';
|
import { CoreLoggerProvider } from '@providers/logger';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
|
@ -48,11 +48,12 @@ export interface CoreQuestionBehaviourHandler extends CoreDelegateHandler {
|
||||||
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
* If the behaviour requires to show some extra data, it should return the components to render it.
|
* If the behaviour requires to show some extra data, it should return the components to render it.
|
||||||
*
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
* @param {any} question The question.
|
* @param {any} question The question.
|
||||||
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
||||||
* (e.g. certainty options). Don't return anything if no extra data is required.
|
* (e.g. certainty options). Don't return anything if no extra data is required.
|
||||||
*/
|
*/
|
||||||
handleQuestion?(question: any): any[] | Promise<any[]>;
|
handleQuestion?(injector: Injector, question: any): any[] | Promise<any[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,14 +91,15 @@ export class CoreQuestionBehaviourDelegate extends CoreDelegate {
|
||||||
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
* If the behaviour requires to show some extra data, it should return a directive to render it.
|
* If the behaviour requires to show some extra data, it should return a directive to render it.
|
||||||
*
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
* @param {string} behaviour Default behaviour.
|
* @param {string} behaviour Default behaviour.
|
||||||
* @param {any} question The question.
|
* @param {any} question The question.
|
||||||
* @return {Promise<any[]>} Promise resolved with components to render some extra data in the question.
|
* @return {Promise<any[]>} Promise resolved with components to render some extra data in the question.
|
||||||
*/
|
*/
|
||||||
handleQuestion(behaviour: string, question: any): Promise<any[]> {
|
handleQuestion(injector: Injector, behaviour: string, question: any): Promise<any[]> {
|
||||||
behaviour = this.questionDelegate.getBehaviourForQuestion(question, behaviour);
|
behaviour = this.questionDelegate.getBehaviourForQuestion(question, behaviour);
|
||||||
|
|
||||||
return Promise.resolve(this.executeFunctionOnEnabled(behaviour, 'handleQuestion', [question]));
|
return Promise.resolve(this.executeFunctionOnEnabled(behaviour, 'handleQuestion', [injector, question]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { CoreQuestionBehaviourHandler } from './behaviour-delegate';
|
import { CoreQuestionBehaviourHandler } from './behaviour-delegate';
|
||||||
import { CoreQuestionProvider, CoreQuestionState } from '@core/question/providers/question';
|
import { CoreQuestionProvider, CoreQuestionState } from '@core/question/providers/question';
|
||||||
|
|
||||||
|
@ -46,11 +46,12 @@ export class CoreQuestionBehaviourDefaultHandler implements CoreQuestionBehaviou
|
||||||
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
* If the behaviour requires to show some extra data, it should return the components to render it.
|
* If the behaviour requires to show some extra data, it should return the components to render it.
|
||||||
*
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
* @param {any} question The question.
|
* @param {any} question The question.
|
||||||
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
||||||
* (e.g. certainty options). Don't return anything if no extra data is required.
|
* (e.g. certainty options). Don't return anything if no extra data is required.
|
||||||
*/
|
*/
|
||||||
handleQuestion(question: any): any[] | Promise<any[]> {
|
handleQuestion(injector: Injector, question: any): any[] | Promise<any[]> {
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
// (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 { CoreSitePluginsProvider } from '../providers/siteplugins';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for components that will display a component using core-compile-html and want to call a
|
||||||
|
* componentInit function returned by the handler JS.
|
||||||
|
*/
|
||||||
|
export class CoreSitePluginsCompileInitComponent {
|
||||||
|
content = ''; // Content.
|
||||||
|
jsData: any; // Data to pass to the component.
|
||||||
|
protected handlerSchema: any; // The handler data.
|
||||||
|
|
||||||
|
constructor(protected sitePluginsProvider: CoreSitePluginsProvider) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called when the component is created.
|
||||||
|
*
|
||||||
|
* @param {any} instance The component instance.
|
||||||
|
*/
|
||||||
|
componentCreated(instance: any): void {
|
||||||
|
// Check if the JS defined an init function.
|
||||||
|
if (instance && this.handlerSchema && this.handlerSchema.methodJSResult &&
|
||||||
|
this.handlerSchema.methodJSResult.componentInit) {
|
||||||
|
this.handlerSchema.methodJSResult.componentInit.apply(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the handler data.
|
||||||
|
*
|
||||||
|
* @param {string} name The name of the handler.
|
||||||
|
*/
|
||||||
|
getHandlerData(name: string): void {
|
||||||
|
// Retrieve the handler data.
|
||||||
|
const handler = this.sitePluginsProvider.getSitePluginHandler(name);
|
||||||
|
|
||||||
|
this.handlerSchema = handler && handler.handlerSchema;
|
||||||
|
|
||||||
|
if (this.handlerSchema) {
|
||||||
|
// Load first template.
|
||||||
|
if (this.handlerSchema.methodTemplates && this.handlerSchema.methodTemplates.length) {
|
||||||
|
this.content = handler.handlerSchema.methodTemplates[0].html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 { Injector } from '@angular/core';
|
||||||
|
import { CoreQuestionBehaviourDefaultHandler } from '@core/question/providers/default-behaviour-handler';
|
||||||
|
import { CoreSitePluginsQuestionBehaviourComponent } from '../components/question-behaviour/question-behaviour';
|
||||||
|
import { CoreQuestionProvider } from '@core/question/providers/question';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler to display a question behaviour site plugin.
|
||||||
|
*/
|
||||||
|
export class CoreSitePluginsQuestionBehaviourHandler extends CoreQuestionBehaviourDefaultHandler {
|
||||||
|
|
||||||
|
constructor(questionProvider: CoreQuestionProvider, public name: string, public type: string, public hasTemplate: boolean) {
|
||||||
|
super(questionProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a question behaviour.
|
||||||
|
* If the behaviour requires a submit button, it should add it to question.behaviourButtons.
|
||||||
|
* If the behaviour requires to show some extra data, it should return the components to render it.
|
||||||
|
*
|
||||||
|
* @param {Injector} injector Injector.
|
||||||
|
* @param {any} question The question.
|
||||||
|
* @return {any[]|Promise<any[]>} Components (or promise resolved with components) to render some extra data in the question
|
||||||
|
* (e.g. certainty options). Don't return anything if no extra data is required.
|
||||||
|
*/
|
||||||
|
handleQuestion(injector: Injector, question: any): any[] | Promise<any[]> {
|
||||||
|
if (this.hasTemplate) {
|
||||||
|
return [CoreSitePluginsQuestionBehaviourComponent];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ import { CoreSitePluginsCourseOptionComponent } from './course-option/course-opt
|
||||||
import { CoreSitePluginsCourseFormatComponent } from './course-format/course-format';
|
import { CoreSitePluginsCourseFormatComponent } from './course-format/course-format';
|
||||||
import { CoreSitePluginsUserProfileFieldComponent } from './user-profile-field/user-profile-field';
|
import { CoreSitePluginsUserProfileFieldComponent } from './user-profile-field/user-profile-field';
|
||||||
import { CoreSitePluginsQuestionComponent } from './question/question';
|
import { CoreSitePluginsQuestionComponent } from './question/question';
|
||||||
|
import { CoreSitePluginsQuestionBehaviourComponent } from './question-behaviour/question-behaviour';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -32,7 +33,8 @@ import { CoreSitePluginsQuestionComponent } from './question/question';
|
||||||
CoreSitePluginsCourseOptionComponent,
|
CoreSitePluginsCourseOptionComponent,
|
||||||
CoreSitePluginsCourseFormatComponent,
|
CoreSitePluginsCourseFormatComponent,
|
||||||
CoreSitePluginsUserProfileFieldComponent,
|
CoreSitePluginsUserProfileFieldComponent,
|
||||||
CoreSitePluginsQuestionComponent
|
CoreSitePluginsQuestionComponent,
|
||||||
|
CoreSitePluginsQuestionBehaviourComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
@ -49,14 +51,16 @@ import { CoreSitePluginsQuestionComponent } from './question/question';
|
||||||
CoreSitePluginsCourseOptionComponent,
|
CoreSitePluginsCourseOptionComponent,
|
||||||
CoreSitePluginsCourseFormatComponent,
|
CoreSitePluginsCourseFormatComponent,
|
||||||
CoreSitePluginsUserProfileFieldComponent,
|
CoreSitePluginsUserProfileFieldComponent,
|
||||||
CoreSitePluginsQuestionComponent
|
CoreSitePluginsQuestionComponent,
|
||||||
|
CoreSitePluginsQuestionBehaviourComponent
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
CoreSitePluginsModuleIndexComponent,
|
CoreSitePluginsModuleIndexComponent,
|
||||||
CoreSitePluginsCourseOptionComponent,
|
CoreSitePluginsCourseOptionComponent,
|
||||||
CoreSitePluginsCourseFormatComponent,
|
CoreSitePluginsCourseFormatComponent,
|
||||||
CoreSitePluginsUserProfileFieldComponent,
|
CoreSitePluginsUserProfileFieldComponent,
|
||||||
CoreSitePluginsQuestionComponent
|
CoreSitePluginsQuestionComponent,
|
||||||
|
CoreSitePluginsQuestionBehaviourComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class CoreSitePluginsComponentsModule {}
|
export class CoreSitePluginsComponentsModule {}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<core-compile-html [text]="content" [jsData]="jsData" (created)="componentCreated($event)"></core-compile-html>
|
|
@ -0,0 +1,58 @@
|
||||||
|
// (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, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { CoreSitePluginsProvider } from '../../providers/siteplugins';
|
||||||
|
import { CoreSitePluginsCompileInitComponent } from '../../classes/compile-init-component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component that displays a question behaviour created using a site plugin.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'core-site-plugins-question-behaviour',
|
||||||
|
templateUrl: 'question-behaviour.html',
|
||||||
|
})
|
||||||
|
export class CoreSitePluginsQuestionBehaviourComponent extends CoreSitePluginsCompileInitComponent implements OnInit {
|
||||||
|
@Input() question: any; // The question where the behaviour will be rendered.
|
||||||
|
@Input() component: string; // The component the question belongs to.
|
||||||
|
@Input() componentId: number; // ID of the component the question belongs to.
|
||||||
|
@Input() attemptId: number; // Attempt ID.
|
||||||
|
@Input() offlineEnabled?: boolean | string; // Whether the question can be answered in offline.
|
||||||
|
@Output() buttonClicked: EventEmitter<any>; // Should emit an event when a behaviour button is clicked.
|
||||||
|
@Output() onAbort: EventEmitter<void>; // Should emit an event if the question should be aborted.
|
||||||
|
|
||||||
|
constructor(sitePluginsProvider: CoreSitePluginsProvider) {
|
||||||
|
super(sitePluginsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component being initialized.
|
||||||
|
*/
|
||||||
|
ngOnInit(): void {
|
||||||
|
// Pass the input and output data to the component.
|
||||||
|
this.jsData = {
|
||||||
|
question: this.question,
|
||||||
|
component: this.component,
|
||||||
|
componentId: this.componentId,
|
||||||
|
attemptId: this.attemptId,
|
||||||
|
offlineEnabled: this.offlineEnabled,
|
||||||
|
buttonClicked: this.buttonClicked,
|
||||||
|
onAbort: this.onAbort
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.question) {
|
||||||
|
this.getHandlerData('qbehaviour_' + this.question.preferredBehaviour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
<core-compile-html [text]="content" [jsData]="jsData"></core-compile-html>
|
<core-compile-html [text]="content" [jsData]="jsData" (created)="componentCreated($event)"></core-compile-html>
|
||||||
|
|
|
@ -12,10 +12,9 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnInit, Input, Output, EventEmitter, ViewChild, OnDestroy } from '@angular/core';
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
import { CoreSitePluginsProvider } from '../../providers/siteplugins';
|
import { CoreSitePluginsProvider } from '../../providers/siteplugins';
|
||||||
import { CoreCompileHtmlComponent } from '@core/compile/components/compile-html/compile-html';
|
import { CoreSitePluginsCompileInitComponent } from '../../classes/compile-init-component';
|
||||||
import { Subscription } from 'rxjs';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays a question created using a site plugin.
|
* Component that displays a question created using a site plugin.
|
||||||
|
@ -24,7 +23,7 @@ import { Subscription } from 'rxjs';
|
||||||
selector: 'core-site-plugins-question',
|
selector: 'core-site-plugins-question',
|
||||||
templateUrl: 'question.html',
|
templateUrl: 'question.html',
|
||||||
})
|
})
|
||||||
export class CoreSitePluginsQuestionComponent implements OnInit, OnDestroy {
|
export class CoreSitePluginsQuestionComponent extends CoreSitePluginsCompileInitComponent implements OnInit {
|
||||||
@Input() question: any; // The question to render.
|
@Input() question: any; // The question to render.
|
||||||
@Input() component: string; // The component the question belongs to.
|
@Input() component: string; // The component the question belongs to.
|
||||||
@Input() componentId: number; // ID of the component the question belongs to.
|
@Input() componentId: number; // ID of the component the question belongs to.
|
||||||
|
@ -33,13 +32,9 @@ export class CoreSitePluginsQuestionComponent implements OnInit, OnDestroy {
|
||||||
@Output() buttonClicked: EventEmitter<any>; // Should emit an event when a behaviour button is clicked.
|
@Output() buttonClicked: EventEmitter<any>; // Should emit an event when a behaviour button is clicked.
|
||||||
@Output() onAbort: EventEmitter<void>; // Should emit an event if the question should be aborted.
|
@Output() onAbort: EventEmitter<void>; // Should emit an event if the question should be aborted.
|
||||||
|
|
||||||
@ViewChild(CoreCompileHtmlComponent) compileComponent: CoreCompileHtmlComponent;
|
constructor(sitePluginsProvider: CoreSitePluginsProvider) {
|
||||||
|
super(sitePluginsProvider);
|
||||||
content = ''; // Content.
|
}
|
||||||
jsData;
|
|
||||||
protected componentObserver: Subscription;
|
|
||||||
|
|
||||||
constructor(protected sitePluginsProvider: CoreSitePluginsProvider) { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component being initialized.
|
* Component being initialized.
|
||||||
|
@ -57,34 +52,7 @@ export class CoreSitePluginsQuestionComponent implements OnInit, OnDestroy {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.question) {
|
if (this.question) {
|
||||||
// Retrieve the handler data.
|
this.getHandlerData('qtype_' + this.question.type);
|
||||||
const handler = this.sitePluginsProvider.getSitePluginHandler('qtype_' + this.question.type),
|
|
||||||
handlerSchema = handler && handler.handlerSchema;
|
|
||||||
|
|
||||||
if (handlerSchema) {
|
|
||||||
// Load first template.
|
|
||||||
if (handlerSchema.methodTemplates && handlerSchema.methodTemplates.length) {
|
|
||||||
this.content = handler.handlerSchema.methodTemplates[0].html;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the instance to be created.
|
|
||||||
if (this.compileComponent && this.compileComponent.componentObservable &&
|
|
||||||
handlerSchema.methodJSResult && handlerSchema.methodJSResult.componentInit) {
|
|
||||||
this.componentObserver = this.compileComponent.componentObservable.subscribe((instance) => {
|
|
||||||
if (instance) {
|
|
||||||
// Instance created, call component init.
|
|
||||||
handlerSchema.methodJSResult.componentInit.apply(instance);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Component destroyed.
|
|
||||||
*/
|
|
||||||
ngOnDestroy(): void {
|
|
||||||
this.componentObserver && this.componentObserver.unsubscribe();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<core-compile-html [text]="content" [jsData]="jsData"></core-compile-html>
|
<core-compile-html [text]="content" [jsData]="jsData" (created)="componentCreated($event)"></core-compile-html>
|
||||||
|
|
|
@ -12,10 +12,9 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnInit, Input, ViewChild, OnDestroy } from '@angular/core';
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
import { CoreSitePluginsProvider } from '../../providers/siteplugins';
|
import { CoreSitePluginsProvider } from '../../providers/siteplugins';
|
||||||
import { CoreCompileHtmlComponent } from '@core/compile/components/compile-html/compile-html';
|
import { CoreSitePluginsCompileInitComponent } from '../../classes/compile-init-component';
|
||||||
import { Subscription } from 'rxjs';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays a user profile field created using a site plugin.
|
* Component that displays a user profile field created using a site plugin.
|
||||||
|
@ -24,20 +23,16 @@ import { Subscription } from 'rxjs';
|
||||||
selector: 'core-site-plugins-user-profile-field',
|
selector: 'core-site-plugins-user-profile-field',
|
||||||
templateUrl: 'user-profile-field.html',
|
templateUrl: 'user-profile-field.html',
|
||||||
})
|
})
|
||||||
export class CoreSitePluginsUserProfileFieldComponent implements OnInit, OnDestroy {
|
export class CoreSitePluginsUserProfileFieldComponent extends CoreSitePluginsCompileInitComponent implements OnInit {
|
||||||
@Input() field: any; // The profile field to be rendered.
|
@Input() field: any; // The profile field to be rendered.
|
||||||
@Input() signup = false; // True if editing the field in signup. Defaults to false.
|
@Input() signup = false; // True if editing the field in signup. Defaults to false.
|
||||||
@Input() edit = false; // True if editing the field. Defaults to false.
|
@Input() edit = false; // True if editing the field. Defaults to false.
|
||||||
@Input() form?: any; // Form where to add the form control. Required if edit=true or signup=true.
|
@Input() form?: any; // Form where to add the form control. Required if edit=true or signup=true.
|
||||||
@Input() registerAuth?: string; // Register auth method. E.g. 'email'.
|
@Input() registerAuth?: string; // Register auth method. E.g. 'email'.
|
||||||
|
|
||||||
@ViewChild(CoreCompileHtmlComponent) compileComponent: CoreCompileHtmlComponent;
|
constructor(sitePluginsProvider: CoreSitePluginsProvider) {
|
||||||
|
super(sitePluginsProvider);
|
||||||
content = ''; // Content.
|
}
|
||||||
jsData;
|
|
||||||
protected componentObserver: Subscription;
|
|
||||||
|
|
||||||
constructor(protected sitePluginsProvider: CoreSitePluginsProvider) { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component being initialized.
|
* Component being initialized.
|
||||||
|
@ -54,34 +49,7 @@ export class CoreSitePluginsUserProfileFieldComponent implements OnInit, OnDestr
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.field) {
|
if (this.field) {
|
||||||
// Retrieve the handler data.
|
this.getHandlerData(this.field.type || this.field.datatype);
|
||||||
const handler = this.sitePluginsProvider.getSitePluginHandler(this.field.type || this.field.datatype),
|
|
||||||
handlerSchema = handler && handler.handlerSchema;
|
|
||||||
|
|
||||||
if (handlerSchema) {
|
|
||||||
// Load first template.
|
|
||||||
if (handlerSchema.methodTemplates && handlerSchema.methodTemplates.length) {
|
|
||||||
this.content = handler.handlerSchema.methodTemplates[0].html;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the instance to be created.
|
|
||||||
if (this.compileComponent && this.compileComponent.componentObservable &&
|
|
||||||
handlerSchema.methodJSResult && handlerSchema.methodJSResult.componentInit) {
|
|
||||||
this.componentObserver = this.compileComponent.componentObservable.subscribe((instance) => {
|
|
||||||
if (instance) {
|
|
||||||
// Instance created, call component init.
|
|
||||||
handlerSchema.methodJSResult.componentInit.apply(instance);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Component destroyed.
|
|
||||||
*/
|
|
||||||
ngOnDestroy(): void {
|
|
||||||
this.componentObserver && this.componentObserver.unsubscribe();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { CoreUrlUtilsProvider } from '@providers/utils/url';
|
||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreSitePluginsProvider } from './siteplugins';
|
import { CoreSitePluginsProvider } from './siteplugins';
|
||||||
import { CoreCompileProvider } from '@core/compile/providers/compile';
|
import { CoreCompileProvider } from '@core/compile/providers/compile';
|
||||||
|
import { CoreQuestionProvider } from '@core/question/providers/question';
|
||||||
|
|
||||||
// Delegates
|
// Delegates
|
||||||
import { CoreMainMenuDelegate } from '@core/mainmenu/providers/delegate';
|
import { CoreMainMenuDelegate } from '@core/mainmenu/providers/delegate';
|
||||||
|
@ -36,6 +37,7 @@ import { CoreUserDelegate } from '@core/user/providers/user-delegate';
|
||||||
import { CoreUserProfileFieldDelegate } from '@core/user/providers/user-profile-field-delegate';
|
import { CoreUserProfileFieldDelegate } from '@core/user/providers/user-profile-field-delegate';
|
||||||
import { CoreSettingsDelegate } from '@core/settings/providers/delegate';
|
import { CoreSettingsDelegate } from '@core/settings/providers/delegate';
|
||||||
import { CoreQuestionDelegate } from '@core/question/providers/delegate';
|
import { CoreQuestionDelegate } from '@core/question/providers/delegate';
|
||||||
|
import { CoreQuestionBehaviourDelegate } from '@core/question/providers/behaviour-delegate';
|
||||||
import { AddonMessageOutputDelegate } from '@addon/messageoutput/providers/delegate';
|
import { AddonMessageOutputDelegate } from '@addon/messageoutput/providers/delegate';
|
||||||
|
|
||||||
// Handler classes.
|
// Handler classes.
|
||||||
|
@ -48,6 +50,7 @@ import { CoreSitePluginsUserProfileHandler } from '../classes/user-handler';
|
||||||
import { CoreSitePluginsUserProfileFieldHandler } from '../classes/user-profile-field-handler';
|
import { CoreSitePluginsUserProfileFieldHandler } from '../classes/user-profile-field-handler';
|
||||||
import { CoreSitePluginsSettingsHandler } from '../classes/settings-handler';
|
import { CoreSitePluginsSettingsHandler } from '../classes/settings-handler';
|
||||||
import { CoreSitePluginsQuestionHandler } from '../classes/question-handler';
|
import { CoreSitePluginsQuestionHandler } from '../classes/question-handler';
|
||||||
|
import { CoreSitePluginsQuestionBehaviourHandler } from '../classes/question-behaviour-handler';
|
||||||
import { CoreSitePluginsMessageOutputHandler } from '../classes/message-output-handler';
|
import { CoreSitePluginsMessageOutputHandler } from '../classes/message-output-handler';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,6 +75,7 @@ export class CoreSitePluginsHelperProvider {
|
||||||
private courseFormatDelegate: CoreCourseFormatDelegate, private profileFieldDelegate: CoreUserProfileFieldDelegate,
|
private courseFormatDelegate: CoreCourseFormatDelegate, private profileFieldDelegate: CoreUserProfileFieldDelegate,
|
||||||
private textUtils: CoreTextUtilsProvider, private filepoolProvider: CoreFilepoolProvider,
|
private textUtils: CoreTextUtilsProvider, private filepoolProvider: CoreFilepoolProvider,
|
||||||
private settingsDelegate: CoreSettingsDelegate, private questionDelegate: CoreQuestionDelegate,
|
private settingsDelegate: CoreSettingsDelegate, private questionDelegate: CoreQuestionDelegate,
|
||||||
|
private questionBehaviourDelegate: CoreQuestionBehaviourDelegate, private questionProvider: CoreQuestionProvider,
|
||||||
private messageOutputDelegate: AddonMessageOutputDelegate) {
|
private messageOutputDelegate: AddonMessageOutputDelegate) {
|
||||||
|
|
||||||
this.logger = logger.getInstance('CoreSitePluginsHelperProvider');
|
this.logger = logger.getInstance('CoreSitePluginsHelperProvider');
|
||||||
|
@ -450,6 +454,10 @@ export class CoreSitePluginsHelperProvider {
|
||||||
promise = Promise.resolve(this.registerQuestionHandler(plugin, handlerName, handlerSchema, result));
|
promise = Promise.resolve(this.registerQuestionHandler(plugin, handlerName, handlerSchema, result));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'CoreQuestionBehaviourDelegate':
|
||||||
|
promise = Promise.resolve(this.registerQuestionBehaviourHandler(plugin, handlerName, handlerSchema, result));
|
||||||
|
break;
|
||||||
|
|
||||||
case 'AddonMessageOutputDelegate':
|
case 'AddonMessageOutputDelegate':
|
||||||
promise = Promise.resolve(this.registerMessageOutputHandler(plugin, handlerName, handlerSchema, result));
|
promise = Promise.resolve(this.registerMessageOutputHandler(plugin, handlerName, handlerSchema, result));
|
||||||
break;
|
break;
|
||||||
|
@ -666,6 +674,57 @@ export class CoreSitePluginsHelperProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a handler in an plugin, register it in the question behaviour 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<string>} A string (or a promise resolved with a string) to identify the handler.
|
||||||
|
*/
|
||||||
|
protected registerQuestionBehaviourHandler(plugin: any, handlerName: string, handlerSchema: any, initResult: any)
|
||||||
|
: string | Promise<string> {
|
||||||
|
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 question behaviour delegate:', plugin, handlerSchema, initResult);
|
||||||
|
|
||||||
|
// Execute the main method and its JS. The template returned will be used in the question 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('qbehaviour_', ''),
|
||||||
|
behaviourHandler = new CoreSitePluginsQuestionBehaviourHandler(this.questionProvider, uniqueName, type,
|
||||||
|
result.templates.length);
|
||||||
|
|
||||||
|
// 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 behaviourHandler) {
|
||||||
|
if (property != 'constructor' && typeof behaviourHandler[property] == 'function' &&
|
||||||
|
typeof result.jsResult[property] == 'function') {
|
||||||
|
behaviourHandler[property] = result.jsResult[property].bind(behaviourHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.questionBehaviourDelegate.registerHandler(behaviourHandler);
|
||||||
|
|
||||||
|
return plugin.component;
|
||||||
|
}).catch((err) => {
|
||||||
|
this.logger.error('Error executing main method for question', handlerSchema.method, err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a handler in an plugin, register it in the settings delegate.
|
* Given a handler in an plugin, register it in the settings delegate.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue