@pie-element/explicit-constructed-response 3.9.2 → 3.9.3-next.1016

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +204 -0
  2. package/configure/CHANGELOG.md +176 -0
  3. package/configure/lib/alternateResponses.js +45 -12
  4. package/configure/lib/alternateResponses.js.map +1 -1
  5. package/configure/lib/alternateSection.js +116 -19
  6. package/configure/lib/alternateSection.js.map +1 -1
  7. package/configure/lib/defaults.js +30 -0
  8. package/configure/lib/defaults.js.map +1 -1
  9. package/configure/lib/ecr-toolbar.js +19 -7
  10. package/configure/lib/ecr-toolbar.js.map +1 -1
  11. package/configure/lib/index.js +3 -3
  12. package/configure/lib/main.js +250 -42
  13. package/configure/lib/main.js.map +1 -1
  14. package/configure/lib/markupUtils.js +29 -3
  15. package/configure/lib/markupUtils.js.map +1 -1
  16. package/configure/lib/utils.js +15 -0
  17. package/configure/lib/utils.js.map +1 -0
  18. package/configure/package.json +3 -3
  19. package/controller/CHANGELOG.md +61 -0
  20. package/controller/lib/index.js +99 -6
  21. package/controller/lib/index.js.map +1 -1
  22. package/controller/package.json +1 -1
  23. package/docs/config-schema.json +116 -0
  24. package/docs/config-schema.json.md +89 -1
  25. package/docs/demo/generate.js +3 -1
  26. package/docs/pie-schema.json +57 -0
  27. package/docs/pie-schema.json.md +45 -0
  28. package/lib/index.js +5 -1
  29. package/lib/index.js.map +1 -1
  30. package/lib/main.js +75 -24
  31. package/lib/main.js.map +1 -1
  32. package/lib/print.js +115 -0
  33. package/lib/print.js.map +1 -0
  34. package/package.json +11 -7
  35. package/module/configure.js +0 -2121
  36. package/module/controller.js +0 -20840
  37. package/module/demo.js +0 -44
  38. package/module/element.js +0 -240
  39. package/module/index.html +0 -16
  40. package/module/manifest.json +0 -10
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/markupUtils.js"],"names":["removeUnwantedCharacters","markup","replace","createElementFromHTML","htmlString","div","document","createElement","innerHTML","trim","processMarkup","newMarkup","slateMarkup","index","querySelectorAll","forEach","s","replaceWith","REGEX","createSlateMarkup","choices","match","g","label"],"mappings":";;;;;;;;;AAAA;;AAEO,IAAMA,wBAAwB,GAAG,SAA3BA,wBAA2B,CAAAC,MAAM;AAAA,SAC5CA,MAAM,CACHC,OADH,CACW,0CADX,EACuD,EADvD,EAEGA,OAFH,CAEW,MAFX,EAEmB,GAFnB,EAEwBA,OAFxB,CAEgC,OAFhC,EAEyC,GAFzC,CAD4C;AAAA,CAAvC;;;;AAKP,IAAMC,qBAAqB,GAAG,SAAxBA,qBAAwB,GAAqB;AAAA,MAApBC,UAAoB,uEAAP,EAAO;AACjD,MAAMC,GAAG,GAAGC,QAAQ,CAACC,aAAT,CAAuB,KAAvB,CAAZ;AAEAF,EAAAA,GAAG,CAACG,SAAJ,GAAgBJ,UAAU,CAACK,IAAX,EAAhB;AAEA,SAAOJ,GAAP;AACD,CAND;;AAQO,IAAMK,aAAa,GAAG,SAAhBA,aAAgB,CAAAT,MAAM,EAAI;AACrC,MAAMU,SAAS,GAAGX,wBAAwB,CAACC,MAAM,IAAI,EAAX,CAA1C;AACA,MAAMW,WAAW,GAAGT,qBAAqB,CAACQ,SAAS,IAAI,EAAd,CAAzC;AACA,MAAIE,KAAK,GAAG,CAAZ;AAEAD,EAAAA,WAAW,CAACE,gBAAZ,CAA6B,6CAA7B,EAA4EC,OAA5E,CAAoF,UAAAC,CAAC,EAAI;AACvFA,IAAAA,CAAC,CAACC,WAAF,aAAmBJ,KAAK,EAAxB;AACD,GAFD;AAIA,SAAOD,WAAW,CAACJ,SAAnB;AACD,CAVM;;;AAYP,IAAMU,KAAK,GAAG,gBAAd;;AAEO,IAAMC,iBAAiB,GAAG,SAApBA,iBAAoB,CAAClB,MAAD,EAASmB,OAAT,EAAqB;AACpD,MAAI,CAACnB,MAAL,EAAa;AACX,WAAO,EAAP;AACD;;AAED,MAAMU,SAAS,GAAGX,wBAAwB,CAACC,MAAD,CAA1C;AAEA,SAAOU,SAAS,CAACT,OAAV,CAAkBgB,KAAlB,EAAyB,UAACG,KAAD,EAAQC,CAAR,EAAc;AAC5C,QAAMC,KAAK,GAAGH,OAAO,CAACE,CAAD,CAAP,CAAW,CAAX,EAAcC,KAAd,IAAuB,EAArC;AAEA,oFAAsED,CAAtE,6BAAwF,wBAAOC,KAAP,CAAxF;AACD,GAJM,CAAP;AAKD,CAZM","sourcesContent":["import escape from 'lodash/escape';\n\nexport const removeUnwantedCharacters = markup =>\n markup\n .replace(/(\\t+(?!imes))|(\\n)|(\\\\t+(?!imes))|(\\\\n)/g, '')\n .replace(/\\\\\"/g, '\"').replace(/\\\\\\//g, '/');\n\nconst createElementFromHTML = (htmlString = '') => {\n const div = document.createElement('div');\n\n div.innerHTML = htmlString.trim();\n\n return div;\n};\n\nexport const processMarkup = markup => {\n const newMarkup = removeUnwantedCharacters(markup || '');\n const slateMarkup = createElementFromHTML(newMarkup || '');\n let index = 0;\n\n slateMarkup.querySelectorAll('[data-type=\"explicit_constructed_response\"]').forEach(s => {\n s.replaceWith(`{{${index++}}}`);\n });\n\n return slateMarkup.innerHTML;\n};\n\nconst REGEX = /\\{\\{(\\d+)\\}\\}/g;\n\nexport const createSlateMarkup = (markup, choices) => {\n if (!markup) {\n return '';\n }\n\n const newMarkup = removeUnwantedCharacters(markup);\n\n return newMarkup.replace(REGEX, (match, g) => {\n const label = choices[g][0].label || '';\n\n return `<span data-type=\"explicit_constructed_response\" data-index=\"${g}\" data-value=\"${escape(label)}\"></span>`;\n });\n};\n"],"file":"markupUtils.js"}
1
+ {"version":3,"sources":["../src/markupUtils.js"],"names":["tSymbols","nSymbols","matchTabAndNewLine","RegExp","removeUnwantedCharacters","markup","replace","createElementFromHTML","htmlString","div","document","createElement","innerHTML","trim","processMarkup","newMarkup","slateMarkup","index","querySelectorAll","forEach","s","replaceWith","REGEX","createSlateMarkup","choices","match","g","label","getAdjustedLength","length"],"mappings":";;;;;;;;;AAAA;;AAEA;AACA,IAAMA,QAAQ,GAAG,+BAAjB,C,CACA;;AACA,IAAMC,QAAQ,GAAG,sCAAjB,C,CACA;;AACA,IAAMC,kBAAkB,GAAG,IAAIC,MAAJ,kBAAqBH,QAArB,uBAA0CC,QAA1C,yBAAiED,QAAjE,yBAAwFC,QAAxF,SAAsG,GAAtG,CAA3B;;AAEO,IAAMG,wBAAwB,GAAG,SAA3BA,wBAA2B,CAAAC,MAAM;AAAA,SAC5CA,MAAM,CAACC,OAAP,CAAeJ,kBAAf,EAAmC,EAAnC,EAAuCI,OAAvC,CAA+C,MAA/C,EAAuD,GAAvD,EAA4DA,OAA5D,CAAoE,OAApE,EAA6E,GAA7E,CAD4C;AAAA,CAAvC;;;;AAGP,IAAMC,qBAAqB,GAAG,SAAxBA,qBAAwB,GAAqB;AAAA,MAApBC,UAAoB,uEAAP,EAAO;AACjD,MAAMC,GAAG,GAAGC,QAAQ,CAACC,aAAT,CAAuB,KAAvB,CAAZ;AAEAF,EAAAA,GAAG,CAACG,SAAJ,GAAgBJ,UAAU,CAACK,IAAX,EAAhB;AAEA,SAAOJ,GAAP;AACD,CAND;;AAQO,IAAMK,aAAa,GAAG,SAAhBA,aAAgB,CAAAT,MAAM,EAAI;AACrC,MAAMU,SAAS,GAAGX,wBAAwB,CAACC,MAAM,IAAI,EAAX,CAA1C;AACA,MAAMW,WAAW,GAAGT,qBAAqB,CAACQ,SAAS,IAAI,EAAd,CAAzC;AACA,MAAIE,KAAK,GAAG,CAAZ;AAEAD,EAAAA,WAAW,CAACE,gBAAZ,CAA6B,6CAA7B,EAA4EC,OAA5E,CAAoF,UAAAC,CAAC,EAAI;AACvFA,IAAAA,CAAC,CAACC,WAAF,aAAmBJ,KAAK,EAAxB;AACD,GAFD;AAIA,SAAOD,WAAW,CAACJ,SAAnB;AACD,CAVM;;;AAYP,IAAMU,KAAK,GAAG,gBAAd;;AAEO,IAAMC,iBAAiB,GAAG,SAApBA,iBAAoB,CAAClB,MAAD,EAASmB,OAAT,EAAqB;AACpD,MAAI,CAACnB,MAAL,EAAa;AACX,WAAO,EAAP;AACD;;AAED,MAAMU,SAAS,GAAGX,wBAAwB,CAACC,MAAD,CAA1C;AAEA,SAAOU,SAAS,CAACT,OAAV,CAAkBgB,KAAlB,EAAyB,UAACG,KAAD,EAAQC,CAAR,EAAc;AAC5C,QAAMC,KAAK,GAAGH,OAAO,CAACE,CAAD,CAAP,CAAW,CAAX,EAAcC,KAAd,IAAuB,EAArC;AAEA,oFAAsED,CAAtE,6BAAwF,wBAAOC,KAAP,CAAxF;AACD,GAJM,CAAP;AAKD,CAZM,C,CAcP;;;;;AACO,IAAMC,iBAAiB,GAAG,SAApBA,iBAAoB,CAAAC,MAAM,EAAI;AACzC,MAAIA,MAAM,IAAI,CAAd,EAAiB;AACf,WAAOA,MAAM,GAAG,CAAhB;AACD;;AAED,MAAIA,MAAM,IAAI,CAAd,EAAiB;AACf,WAAOA,MAAM,GAAG,CAAhB;AACD;;AAED,MAAIA,MAAM,IAAI,CAAd,EAAiB;AACf,WAAOA,MAAM,GAAG,CAAhB;AACD;;AAED,SAAOA,MAAM,GAAG,CAAhB;AACD,CAdM","sourcesContent":["import escape from 'lodash/escape';\n\n// do not remove \\t from \\times, \\triangle, \\tan, \\theta or \\therefore\nconst tSymbols = 'imes|riangle|an|heta|herefore';\n// do not remove \\n from \\nthroot, \\nparallel, \\ncong, \\napprox, \\neq, \\ne or \\nsim\nconst nSymbols = 'throot|parallel|cong|approx|eq|e|sim';\n// match all \\t and \\n that are not part of math symbols that starts with \\t or \\n\nconst matchTabAndNewLine = new RegExp(`(\\\\t(?!${tSymbols}))|(\\\\n(?!${nSymbols}))|(\\\\\\\\t(?!${tSymbols}))|(\\\\\\\\n(?!${nSymbols}))`, 'g');\n\nexport const removeUnwantedCharacters = markup =>\n markup.replace(matchTabAndNewLine, '').replace(/\\\\\"/g, '\"').replace(/\\\\\\//g, '/');\n\nconst createElementFromHTML = (htmlString = '') => {\n const div = document.createElement('div');\n\n div.innerHTML = htmlString.trim();\n\n return div;\n};\n\nexport const processMarkup = markup => {\n const newMarkup = removeUnwantedCharacters(markup || '');\n const slateMarkup = createElementFromHTML(newMarkup || '');\n let index = 0;\n\n slateMarkup.querySelectorAll('[data-type=\"explicit_constructed_response\"]').forEach(s => {\n s.replaceWith(`{{${index++}}}`);\n });\n\n return slateMarkup.innerHTML;\n};\n\nconst REGEX = /\\{\\{(\\d+)\\}\\}/g;\n\nexport const createSlateMarkup = (markup, choices) => {\n if (!markup) {\n return '';\n }\n\n const newMarkup = removeUnwantedCharacters(markup);\n\n return newMarkup.replace(REGEX, (match, g) => {\n const label = choices[g][0].label || '';\n\n return `<span data-type=\"explicit_constructed_response\" data-index=\"${g}\" data-value=\"${escape(label)}\"></span>`;\n });\n};\n\n// also used in controller/src/index.js\nexport const getAdjustedLength = length => {\n if (length <= 2) {\n return length + 2;\n }\n\n if (length <= 4) {\n return length + 3;\n }\n\n if (length <= 6) {\n return length + 4;\n }\n\n return length + 5;\n};\n"],"file":"markupUtils.js"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.generateValidationMessage = void 0;
7
+
8
+ var generateValidationMessage = function generateValidationMessage(config) {
9
+ var maxResponseAreas = config.maxResponseAreas;
10
+ var responseAreasMessage = '\nCorrect answers should not be blank.' + '\nEach answer defined for a response area should be unique.' + '\nThere should be at least 1 ' + (maxResponseAreas ? "and at most ".concat(maxResponseAreas, " ") : '') + 'response area' + (maxResponseAreas ? 's' : '') + ' defined.';
11
+ return 'Validation requirements:' + responseAreasMessage;
12
+ };
13
+
14
+ exports.generateValidationMessage = generateValidationMessage;
15
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.js"],"names":["generateValidationMessage","config","maxResponseAreas","responseAreasMessage"],"mappings":";;;;;;;AAAO,IAAMA,yBAAyB,GAAG,SAA5BA,yBAA4B,CAAAC,MAAM,EAAI;AACjD,MAAQC,gBAAR,GAA6BD,MAA7B,CAAQC,gBAAR;AAEA,MAAMC,oBAAoB,GAAG,2CAC3B,6DAD2B,GAE3B,+BAF2B,IAG1BD,gBAAgB,yBAAkBA,gBAAlB,SAAwC,EAH9B,IAI3B,eAJ2B,IAIRA,gBAAgB,GAAG,GAAH,GAAS,EAJjB,IAIuB,WAJpD;AAMA,SAAO,6BAA6BC,oBAApC;AACD,CAVM","sourcesContent":["export const generateValidationMessage = config => {\n const { maxResponseAreas } = config;\n\n const responseAreasMessage = '\\nCorrect answers should not be blank.' +\n '\\nEach answer defined for a response area should be unique.' +\n '\\nThere should be at least 1 ' +\n (maxResponseAreas ? `and at most ${maxResponseAreas} ` : '') +\n 'response area' + (maxResponseAreas ? 's' : '') + ' defined.';\n\n return 'Validation requirements:' + responseAreasMessage;\n};\n"],"file":"utils.js"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pie-element/explicit-constructed-response-configure",
3
- "version": "3.5.27",
3
+ "version": "3.7.6",
4
4
  "private": true,
5
5
  "main": "lib/index.js",
6
6
  "modue": "src/index.js",
@@ -8,8 +8,8 @@
8
8
  "@material-ui/core": "^3.9.2",
9
9
  "@material-ui/icons": "^3.0.1",
10
10
  "@pie-framework/pie-configure-events": "^1.2.0",
11
- "@pie-lib/config-ui": "^10.9.2",
12
- "@pie-lib/editable-html": "^7.16.19",
11
+ "@pie-lib/config-ui": "^10.13.3",
12
+ "@pie-lib/editable-html": "^7.22.6",
13
13
  "classnames": "^2.2.6",
14
14
  "debug": "^3.1.0",
15
15
  "lodash": "^4.17.15",
@@ -3,6 +3,67 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.4.8](https://github.com/pie-framework/pie-elements/compare/@pie-element/explicit-constructed-response-controller@3.4.7...@pie-element/explicit-constructed-response-controller@3.4.8) (2022-03-28)
7
+
8
+ **Note:** Version bump only for package @pie-element/explicit-constructed-response-controller
9
+
10
+
11
+
12
+
13
+
14
+ ## [3.4.7](https://github.com/pie-framework/pie-elements/compare/@pie-element/explicit-constructed-response-controller@3.4.6...@pie-element/explicit-constructed-response-controller@3.4.7) (2022-03-08)
15
+
16
+ **Note:** Version bump only for package @pie-element/explicit-constructed-response-controller
17
+
18
+
19
+
20
+
21
+
22
+ ## [3.4.3](https://github.com/pie-framework/pie-elements/compare/@pie-element/explicit-constructed-response-controller@3.4.2...@pie-element/explicit-constructed-response-controller@3.4.3) (2021-12-01)
23
+
24
+ **Note:** Version bump only for package @pie-element/explicit-constructed-response-controller
25
+
26
+
27
+
28
+
29
+
30
+ ## [3.4.2](https://github.com/pie-framework/pie-elements/compare/@pie-element/explicit-constructed-response-controller@3.4.1...@pie-element/explicit-constructed-response-controller@3.4.2) (2021-11-29)
31
+
32
+ **Note:** Version bump only for package @pie-element/explicit-constructed-response-controller
33
+
34
+
35
+
36
+
37
+
38
+ ## [3.4.1](https://github.com/pie-framework/pie-elements/compare/@pie-element/explicit-constructed-response-controller@3.3.3...@pie-element/explicit-constructed-response-controller@3.4.1) (2021-11-11)
39
+
40
+ **Note:** Version bump only for package @pie-element/explicit-constructed-response-controller
41
+
42
+
43
+
44
+
45
+
46
+ # [3.4.0](https://github.com/pie-framework/pie-elements/compare/@pie-element/explicit-constructed-response-controller@3.3.2...@pie-element/explicit-constructed-response-controller@3.4.0) (2021-11-11)
47
+
48
+
49
+ ### Features
50
+
51
+ * **explicit-constructed-response:** Added a max limit of characters and adjusted the width PD-794 ([135f176](https://github.com/pie-framework/pie-elements/commit/135f176402187e9a6120b88768ae7fb0152ac418))
52
+ * **explicit-constructed-response:** Calculate maxChoicesLength if it's undefined. Fixed delete response area and choices bug. BREAKING CHANGE: add maxChoicesLength prop ([97431b9](https://github.com/pie-framework/pie-elements/commit/97431b9c3fbdafd84e040653c54d5f04bae16a1d))
53
+
54
+
55
+
56
+
57
+
58
+
59
+ ## [3.3.3](https://github.com/pie-framework/pie-elements/compare/@pie-element/explicit-constructed-response-controller@3.3.2...@pie-element/explicit-constructed-response-controller@3.3.3) (2021-10-18)
60
+
61
+ **Note:** Version bump only for package @pie-element/explicit-constructed-response-controller
62
+
63
+
64
+
65
+
66
+
6
67
  ## [3.3.2](https://github.com/pie-framework/pie-elements/compare/@pie-element/explicit-constructed-response-controller@3.3.0...@pie-element/explicit-constructed-response-controller@3.3.2) (2021-08-05)
7
68
 
8
69
 
@@ -5,12 +5,18 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
+ exports.getScore = exports.createCorrectResponseSession = void 0;
8
9
  exports.model = model;
10
+ exports.normalize = void 0;
9
11
  exports.outcome = outcome;
10
- exports.createCorrectResponseSession = exports.getScore = exports.prepareVal = exports.normalize = exports.prepareChoice = void 0;
12
+ exports.validate = exports.prepareVal = exports.prepareChoice = void 0;
11
13
 
12
14
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
13
15
 
16
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
17
+
18
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
19
+
14
20
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
15
21
 
16
22
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
@@ -27,9 +33,9 @@ var _debug = _interopRequireDefault(require("debug"));
27
33
 
28
34
  var _controllerUtils = require("@pie-lib/controller-utils");
29
35
 
30
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
36
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
31
37
 
32
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
38
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
33
39
 
34
40
  var log = (0, _debug["default"])('explicit-constructed-response:controller');
35
41
 
@@ -63,6 +69,23 @@ var getFeedback = function getFeedback(value) {
63
69
  }
64
70
 
65
71
  return 'incorrect';
72
+ }; // also used in configure/src/markupUtils.js
73
+
74
+
75
+ var getAdjustedLength = function getAdjustedLength(length) {
76
+ if (length <= 2) {
77
+ return length + 2;
78
+ }
79
+
80
+ if (length <= 4) {
81
+ return length + 3;
82
+ }
83
+
84
+ if (length <= 6) {
85
+ return length + 4;
86
+ }
87
+
88
+ return length + 5;
66
89
  };
67
90
 
68
91
  var normalize = function normalize(question) {
@@ -86,7 +109,7 @@ exports.normalize = normalize;
86
109
  function model(question, session, env) {
87
110
  return new Promise( /*#__PURE__*/function () {
88
111
  var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(resolve) {
89
- var normalizedQuestion, defaultFeedback, _ref2, _ref2$value, value, preparChoiceFn, choices, feedback, showNote, out;
112
+ var normalizedQuestion, defaultFeedback, _ref2, _ref2$value, value, preparChoiceFn, choices, feedback, showNote, _normalizedQuestion$m, maxLengthPerChoice, maxLengthPerChoiceEnabled, undefinedLengths, out;
90
113
 
91
114
  return _regenerator["default"].wrap(function _callee$(_context) {
92
115
  while (1) {
@@ -96,7 +119,7 @@ function model(question, session, env) {
96
119
  // like: { label: 'test' }
97
120
  if (question.choices) {
98
121
  Object.keys(question.choices).forEach(function (key) {
99
- question.choices[key] = question.choices[key].map(function (item, index) {
122
+ question.choices[key] = (question.choices[key] || []).map(function (item, index) {
100
123
  if (!item.value) {
101
124
  log('Choice does not contain "value" property, which is required.', item);
102
125
  return _objectSpread({
@@ -140,6 +163,19 @@ function model(question, session, env) {
140
163
  showNote = true;
141
164
  }
142
165
  });
166
+ _normalizedQuestion$m = normalizedQuestion.maxLengthPerChoice, maxLengthPerChoice = _normalizedQuestion$m === void 0 ? [] : _normalizedQuestion$m, maxLengthPerChoiceEnabled = normalizedQuestion.maxLengthPerChoiceEnabled;
167
+ undefinedLengths = !maxLengthPerChoice.length; // calculate maxLengthPerChoice array if it is not defined or defined incorrectly
168
+
169
+ Object.values(choices).forEach(function (choice, index) {
170
+ var labelLengthsArr = (choice || []).map(function (choice) {
171
+ return (choice.label || '').length;
172
+ });
173
+ var length = Math.max.apply(Math, (0, _toConsumableArray2["default"])(labelLengthsArr));
174
+
175
+ if (undefinedLengths || !maxLengthPerChoice[index] || maxLengthPerChoice[index] < length || maxLengthPerChoice[index] > length + 10) {
176
+ maxLengthPerChoice[index] = getAdjustedLength(length);
177
+ }
178
+ });
143
179
  out = {
144
180
  disabled: env.mode !== 'gather',
145
181
  mode: env.mode,
@@ -150,6 +186,10 @@ function model(question, session, env) {
150
186
  env: env,
151
187
  note: normalizedQuestion.note,
152
188
  showNote: showNote,
189
+ maxLengthPerChoice: maxLengthPerChoice,
190
+ maxLengthPerChoiceEnabled: maxLengthPerChoiceEnabled,
191
+ displayType: normalizedQuestion.displayType,
192
+ playerSpellCheckEnabled: normalizedQuestion.playerSpellCheckEnabled,
153
193
  responseCorrect: env.mode === 'evaluate' ? getScore(normalizedQuestion, session) === 1 : undefined
154
194
  };
155
195
 
@@ -163,7 +203,7 @@ function model(question, session, env) {
163
203
 
164
204
  resolve(out);
165
205
 
166
- case 13:
206
+ case 16:
167
207
  case "end":
168
208
  return _context.stop();
169
209
  }
@@ -260,4 +300,57 @@ var createCorrectResponseSession = function createCorrectResponseSession(questio
260
300
  };
261
301
 
262
302
  exports.createCorrectResponseSession = createCorrectResponseSession;
303
+
304
+ var validate = function validate() {
305
+ var model = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
306
+ var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
307
+ var choices = model.choices,
308
+ markup = model.markup;
309
+ var maxResponseAreas = config.maxResponseAreas;
310
+ var allChoicesErrors = {};
311
+ Object.entries(choices || {}).forEach(function (_ref4) {
312
+ var _ref5 = (0, _slicedToArray2["default"])(_ref4, 2),
313
+ key = _ref5[0],
314
+ values = _ref5[1];
315
+
316
+ var reversedChoices = (0, _toConsumableArray2["default"])(values || []).reverse();
317
+ var choicesErrors = {};
318
+ reversedChoices.forEach(function (choice, index) {
319
+ var value = choice.value,
320
+ label = choice.label;
321
+
322
+ if (label === '' || label === '<div></div>') {
323
+ choicesErrors[value] = 'Content should not be empty.';
324
+ } else {
325
+ var identicalAnswer = reversedChoices.slice(index + 1).some(function (c) {
326
+ return c.label === label;
327
+ });
328
+
329
+ if (identicalAnswer) {
330
+ choicesErrors[value] = 'Content should be unique.';
331
+ }
332
+ }
333
+ });
334
+
335
+ if (!(0, _isEmpty["default"])(choicesErrors)) {
336
+ allChoicesErrors[key] = choicesErrors;
337
+ }
338
+ });
339
+ var errors = {};
340
+ var nbOfResponseAreas = (markup.match(/\{\{(\d+)\}\}/g) || []).length;
341
+
342
+ if (nbOfResponseAreas > maxResponseAreas) {
343
+ errors.responseAreasError = "No more than ".concat(maxResponseAreas, " response areas should be defined.");
344
+ } else if (nbOfResponseAreas < 1) {
345
+ errors.responseAreasError = 'There should be at least 1 response area defined.';
346
+ }
347
+
348
+ if (!(0, _isEmpty["default"])(allChoicesErrors)) {
349
+ errors.choicesErrors = allChoicesErrors;
350
+ }
351
+
352
+ return errors;
353
+ };
354
+
355
+ exports.validate = validate;
263
356
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.js"],"names":["log","prepareChoice","mode","defaultFeedback","choice","out","label","value","correct","feedbackType","feedback","type","getFeedback","normalize","question","rationaleEnabled","promptEnabled","teacherInstructionsEnabled","studentInstructionsEnabled","model","session","env","Promise","resolve","choices","Object","keys","forEach","key","map","item","index","normalizedQuestion","assign","incorrect","preparChoiceFn","obj","area","respArea","chosenValue","val","c","prepareVal","showNote","values","length","disabled","prompt","markup","note","responseCorrect","getScore","undefined","role","rationale","teacherInstructions","getTextFromHTML","html","replace","trim","config","responseAreas","match","maxScore","correctCount","total","str","toFixed","parseFloat","outcome","partialScoringEnabled","partialScoring","enabled","score","empty","createCorrectResponseSession","i","id"],"mappings":"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","sourcesContent":["import map from 'lodash/map';\nimport reduce from 'lodash/reduce';\nimport find from 'lodash/find';\nimport isEmpty from 'lodash/isEmpty';\nimport debug from 'debug';\nimport { partialScoring } from '@pie-lib/controller-utils';\n\nconst log = debug('explicit-constructed-response:controller');\n\nexport const prepareChoice = (mode, defaultFeedback) => choice => {\n const out = {\n label: choice.label,\n value: choice.value\n };\n\n if (mode === 'evaluate') {\n out.correct = true;\n\n const feedbackType = (choice.feedback && choice.feedback.type) || 'none';\n\n if (feedbackType === 'default') {\n out.feedback = defaultFeedback['correct'];\n } else if (feedbackType === 'custom') {\n out.feedback = choice.feedback.value;\n }\n }\n\n return out;\n};\n\nconst getFeedback = value => {\n if (value) {\n return 'correct';\n }\n\n return 'incorrect';\n};\n\nexport const normalize = question => ({\n rationaleEnabled: true,\n promptEnabled: true,\n teacherInstructionsEnabled: true,\n studentInstructionsEnabled: true,\n ...question,\n});\n\n/**\n *\n * @param {*} question\n * @param {*} session\n * @param {*} env\n */\nexport function model(question, session, env) {\n return new Promise(async resolve => {\n // this was added to treat an exception, when the model has choices without the \"value\" property\n // like: { label: 'test' }\n if (question.choices) {\n Object.keys(question.choices).forEach(key => {\n question.choices[key] = question.choices[key].map((item, index) => {\n if (!item.value) {\n log('Choice does not contain \"value\" property, which is required.', item);\n return { value: `${index}`, ...item };\n }\n\n return item;\n })\n });\n }\n\n const normalizedQuestion = normalize(question);\n const defaultFeedback = Object.assign(\n { correct: 'Correct', incorrect: 'Incorrect' },\n normalizedQuestion.defaultFeedback\n );\n\n const { value = {} } = session || {};\n\n const preparChoiceFn = prepareChoice(env.mode, defaultFeedback);\n\n let choices = reduce(\n normalizedQuestion.choices,\n (obj, area, key) => {\n obj[key] = map(area, preparChoiceFn);\n\n return obj;\n },\n {}\n );\n let feedback = {};\n\n if (env.mode === 'evaluate') {\n feedback = reduce(normalizedQuestion.choices, (obj, respArea, key) => {\n const chosenValue = value && value[key];\n const val = !isEmpty(chosenValue) && find(respArea, c => prepareVal(c.label) === prepareVal(chosenValue));\n\n obj[key] = getFeedback(val);\n\n return obj;\n }, {});\n }\n\n let showNote = false;\n // check if a choice has an alternate\n Object.values(choices).forEach(choice => {\n if (choice && choice.length > 1) {\n showNote = true;\n }\n });\n\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n prompt: normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : null,\n markup: normalizedQuestion.markup,\n choices,\n feedback,\n env,\n note: normalizedQuestion.note,\n showNote,\n responseCorrect:\n env.mode === 'evaluate' ? getScore(normalizedQuestion, session) === 1 : undefined\n };\n\n if (\n env.role === 'instructor' &&\n (env.mode === 'view' || env.mode === 'evaluate')\n ) {\n out.rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : null;\n out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled ? normalizedQuestion.teacherInstructions : null;\n } else {\n out.rationale = null;\n out.teacherInstructions = null;\n }\n\n resolve(out);\n });\n}\n\nconst getTextFromHTML = (html) => {\n return (html || '').replace(/<\\/?[^>]+(>|$)/g, '');\n};\n\nexport const prepareVal = html => {\n const value = getTextFromHTML(html);\n\n return value.trim();\n};\n\nexport const getScore = (config, session) => {\n const { value } = session || {};\n\n if (!session || isEmpty(session) || !value) {\n return 0;\n }\n\n const responseAreas = config.markup && config.markup.match(/\\{\\{(.)\\}\\}/g);\n const maxScore = responseAreas ? responseAreas.length : 0;\n const correctCount = reduce(config.choices, (total, respArea, key) => {\n const chosenValue = value && value[key];\n\n if (isEmpty(chosenValue) || !find(respArea, c => prepareVal(c.label) === prepareVal(chosenValue))) {\n return total;\n }\n\n return total + 1;\n }, 0);\n\n const str = maxScore ? (correctCount / maxScore).toFixed(2) : 0;\n\n return parseFloat(str);\n};\n\n/**\n *\n * The score is partial by default for checkbox mode, allOrNothing for radio mode.\n * To disable partial scoring for checkbox mode you either set model.partialScoring = false or env.partialScoring =\n * false. the value in `env` will override the value in `model`.\n * @param {Object} model - the main model\n * @param {boolean} model.partialScoring - is partial scoring enabled (if undefined set to to true)\n * @param {*} session\n * @param {Object} env\n * @param {boolean} env.partialScoring - is partial scoring enabled (if undefined default to true) This overrides\n * `model.partialScoring`.\n */\nexport function outcome(model, session, env = {}) {\n return new Promise(resolve => {\n const partialScoringEnabled = partialScoring.enabled(model, env);\n const score = getScore(model, session);\n\n resolve({ score: partialScoringEnabled ? score : score === 1 ? 1 : 0, empty: isEmpty(session) });\n });\n}\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise(resolve => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const { choices } = question;\n const value = {};\n\n Object.keys(choices).forEach((key, i) => {\n value[i] = choices[key][0].label;\n });\n\n resolve({\n id: '1',\n value\n });\n } else {\n resolve(null);\n }\n });\n};\n"],"file":"index.js"}
1
+ {"version":3,"sources":["../src/index.js"],"names":["log","prepareChoice","mode","defaultFeedback","choice","out","label","value","correct","feedbackType","feedback","type","getFeedback","getAdjustedLength","length","normalize","question","rationaleEnabled","promptEnabled","teacherInstructionsEnabled","studentInstructionsEnabled","model","session","env","Promise","resolve","choices","Object","keys","forEach","key","map","item","index","normalizedQuestion","assign","incorrect","preparChoiceFn","obj","area","respArea","chosenValue","val","c","prepareVal","showNote","values","maxLengthPerChoice","maxLengthPerChoiceEnabled","undefinedLengths","labelLengthsArr","Math","max","disabled","prompt","markup","note","displayType","playerSpellCheckEnabled","responseCorrect","getScore","undefined","role","rationale","teacherInstructions","getTextFromHTML","html","replace","trim","config","responseAreas","match","maxScore","correctCount","total","str","toFixed","parseFloat","outcome","partialScoringEnabled","partialScoring","enabled","score","empty","createCorrectResponseSession","i","id","validate","maxResponseAreas","allChoicesErrors","entries","reversedChoices","reverse","choicesErrors","identicalAnswer","slice","some","errors","nbOfResponseAreas","responseAreasError"],"mappings":"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","sourcesContent":["import map from 'lodash/map';\nimport reduce from 'lodash/reduce';\nimport find from 'lodash/find';\nimport isEmpty from 'lodash/isEmpty';\nimport debug from 'debug';\nimport { partialScoring } from '@pie-lib/controller-utils';\n\nconst log = debug('explicit-constructed-response:controller');\n\nexport const prepareChoice = (mode, defaultFeedback) => choice => {\n const out = {\n label: choice.label,\n value: choice.value\n };\n\n if (mode === 'evaluate') {\n out.correct = true;\n\n const feedbackType = (choice.feedback && choice.feedback.type) || 'none';\n\n if (feedbackType === 'default') {\n out.feedback = defaultFeedback['correct'];\n } else if (feedbackType === 'custom') {\n out.feedback = choice.feedback.value;\n }\n }\n\n return out;\n};\n\nconst getFeedback = value => {\n if (value) {\n return 'correct';\n }\n\n return 'incorrect';\n};\n\n// also used in configure/src/markupUtils.js\nconst getAdjustedLength = length => {\n if (length <= 2) {\n return length + 2;\n }\n\n if (length <= 4) {\n return length + 3;\n }\n\n if (length <= 6) {\n return length + 4;\n }\n\n return length + 5;\n};\n\nexport const normalize = question => ({\n rationaleEnabled: true,\n promptEnabled: true,\n teacherInstructionsEnabled: true,\n studentInstructionsEnabled: true,\n ...question,\n});\n\n/**\n *\n * @param {*} question\n * @param {*} session\n * @param {*} env\n */\nexport function model(question, session, env) {\n return new Promise(async resolve => {\n // this was added to treat an exception, when the model has choices without the \"value\" property\n // like: { label: 'test' }\n if (question.choices) {\n Object.keys(question.choices).forEach(key => {\n question.choices[key] = (question.choices[key] || []).map((item, index) => {\n if (!item.value) {\n log('Choice does not contain \"value\" property, which is required.', item);\n return { value: `${index}`, ...item };\n }\n\n return item;\n })\n });\n }\n\n const normalizedQuestion = normalize(question);\n const defaultFeedback = Object.assign(\n { correct: 'Correct', incorrect: 'Incorrect' },\n normalizedQuestion.defaultFeedback\n );\n\n const { value = {} } = session || {};\n\n const preparChoiceFn = prepareChoice(env.mode, defaultFeedback);\n\n let choices = reduce(\n normalizedQuestion.choices,\n (obj, area, key) => {\n obj[key] = map(area, preparChoiceFn);\n\n return obj;\n },\n {}\n );\n let feedback = {};\n\n if (env.mode === 'evaluate') {\n feedback = reduce(normalizedQuestion.choices, (obj, respArea, key) => {\n const chosenValue = value && value[key];\n const val = !isEmpty(chosenValue) && find(respArea, c => prepareVal(c.label) === prepareVal(chosenValue));\n\n obj[key] = getFeedback(val);\n\n return obj;\n }, {});\n }\n\n let showNote = false;\n // check if a choice has an alternate\n Object.values(choices).forEach(choice => {\n if (choice && choice.length > 1) {\n showNote = true;\n }\n });\n\n const { maxLengthPerChoice = [], maxLengthPerChoiceEnabled } = normalizedQuestion;\n const undefinedLengths = !maxLengthPerChoice.length;\n\n // calculate maxLengthPerChoice array if it is not defined or defined incorrectly\n Object.values(choices).forEach((choice, index) => {\n const labelLengthsArr = (choice || []).map(choice => (choice.label || '').length);\n const length = Math.max(...labelLengthsArr);\n\n if (\n undefinedLengths\n || !maxLengthPerChoice[index]\n || maxLengthPerChoice[index] < length\n || maxLengthPerChoice[index] > length + 10\n ) {\n maxLengthPerChoice[index] = getAdjustedLength(length);\n }\n });\n\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n prompt: normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : null,\n markup: normalizedQuestion.markup,\n choices,\n feedback,\n env,\n note: normalizedQuestion.note,\n showNote,\n maxLengthPerChoice,\n maxLengthPerChoiceEnabled,\n displayType: normalizedQuestion.displayType,\n playerSpellCheckEnabled: normalizedQuestion.playerSpellCheckEnabled,\n responseCorrect:\n env.mode === 'evaluate' ? getScore(normalizedQuestion, session) === 1 : undefined\n };\n\n if (\n env.role === 'instructor' &&\n (env.mode === 'view' || env.mode === 'evaluate')\n ) {\n out.rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : null;\n out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled ? normalizedQuestion.teacherInstructions : null;\n } else {\n out.rationale = null;\n out.teacherInstructions = null;\n }\n\n resolve(out);\n });\n}\n\nconst getTextFromHTML = (html) => {\n return (html || '').replace(/<\\/?[^>]+(>|$)/g, '');\n};\n\nexport const prepareVal = html => {\n const value = getTextFromHTML(html);\n\n return value.trim();\n};\n\nexport const getScore = (config, session) => {\n const { value } = session || {};\n\n if (!session || isEmpty(session) || !value) {\n return 0;\n }\n\n const responseAreas = config.markup && config.markup.match(/\\{\\{(.)\\}\\}/g);\n const maxScore = responseAreas ? responseAreas.length : 0;\n const correctCount = reduce(config.choices, (total, respArea, key) => {\n const chosenValue = value && value[key];\n\n if (isEmpty(chosenValue) || !find(respArea, c => prepareVal(c.label) === prepareVal(chosenValue))) {\n return total;\n }\n\n return total + 1;\n }, 0);\n\n const str = maxScore ? (correctCount / maxScore).toFixed(2) : 0;\n\n return parseFloat(str);\n};\n\n/**\n *\n * The score is partial by default for checkbox mode, allOrNothing for radio mode.\n * To disable partial scoring for checkbox mode you either set model.partialScoring = false or env.partialScoring =\n * false. the value in `env` will override the value in `model`.\n * @param {Object} model - the main model\n * @param {boolean} model.partialScoring - is partial scoring enabled (if undefined set to to true)\n * @param {*} session\n * @param {Object} env\n * @param {boolean} env.partialScoring - is partial scoring enabled (if undefined default to true) This overrides\n * `model.partialScoring`.\n */\nexport function outcome(model, session, env = {}) {\n return new Promise(resolve => {\n const partialScoringEnabled = partialScoring.enabled(model, env);\n const score = getScore(model, session);\n\n resolve({ score: partialScoringEnabled ? score : score === 1 ? 1 : 0, empty: isEmpty(session) });\n });\n}\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise(resolve => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const { choices } = question;\n const value = {};\n\n Object.keys(choices).forEach((key, i) => {\n value[i] = choices[key][0].label;\n });\n\n resolve({\n id: '1',\n value\n });\n } else {\n resolve(null);\n }\n });\n};\n\nexport const validate = (model = {}, config = {}) => {\n const { choices, markup } = model;\n const { maxResponseAreas } = config;\n const allChoicesErrors = {};\n\n Object.entries(choices || {}).forEach(([key, values]) => {\n const reversedChoices = [...values || []].reverse();\n const choicesErrors = {};\n\n reversedChoices.forEach((choice, index) => {\n const { value, label } = choice;\n\n if (label === '' || label === '<div></div>') {\n choicesErrors[value] = 'Content should not be empty.';\n } else {\n const identicalAnswer = reversedChoices.slice(index + 1).some(c => c.label === label);\n\n if (identicalAnswer) {\n choicesErrors[value] = 'Content should be unique.';\n }\n }\n });\n\n if (!isEmpty(choicesErrors)) {\n allChoicesErrors[key] = choicesErrors;\n }\n });\n\n const errors = {};\n const nbOfResponseAreas = (markup.match(/\\{\\{(\\d+)\\}\\}/g) || []).length;\n\n if (nbOfResponseAreas > maxResponseAreas) {\n errors.responseAreasError = `No more than ${maxResponseAreas} response areas should be defined.`;\n } else if (nbOfResponseAreas < 1) {\n errors.responseAreasError = 'There should be at least 1 response area defined.';\n }\n\n if (!isEmpty(allChoicesErrors)) {\n errors.choicesErrors = allChoicesErrors;\n }\n\n return errors;\n};\n"],"file":"index.js"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pie-element/explicit-constructed-response-controller",
3
3
  "private": true,
4
- "version": "3.3.2",
4
+ "version": "3.4.8",
5
5
  "description": "",
6
6
  "main": "lib/index.js",
7
7
  "module": "src/index.js",
@@ -51,6 +51,38 @@
51
51
  }
52
52
  }
53
53
  },
54
+ "spellCheck": {
55
+ "title": "ConfigureProp",
56
+ "type": "object",
57
+ "properties": {
58
+ "settings": {
59
+ "description": "Indicates if the item has to be displayed in the Settings Panel",
60
+ "type": "boolean",
61
+ "title": "settings"
62
+ },
63
+ "label": {
64
+ "description": "Indicates the label for the item that has to be displayed in the Settings Panel",
65
+ "type": "string",
66
+ "title": "label"
67
+ }
68
+ }
69
+ },
70
+ "playerSpellCheck": {
71
+ "title": "ConfigureProp",
72
+ "type": "object",
73
+ "properties": {
74
+ "settings": {
75
+ "description": "Indicates if the item has to be displayed in the Settings Panel",
76
+ "type": "boolean",
77
+ "title": "settings"
78
+ },
79
+ "label": {
80
+ "description": "Indicates the label for the item that has to be displayed in the Settings Panel",
81
+ "type": "string",
82
+ "title": "label"
83
+ }
84
+ }
85
+ },
54
86
  "autoScoring": {
55
87
  "title": "ConfigureProp",
56
88
  "type": "object",
@@ -131,6 +163,69 @@
131
163
  }
132
164
  }
133
165
  },
166
+ "maxLengthPerChoice": {
167
+ "title": "ConfigureProp",
168
+ "type": "object",
169
+ "properties": {
170
+ "settings": {
171
+ "description": "Indicates if the item has to be displayed in the Settings Panel",
172
+ "type": "boolean",
173
+ "title": "settings"
174
+ },
175
+ "label": {
176
+ "description": "Indicates the label for the item that has to be displayed in the Settings Panel",
177
+ "type": "string",
178
+ "title": "label"
179
+ }
180
+ }
181
+ },
182
+ "maxResponseAreas": {
183
+ "description": "Maximum number of response areas",
184
+ "type": "number",
185
+ "title": "maxResponseAreas"
186
+ },
187
+ "maxImageWidth": {
188
+ "title": "ConfigureMaxImageDimensionsProp",
189
+ "type": "object",
190
+ "properties": {
191
+ "teacherInstructions": {
192
+ "description": "Indicates the max dimension for images in teacher instructions",
193
+ "type": "number",
194
+ "title": "teacherInstructions"
195
+ },
196
+ "prompt": {
197
+ "description": "Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified",
198
+ "type": "number",
199
+ "title": "prompt"
200
+ },
201
+ "rationale": {
202
+ "description": "Indicates the max dimension for images in rationale",
203
+ "type": "number",
204
+ "title": "rationale"
205
+ }
206
+ }
207
+ },
208
+ "maxImageHeight": {
209
+ "title": "ConfigureMaxImageDimensionsProp",
210
+ "type": "object",
211
+ "properties": {
212
+ "teacherInstructions": {
213
+ "description": "Indicates the max dimension for images in teacher instructions",
214
+ "type": "number",
215
+ "title": "teacherInstructions"
216
+ },
217
+ "prompt": {
218
+ "description": "Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified",
219
+ "type": "number",
220
+ "title": "prompt"
221
+ },
222
+ "rationale": {
223
+ "description": "Indicates the max dimension for images in rationale",
224
+ "type": "number",
225
+ "title": "rationale"
226
+ }
227
+ }
228
+ },
134
229
  "showPrompt": {
135
230
  "description": "Determines whether prompt field will be displayed or not",
136
231
  "default": true,
@@ -166,6 +261,27 @@
166
261
  "title": "label"
167
262
  }
168
263
  }
264
+ },
265
+ "ConfigureMaxImageDimensionsProp": {
266
+ "title": "ConfigureMaxImageDimensionsProp",
267
+ "type": "object",
268
+ "properties": {
269
+ "teacherInstructions": {
270
+ "description": "Indicates the max dimension for images in teacher instructions",
271
+ "type": "number",
272
+ "title": "teacherInstructions"
273
+ },
274
+ "prompt": {
275
+ "description": "Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified",
276
+ "type": "number",
277
+ "title": "prompt"
278
+ },
279
+ "rationale": {
280
+ "description": "Indicates the max dimension for images in rationale",
281
+ "type": "number",
282
+ "title": "rationale"
283
+ }
284
+ }
169
285
  }
170
286
  },
171
287
  "$schema": "http://json-schema.org/draft-07/schema#"
@@ -38,6 +38,30 @@ Indicates if the item has to be displayed in the Settings Panel
38
38
 
39
39
  Indicates the label for the item that has to be displayed in the Settings Panel
40
40
 
41
+ # `spellCheck` (object)
42
+
43
+ Properties of the `spellCheck` object:
44
+
45
+ ## `settings` (boolean)
46
+
47
+ Indicates if the item has to be displayed in the Settings Panel
48
+
49
+ ## `label` (string)
50
+
51
+ Indicates the label for the item that has to be displayed in the Settings Panel
52
+
53
+ # `playerSpellCheck` (object)
54
+
55
+ Properties of the `playerSpellCheck` object:
56
+
57
+ ## `settings` (boolean)
58
+
59
+ Indicates if the item has to be displayed in the Settings Panel
60
+
61
+ ## `label` (string)
62
+
63
+ Indicates the label for the item that has to be displayed in the Settings Panel
64
+
41
65
  # `autoScoring` (object)
42
66
 
43
67
  Properties of the `autoScoring` object:
@@ -98,6 +122,54 @@ Indicates if the item has to be displayed in the Settings Panel
98
122
 
99
123
  Indicates the label for the item that has to be displayed in the Settings Panel
100
124
 
125
+ # `maxLengthPerChoice` (object)
126
+
127
+ Properties of the `maxLengthPerChoice` object:
128
+
129
+ ## `settings` (boolean)
130
+
131
+ Indicates if the item has to be displayed in the Settings Panel
132
+
133
+ ## `label` (string)
134
+
135
+ Indicates the label for the item that has to be displayed in the Settings Panel
136
+
137
+ # `maxResponseAreas` (number)
138
+
139
+ Maximum number of response areas
140
+
141
+ # `maxImageWidth` (object)
142
+
143
+ Properties of the `maxImageWidth` object:
144
+
145
+ ## `teacherInstructions` (number)
146
+
147
+ Indicates the max dimension for images in teacher instructions
148
+
149
+ ## `prompt` (number)
150
+
151
+ Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified
152
+
153
+ ## `rationale` (number)
154
+
155
+ Indicates the max dimension for images in rationale
156
+
157
+ # `maxImageHeight` (object)
158
+
159
+ Properties of the `maxImageHeight` object:
160
+
161
+ ## `teacherInstructions` (number)
162
+
163
+ Indicates the max dimension for images in teacher instructions
164
+
165
+ ## `prompt` (number)
166
+
167
+ Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified
168
+
169
+ ## `rationale` (number)
170
+
171
+ Indicates the max dimension for images in rationale
172
+
101
173
  # `showPrompt` (boolean)
102
174
 
103
175
  Determines whether prompt field will be displayed or not
@@ -132,4 +204,20 @@ Indicates if the item has to be displayed in the Settings Panel
132
204
 
133
205
  ### `label` (string)
134
206
 
135
- Indicates the label for the item that has to be displayed in the Settings Panel
207
+ Indicates the label for the item that has to be displayed in the Settings Panel
208
+
209
+ ## `ConfigureMaxImageDimensionsProp` (object)
210
+
211
+ Properties of the `ConfigureMaxImageDimensionsProp` object:
212
+
213
+ ### `teacherInstructions` (number)
214
+
215
+ Indicates the max dimension for images in teacher instructions
216
+
217
+ ### `prompt` (number)
218
+
219
+ Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified
220
+
221
+ ### `rationale` (number)
222
+
223
+ Indicates the max dimension for images in rationale
@@ -12,7 +12,9 @@ exports.model = (id, element) => ({
12
12
  1: [choice('over', '0'), choice('past', '1'), choice('beyond', '2')],
13
13
  2: [choice('moon', '0')]
14
14
  },
15
+ maxLengthPerChoice: [7, 10, 4],
15
16
  prompt: 'Complete the sentence',
16
17
  note: 'The answer shown above is the most common correct answer for this item. One or more additional correct answers are also defined, and will also be recognized as correct.',
17
- promptEnabled: true
18
+ promptEnabled: true,
19
+ toolbarEditorPosition: 'bottom'
18
20
  });