UNPKG

tailor-teaching-elements

Version:
1,916 lines (1,695 loc) 122 kB
import get from 'lodash/get'; import 'quill/dist/quill.core.css'; import 'jodit/build/jodit.min.css'; import VueScrollTo from 'vue-scrollto'; import map from 'lodash/map'; import sortBy from 'lodash/sortBy'; import Draggable from 'vuedraggable'; import includes from 'lodash/includes'; import mapValues from 'lodash/mapValues'; import reduce from 'lodash/reduce'; import shuffle from 'lodash/shuffle'; import camelCase from 'lodash/camelCase'; import isArray from 'lodash/isArray'; import isBoolean from 'lodash/isBoolean'; import isNumber from 'lodash/isNumber'; import find from 'lodash/find'; import zipWith from 'lodash/zipWith'; import every from 'lodash/every'; import isEqual from 'lodash/isEqual'; import toLower from 'lodash/toLower'; import xor from 'lodash/xor'; import _uniqueId from 'lodash/uniqueId'; import APlayer from 'vue-aplayer'; import join from 'url-join'; import { PlyrueComponent } from 'plyrue'; var ASSESSMENT_TYPE = { MC: 'multiple-choice', MQ: 'matching-question', SC: 'single-choice', TF: 'true-false', NR: 'numerical-response', TR: 'text-response', FB: 'fill-blank', DD: 'drag-drop' }; var TE_TYPE = { AUDIO: 'te-audio', BREAK: 'te-break', EMBED: 'te-embed', HTML: 'te-html', FILE: 'te-file', IMAGE: 'te-image', ASSESSMENT: 'te-assessment', REFLECTION: 'te-reflection', VIDEO: 'te-video', ACCORDION: 'te-accordion', CAROUSEL: 'te-carousel', JODIT_HTML: 'te-jodit-html', MODAL: 'te-modal', TABLE: 'te-table', PDF: 'te-pdf', BRIGHTCOVE_VIDEO: 'te-brightcove-video' }; var subTypeInfo = { MC: { type: 'MC', title: 'Multiple choice', class: 'multiple-choice', helperText: 'Select the choice(s) that best answers the question below.', feedback: true }, SC: { type: 'SC', title: 'Single choice', class: 'single-choice', helperText: 'Select one choice that best answers the question below.', feedback: true }, TR: { type: 'TR', title: 'Text response', class: 'text-response', helperText: 'Enter text into the empty field below and submit your answer to see the suggested answer.', feedback: true, allowRetake: false }, NR: { type: 'NR', title: 'Numerical response', class: 'numerical-response', helperText: 'Enter a number in the field below.', feedback: false }, TF: { type: 'TF', title: 'True - false', class: 'true-false', helperText: 'Answer the question with true or false.', feedback: true }, FB: { type: 'FB', title: 'Fill in the blank', class: 'fill-blank', helperText: 'Enter text into the empty field(s) below and submit your answer for feedback.' }, DD: { type: 'DD', title: 'Drag & Drop', class: 'drag-drop', helperText: 'Group items by dragging them into their corresponding boxes.' }, MQ: { type: 'MQ', title: 'Matching question', class: 'matching-question', helperText: 'Match items by dragging and dropping each item into the corresponding box.' } }; // // // // // // // // // // // // // // // // // // // // // // // var EXPANDED_HEIGHT = '98vh'; var script = { name: 'te-embed', props: { height: { type: [Number, String], default: 600 }, url: { type: String, required: true } }, data: function data() { return { expanded: false, showOverlay: true }; }, computed: { embedHeight: function embedHeight() { return this.expanded ? EXPANDED_HEIGHT : "".concat(this.height, "px"); } }, methods: { toggleExpand: function toggleExpand() { this.expanded = !this.expanded; if (this.showOverlay) this.showOverlay = false; } } }; function styleInject(css, ref) { if ( ref === void 0 ) ref = {}; var insertAt = ref.insertAt; if (!css || typeof document === 'undefined') { return; } var head = document.head || document.getElementsByTagName('head')[0]; var style = document.createElement('style'); style.type = 'text/css'; if (insertAt === 'top') { if (head.firstChild) { head.insertBefore(style, head.firstChild); } else { head.appendChild(style); } } else { head.appendChild(style); } if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } } var css = ".te-embed{position:relative;overflow:auto}.te-embed .content{width:100%}.te-embed .te-embed-toolbar{opacity:0;position:absolute;top:0;left:0;z-index:1;padding:7px 0 0 7px;font-size:16px;transition:opacity .7s}.te-embed .te-embed-toolbar .tes-icon{padding:3px 6px;background-color:#e0e0e0;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.87);transition:background-color .5s}.te-embed .te-embed-toolbar .tes-icon:hover{background-color:#d0d0d0}.te-embed .te-embed-toolbar .mdi-close{font-size:18px}.te-embed:hover .te-embed-toolbar{opacity:1}.te-embed.expanded{position:fixed;top:50%;left:50%;z-index:10000;transform:translate(-50%,-50%);width:98%;box-shadow:0 2px 4px rgba(0,0,0,.87)}.interactive{position:absolute;top:0;right:0;bottom:0;left:0}"; styleInject(css); function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { if (typeof shadowMode !== 'boolean') { createInjectorSSR = createInjector; createInjector = shadowMode; shadowMode = false; } // Vue.extend constructor export interop. const options = typeof script === 'function' ? script.options : script; // render functions if (template && template.render) { options.render = template.render; options.staticRenderFns = template.staticRenderFns; options._compiled = true; // functional template if (isFunctionalTemplate) { options.functional = true; } } // scopedId if (scopeId) { options._scopeId = scopeId; } let hook; if (moduleIdentifier) { // server build hook = function (context) { // 2.3 injection context = context || // cached call (this.$vnode && this.$vnode.ssrContext) || // stateful (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional // 2.2 with runInNewContext: true if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { context = __VUE_SSR_CONTEXT__; } // inject component styles if (style) { style.call(this, createInjectorSSR(context)); } // register component module identifier for async chunk inference if (context && context._registeredComponents) { context._registeredComponents.add(moduleIdentifier); } }; // used by ssr in case component is cached and beforeCreate // never gets called options._ssrRegister = hook; } else if (style) { hook = shadowMode ? function (context) { style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot)); } : function (context) { style.call(this, createInjector(context)); }; } if (hook) { if (options.functional) { // register for functional component in vue file const originalRender = options.render; options.render = function renderWithStyleInjection(h, context) { hook.call(context); return originalRender(h, context); }; } else { // inject component registration as beforeCreate hook const existing = options.beforeCreate; options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; } } return script; } const isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()); /* script */ var __vue_script__ = script; /* template */ var __vue_render__ = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "te-embed", class: { expanded: _vm.expanded } }, [_c('iframe', { staticClass: "content", style: { height: _vm.embedHeight }, attrs: { "src": _vm.url, "frameborder": "0" } }), _vm._v(" "), _c('div', { directives: [{ name: "show", rawName: "v-show", value: _vm.showOverlay, expression: "showOverlay" }], staticClass: "interactive", on: { "click": function click($event) { _vm.showOverlay = false; } } }), _vm._v(" "), _c('div', { staticClass: "te-embed-toolbar" }, [_c('span', { staticClass: "mdi tes-icon", class: _vm.expanded ? 'mdi-close' : 'mdi-arrow-expand-all', on: { "click": _vm.toggleExpand } })])]); }; var __vue_staticRenderFns__ = []; /* style */ var __vue_inject_styles__ = undefined; /* scoped */ var __vue_scope_id__ = undefined; /* module identifier */ var __vue_module_identifier__ = undefined; /* functional template */ var __vue_is_functional_template__ = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__ = normalizeComponent({ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, false, undefined, undefined, undefined); // var script$1 = { name: 'te-html', props: { content: { type: String, required: true } } }; var css$1 = ".te-html .content{padding:12px 15px}.te-html .blank{display:inline-block;margin:0 5px}.te-html .blank .blank-line{display:inline-block;width:50px;border-bottom:1px solid #000}"; styleInject(css$1); /* script */ var __vue_script__$1 = script$1; /* template */ var __vue_render__$1 = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "ql-container te-html" }, [_c('div', { staticClass: "ql-editor content", domProps: { "innerHTML": _vm._s(_vm.content) } })]); }; var __vue_staticRenderFns__$1 = []; /* style */ var __vue_inject_styles__$1 = undefined; /* scoped */ var __vue_scope_id__$1 = undefined; /* module identifier */ var __vue_module_identifier__$1 = undefined; /* functional template */ var __vue_is_functional_template__$1 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$1 = normalizeComponent({ render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 }, __vue_inject_styles__$1, __vue_script__$1, __vue_scope_id__$1, __vue_is_functional_template__$1, __vue_module_identifier__$1, false, undefined, undefined, undefined); // // // // // // var script$2 = { name: 'te-image', props: { url: { type: String, required: true } } }; var css$2 = ".te-image img{display:block;max-width:100%;height:auto;margin:0 auto}"; styleInject(css$2); /* script */ var __vue_script__$2 = script$2; /* template */ var __vue_render__$2 = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "te-image" }, [_c('img', { attrs: { "src": _vm.url } })]); }; var __vue_staticRenderFns__$2 = []; /* style */ var __vue_inject_styles__$2 = undefined; /* scoped */ var __vue_scope_id__$2 = undefined; /* module identifier */ var __vue_module_identifier__$2 = undefined; /* functional template */ var __vue_is_functional_template__$2 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$2 = normalizeComponent({ render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 }, __vue_inject_styles__$2, __vue_script__$2, __vue_scope_id__$2, __vue_is_functional_template__$2, __vue_module_identifier__$2, false, undefined, undefined, undefined); // var script$3 = { name: 'te-passage', props: { content: { type: String, required: true } } }; var css$3 = ".te-jodit-html-content .jodit_wysiwyg{overflow:visible!important}.te-jodit-html-content .tce-jodit-tooltip{display:inline-block;position:relative;background:rgba(205,215,220,.7);text-decoration:underline dotted #455a64;cursor:help}.te-jodit-html-content .tce-jodit-tooltip::before{content:\"\";position:absolute;bottom:100%;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #455a64}.te-jodit-html-content .tce-jodit-tooltip::after{content:attr(data-tooltip);position:absolute;bottom:calc(100% + 6px - 1px);left:-10px;min-width:150px;max-width:300px;padding:5px;text-align:center;color:#fff;font-size:.9em;background:#455a64;border-radius:2px}.te-jodit-html-content .tce-jodit-tooltip::after,.te-jodit-html-content .tce-jodit-tooltip::before{visibility:hidden;transition:opacity .1s ease-out,margin .1s ease-out;opacity:0}.te-jodit-html-content .tce-jodit-tooltip:hover::after,.te-jodit-html-content .tce-jodit-tooltip:hover::before{visibility:visible;margin-bottom:3px;opacity:1}"; styleInject(css$3); /* script */ var __vue_script__$3 = script$3; /* template */ var __vue_render__$3 = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "jodit_container te-jodit-html-content" }, [_c('div', { staticClass: "jodit_wysiwyg", domProps: { "innerHTML": _vm._s(_vm.content) } })]); }; var __vue_staticRenderFns__$3 = []; /* style */ var __vue_inject_styles__$3 = undefined; /* scoped */ var __vue_scope_id__$3 = undefined; /* module identifier */ var __vue_module_identifier__$3 = undefined; /* functional template */ var __vue_is_functional_template__$3 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$3 = normalizeComponent({ render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 }, __vue_inject_styles__$3, __vue_script__$3, __vue_scope_id__$3, __vue_is_functional_template__$3, __vue_module_identifier__$3, false, undefined, undefined, undefined); // var resolveElement = function resolveElement(type) { return TE_TYPE[type]; }; var script$4 = { name: 'te-primitive', inheritAttrs: false, props: { type: { type: String, required: true }, width: { type: Number, default: 12 } }, methods: { resolveElement: resolveElement }, components: { TeEmbed: __vue_component__, TeHtml: __vue_component__$1, TeImage: __vue_component__$2, TeJoditHtml: __vue_component__$3 } }; /* script */ var __vue_script__$4 = script$4; /* template */ var __vue_render__$4 = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "te-container", class: "col-xs-" + _vm.width }, [_c('div', { staticClass: "teaching-element" }, [_c(_vm.resolveElement(_vm.type), _vm._b({ tag: "component" }, 'component', _vm.$attrs, false))], 1)]); }; var __vue_staticRenderFns__$4 = []; /* style */ var __vue_inject_styles__$4 = undefined; /* scoped */ var __vue_scope_id__$4 = undefined; /* module identifier */ var __vue_module_identifier__$4 = undefined; /* functional template */ var __vue_is_functional_template__$4 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$4 = normalizeComponent({ render: __vue_render__$4, staticRenderFns: __vue_staticRenderFns__$4 }, __vue_inject_styles__$4, __vue_script__$4, __vue_scope_id__$4, __vue_is_functional_template__$4, __vue_module_identifier__$4, false, undefined, undefined, undefined); // var DEFAULT_SCROLL_OPTIONS = { container: 'body', easing: 'ease', cancelable: true, offset: 0, onDone: false, onCancel: false }; var script$5 = { name: 'te-accordion-item', props: { elements: { type: Array, required: true }, heading: { type: String, required: true }, options: { type: Object, default: function _default() { return {}; } } }, data: function data() { return { expanded: false }; }, methods: { toggle: function toggle() { this.expanded = !this.expanded; if (this.expanded) this.scroll(); }, scroll: function scroll() { var options = Object.assign({}, DEFAULT_SCROLL_OPTIONS, this.options.scroll); VueScrollTo.scrollTo(this.$el, 500, options); } }, components: { Primitive: __vue_component__$4 } }; var css$4 = ".accordion-header{position:relative;height:60px;font-size:16px;cursor:pointer;text-align:justify}.accordion-active .accordion-header{font-weight:500}.accordion-header .contents{padding:12px;line-height:34px}.accordion-header .contents .title{display:inline-block;width:90%;max-width:90%;padding-top:1px;line-height:1em;vertical-align:middle}.accordion-header .icon{position:absolute;top:50%;right:25px;transform:translateY(-50%);font-size:16px}.accordion-body{height:auto;padding:32px 8px}.slide-fade-enter-active,.slide-fade-leave-active{overflow:hidden;margin-top:0;margin-bottom:0;transition:all .5s cubic-bezier(.165,.84,.44,1)}.slide-fade-enter,.slide-fade-leave-to{height:0;padding-top:0;padding-bottom:0}"; styleInject(css$4); /* script */ var __vue_script__$5 = script$5; /* template */ var __vue_render__$5 = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('li', { class: { 'accordion-active': _vm.expanded }, on: { "scroll": _vm.scroll } }, [_c('div', { staticClass: "accordion-header", on: { "click": _vm.toggle } }, [_c('div', { staticClass: "contents" }, [_c('span', { staticClass: "title" }, [_vm._v(_vm._s(_vm.heading))])]), _vm._v(" "), _c('span', { staticClass: "icon" })]), _vm._v(" "), _c('transition', { attrs: { "name": "slide-fade" } }, [_c('div', { directives: [{ name: "show", rawName: "v-show", value: _vm.expanded, expression: "expanded" }], staticClass: "accordion-body" }, [_c('div', { staticClass: "row" }, _vm._l(_vm.elements, function (ref) { var id = ref.id; var type = ref.type; var data = ref.data; return _c('primitive', _vm._b({ key: id, attrs: { "type": type } }, 'primitive', data, false)); }), 1)])])], 1); }; var __vue_staticRenderFns__$5 = []; /* style */ var __vue_inject_styles__$5 = undefined; /* scoped */ var __vue_scope_id__$5 = undefined; /* module identifier */ var __vue_module_identifier__$5 = undefined; /* functional template */ var __vue_is_functional_template__$5 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$5 = normalizeComponent({ render: __vue_render__$5, staticRenderFns: __vue_staticRenderFns__$5 }, __vue_inject_styles__$5, __vue_script__$5, __vue_scope_id__$5, __vue_is_functional_template__$5, __vue_module_identifier__$5, false, undefined, undefined, undefined); function getElements(item, embeds) { var elements = map(item.body, function (_, id) { return embeds[id]; }); return sortBy(elements, 'position'); } var embedHost = { props: { embeds: { type: Object, default: function _default() { return {}; } }, items: { type: Object, required: true } }, computed: { embeddedItems: function embeddedItems() { var _this = this; return map(this.items, function (item) { return { elements: getElements(item, _this.embeds), heading: item.header, id: item.id }; }); } } }; // var script$6 = { name: 'te-accordion', mixins: [embedHost], props: { options: { type: Object, default: function _default() { return {}; } } }, computed: { itemOptions: function itemOptions() { return get(this.options, 'accordion.item'); } }, components: { AccordionItem: __vue_component__$5 } }; var css$5 = ".accordion{margin:0;padding-left:0;list-style-type:none}"; styleInject(css$5); /* script */ var __vue_script__$6 = script$6; /* template */ var __vue_render__$6 = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('ul', { staticClass: "accordion" }, _vm._l(_vm.embeddedItems, function (item) { return _c('accordion-item', _vm._b({ key: item.id, attrs: { "options": _vm.itemOptions } }, 'accordion-item', item, false)); }), 1); }; var __vue_staticRenderFns__$6 = []; /* style */ var __vue_inject_styles__$6 = undefined; /* scoped */ var __vue_scope_id__$6 = undefined; /* module identifier */ var __vue_module_identifier__$6 = undefined; /* functional template */ var __vue_is_functional_template__$6 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$6 = normalizeComponent({ render: __vue_render__$6, staticRenderFns: __vue_staticRenderFns__$6 }, __vue_inject_styles__$6, __vue_script__$6, __vue_scope_id__$6, __vue_is_functional_template__$6, __vue_module_identifier__$6, false, undefined, undefined, undefined); var buildBlankReplacer = (function (counter) { return function () { return "<span class='blank'>\n <span>".concat(++counter.val, "</span>\n <span class=\"blank-line\"></span>\n </span>"); }; }); // // // // // // // // // // // // var script$7 = { props: { disabled: { type: Boolean, default: false }, retake: { type: Boolean, default: false } }, computed: { btnLabel: function btnLabel() { return this.retake ? 'Retake' : 'Submit'; } }, methods: { onClick: function onClick() { var _this = this; setTimeout(function () { return _this.$emit(_this.retake ? 'reset' : 'submit'); }, 0); } } }; var css$6 = ".assessment .controls{width:50%;float:right;text-align:right;cursor:auto}.assessment .controls .btn-submit{min-width:85px;padding:7px 15px}.assessment .controls .btn-submit.retake{pointer-events:all}"; styleInject(css$6); /* script */ var __vue_script__$7 = script$7; /* template */ var __vue_render__$7 = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "controls" }, [_c('button', { staticClass: "btn btn-submit", class: { disabled: _vm.disabled && !_vm.retake, retake: _vm.retake }, attrs: { "disabled": _vm.disabled && !_vm.retake }, on: { "click": _vm.onClick } }, [_vm._v("\n " + _vm._s(_vm.btnLabel) + "\n ")])]); }; var __vue_staticRenderFns__$7 = []; /* style */ var __vue_inject_styles__$7 = undefined; /* scoped */ var __vue_scope_id__$7 = undefined; /* module identifier */ var __vue_module_identifier__$7 = undefined; /* functional template */ var __vue_is_functional_template__$7 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$7 = normalizeComponent({ render: __vue_render__$7, staticRenderFns: __vue_staticRenderFns__$7 }, __vue_inject_styles__$7, __vue_script__$7, __vue_scope_id__$7, __vue_is_functional_template__$7, __vue_module_identifier__$7, false, undefined, undefined, undefined); // var formatAnswers = function formatAnswers(answers) { var grouped = map(answers, function (answer, id) { return { id: id, answer: answer }; }); return shuffle(grouped); }; var defaults = { groupsPerRow: 3, removeClass: 'mdi mdi-close' }; var script$8 = { props: { answers: { type: Object, required: true }, correct: { type: Object, required: true }, disabled: { type: Boolean, default: false }, groups: { type: Object, required: true }, options: { type: Object, default: function _default() { return {}; } }, retake: { type: Boolean, default: false }, submission: { type: Object, default: function _default() { return {}; } } }, data: function data() { return { dragging: false, userAnswer: mapValues(this.groups, function () { return []; }), answersCollection: formatAnswers(this.answers) }; }, computed: { config: function config(vm) { return Object.assign({}, defaults, {}, vm.options.dragDrop); }, colWidth: function colWidth(vm) { return 12 / vm.config.groupsPerRow; }, draggableOptions: function draggableOptions() { return { animation: 150, disabled: this.disabled, chosenClass: 'chosen', dragClass: 'drag', ghostClass: 'ghost', group: "tesDragDrop-".concat(this._uid) }; }, groupsCollection: function groupsCollection() { return map(this.groups, function (group, id) { return { id: id, group: group }; }); }, isBoxFull: function isBoxFull() { return this.answersCollection.length === 0; }, removeClass: function removeClass() { return get(this.options.dragDrop, 'removeClass', 'mdi mdi-close'); }, canPartiallyRetake: function canPartiallyRetake() { return get(this.options.dragDrop, 'partialRetake', false); } }, methods: { answerClasses: function answerClasses(groupId, answerId) { var correct = this.correct, disabled = this.disabled; if (!disabled) return; return includes(correct[groupId], answerId) ? 'te-correct' : 'te-incorrect'; }, removeFromBox: function removeFromBox(id, answer) { if (this.disabled) return; // Remove from box and add to answers array this.userAnswer[id] = this.userAnswer[id].filter(function (a) { return a.id !== answer.id; }); this.answersCollection.push(answer); }, partiallyRetake: function partiallyRetake() { var correct = this.correct, userAnswer = this.userAnswer; var data = reduce(userAnswer, function (acc, group, id) { acc.userAnswer[id] = []; group.forEach(function (answer) { var included = includes(correct[id], answer.id); if (included) return acc.userAnswer[id].push(answer); acc.answersCollection.push(answer); }); return acc; }, { userAnswer: {}, answersCollection: [] }); Object.assign(this, data); }, update: function update(userAnswer) { this.$emit('update', { userAnswer: userAnswer }); }, initializeSubmission: function initializeSubmission(submission) { var _this = this; if (!submission) return; this.answersCollection = formatAnswers(this.answers); this.userAnswer = mapValues(this.groups, function () { return []; }); Object.keys(submission).forEach(function (groupId) { submission[groupId].forEach(function (answerId) { var findAnswer = function findAnswer(it) { return it.id === answerId; }; var answer = _this.answersCollection.find(findAnswer); var answerIndex = _this.answersCollection.findIndex(findAnswer); _this.userAnswer[groupId].push(answer); _this.answersCollection.splice(answerIndex, 1); }); }); } }, watch: { retake: function retake(val) { if (!val) return; if (this.canPartiallyRetake) return this.partiallyRetake(); this.answersCollection = formatAnswers(this.answers); this.userAnswer = mapValues(this.groups, function () { return []; }); }, submission: { handler: 'initializeSubmission', immediate: true }, userAnswer: { handler: function handler() { var isBoxFull = this.isBoxFull, update = this.update, userAnswer = this.userAnswer; if (!isBoxFull) return; update(mapValues(userAnswer, function (answer) { return map(answer, 'id'); })); }, deep: true }, isBoxFull: function isBoxFull(val, oldVal) { if (!val && oldVal) this.update(null); } }, components: { Draggable: Draggable } }; var css$7 = ".ghost{opacity:.5}.answers{min-height:100px}.answers .answer{display:inline-block;margin:0 10px 10px 0;padding:10px 20px;cursor:default}.group>.box .ghost,.group>.box .response{display:inline-block;margin:5px;padding:5px 20px;cursor:default}.group>.box .response{position:relative}.group>.box .response .btn-close{position:absolute;top:0;right:0;margin:0;padding:0;font-size:12px;background-color:transparent;outline:0;box-shadow:none}.group>.box .response .btn-close:active{box-shadow:none}.row.groups{display:flex;flex-wrap:wrap}.row.groups .group-container{display:flex;flex-direction:column;justify-content:space-between}.row.groups .group-container .group-title{display:flex;flex-grow:2;flex-direction:column;justify-content:center}.row.groups .group-container .group{height:250px}.row.groups .group-container .group .box{height:100%;overflow:scroll}"; styleInject(css$7); /* script */ var __vue_script__$8 = script$8; /* template */ var __vue_render__$8 = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "form-group" }, [_c('span', { staticClass: "form-label" }, [_vm._v("Solution")]), _vm._v(" "), _c('div', { staticClass: "row answers" }, [_c('draggable', { staticClass: "col-xs-12", attrs: { "options": _vm.draggableOptions }, on: { "start": function start($event) { _vm.dragging = true; }, "end": function end($event) { _vm.dragging = false; } }, model: { value: _vm.answersCollection, callback: function callback($$v) { _vm.answersCollection = $$v; }, expression: "answersCollection" } }, _vm._l(_vm.answersCollection, function (ref) { var id = ref.id; var answer = ref.answer; return _c('span', { key: id, staticClass: "answer" }, [_vm._v("\n " + _vm._s(answer) + "\n ")]); }), 0)], 1), _vm._v(" "), _c('div', { staticClass: "row groups" }, _vm._l(_vm.groupsCollection, function (ref) { var id = ref.id; var group = ref.group; return _c('div', { key: id, staticClass: "group-container", class: "col-xs-" + _vm.colWidth }, [_c('h3', { staticClass: "group-title" }, [_vm._v(_vm._s(group))]), _vm._v(" "), _c('div', { staticClass: "group" }, [_c('draggable', { staticClass: "box", class: { drop: _vm.dragging }, attrs: { "options": _vm.draggableOptions, "element": "div" }, model: { value: _vm.userAnswer[id], callback: function callback($$v) { _vm.$set(_vm.userAnswer, id, $$v); }, expression: "userAnswer[id]" } }, _vm._l(_vm.userAnswer[id], function (response) { return _c('div', { key: response.id, staticClass: "response", class: _vm.answerClasses(id, response.id) }, [_vm._v("\n " + _vm._s(response.answer) + "\n "), !_vm.disabled ? _c('button', { staticClass: "btn btn-close", on: { "click": function click($event) { return _vm.removeFromBox(id, response); } } }, [_c('span', { class: _vm.config.removeClass })]) : _vm._e()]); }), 0)], 1)]); }), 0)]); }; var __vue_staticRenderFns__$8 = []; /* style */ var __vue_inject_styles__$8 = undefined; /* scoped */ var __vue_scope_id__$8 = undefined; /* module identifier */ var __vue_module_identifier__$8 = undefined; /* functional template */ var __vue_is_functional_template__$8 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$8 = normalizeComponent({ render: __vue_render__$8, staticRenderFns: __vue_staticRenderFns__$8 }, __vue_inject_styles__$8, __vue_script__$8, __vue_scope_id__$8, __vue_is_functional_template__$8, __vue_module_identifier__$8, false, undefined, undefined, undefined); function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var _rules; var TYPES = { LATIN: { UPPER: 'upper-latin', LOWER: 'lower-latin' }, DECIMAL: 'decimal', NONE: 'none' }; var rules = (_rules = {}, _defineProperty(_rules, TYPES.LATIN.UPPER, function (index) { return String.fromCharCode(Number(index) + 65); }), _defineProperty(_rules, TYPES.LATIN.LOWER, function (index) { return String.fromCharCode(Number(index) + 97); }), _defineProperty(_rules, TYPES.DECIMAL, function (index) { return Number(index) + 1; }), _rules); // var toArray = function toArray(arg) { return isArray(arg) ? arg : [arg]; }; var noFeedback = ['TR', 'NR']; var defaults$1 = { multipleChoice: { type: TYPES.LATIN.UPPER }, numericalResponse: { type: TYPES.NONE }, singleChoice: { type: TYPES.LATIN.UPPER }, textResponse: { type: TYPES.NONE }, trueFalse: { type: TYPES.LATIN.UPPER } }; var script$9 = { props: { correct: { type: [Number, Array, Object, String, Boolean], default: null }, feedback: { type: Object, default: function _default() { return {}; } }, options: { type: Object, default: function _default() { return {}; } }, type: { type: String, required: true }, userAnswer: { type: [Number, String, Array, Object, Boolean], default: null }, isRandomizable: { type: Boolean, required: true } }, computed: { assessmentType: function assessmentType(vm) { return camelCase(ASSESSMENT_TYPE[vm.type]); }, config: function config(vm) { return Object.assign({}, defaults$1[vm.assessmentType], {}, vm.options[vm.assessmentType]); }, title: function title() { return this.type === 'TR' ? 'Suggested Solution' : 'Solution'; }, allFeedback: function allFeedback() { var config = this.config, feedback = this.feedback; var rule = rules[config.type]; return map(feedback, function (content, key) { return { prefix: rule(key), content: content }; }); }, hasRandomResponses: function hasRandomResponses() { return this.isRandomizable && this.config.randomize; }, feedbacks: function feedbacks() { var _this = this; if (includes(noFeedback, this.type)) return [{ content: this.correct }]; if (!this.feedback) return []; var options = this.options, hasRandomResponses = this.hasRandomResponses, allFeedback = this.allFeedback; if (options.showFeedback && !hasRandomResponses) return allFeedback; return toArray(this.userAnswer).reduce(function (acc, it) { var feedback = _this.getData(it); if (feedback.content) acc.push(feedback); return acc; }, []); }, show: function show() { return !!this.feedbacks.length; } }, methods: { getPrefix: function getPrefix(answer) { var index = this.isRandomizable ? answer.index : answer; return rules[this.config.type](index); }, getContent: function getContent(answer) { var index = this.isRandomizable ? answer.key : answer; return this.feedback[index]; }, getData: function getData(answer) { answer = isBoolean(answer) ? Number(!answer) : answer; var prefix = this.getPrefix(answer); var content = this.getContent(answer); return { prefix: prefix, content: content }; } } }; var css$8 = ".assessment .feedback{position:relative;border:1px dotted #ccc}.assessment .feedback .form-label{margin-top:10px;color:#000}.assessment .feedback .feedback-content,.assessment .feedback .form-label{margin-bottom:10px;padding-left:15px}.assessment .feedback .content-row{white-space:pre-wrap}.assessment .feedback::before{content:\"\";display:inline-block;position:absolute;top:0;left:50%;border:9px dotted #ccc;border-color:#ccc transparent transparent transparent}.assessment .feedback::after{content:\"\";display:inline-block;position:absolute;top:-1px;left:50%;border:9px dotted #ccc;border-color:#fff transparent transparent transparent}"; styleInject(css$8); /* script */ var __vue_script__$9 = script$9; /* template */ var __vue_render__$9 = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _vm.show ? _c('div', { staticClass: "ql-container feedback" }, [_c('div', { staticClass: "form-label" }, [_vm._v(_vm._s(_vm.title))]), _vm._v(" "), _vm._l(_vm.feedbacks, function (ref, index) { var prefix = ref.prefix; var content = ref.content; return _c('div', { key: index, staticClass: "ql-editor feedback-content" }, [prefix ? _c('span', { staticClass: "prefix" }, [_vm._v(_vm._s(prefix) + ".")]) : _vm._e(), _vm._v(" "), _c('span', { staticClass: "content-row", domProps: { "innerHTML": _vm._s(content) } })]); })], 2) : _vm._e(); }; var __vue_staticRenderFns__$9 = []; /* style */ var __vue_inject_styles__$9 = undefined; /* scoped */ var __vue_scope_id__$9 = undefined; /* module identifier */ var __vue_module_identifier__$9 = undefined; /* functional template */ var __vue_is_functional_template__$9 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$9 = normalizeComponent({ render: __vue_render__$9, staticRenderFns: __vue_staticRenderFns__$9 }, __vue_inject_styles__$9, __vue_script__$9, __vue_scope_id__$9, __vue_is_functional_template__$9, __vue_module_identifier__$9, false, undefined, undefined, undefined); // // // // // // // // // // // // // // // // // // // // // // // // var script$a = { props: { question: { type: Array, required: true }, disabled: { type: Boolean, default: false }, submission: { type: Array, default: function _default() { return []; } }, retake: { type: Boolean, default: false } }, data: function data() { return { userAnswer: this.submission || [] }; }, computed: { blankCount: function blankCount() { return this.question.reduce(function (total, _ref) { var _ref$count = _ref.count, count = _ref$count === void 0 ? 0 : _ref$count; return total + count; }, 0); } }, methods: { update: function update() { var userAnswer = this.userAnswer.filter(function (it) { return !!it.trim(); }); if (userAnswer.length !== this.blankCount) userAnswer = null; this.$emit('update', { userAnswer: userAnswer }); } }, watch: { retake: function retake(val) { if (val) this.userAnswer = []; }, submission: function submission(val) { this.userAnswer = val || []; }, userAnswer: 'update' } }; var css$9 = ".assessment.fill-blank .answer-group{margin-top:10px}.assessment.fill-blank ul{padding:0 0 0 10px;list-style:none}.assessment.fill-blank ul li{padding:5px 0}"; styleInject(css$9); /* script */ var __vue_script__$a = script$a; /* template */ var __vue_render__$a = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "form-group" }, [_c('span', { staticClass: "form-label" }, [_vm._v("Solution")]), _vm._v(" "), _vm._l(_vm.blankCount, function (index) { return _c('div', { key: index, staticClass: "answer-group" }, [_c('ul', [_c('li', [_c('div', { staticClass: "input-group" }, [_c('div', { staticClass: "input-group-addon" }, [_vm._v(_vm._s(index))]), _vm._v(" "), _c('input', { directives: [{ name: "model", rawName: "v-model", value: _vm.userAnswer[index - 1], expression: "userAnswer[index - 1]" }], staticClass: "form-control", attrs: { "disabled": _vm.disabled, "type": "text", "placeholder": "Solution..." }, domProps: { "value": _vm.userAnswer[index - 1] }, on: { "input": function input($event) { if ($event.target.composing) { return; } _vm.$set(_vm.userAnswer, index - 1, $event.target.value); } } })])])])]); })], 2); }; var __vue_staticRenderFns__$a = []; /* style */ var __vue_inject_styles__$a = undefined; /* scoped */ var __vue_scope_id__$a = undefined; /* module identifier */ var __vue_module_identifier__$a = undefined; /* functional template */ var __vue_is_functional_template__$a = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$a = normalizeComponent({ render: __vue_render__$a, staticRenderFns: __vue_staticRenderFns__$a }, __vue_inject_styles__$a, __vue_script__$a, __vue_scope_id__$a, __vue_is_functional_template__$a, __vue_module_identifier__$a, false, undefined, undefined, undefined); // // // // // // // // // // var script$b = { props: { content: { type: String, required: true } }, data: function data() { return { show: false }; }, computed: { icon: function icon() { return this.show ? 'up' : 'down'; } } }; var css$a = ".assessment .hint-content{margin:10px 0}"; styleInject(css$a); /* script */ var __vue_script__$b = script$b; /* template */ var __vue_render__$b = function __vue_render__() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "hint" }, [_c('button', { staticClass: "btn btn-hint", on: { "click": function click($event) { _vm.show = !_vm.show; } } }, [_c('span', { class: "mdi mdi-chevron-" + _vm.icon }), _vm._v("\n Hint\n ")]), _vm._v(" "), _c('p', { directives: [{ name: "show", rawName: "v-show", value: _vm.show, expression: "show" }], staticClass: "hint-content" }, [_vm._v(_vm._s(_vm.content))])]); }; var __vue_staticRenderFns__$b = []; /* style */ var __vue_inject_styles__$b = undefined; /* scoped */ var __vue_scope_id__$b = undefined; /* module identifier */ var __vue_module_identifier__$b = undefined; /* functional template */ var __vue_is_functional_template__$b = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$b = normalizeComponent({ render: __vue_render__$b, staticRenderFns: __vue_staticRenderFns__$b }, __vue_inject_styles__$b, __vue_script__$b, __vue_scope_id__$b, __vue_is_functional_template__$b, __vue_module_identifier__$b, false, undefined, undefined, undefined); // var script$c = { props: { correct: { type: Object, required: true }, disabled: { type: Boolean, default: false }, headings: { type: Object, required: true }, options: { type: Object, default: function _default() { return {}; } }, premises: { type: Array, required: true }, responses: { type: Array, required: true }, retake: { type: Boolean, default: false }, submission: { type: Object, default: function _default() { return {}; } } }, data: function data() { return { dragOptions: { group: { name: "match-".concat(this._uid), pull: 'clone', put: false, revertClone: true }, sort: false }, source: [], target: [], draggingItem: null }; }, computed: { premiseHeading: function premiseHeading() { return get(this.headings, 'premise', 'Premise'); }, responseHeading: function responseHeading() { return get(this.headings, 'response', 'Response'); }, isDragging: function isDragging() { return isNumber(this.draggingItem); }, isValid: function isValid() { return this.source.every(function (_ref) { var dragged = _ref.dragged; return dragged; }); }, canPartiallyRetake: function canPartiallyRetake() { return get(this.options.matchingQuestions, 'partialRetake', false); } }, methods: { getOptions: function getOptions(item) { return { group: { name: "match-".concat(this._uid), put: item.answers.length < 1 }, sort: false, filter: '.disabled' }; }, onDragStart: function onDragStart(e) { e.clone.className += ' cloned'; this.draggingItem = e.oldIndex; }, onDragEnd: function onDragEnd() { this.draggingItem = null; }, onAdd: function onAdd() { this.source[this.draggingItem].dragged = true; this.update(); }, answerClasses: function answerClasses(_ref2) { var key = _ref2.key, answers = _ref2.answers; var disabled = this.disabled, correct = this.correct; if (!disabled) return; var isCorrect = key === correct[answers[0].key]; return isCorrect ? 'te-correct' : 'te-incorrect'; }, remove: function remove(item) { var premise = item.answers[0]; premise.dragged = false; item.answers = []; }, draggable: function draggable(item) { return get(item.answers, '0.value', ''); }, partiallyRetake: function partiallyRetake() { var _this = this; var correct = this.correct, target = this.target; target.forEach(function (response) { var key = response.answers[0].key; if (correct[key] !== response.key) _this.remove(response); }); }, update: function update() { var reducer = function reducer(acc, _ref3) { var answers = _ref3.answers, key = _ref3.key; if (answers.length) acc[answers[0].key] = key; return acc; }; this.$emit('update', { userAnswer: reduce(this.target, reducer, {}) }); }, initialize: function initialize() { var premises = this.premises, responses = this.responses; this.source = shuffle(premises.map(function (it) { return Object.assign({}, it, { dragged: false }); })); this.target = sortBy(responses.map(function (it) { return Object.assign({}, it, { answers: [] }); }), 'key'); }, initializeSubmission: function initializeSubmission(submission) { var _this2 = this; if (!submission) return; Object.keys(submission).forEach(function (key) { var source = _this2.source.find(function (it) { return it.key === key; }); var target = _this2.target.find(function (it) { return it.key === submission[key]; }); target.answers.push(source); source.dragged = true; }); } }, watch: { retake: function retake(val) { if (!val) return; if (this.canPartiallyRetake) return this.partiallyRetake(); this.initialize(); this.update(); }, isValid: function isValid(val) { this.$emit('validateAnswer', { isValid: val }); }, submission: 'initializeSubmission' }, created: function created() { this.initialize(); this.initializeSubmission(this.submission); }, components: { Draggable: Draggable } }; var css$b = ".assessment.matching-question .drag-spot{margin-bottom:10px;cursor:move}.assessment.matching-question .item{display:inline-block;padding:10px 20px 10px 20px;background-color:#f5f5f5;border:1px solid grey}.assessment.matching-question .dragged{visibility:hidden}.assessment.matching-question .drop-spot{margin-bottom:10px;padding:5px 0;border:1px solid grey}.assessment.matching-question .drop-spot .item{display:block;position:relative;margin:5px 0;padding:10px 35px 10px 20px;background-color:transparent;border:none}.assessment.matching-question .drop-spot .item .mdi-close{position:absolute;top:11px;right:17px;cursor:pointer;pointer-events:all}.assessment.matching-question .sortable-drag{display:inline-block}.assessment.matching-question .sortable-drag .item{background-color:#fff}.assessment.matching-question .cloned .item,.assessment.matching-question .drag-container .sortable-ghost .item{border:1px dashed #ccc}.assessment.matching-question .drop-area{background-color:#f4eef3;border:1px dashed #72246c}"; styleInject(css$b); /* script */ var __vue_script__$c = script$c; /* template */ var __vue_render__$c = function __vue_render__() { var _vm = this; var _h = _vm.$cr