diff --git a/editor/question.html b/editor/question.html index 0da1e12..1e988a1 100644 --- a/editor/question.html +++ b/editor/question.html @@ -102,6 +102,15 @@

Configuration

Configuration

+
+ + +
Partial Scoring
diff --git a/editor/question.js b/editor/question.js new file mode 100644 index 0000000..229b55c --- /dev/null +++ b/editor/question.js @@ -0,0 +1,503 @@ +/* + * Plugin to create question + * @class org.ekstep.question.QuestionCreationFormController + * @author Jagadish Pujari + */ +angular.module('org.ekstep.question', ['org.ekstep.metadataform']) + .controller('QuestionCreationFormController', ['$scope', 'instance', 'questionData', function ($scope, instance, questionData) { + var ctrl = this; + ctrl.templatesScreen = true; + ctrl.questionMetadataScreen = false; + ctrl.Totalconcepts = 0; + ctrl.category = ''; + ctrl.editState = false; + ctrl.questionUnitTemplateURL = ''; + ctrl.editMode = false; + ctrl.defaultActiveMenu = 'MCQ'; + ctrl.selectedTemplatePluginData = {}; + ctrl.questionCreationFormData = {}; + ctrl.TotalconceptsData = []; + ctrl.selectedConceptsData = []; + ctrl.questionUnitValidated = false; + ctrl.level = ['EASY', 'MEDIUM', 'DIFFICULT']; + ctrl.conceptsCheck = false; + ctrl.questionData = {'questionMaxScore': 1}; + ctrl.plugins = {'concepts': 'org.ekstep.conceptselector:init'}; + ctrl.templatesType = ['Horizontal', 'Vertical', 'Grid']; + ctrl.questionData.isShuffleOption = false; + ctrl.questionData.isPartialScore = true; + ctrl.questionData.templateType = ctrl.templatesType[0]; + ctrl.refreshPreview = false; + ctrl.noTemplatesFound = ""; + ctrl.questionTemplates = []; + ctrl.questionMetaData = {}; + ctrl._constants = { + previewPlugin: 'org.ekstep.questionset.preview', + questionPlugin: 'org.ekstep.question', + questionsetPlugin: 'org.ekstep.questionset', + questionbankPlugin: 'org.ekstep.questionbank' + }; + + ctrl.init = function () { + ecEditor.addEventListener('editor:template:loaded', function (event, object) { + if(object.formAction == 'question-meta-save') { + ctrl.metadataform = object.templatePath; + } + }); + + if (!ecEditor._.isEmpty(questionData)) { + ctrl.editState = true; + ctrl.showQuestionForm(); + } else { + ctrl.showTemplates(); + } + + ecEditor.dispatchEvent(ctrl.plugins.concepts, { + element: 'conceptsTextBoxMeta', + selectedConcepts: ctrl.TotalconceptsData, // All composite keys except mediaType + callback: function (data) { + ctrl.Totalconcepts = data.length; + if (data.length > 0) + ctrl.conceptsCheck = true; + _.each(data, function (val, key) { + ctrl.selectedConceptsData[key] = val.id; + }); + $scope.$safeApply(); + } + }); + + $scope.$on('question:form:valid', ctrl.formValid); + $scope.$on('question:form:inValid', ctrl.formInValid); + EventBus.listeners['editor:form:data'] = undefined; + ecEditor.addEventListener('editor:form:data', ctrl.saveMetaData); + } + + + ctrl.loadPlugins = function(plugins, manifestMedia, cb) { + var pluginObj = []; + if (!Array.isArray(plugins)) { + pluginObj.push(plugins); + plugins = pluginObj; + } + org.ekstep.pluginframework.pluginManager.loadAllPlugins(plugins, manifestMedia, function() { + if (typeof PluginManager != 'undefined') { + PluginManager.pluginMap = org.ekstep.pluginframework.pluginManager.plugins; + } + if (cb) cb(); + }); + }; + + ctrl.showTemplates = function() { + ctrl.templatesScreen = true; + ctrl.questionMetadataScreen = false; + var qsInstance = org.ekstep.pluginframework.pluginManager.getPluginManifest(ctrl._constants.questionsetPlugin); + var qsVesrion = qsInstance.ver.split('.')[0]; + var data = { + "request": { + "filters": { + "objectType": ["Content"], + "contentType": ["Plugin"], + "targets.id": ctrl._constants.questionsetPlugin, + "targets.ver": {'<=': Number(qsVesrion)}, + "status": "Live" + }, + "limit": 50, + "fields": ['contentType','semanticVersion','appIcon'] + } + }; + + ecEditor.getService('search').search(data, function(err, resp) { + + var PluginsData = resp.data.result.content; + var plugins = [] + + ecEditor._.forEach(PluginsData, function(value, key) { + if (value) { + var obj = { + "id": value.identifier, + "ver": value.semanticVersion, + "type": 'plugin' + } + plugins.push(obj); + } + }); + + ctrl.loadPlugins(plugins, [], function() { + ctrl.questionTemplates = []; + _.each(PluginsData, function(val, key) { // eslint-disable-line no-unused-vars + if (val.contentType == "Plugin") { + var instance = org.ekstep.pluginframework.pluginManager.getPluginManifest(val.identifier); + var pluginID = val.identifier; + var ver = val.semanticVersion; + if (!_.isUndefined(instance.templates)) { + _.each(instance.templates, function(v, k) { // eslint-disable-line no-unused-vars + v.pluginID = pluginID; + v.ver = ver; + var thumbnail = val.appIcon; + v.thumbnail1 = thumbnail; + var allMenus = v; + ctrl.questionTemplates.push(allMenus); + }); + } else { + ctrl.noTemplatesFound = "There are no templates available"; + } + } + }); + $scope.$safeApply(); + }); + }); + } + + ctrl.showQuestionForm = function () { + ctrl.templatesScreen = false; + ctrl.questionMetadataScreen = false; + ctrl.editMode = true; + var questionData1 = typeof questionData.body == "string" ? JSON.parse(questionData.body) : questionData.body; + ctrl.assessmentId = questionData.identifier; + ctrl.questionData = questionData1; + ctrl.questionCreationFormData = questionData1.data.data; + ctrl.questionData.qcMedium = questionData1.data.config.metadata.medium; + ctrl.questionData.questionTitle = questionData1.data.config.metadata.title; + ctrl.questionData.qcLevel = questionData1.data.config.metadata.qlevel; + ctrl.questionData.subject = questionData1.data.config.metadata.subject; + ctrl.questionData.board = questionData1.data.config.metadata.board; + ctrl.questionData.templateType = questionData1.data.config.layout; + ctrl.questionData.isPartialScore = questionData1.data.config.partial_scoring; + ctrl.questionData.qcGrade = questionData1.data.config.metadata.gradeLevel; + ctrl.questionData.isShuffleOption = questionData1.data.config.isShuffleOption; + ctrl.category = questionData.category; + if (questionData1.data.config.metadata.concepts) { + ctrl.Totalconcepts = questionData1.data.config.metadata.concepts.length; + } + ctrl.questionData.concepts = questionData1.data.config.metadata.concepts; + ctrl.selectedConceptsData = questionData1.data.config.metadata.concepts; + ctrl.questionData.questionDesc = questionData1.data.config.metadata.description; + ctrl.questionData.questionMaxScore = questionData1.data.config.metadata.max_score; + ctrl.conceptsCheck = true; + $scope.questionEditData = questionData1.data; //Using this variable in question unit plugin for editing question + var pluginID = questionData1.data.plugin.id; + var pluginVer = questionData1.data.plugin.version; + var pluginTemplateId = questionData1.data.plugin.templateId; + var editCreateQuestionFormInstance = org.ekstep.pluginframework.pluginManager.getPluginManifest(questionData1.data.plugin.id); + _.each(editCreateQuestionFormInstance.templates, function (value, key) { // eslint-disable-line no-unused-vars + if (value.editor.template == questionData1.data.plugin.templateId) { + var templatePathEdit = ecEditor.resolvePluginResource(pluginID, pluginVer, value.editor.templateURL); + ctrl.questionUnitTemplateURL = templatePathEdit; + } + }); + + ctrl.selectedTemplatePluginData.plugin = { // Question Unit Plugin Information + "id": pluginID, // Id of plugin + "version": pluginVer, // Version of plugin + "templateId": pluginTemplateId // Template Id of the question unit + }; + $scope.$safeApply(); + }; + + ctrl.setPreviewData = function () { + var confData = {}; + var qObj = { + "config": '{"metadata":{"title":"question title","description":"question description","medium":"English"},"max_time":0,"max_score":1,"partial_scoring":' + ctrl.questionData.isPartialScore + ',"isShuffleOption":' + ctrl.questionData.isShuffleOption + ',"layout":' + JSON.stringify(ctrl.questionData.templateType) + '}', + "data": JSON.stringify(ctrl.questionCreationFormData), + "id": "c943d0a907274471a0572e593eab49c2", + "pluginId": ctrl.selectedTemplatePluginData.plugin.id, + "pluginVer": ctrl.selectedTemplatePluginData.plugin.version, + "templateId": ctrl.selectedTemplatePluginData.plugin.templateId, + "type": "unit" + } + var questions = []; + var data = { + "org.ekstep.questionset": {} + }; + + questions.push(qObj); + data[ctrl._constants.questionsetPlugin][ctrl._constants.questionPlugin] = questions; + confData = {"contentBody": {}, "parentElement": true, "element": "#iframeArea"}; + document.getElementById("iframeArea").contentDocument.location.reload(true); + var pluginInstances = ecEditor.getPluginInstances(); + var previewInstance = _.find(pluginInstances, function (pi) { + return pi.manifest.id === ctrl._constants.previewPlugin + }); + if (_.isUndefined(previewInstance)) { + previewInstance = ecEditor.instantiatePlugin(ctrl._constants.previewPlugin); + } + confData.contentBody = previewInstance.getQuestionPreviwContent(data[ctrl._constants.questionsetPlugin]); + ecEditor.dispatchEvent("atpreview:show", confData); + }; + + ctrl.loadPreview = function () { + if (ctrl.editMode === true) { + setTimeout(function () { + ctrl.setPreviewData(); + }, 100); + } + }; + + ctrl.loadDropdown = function () { + $('.ui.dropdown').dropdown({}); + }; + + ctrl.updatePreview = function () { + ctrl.showPreview(); + }; + + ctrl.showMetaform = function () { + ctrl.refreshPreview = false; + ctrl.validateQuestionCreationForm(); + }; + + ctrl.showPreview = function () { + ctrl.refreshPreview = true; + if (!ctrl.questionMetadataScreen) { + ctrl.validateQuestionCreationForm(); + } else { + ctrl.setPreviewData(); + } + }; + + ctrl.cancel = function () { + $scope.closeThisDialog(); + }; + + ctrl.setBackButtonState = function () { + if (ctrl.editState) { + if (ctrl.questionMetadataScreen) { + return false; + } else { + return true; + } + } else { + return false; + } + }; + + ctrl.back = function () { + if (!ctrl.questionMetadataScreen) { + ctrl.questionMetadataScreen = true; + ctrl.templatesScreen = true; + ctrl.showTemplates(); + } else { + var metaFormScope = $('#question-meta-form #content-meta-form').scope(); + ctrl.questionData.questionTitle = metaFormScope.contentMeta.name; + ctrl.questionData.qcMedium = metaFormScope.contentMeta.medium; + ctrl.questionData.qcLevel = metaFormScope.contentMeta.level; + ctrl.questionData.questionDesc = metaFormScope.contentMeta.description; + ctrl.questionData.questionMaxScore = metaFormScope.contentMeta.max_score; + ctrl.questionData.qcGrade = metaFormScope.contentMeta.gradeLevel; + ctrl.questionData.concepts = metaFormScope.contentMeta.concepts; + + ctrl.questionMetadataScreen = false; + } + }; + + ctrl.addCreateQuestionForm = function (obj) { + $('.ui.dropdown').dropdown({}); + ctrl.category = obj.category; + ctrl.templatesScreen = false; + ctrl.questionMetadataScreen = false; + ctrl.templateName = obj.title; + ctrl.selectedTemplatePluginData.plugin = { // Question Unit Plugin Information + "id": obj.pluginID, // Id of plugin + "version": obj.ver, // Version of plugin + "templateId": obj.editor.template // Template Id of the question unit + }; + ctrl.unitPlugin = obj.pluginID; + ctrl.pluginVer = obj.ver; + ctrl.templateId = obj.editor.template; + // var controllerPath = ecEditor.resolvePluginResource(obj.pluginID, obj.ver, obj.editor.controllerURL); + var templatePath = ecEditor.resolvePluginResource(obj.pluginID, obj.ver, obj.editor.templateURL); + ctrl.questionUnitTemplateURL = templatePath + '?BUILDNUMBER'; + }; + + ctrl.validateQuestionCreationForm = function (event) { // eslint-disable-line no-unused-vars + $scope.$broadcast('question:form:val'); + }; + + ctrl.formValid = function (event, data) { + ctrl.questionCreationFormData = data; + ctrl.setPreviewData(); + if (!ctrl.refreshPreview) { + ctrl.formIsValid(); + } + }; + + ctrl.formInValid = function () { + + }; + + ctrl.formIsValid = function () { + ctrl.questionMetadataScreen = true; + //comment because in edit question the question and question title are not + if (ctrl.category == 'FTB') { + ctrl.questionData.questionTitle = _.isUndefined(ctrl.questionData.questionTitle) ? ctrl.questionCreationFormData.question.text.replace(/\[\[.*?\]\]/g, '____') : ctrl.questionData.questionTitle; + } else { + ctrl.questionData.questionTitle = _.isUndefined(ctrl.questionData.questionTitle) ? ctrl.questionCreationFormData.question.text : ctrl.questionData.questionTitle; + } + ctrl.questionData.questionTitle = ctrl.extractHTML(ctrl.questionData.questionTitle); + $('.QuestionMetaForm .ui.dropdown').dropdown({}); + ctrl.questionMetaData.name = ctrl.questionData.questionTitle; + ctrl.questionMetaData.medium = ctrl.questionData.qcMedium; + ctrl.questionMetaData.level = ctrl.questionData.qcLevel; + ctrl.questionMetaData.description = ctrl.questionData.questionDesc; + ctrl.questionMetaData.max_score = ctrl.questionData.questionMaxScore; + ctrl.questionMetaData.gradeLevel = ctrl.questionData.qcGrade; + ctrl.questionMetaData.concepts = ctrl.questionData.concepts; + ctrl.questionMetaData.subject = ctrl.questionData.subject; + ctrl.questionMetaData.board = ctrl.questionData.board; + if (ctrl.questionMetaData.concepts) { + ctrl.questionMetaData.conceptData = "(" + ctrl.questionData.concepts.length + ") concepts selected"; + } + + ecEditor.dispatchEvent('org.ekstep.editcontentmeta:showpopup', { + action: 'question-meta-save', + subType: 'questions', + framework: ecEditor.getContext('framework'), + rootOrgId: ecEditor.getContext('channel'), + type: 'content', + popup: false, + metadata: ctrl.questionMetaData + }); + }; + + ctrl.saveQuestion = function (assessmentId, data) { + //If identifier present update the question data + ecEditor.getService('assessment').saveQuestionV3(assessmentId, data, function (err, resp) { + if (!err) { + var qMetadata = ctrl.qFormData.request.assessment_item.metadata; + qMetadata.identifier = resp.data.result.node_id; + ecEditor.dispatchEvent(ctrl._constants.questionbankPlugin + ':saveQuestion', qMetadata); + $scope.closeThisDialog(); + } else { + //toast with error message + ecEditor.dispatchEvent("org.ekstep.toaster:error", { + title: 'Failed to save question...', + position: 'topCenter', + }); + } + }); + } + + ctrl.sendMetaData = function () { + var formElement = $("#questionMetadataTemplate").find("#content-meta-form"); + var frmScope = formElement.scope(); + ecEditor.dispatchEvent("metadata:form:onsuccess", {form: frmScope.metaForm}); + }; + + ctrl.saveMetaData = function (event, object) { + var metaDataObject = object.formData.metaData; + for (var property in object.formData.metaData) { + if (metaDataObject[property]) { + ctrl.questionMetaData[property] = metaDataObject[property]; + } + } + var questionFormData = {}; + var data = {}; // TODO: You have to get this from Q.Unit plugin(getData()) + data.plugin = ctrl.selectedTemplatePluginData.plugin; + data.data = ctrl.questionCreationFormData; + + var metadataObj = { category: ctrl.category, title: ctrl.questionMetaData.name, medium: ctrl.questionMetaData.medium, qlevel: ctrl.questionMetaData.level, gradeLevel: ctrl.questionMetaData.gradeLevel, concepts: ctrl.questionMetaData.concepts, description: ctrl.questionMetaData.description, max_score: ctrl.questionMetaData.max_score, subject: ctrl.questionMetaData.subject, board: ctrl.questionMetaData.board }; + data.config = { "metadata": metadataObj, "max_time": 0, "max_score": ctrl.questionData.questionMaxScore, "partial_scoring": ctrl.questionData.isPartialScore, "layout": ctrl.questionData.templateType, "isShuffleOption" : ctrl.questionData.isShuffleOption, "questionCount": ctrl.questionCreationFormData.questionCount}; + + data.media = ctrl.questionCreationFormData.media; + questionFormData.data = data; + var metadata = { + "code": "NA", + "name": ctrl.questionMetaData.name, + "qlevel": ctrl.questionMetaData.level, + "title": ctrl.questionMetaData.name, + "question": ctrl.questionCreationFormData.question.text, + "max_score": ctrl.questionMetaData.max_score, + "isShuffleOption" : ctrl.questionData.isShuffleOption, + "body": JSON.stringify(questionFormData), + "medium": ctrl.questionMetaData.medium, + "subject": ctrl.questionMetaData.subject, + "board": ctrl.questionMetaData.board, + "itemType": "UNIT", + "version": 2, + "category": ctrl.category, + "description": ctrl.questionMetaData.description, + "createdBy": window.context.user.id, + "channel": ecEditor.getContext('channel'), + "type": ctrl.category.toLowerCase(), // backward compatibility + "template": "NA", // backward compatibility + "template_id": "NA", // backward compatibility + }; + var dynamicOptions = [{"answer": true, "value": {"type": "text", "asset": "1"}}]; + var mtfoptions = [{ + "value": { + "type": "mixed", + "text": "इक", + "image": "", + "count": "", + "audio": "", + "resvalue": "इक", + "resindex": 0 + }, + "index": 0 + }]; + switch (ctrl.category) { + case 'MCQ': + metadata.options = dynamicOptions; + break; + case 'FTB': + metadata.answer = dynamicOptions; + break; + case 'MTF': + metadata.lhs_options = mtfoptions; + metadata.rhs_options = mtfoptions; + break; + default: + metadata.options = dynamicOptions; + break; + } + ctrl.qFormData = { + "request": { + "assessment_item": { + "objectType": "AssessmentItem", + "metadata": metadata + } + } + }; + + /*Save data and get response and dispatch event with response to questionbank plugin*/ + ctrl.saveQuestion(ctrl.assessmentId, ctrl.qFormData); + }; + + ctrl.extractHTML = function(htmlElement) { + var divElement= document.createElement('div'); + divElement.innerHTML= htmlElement; + return divElement.textContent || divElement.innerText; + } + + ctrl.genImpressionTelemetry = function(data) { + if (data) ecEditor.getService('telemetry').impression({ + "type": data.type, + "subtype": data.subtype, + "pageid": data.pageid, + "uri": encodeURIComponent(location.href), + "visits": { + 'objid': data.visits.objid, + 'objtype': data.visits.objtype + } + }) + } + + ctrl.generateTelemetry = function(data, event) { + if (data) ecEditor.getService('telemetry').interact({ + "type": data.type, + "id": data.id, + "pageid": 'question-creation-form', + "target": { + "id": data.target.id, + "ver": data.target.ver, + "type": data.target.type + }, + "plugin": { + "id": instance.manifest.id, + "ver": instance.manifest.ver + } + }) + } + ctrl.init(); + }]); +//# sourceURL=question.js \ No newline at end of file diff --git a/editor/style.css b/editor/style.css index 27e8871..1909f9d 100644 --- a/editor/style.css +++ b/editor/style.css @@ -267,4 +267,8 @@ color: white; .formDiv{ overflow: auto; -} \ No newline at end of file +} + +.pull-left{ + float: left; +}