@pie-element/ebsr 14.2.2-next.2 → 14.2.2

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 (97) hide show
  1. package/CHANGELOG.json +1547 -0
  2. package/CHANGELOG.md +2291 -0
  3. package/LICENSE.md +5 -0
  4. package/README.md +62 -0
  5. package/configure/CHANGELOG.json +992 -0
  6. package/configure/CHANGELOG.md +2154 -0
  7. package/configure/lib/defaults.js +229 -0
  8. package/configure/lib/defaults.js.map +1 -0
  9. package/configure/lib/index.js +154 -0
  10. package/configure/lib/index.js.map +1 -0
  11. package/configure/lib/main.js +222 -0
  12. package/configure/lib/main.js.map +1 -0
  13. package/configure/package.json +23 -0
  14. package/configure/src/__tests__/index.test.js +492 -0
  15. package/configure/src/defaults.js +173 -0
  16. package/configure/src/index.js +174 -0
  17. package/configure/src/main.jsx +235 -0
  18. package/controller/CHANGELOG.json +552 -0
  19. package/controller/CHANGELOG.md +1286 -0
  20. package/controller/lib/defaults.js +31 -0
  21. package/controller/lib/defaults.js.map +1 -0
  22. package/controller/lib/index.js +448 -0
  23. package/controller/lib/index.js.map +1 -0
  24. package/controller/lib/utils.js +18 -0
  25. package/controller/lib/utils.js.map +1 -0
  26. package/controller/package.json +18 -0
  27. package/controller/src/__tests__/index.test.js +591 -0
  28. package/controller/src/__tests__/utils.test.js +48 -0
  29. package/controller/src/defaults.js +25 -0
  30. package/controller/src/index.js +442 -0
  31. package/controller/src/utils.js +18 -0
  32. package/docs/config-schema.json +5787 -0
  33. package/docs/config-schema.json.md +4278 -0
  34. package/docs/demo/config.js +8 -0
  35. package/docs/demo/generate.js +52 -0
  36. package/docs/demo/index.html +2 -0
  37. package/docs/demo/session.js +14 -0
  38. package/docs/pie-schema.json +2911 -0
  39. package/docs/pie-schema.json.md +2142 -0
  40. package/ebsr.png +0 -0
  41. package/lib/index.js +207 -0
  42. package/lib/index.js.map +1 -0
  43. package/lib/print.js +186 -0
  44. package/lib/print.js.map +1 -0
  45. package/module/configure.js +1 -0
  46. package/module/controller.js +5664 -0
  47. package/module/demo.js +77 -0
  48. package/module/element.js +1 -0
  49. package/module/index.html +21 -0
  50. package/module/manifest.json +14 -0
  51. package/module/print-demo.js +115 -0
  52. package/module/print.html +18 -0
  53. package/module/print.js +1 -0
  54. package/package.json +19 -88
  55. package/src/__tests__/index.test.js +129 -0
  56. package/src/index.js +222 -0
  57. package/src/print.js +207 -0
  58. package/configure.js +0 -2
  59. package/controller.js +0 -1
  60. package/dist/author/defaults.d.ts +0 -348
  61. package/dist/author/defaults.js +0 -161
  62. package/dist/author/index.d.ts +0 -34
  63. package/dist/author/index.js +0 -78
  64. package/dist/author/main.d.ts +0 -22
  65. package/dist/author/main.js +0 -121
  66. package/dist/browser/author/index.js +0 -13947
  67. package/dist/browser/author/index.js.map +0 -1
  68. package/dist/browser/browser-CdX8WGiZ.js +0 -207
  69. package/dist/browser/browser-CdX8WGiZ.js.map +0 -1
  70. package/dist/browser/controller/index.js +0 -257
  71. package/dist/browser/controller/index.js.map +0 -1
  72. package/dist/browser/delivery/index.js +0 -133
  73. package/dist/browser/delivery/index.js.map +0 -1
  74. package/dist/browser/dist-CaWRqnXk.js +0 -62
  75. package/dist/browser/dist-CaWRqnXk.js.map +0 -1
  76. package/dist/browser/dist-D9ARZhQk.js +0 -1426
  77. package/dist/browser/dist-D9ARZhQk.js.map +0 -1
  78. package/dist/browser/dist-DQkngCcw.js +0 -36
  79. package/dist/browser/dist-DQkngCcw.js.map +0 -1
  80. package/dist/browser/print/index.js +0 -107
  81. package/dist/browser/print/index.js.map +0 -1
  82. package/dist/controller/defaults.d.ts +0 -15
  83. package/dist/controller/defaults.js +0 -26
  84. package/dist/controller/index.d.ts +0 -42
  85. package/dist/controller/index.js +0 -185
  86. package/dist/controller/utils.d.ts +0 -10
  87. package/dist/controller/utils.js +0 -8
  88. package/dist/delivery/index.d.ts +0 -26
  89. package/dist/delivery/index.js +0 -132
  90. package/dist/index.d.ts +0 -1
  91. package/dist/index.iife.d.ts +0 -8
  92. package/dist/index.iife.js +0 -165
  93. package/dist/index.js +0 -2
  94. package/dist/print/index.d.ts +0 -25
  95. package/dist/print/index.js +0 -106
  96. package/dist/runtime-support.d.ts +0 -12
  97. package/dist/runtime-support.js +0 -12
@@ -0,0 +1,173 @@
1
+ import { cloneDeep } from 'lodash-es';
2
+
3
+ const defaultConfig = {
4
+ addChoiceButton: {
5
+ settings: true,
6
+ label: 'Add a Choice',
7
+ },
8
+ choiceMode: {
9
+ settings: true,
10
+ label: 'Response Type',
11
+ },
12
+ choicePrefix: {
13
+ settings: true,
14
+ label: 'Choice Labels',
15
+ },
16
+ deleteChoice: {
17
+ settings: true,
18
+ },
19
+ feedback: {
20
+ settings: true,
21
+ label: 'Feedback',
22
+ },
23
+ lockChoiceOrder: {
24
+ settings: true,
25
+ label: 'Lock Choice Order',
26
+ },
27
+ prompt: {
28
+ settings: true,
29
+ label: 'Prompt',
30
+ inputConfiguration: {
31
+ audio: { disabled: false },
32
+ video: { disabled: false },
33
+ image: { disabled: false },
34
+ },
35
+ required: false,
36
+ },
37
+ rationale: {
38
+ settings: true,
39
+ label: 'Rationale',
40
+ inputConfiguration: {
41
+ audio: { disabled: false },
42
+ video: { disabled: false },
43
+ image: { disabled: false },
44
+ },
45
+ required: false,
46
+ },
47
+ settingsPanelDisabled: true,
48
+ studentInstructions: {
49
+ settings: false,
50
+ label: 'Student Instructions',
51
+ },
52
+ teacherInstructions: {
53
+ settings: true,
54
+ label: 'Teacher Instructions',
55
+ inputConfiguration: {
56
+ audio: { disabled: false },
57
+ video: { disabled: false },
58
+ image: { disabled: false },
59
+ },
60
+ required: false,
61
+ },
62
+ choicesLayout: {
63
+ settings: false,
64
+ label: 'Choices Layout',
65
+ },
66
+ gridColumns: {
67
+ label: 'Grid columns',
68
+ },
69
+ spellCheck: {
70
+ label: 'Spellcheck',
71
+ settings: false,
72
+ enabled: true,
73
+ },
74
+ maxImageWidth: {
75
+ teacherInstructions: 300,
76
+ prompt: 300,
77
+ rationale: 636,
78
+ choices: 636,
79
+ },
80
+ maxImageHeight: {
81
+ teacherInstructions: 300,
82
+ prompt: 300,
83
+ rationale: 300,
84
+ choices: 300,
85
+ },
86
+ mathMlOptions: {
87
+ mmlOutput: false,
88
+ mmlEditing: false,
89
+ },
90
+ choices: {
91
+ inputConfiguration: {
92
+ audio: { disabled: false },
93
+ video: { disabled: false },
94
+ image: { disabled: false },
95
+ },
96
+ },
97
+ baseInputConfiguration: {
98
+ h3: { disabled: true },
99
+ audio: { disabled: false },
100
+ video: { disabled: false },
101
+ image: { disabled: false },
102
+ textAlign: { disabled: true },
103
+ showParagraphs: { disabled: false },
104
+ separateParagraphs: { disabled: true },
105
+ },
106
+ };
107
+
108
+ const partModel = (base) => ({
109
+ choiceMode: 'radio',
110
+ choicePrefix: 'letters',
111
+ choices: [],
112
+ choicesLayout: 'vertical',
113
+ feedbackEnabled: false,
114
+ gridColumns: 2,
115
+ prompt: '',
116
+ promptEnabled: true,
117
+ rationale: '',
118
+ rationaleEnabled: true,
119
+ spellCheckEnabled: true,
120
+ studentInstructionsEnabled: true,
121
+ teacherInstructions: '',
122
+ teacherInstructionsEnabled: true,
123
+ toolbarEditorPosition: 'bottom',
124
+ ...base,
125
+ });
126
+
127
+ export default {
128
+ model: {
129
+ partLabels: false,
130
+ partLabelType: 'Letters',
131
+ // partialScoring: false,
132
+ partA: partModel(),
133
+ partB: partModel(),
134
+ },
135
+ configuration: {
136
+ baseInputConfiguration: {
137
+ h3: { disabled: true },
138
+ audio: { disabled: false },
139
+ video: { disabled: false },
140
+ image: { disabled: false },
141
+ textAlign: { disabled: true },
142
+ showParagraphs: { disabled: false },
143
+ separateParagraphs: { disabled: true },
144
+ },
145
+ partialScoring: {
146
+ label: 'Allow Partial Scoring',
147
+ // this will turn off partial scoring toggle in the settings tab by default for the interaction
148
+ // as we'd like partial scoring to be controlled from the environment entirely
149
+ // if any other consumers would like to enable it for themselves, they can do so from their model directly.
150
+ settings: false,
151
+ },
152
+ scoringType: {
153
+ settings: false,
154
+ label: 'Scoring Type',
155
+ },
156
+ partA: cloneDeep(defaultConfig),
157
+ partB: cloneDeep(defaultConfig),
158
+ partLabels: {
159
+ settings: true,
160
+ label: 'Part Labels',
161
+ },
162
+ settingsPanelDisabled: false,
163
+ language: {
164
+ settings: false,
165
+ label: 'Specify Language',
166
+ enabled: false,
167
+ },
168
+ languageChoices: {
169
+ label: 'Language Choices',
170
+ options: [],
171
+ },
172
+ },
173
+ };
@@ -0,0 +1,174 @@
1
+ import React from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { ModelUpdatedEvent } from '@pie-framework/pie-configure-events';
4
+ import MultipleChoiceConfigure from '@pie-element/multiple-choice/configure/lib';
5
+ import { defaults } from 'lodash-es';
6
+ import Main from './main';
7
+
8
+ import sensibleDefaults from './defaults';
9
+
10
+ const MODEL_UPDATED = ModelUpdatedEvent.TYPE;
11
+ const MC_TAG_NAME = 'ebsr-multiple-choice-configure';
12
+
13
+ class EbsrMCConfigure extends MultipleChoiceConfigure {}
14
+ const defineMultipleChoice = () => {
15
+ if (!customElements.get(MC_TAG_NAME)) {
16
+ customElements.define(MC_TAG_NAME, EbsrMCConfigure);
17
+ }
18
+ };
19
+
20
+ defineMultipleChoice();
21
+
22
+ const prepareCustomizationObject = (config, model) => {
23
+ const configuration = defaults(config, sensibleDefaults.configuration);
24
+
25
+ return {
26
+ configuration,
27
+ model,
28
+ };
29
+ };
30
+
31
+ const { model: modelDefault } = sensibleDefaults || {};
32
+
33
+ export default class EbsrConfigure extends HTMLElement {
34
+ static createDefaultModel = ({ partA = {}, partB = {}, ...model } = {}, defaults = modelDefault) => ({
35
+ ...defaults,
36
+ ...model,
37
+ partA: {
38
+ ...defaults.partA,
39
+ ...partA,
40
+ choicesLayout:
41
+ partA.choicesLayout || (partA.verticalMode === false && 'horizontal') || defaults.partA.choicesLayout,
42
+ },
43
+ partB: {
44
+ ...defaults.partB,
45
+ ...partB,
46
+ choicesLayout:
47
+ partB.choicesLayout || (partB.verticalMode === false && 'horizontal') || defaults.partB.choicesLayout,
48
+ },
49
+ });
50
+
51
+ constructor() {
52
+ super();
53
+ this._root = null;
54
+
55
+ this._model = EbsrConfigure.createDefaultModel();
56
+
57
+ this._configuration = sensibleDefaults.configuration;
58
+ this.onConfigurationChanged = this.onConfigurationChanged.bind(this);
59
+ }
60
+
61
+ set model(m) {
62
+ this._model = EbsrConfigure.createDefaultModel(m, this._model);
63
+
64
+ this._render();
65
+ }
66
+
67
+ dispatchModelUpdated(reset) {
68
+ const resetValue = !!reset;
69
+
70
+ this.dispatchEvent(new ModelUpdatedEvent(this._model, resetValue));
71
+ }
72
+
73
+ onModelChanged = (m, reset) => {
74
+ this._model = EbsrConfigure.createDefaultModel(m, this._model);
75
+
76
+ this.dispatchModelUpdated(reset);
77
+ this._render();
78
+ };
79
+
80
+ set configuration(c) {
81
+ const info = prepareCustomizationObject(c, this._model);
82
+
83
+ const newConfiguration = {
84
+ ...sensibleDefaults.configuration,
85
+ ...info.configuration,
86
+ };
87
+
88
+ this._configuration = newConfiguration;
89
+
90
+ // if language:enabled is true, then the corresponding default item model should include a language value;
91
+ // if it is false, then the language field should be omitted from the item model.
92
+ // if a default item model includes a language value (e.g., en_US) and the corresponding authoring view settings have language:settings = true,
93
+ // then (a) language:enabled should also be true, and (b) that default language value should be represented in languageChoices[] (as a key).
94
+ if (newConfiguration?.language?.enabled) {
95
+ if (newConfiguration?.languageChoices?.options?.length) {
96
+ this._model.language = newConfiguration?.languageChoices.options[0].value;
97
+ }
98
+ } else if (newConfiguration.language.settings && this._model.language) {
99
+ this._configuration.language.enabled = true;
100
+
101
+ if (!this._configuration.languageChoices.options || !this._configuration.languageChoices.options.length) {
102
+ this._configuration.languageChoices.options = [];
103
+ }
104
+
105
+ // check if the language is already included in the languageChoices.options array
106
+ // and if not, then add it.
107
+ if (!this._configuration.languageChoices.options.find((option) => option.value === this._model.language)) {
108
+ this._configuration.languageChoices.options.push({
109
+ value: this._model.language,
110
+ label: this._model.language,
111
+ });
112
+ }
113
+ } else {
114
+ delete this._model.language;
115
+ }
116
+
117
+ this._render();
118
+ }
119
+
120
+ onConfigurationChanged(c) {
121
+ this._configuration = prepareCustomizationObject(c, this._model).configuration;
122
+
123
+ if (this._model) {
124
+ this.onModelChanged(this._model);
125
+ }
126
+
127
+ this._render();
128
+ }
129
+
130
+ onModelUpdated = (e) => {
131
+ if (e.target === this) {
132
+ return;
133
+ }
134
+
135
+ e.preventDefault();
136
+ e.stopImmediatePropagation();
137
+
138
+ const id = e.target && e.target.getAttribute('id');
139
+
140
+ if (id) {
141
+ if (e.update) {
142
+ this._model[`part${id}`] = e.update;
143
+ }
144
+
145
+ this.dispatchEvent(new ModelUpdatedEvent(this._model));
146
+ }
147
+ };
148
+
149
+ connectedCallback() {
150
+ this.addEventListener(MODEL_UPDATED, this.onModelUpdated);
151
+ this._render();
152
+ }
153
+
154
+ _render() {
155
+ let element = React.createElement(Main, {
156
+ model: this._model,
157
+ configuration: this._configuration,
158
+ onModelChanged: this.onModelChanged,
159
+ onConfigurationChanged: this.onConfigurationChanged,
160
+ });
161
+
162
+ if (!this._root) {
163
+ this._root = createRoot(this);
164
+ }
165
+ this._root.render(element);
166
+ }
167
+
168
+ disconnectedCallback() {
169
+ this.removeEventListener(MODEL_UPDATED, this.onModelUpdated);
170
+ if (this._root) {
171
+ this._root.unmount();
172
+ }
173
+ }
174
+ }
@@ -0,0 +1,235 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { settings, layout } from '@pie-lib/config-ui';
4
+ import { styled } from '@mui/material/styles';
5
+
6
+ const { Panel, toggle, radio, dropdown } = settings;
7
+
8
+ const PartLabel = styled('div')(({ theme }) => ({
9
+ paddingBottom: theme.spacing(2),
10
+ }));
11
+
12
+ const Divider = styled('div')(({ theme }) => ({
13
+ flex: 1,
14
+ height: theme.spacing(2.5),
15
+ }));
16
+
17
+ export class Main extends React.Component {
18
+ static propTypes = {
19
+ configuration: PropTypes.object,
20
+ model: PropTypes.object,
21
+ onModelChanged: PropTypes.func,
22
+ onConfigurationChanged: PropTypes.func,
23
+ };
24
+
25
+ removeExtraChoices = (choices) => {
26
+ let correctFound = false;
27
+
28
+ return (choices || []).map((choice) => {
29
+ if (correctFound) {
30
+ choice.correct = false;
31
+
32
+ return choice;
33
+ }
34
+
35
+ if (choice.correct) {
36
+ correctFound = true;
37
+ }
38
+
39
+ return choice;
40
+ });
41
+ };
42
+
43
+ onModelChanged = (model, key) => {
44
+ const { onModelChanged } = this.props;
45
+
46
+ if (key === 'partA.choiceMode' && model.partA.choiceMode === 'radio') {
47
+ model.partA.choices = this.removeExtraChoices(model.partA.choices);
48
+
49
+ return onModelChanged(model, true);
50
+ }
51
+
52
+ if (key === 'partB.choiceMode' && model.partB.choiceMode === 'radio') {
53
+ model.partB.choices = this.removeExtraChoices(model.partB.choices);
54
+
55
+ return onModelChanged(model, true);
56
+ }
57
+
58
+ return onModelChanged(model);
59
+ };
60
+
61
+ render() {
62
+ const { model, configuration, onConfigurationChanged } = this.props;
63
+ const { partLabelType, partA: modelPartA, partB: modelPartB, extraCSSRules } = model;
64
+ const {
65
+ contentDimensions = {},
66
+ partA = {},
67
+ partB = {},
68
+ partialScoring = {},
69
+ settingsPanelDisabled,
70
+ scoringType = {},
71
+ language = {},
72
+ languageChoices = {},
73
+ ...generalConfiguration
74
+ } = configuration;
75
+ const {
76
+ feedback: feedbackA = {},
77
+ choiceMode: choiceModeA = {},
78
+ choicePrefix: choicePrefixA = {},
79
+ lockChoiceOrder: lockChoiceOrderA = {},
80
+ prompt: promptA = {},
81
+ teacherInstructions: teacherInstructionsA = {},
82
+ studentInstructions: studentInstructionsA = {},
83
+ choicesLayout: choicesLayoutA = {},
84
+ gridColumns: gridColumnsA = {},
85
+ rationale: rationaleA = {},
86
+ spellCheck: spellCheckA = {},
87
+ } = partA || {};
88
+ const {
89
+ feedback: feedbackB = {},
90
+ choiceMode: choiceModeB = {},
91
+ choicePrefix: choicePrefixB = {},
92
+ lockChoiceOrder: lockChoiceOrderB = {},
93
+ prompt: promptB = {},
94
+ teacherInstructions: teacherInstructionsB = {},
95
+ studentInstructions: studentInstructionsB = {},
96
+ choicesLayout: choicesLayoutB = {},
97
+ gridColumns: gridColumnsB = {},
98
+ rationale: rationaleB = {},
99
+ spellCheck: spellCheckB = {},
100
+ } = partB || {};
101
+
102
+ const type = partLabelType || 'Numbers';
103
+ const typeIsNumber = type === 'Numbers';
104
+ const firstPart = `Part ${typeIsNumber ? '1' : 'A'}`;
105
+ const secondPart = `Part ${typeIsNumber ? '2' : 'B'}`;
106
+ const nrOfColumnsAvailable = {
107
+ partA:
108
+ modelPartA.choices && modelPartA.choices.length
109
+ ? Array.from({ length: modelPartA.choices.length }, (_, i) => `${i + 1}`)
110
+ : [],
111
+ partB:
112
+ modelPartB.choices && modelPartB.choices.length
113
+ ? Array.from({ length: modelPartB.choices.length }, (_, i) => `${i + 1}`)
114
+ : [],
115
+ };
116
+
117
+ const panelSettings = {
118
+ partLabels: generalConfiguration.partLabels.settings && toggle(generalConfiguration.partLabels.label),
119
+ partLabelType: model.partLabels && dropdown('', ['Numbers', 'Letters']),
120
+ partialScoring: partialScoring.settings && toggle(partialScoring.label),
121
+ scoringType: scoringType.settings && radio(scoringType.label, ['auto', 'rubric']),
122
+ 'language.enabled': language.settings && toggle(language.label, true),
123
+ language: language.settings && language.enabled && dropdown(languageChoices.label, languageChoices.options),
124
+ };
125
+
126
+ const panelSettingsPartA = {
127
+ 'partA.choiceMode': choiceModeA.settings && radio(choiceModeA.label, ['checkbox', 'radio']),
128
+ 'partA.choicePrefix': choicePrefixA.settings && radio(choicePrefixA.label, ['numbers', 'letters']),
129
+ 'partA.lockChoiceOrder': lockChoiceOrderA.settings && toggle(lockChoiceOrderA.label),
130
+ 'partA.choicesLayout':
131
+ choicesLayoutA.settings && dropdown(choicesLayoutA.label, ['vertical', 'grid', 'horizontal']),
132
+ 'partA.gridColumns':
133
+ choicesLayoutA.settings &&
134
+ modelPartA.choicesLayout === 'grid' &&
135
+ nrOfColumnsAvailable.partA.length > 0 &&
136
+ dropdown(gridColumnsA.label, nrOfColumnsAvailable.partA),
137
+ };
138
+ const panelPropertiesPartA = {
139
+ 'partA.feedbackEnabled': feedbackA.settings && toggle(feedbackA.label),
140
+ 'partA.promptEnabled': promptA.settings && toggle(promptA.label),
141
+ 'partA.teacherInstructionsEnabled': teacherInstructionsA.settings && toggle(teacherInstructionsA.label),
142
+ 'partA.studentInstructionsEnabled': studentInstructionsA.settings && toggle(studentInstructionsA.label),
143
+ 'partA.rationaleEnabled': rationaleA.settings && toggle(rationaleA.label),
144
+ 'partA.spellCheckEnabled': spellCheckA.settings && toggle(spellCheckA.label),
145
+ };
146
+
147
+ const panelSettingsPartB = {
148
+ 'partB.choiceMode': choiceModeB.settings && radio(choiceModeB.label, ['checkbox', 'radio']),
149
+ 'partB.choicePrefix': choicePrefixB.settings && radio(choicePrefixB.label, ['numbers', 'letters']),
150
+ 'partB.lockChoiceOrder': lockChoiceOrderB.settings && toggle(lockChoiceOrderB.label),
151
+ 'partB.choicesLayout':
152
+ choicesLayoutB.settings && dropdown(choicesLayoutB.label, ['vertical', 'grid', 'horizontal']),
153
+ 'partB.gridColumns':
154
+ choicesLayoutB.settings &&
155
+ modelPartB.choicesLayout === 'grid' &&
156
+ nrOfColumnsAvailable.partB.length > 0 &&
157
+ dropdown(gridColumnsB.label, nrOfColumnsAvailable.partB),
158
+ };
159
+ const panelPropertiesPartB = {
160
+ 'partB.feedbackEnabled': feedbackB.settings && toggle(feedbackB.label),
161
+ 'partB.promptEnabled': promptB.settings && toggle(promptB.label),
162
+ 'partB.teacherInstructionsEnabled': teacherInstructionsB.settings && toggle(teacherInstructionsB.label),
163
+ 'partB.studentInstructionsEnabled': studentInstructionsB.settings && toggle(studentInstructionsB.label),
164
+ 'partB.rationaleEnabled': rationaleB.settings && toggle(rationaleB.label),
165
+ 'partB.spellCheckEnabled': spellCheckB.settings && toggle(spellCheckB.label),
166
+ };
167
+
168
+ return (
169
+ <layout.ConfigLayout
170
+ extraCSSRules={extraCSSRules}
171
+ dimensions={contentDimensions}
172
+ hideSettings={settingsPanelDisabled}
173
+ settings={
174
+ <Panel
175
+ model={model}
176
+ onChangeModel={this.onModelChanged}
177
+ configuration={configuration}
178
+ onChangeConfiguration={onConfigurationChanged}
179
+ groups={{
180
+ 'Settings for both': panelSettings,
181
+ [`Settings ${firstPart}`]: panelSettingsPartA,
182
+ [`Properties ${firstPart}`]: panelPropertiesPartA,
183
+ [`Settings ${secondPart}`]: panelSettingsPartB,
184
+ [`Properties ${secondPart}`]: panelPropertiesPartB,
185
+ }}
186
+ />
187
+ }
188
+ >
189
+ {model.partLabels && <PartLabel>{firstPart}</PartLabel>}
190
+ <ebsr-multiple-choice-configure
191
+ id="A"
192
+ key="partA"
193
+ ref={(ref) => {
194
+ if (ref) {
195
+ // do not use destructuring to get model from props
196
+ this.partA = ref;
197
+ this.partA._model = {
198
+ ...this.props.model.partA,
199
+ errors: (this.props.model.errors && this.props.model.errors.partA) || {},
200
+ };
201
+ this.partA.configuration = {
202
+ ...partA,
203
+ ...generalConfiguration,
204
+ };
205
+ }
206
+ }}
207
+ />
208
+
209
+ <Divider />
210
+
211
+ {model.partLabels && <PartLabel>{secondPart}</PartLabel>}
212
+ <ebsr-multiple-choice-configure
213
+ id="B"
214
+ key="partB"
215
+ ref={(ref) => {
216
+ if (ref) {
217
+ // do not use destructuring to get model from props
218
+ this.partB = ref;
219
+ this.partB._model = {
220
+ ...this.props.model.partB,
221
+ errors: (this.props.model.errors && this.props.model.errors.partB) || {},
222
+ };
223
+ this.partB.configuration = {
224
+ ...partB,
225
+ ...generalConfiguration,
226
+ };
227
+ }
228
+ }}
229
+ />
230
+ </layout.ConfigLayout>
231
+ );
232
+ }
233
+ }
234
+
235
+ export default Main;