@pie-lib/config-ui 11.30.2 → 11.30.3-next.155
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.
- package/CHANGELOG.md +7 -78
- package/esm/package.json +3 -0
- package/lib/alert-dialog.js +35 -42
- package/lib/alert-dialog.js.map +1 -1
- package/lib/checkbox.js +56 -71
- package/lib/checkbox.js.map +1 -1
- package/lib/choice-configuration/feedback-menu.js +29 -64
- package/lib/choice-configuration/feedback-menu.js.map +1 -1
- package/lib/choice-configuration/index.js +202 -262
- package/lib/choice-configuration/index.js.map +1 -1
- package/lib/choice-utils.js +6 -18
- package/lib/choice-utils.js.map +1 -1
- package/lib/feedback-config/feedback-selector.js +79 -115
- package/lib/feedback-config/feedback-selector.js.map +1 -1
- package/lib/feedback-config/group.js +26 -40
- package/lib/feedback-config/group.js.map +1 -1
- package/lib/feedback-config/index.js +47 -90
- package/lib/feedback-config/index.js.map +1 -1
- package/lib/form-section.js +31 -33
- package/lib/form-section.js.map +1 -1
- package/lib/help.js +39 -80
- package/lib/help.js.map +1 -1
- package/lib/index.js +1 -31
- package/lib/index.js.map +1 -1
- package/lib/input.js +21 -54
- package/lib/input.js.map +1 -1
- package/lib/inputs.js +61 -95
- package/lib/inputs.js.map +1 -1
- package/lib/langs.js +58 -101
- package/lib/langs.js.map +1 -1
- package/lib/layout/config-layout.js +40 -70
- package/lib/layout/config-layout.js.map +1 -1
- package/lib/layout/index.js +0 -3
- package/lib/layout/index.js.map +1 -1
- package/lib/layout/layout-contents.js +72 -103
- package/lib/layout/layout-contents.js.map +1 -1
- package/lib/layout/settings-box.js +27 -56
- package/lib/layout/settings-box.js.map +1 -1
- package/lib/mui-box/index.js +41 -57
- package/lib/mui-box/index.js.map +1 -1
- package/lib/number-text-field-custom.js +79 -161
- package/lib/number-text-field-custom.js.map +1 -1
- package/lib/number-text-field.js +80 -114
- package/lib/number-text-field.js.map +1 -1
- package/lib/radio-with-label.js +30 -31
- package/lib/radio-with-label.js.map +1 -1
- package/lib/settings/display-size.js +16 -32
- package/lib/settings/display-size.js.map +1 -1
- package/lib/settings/index.js +14 -47
- package/lib/settings/index.js.map +1 -1
- package/lib/settings/panel.js +159 -229
- package/lib/settings/panel.js.map +1 -1
- package/lib/settings/settings-radio-label.js +28 -30
- package/lib/settings/settings-radio-label.js.map +1 -1
- package/lib/settings/toggle.js +35 -46
- package/lib/settings/toggle.js.map +1 -1
- package/lib/tabs/index.js +22 -57
- package/lib/tabs/index.js.map +1 -1
- package/lib/tags-input/index.js +50 -99
- package/lib/tags-input/index.js.map +1 -1
- package/lib/two-choice.js +46 -90
- package/lib/two-choice.js.map +1 -1
- package/lib/with-stateful-model.js +8 -31
- package/lib/with-stateful-model.js.map +1 -1
- package/package.json +20 -12
- package/src/__tests__/alert-dialog.test.jsx +283 -0
- package/src/__tests__/checkbox.test.jsx +249 -0
- package/src/__tests__/form-section.test.jsx +334 -0
- package/src/__tests__/help.test.jsx +184 -0
- package/src/__tests__/input.test.jsx +192 -0
- package/src/__tests__/langs.test.jsx +435 -15
- package/src/__tests__/number-text-field-custom.test.jsx +438 -0
- package/src/__tests__/number-text-field.test.jsx +295 -102
- package/src/__tests__/radio-with-label.test.jsx +259 -0
- package/src/__tests__/settings-panel.test.js +66 -83
- package/src/__tests__/settings.test.jsx +515 -0
- package/src/__tests__/tabs.test.jsx +193 -0
- package/src/__tests__/two-choice.test.js +104 -18
- package/src/__tests__/with-stateful-model.test.jsx +145 -0
- package/src/alert-dialog.jsx +21 -19
- package/src/checkbox.jsx +42 -46
- package/src/choice-configuration/__tests__/feedback-menu.test.jsx +157 -4
- package/src/choice-configuration/__tests__/index.test.jsx +198 -56
- package/src/choice-configuration/feedback-menu.jsx +6 -6
- package/src/choice-configuration/index.jsx +201 -196
- package/src/feedback-config/__tests__/feedback-config.test.jsx +130 -60
- package/src/feedback-config/__tests__/feedback-selector.test.jsx +87 -40
- package/src/feedback-config/feedback-selector.jsx +52 -53
- package/src/feedback-config/group.jsx +21 -22
- package/src/feedback-config/index.jsx +27 -29
- package/src/form-section.jsx +26 -18
- package/src/help.jsx +20 -28
- package/src/input.jsx +1 -1
- package/src/inputs.jsx +34 -50
- package/src/langs.jsx +41 -46
- package/src/layout/__tests__/config.layout.test.jsx +55 -38
- package/src/layout/config-layout.jsx +38 -32
- package/src/layout/layout-contents.jsx +38 -39
- package/src/layout/settings-box.jsx +16 -19
- package/src/mui-box/index.jsx +35 -43
- package/src/number-text-field-custom.jsx +30 -36
- package/src/number-text-field.jsx +45 -29
- package/src/radio-with-label.jsx +25 -13
- package/src/settings/display-size.jsx +12 -11
- package/src/settings/panel.jsx +97 -91
- package/src/settings/settings-radio-label.jsx +25 -13
- package/src/settings/toggle.jsx +30 -29
- package/src/tabs/index.jsx +8 -8
- package/src/tags-input/__tests__/index.test.jsx +88 -37
- package/src/tags-input/index.jsx +35 -38
- package/src/two-choice.jsx +15 -19
- package/src/__tests__/__snapshots__/langs.test.jsx.snap +0 -32
- package/src/__tests__/__snapshots__/settings-panel.test.js.snap +0 -115
- package/src/__tests__/__snapshots__/two-choice.test.js.snap +0 -171
- package/src/choice-configuration/__tests__/__snapshots__/feedback-menu.test.jsx.snap +0 -51
- package/src/choice-configuration/__tests__/__snapshots__/index.test.jsx.snap +0 -519
- package/src/feedback-config/__tests__/__snapshots__/feedback-config.test.jsx.snap +0 -27
- package/src/feedback-config/__tests__/__snapshots__/feedback-selector.test.jsx.snap +0 -38
- package/src/layout/__tests__/__snapshots__/config.layout.test.jsx.snap +0 -59
- package/src/tags-input/__tests__/__snapshots__/index.test.jsx.snap +0 -170
|
@@ -1,117 +1,177 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import {
|
|
4
|
-
import TextField from '@material
|
|
5
|
-
import ActionDelete from '@
|
|
6
|
-
import ArrowRight from '@
|
|
7
|
-
import IconButton from '@material
|
|
8
|
-
import classNames from 'classnames';
|
|
3
|
+
import { styled } from '@mui/material/styles';
|
|
4
|
+
import TextField from '@mui/material/TextField';
|
|
5
|
+
import ActionDelete from '@mui/icons-material/Delete';
|
|
6
|
+
import ArrowRight from '@mui/icons-material/SubdirectoryArrowRight';
|
|
7
|
+
import IconButton from '@mui/material/IconButton';
|
|
9
8
|
import { InputContainer } from '@pie-lib/render-ui';
|
|
10
|
-
import EditableHtml from '@pie-lib/editable-html';
|
|
9
|
+
// import EditableHtml from '@pie-lib/editable-html';
|
|
11
10
|
import { InputCheckbox, InputRadio } from '../inputs';
|
|
12
11
|
import FeedbackMenu from './feedback-menu';
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}))(
|
|
20
|
-
({
|
|
21
|
-
label,
|
|
22
|
-
classes,
|
|
23
|
-
onChange,
|
|
24
|
-
value,
|
|
25
|
-
className,
|
|
26
|
-
imageSupport,
|
|
27
|
-
disableImageAlignmentButtons,
|
|
28
|
-
disabled,
|
|
29
|
-
spellCheck,
|
|
30
|
-
nonEmpty,
|
|
31
|
-
pluginOpts,
|
|
32
|
-
toolbarOpts,
|
|
33
|
-
error,
|
|
34
|
-
maxImageWidth,
|
|
35
|
-
maxImageHeight,
|
|
36
|
-
uploadSoundSupport,
|
|
37
|
-
mathMlOptions = {},
|
|
38
|
-
}) => {
|
|
39
|
-
const names = classNames(classes.labelContainer, className);
|
|
13
|
+
// - mathquill error window not defined
|
|
14
|
+
let EditableHtml;
|
|
15
|
+
if (typeof window !== 'undefined') {
|
|
16
|
+
EditableHtml = require('@pie-lib/editable-html')['default'];
|
|
17
|
+
}
|
|
40
18
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
19
|
+
const StyledEditorHolder = styled('div')(({ theme }) => ({
|
|
20
|
+
marginTop: theme.spacing(2),
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
const EditableHtmlContainer = ({
|
|
24
|
+
label,
|
|
25
|
+
onChange,
|
|
26
|
+
value,
|
|
27
|
+
className,
|
|
28
|
+
imageSupport,
|
|
29
|
+
disableImageAlignmentButtons,
|
|
30
|
+
disabled,
|
|
31
|
+
spellCheck,
|
|
32
|
+
nonEmpty,
|
|
33
|
+
pluginOpts,
|
|
34
|
+
toolbarOpts,
|
|
35
|
+
error,
|
|
36
|
+
maxImageWidth,
|
|
37
|
+
maxImageHeight,
|
|
38
|
+
uploadSoundSupport,
|
|
39
|
+
mathMlOptions = {},
|
|
40
|
+
}) => {
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<InputContainer label={label} className={className}>
|
|
44
|
+
<StyledEditorHolder>
|
|
45
|
+
<EditableHtml
|
|
46
|
+
markup={value || ''}
|
|
47
|
+
disabled={disabled}
|
|
48
|
+
spellCheck={spellCheck}
|
|
49
|
+
nonEmpty={nonEmpty}
|
|
50
|
+
onChange={onChange}
|
|
51
|
+
imageSupport={imageSupport}
|
|
52
|
+
disableImageAlignmentButtons={disableImageAlignmentButtons}
|
|
53
|
+
pluginProps={pluginOpts || {}}
|
|
54
|
+
toolbarOpts={toolbarOpts}
|
|
55
|
+
error={error}
|
|
56
|
+
maxImageWidth={maxImageWidth}
|
|
57
|
+
maxImageHeight={maxImageHeight}
|
|
58
|
+
uploadSoundSupport={uploadSoundSupport}
|
|
59
|
+
languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
|
|
60
|
+
mathMlOptions={mathMlOptions}
|
|
61
|
+
/>
|
|
62
|
+
</StyledEditorHolder>
|
|
63
|
+
</InputContainer>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const StyledFeedbackContainer = styled('div')(() => ({
|
|
68
|
+
position: 'relative',
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
const StyledArrowIcon = styled(ArrowRight)(({ theme }) => ({
|
|
72
|
+
fill: theme.palette.grey[400],
|
|
73
|
+
left: -56,
|
|
74
|
+
position: 'absolute',
|
|
75
|
+
top: 40,
|
|
76
|
+
}));
|
|
77
|
+
|
|
78
|
+
const StyledTextField = styled(TextField)(({ theme }) => ({
|
|
79
|
+
width: '100%',
|
|
80
|
+
marginTop: theme.spacing(2),
|
|
81
|
+
}));
|
|
82
|
+
|
|
83
|
+
const StyledEditableHtmlContainer = styled(EditableHtmlContainer)(({ theme }) => ({
|
|
84
|
+
width: '100%',
|
|
85
|
+
marginTop: theme.spacing(2),
|
|
86
|
+
}));
|
|
87
|
+
|
|
88
|
+
const Feedback = ({ value, onChange, type, correct, defaults, toolbarOpts, mathMlOptions = {} }) => {
|
|
82
89
|
if (!type || type === 'none') {
|
|
83
90
|
return null;
|
|
84
91
|
} else if (type === 'default') {
|
|
85
92
|
return (
|
|
86
|
-
<
|
|
87
|
-
<
|
|
88
|
-
<
|
|
89
|
-
className={classes.text}
|
|
93
|
+
<StyledFeedbackContainer>
|
|
94
|
+
<StyledArrowIcon />
|
|
95
|
+
<StyledTextField
|
|
90
96
|
label="Feedback Text"
|
|
91
97
|
value={correct ? defaults.correct : defaults.incorrect}
|
|
98
|
+
variant="standard"
|
|
92
99
|
/>
|
|
93
|
-
</
|
|
100
|
+
</StyledFeedbackContainer>
|
|
94
101
|
);
|
|
95
102
|
} else {
|
|
96
103
|
return (
|
|
97
|
-
<
|
|
98
|
-
<
|
|
99
|
-
<
|
|
100
|
-
className={classes.text}
|
|
104
|
+
<StyledFeedbackContainer>
|
|
105
|
+
<StyledArrowIcon />
|
|
106
|
+
<StyledEditableHtmlContainer
|
|
101
107
|
label="Feedback Text"
|
|
102
108
|
value={value}
|
|
103
109
|
onChange={onChange}
|
|
104
110
|
toolbarOpts={toolbarOpts}
|
|
105
111
|
mathMlOptions={mathMlOptions}
|
|
106
112
|
/>
|
|
107
|
-
</
|
|
113
|
+
</StyledFeedbackContainer>
|
|
108
114
|
);
|
|
109
115
|
}
|
|
110
|
-
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const StyledIndex = styled('span')(({ theme }) => ({
|
|
119
|
+
paddingRight: theme.spacing(1),
|
|
120
|
+
paddingTop: theme.spacing(3),
|
|
121
|
+
}));
|
|
122
|
+
|
|
123
|
+
const StyledTopRow = styled('div')(() => ({
|
|
124
|
+
display: 'flex',
|
|
125
|
+
alignItems: 'center',
|
|
126
|
+
}));
|
|
127
|
+
|
|
128
|
+
const StyledToggle = styled('div')(({ theme }) => ({
|
|
129
|
+
flex: '0 1 auto',
|
|
130
|
+
paddingTop: theme.spacing(0.5),
|
|
131
|
+
paddingBottom: 0,
|
|
132
|
+
marginRight: 0,
|
|
133
|
+
marginLeft: theme.spacing(1),
|
|
134
|
+
}));
|
|
135
|
+
|
|
136
|
+
const StyledFeedback = styled('div')(({ theme }) => ({
|
|
137
|
+
flex: '0 1 auto',
|
|
138
|
+
paddingTop: theme.spacing(2),
|
|
139
|
+
paddingLeft: 0,
|
|
140
|
+
marginLeft: 0,
|
|
141
|
+
marginRight: theme.spacing(1),
|
|
142
|
+
}));
|
|
143
|
+
|
|
144
|
+
const StyledFeedbackIcon = styled('div')(() => ({
|
|
145
|
+
margin: 0,
|
|
146
|
+
width: 'inherit',
|
|
147
|
+
}));
|
|
148
|
+
|
|
149
|
+
const StyledDeleteIcon = styled('div')(() => ({
|
|
150
|
+
margin: 0,
|
|
151
|
+
width: 'inherit',
|
|
152
|
+
}));
|
|
153
|
+
|
|
154
|
+
const StyledDelete = styled('div')(({ theme }) => ({
|
|
155
|
+
flex: '0 1 auto',
|
|
156
|
+
paddingTop: theme.spacing(2),
|
|
157
|
+
paddingLeft: 0,
|
|
158
|
+
marginLeft: 0,
|
|
159
|
+
}));
|
|
160
|
+
|
|
161
|
+
const StyledMiddleColumn = styled('div')(({ theme }) => ({
|
|
162
|
+
display: 'flex',
|
|
163
|
+
flex: 1,
|
|
164
|
+
flexDirection: 'column',
|
|
165
|
+
marginRight: theme.spacing(1),
|
|
166
|
+
}));
|
|
167
|
+
|
|
168
|
+
const StyledErrorText = styled('div')(({ theme }) => ({
|
|
169
|
+
fontSize: theme.typography.fontSize - 2,
|
|
170
|
+
color: theme.palette.error.main,
|
|
171
|
+
}));
|
|
111
172
|
|
|
112
173
|
export class ChoiceConfiguration extends React.Component {
|
|
113
174
|
static propTypes = {
|
|
114
|
-
classes: PropTypes.object.isRequired,
|
|
115
175
|
noLabels: PropTypes.bool,
|
|
116
176
|
useLetterOrdering: PropTypes.bool,
|
|
117
177
|
className: PropTypes.string,
|
|
@@ -201,7 +261,6 @@ export class ChoiceConfiguration extends React.Component {
|
|
|
201
261
|
render() {
|
|
202
262
|
const {
|
|
203
263
|
data,
|
|
204
|
-
classes,
|
|
205
264
|
mode,
|
|
206
265
|
onDelete,
|
|
207
266
|
defaultFeedback,
|
|
@@ -227,45 +286,43 @@ export class ChoiceConfiguration extends React.Component {
|
|
|
227
286
|
} = this.props;
|
|
228
287
|
|
|
229
288
|
const InputToggle = mode === 'checkbox' ? InputCheckbox : InputRadio;
|
|
230
|
-
const names = classNames(classes.choiceConfiguration, className);
|
|
231
289
|
|
|
232
290
|
return (
|
|
233
|
-
|
|
234
|
-
<div className={classes.topRow}>
|
|
291
|
+
<StyledTopRow>
|
|
235
292
|
{index > 0 && (
|
|
236
|
-
<
|
|
293
|
+
<StyledIndex type="title">
|
|
237
294
|
{useLetterOrdering ? String.fromCharCode(96 + index).toUpperCase() : index}
|
|
238
|
-
</
|
|
295
|
+
</StyledIndex>
|
|
239
296
|
)}
|
|
240
297
|
|
|
241
|
-
<
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
/>
|
|
248
|
-
|
|
249
|
-
<div className={classes.middleColumn}>
|
|
250
|
-
<EditableHtmlContainer
|
|
251
|
-
className={classes.input}
|
|
252
|
-
label={!noLabels ? 'Label' : ''}
|
|
253
|
-
value={data.label}
|
|
254
|
-
onChange={this.onLabelChange}
|
|
255
|
-
imageSupport={imageSupport}
|
|
256
|
-
disableImageAlignmentButtons={disableImageAlignmentButtons}
|
|
257
|
-
disabled={disabled}
|
|
258
|
-
spellCheck={spellCheck}
|
|
259
|
-
nonEmpty={nonEmpty}
|
|
260
|
-
pluginOpts={pluginOpts}
|
|
261
|
-
toolbarOpts={toolbarOpts}
|
|
262
|
-
error={error}
|
|
263
|
-
uploadSoundSupport={uploadSoundSupport}
|
|
264
|
-
mathMlOptions={mathMlOptions}
|
|
265
|
-
maxImageWidth={maxImageWidth}
|
|
266
|
-
maxImageHeight={maxImageHeight}
|
|
298
|
+
<StyledToggle>
|
|
299
|
+
<InputToggle
|
|
300
|
+
onChange={this.onCheckedChange}
|
|
301
|
+
label={!noLabels ? 'Correct' : ''}
|
|
302
|
+
checked={!!data.correct}
|
|
303
|
+
error={noCorrectAnswerError}
|
|
267
304
|
/>
|
|
268
|
-
|
|
305
|
+
</StyledToggle>
|
|
306
|
+
|
|
307
|
+
<StyledMiddleColumn>
|
|
308
|
+
<EditableHtmlContainer
|
|
309
|
+
label={!noLabels ? 'Label' : ''}
|
|
310
|
+
value={data.label}
|
|
311
|
+
onChange={this.onLabelChange}
|
|
312
|
+
imageSupport={imageSupport}
|
|
313
|
+
disableImageAlignmentButtons={disableImageAlignmentButtons}
|
|
314
|
+
disabled={disabled}
|
|
315
|
+
spellCheck={spellCheck}
|
|
316
|
+
nonEmpty={nonEmpty}
|
|
317
|
+
pluginOpts={pluginOpts}
|
|
318
|
+
toolbarOpts={toolbarOpts}
|
|
319
|
+
error={error}
|
|
320
|
+
uploadSoundSupport={uploadSoundSupport}
|
|
321
|
+
mathMlOptions={mathMlOptions}
|
|
322
|
+
maxImageWidth={maxImageWidth}
|
|
323
|
+
maxImageHeight={maxImageHeight}
|
|
324
|
+
/>
|
|
325
|
+
{error && <StyledErrorText>{error}</StyledErrorText>}
|
|
269
326
|
|
|
270
327
|
{allowFeedBack && (
|
|
271
328
|
<Feedback
|
|
@@ -276,90 +333,38 @@ export class ChoiceConfiguration extends React.Component {
|
|
|
276
333
|
toolbarOpts={toolbarOpts}
|
|
277
334
|
/>
|
|
278
335
|
)}
|
|
279
|
-
</
|
|
336
|
+
</StyledMiddleColumn>
|
|
280
337
|
|
|
281
338
|
{allowFeedBack && (
|
|
282
|
-
<
|
|
283
|
-
<
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
339
|
+
<StyledFeedback>
|
|
340
|
+
<InputContainer label={!noLabels ? 'Feedback' : ''}>
|
|
341
|
+
<StyledFeedbackIcon>
|
|
342
|
+
<FeedbackMenu
|
|
343
|
+
onChange={this.onFeedbackTypeChange}
|
|
344
|
+
value={data.feedback}
|
|
345
|
+
/>
|
|
346
|
+
</StyledFeedbackIcon>
|
|
347
|
+
</InputContainer>
|
|
348
|
+
</StyledFeedback>
|
|
291
349
|
)}
|
|
292
350
|
|
|
293
351
|
{allowDelete && (
|
|
294
|
-
<
|
|
295
|
-
<
|
|
296
|
-
<
|
|
297
|
-
|
|
298
|
-
|
|
352
|
+
<StyledDelete>
|
|
353
|
+
<InputContainer label={!noLabels ? 'Delete' : ''}>
|
|
354
|
+
<StyledDeleteIcon>
|
|
355
|
+
<IconButton
|
|
356
|
+
aria-label="delete"
|
|
357
|
+
onClick={onDelete}
|
|
358
|
+
size="large">
|
|
359
|
+
<ActionDelete />
|
|
360
|
+
</IconButton>
|
|
361
|
+
</StyledDeleteIcon>
|
|
362
|
+
</InputContainer>
|
|
363
|
+
</StyledDelete>
|
|
299
364
|
)}
|
|
300
|
-
</
|
|
301
|
-
</div>
|
|
365
|
+
</StyledTopRow>
|
|
302
366
|
);
|
|
303
367
|
}
|
|
304
368
|
}
|
|
305
369
|
|
|
306
|
-
|
|
307
|
-
index: {
|
|
308
|
-
paddingRight: theme.spacing.unit,
|
|
309
|
-
paddingTop: theme.spacing.unit * 3.5,
|
|
310
|
-
},
|
|
311
|
-
choiceConfiguration: {},
|
|
312
|
-
topRow: {
|
|
313
|
-
display: 'flex',
|
|
314
|
-
},
|
|
315
|
-
value: {
|
|
316
|
-
flex: '0.5',
|
|
317
|
-
paddingRight: theme.spacing.unit,
|
|
318
|
-
},
|
|
319
|
-
editorHolder: {
|
|
320
|
-
marginTop: theme.spacing.unit * 2,
|
|
321
|
-
},
|
|
322
|
-
toggle: {
|
|
323
|
-
flex: '0 1 auto',
|
|
324
|
-
paddingTop: theme.spacing.unit / 2,
|
|
325
|
-
paddingBottom: 0,
|
|
326
|
-
marginRight: 0,
|
|
327
|
-
marginLeft: theme.spacing.unit,
|
|
328
|
-
},
|
|
329
|
-
feedback: {
|
|
330
|
-
flex: '0 1 auto',
|
|
331
|
-
paddingTop: theme.spacing.unit * 2,
|
|
332
|
-
paddingLeft: 0,
|
|
333
|
-
marginLeft: 0,
|
|
334
|
-
marginRight: theme.spacing.unit,
|
|
335
|
-
},
|
|
336
|
-
feedbackIcon: {
|
|
337
|
-
margin: 0,
|
|
338
|
-
width: 'inherit',
|
|
339
|
-
},
|
|
340
|
-
deleteIcon: {
|
|
341
|
-
margin: 0,
|
|
342
|
-
width: 'inherit',
|
|
343
|
-
},
|
|
344
|
-
delete: {
|
|
345
|
-
flex: '0 1 auto',
|
|
346
|
-
paddingTop: theme.spacing.unit * 2,
|
|
347
|
-
paddingLeft: 0,
|
|
348
|
-
marginLeft: 0,
|
|
349
|
-
},
|
|
350
|
-
middleColumn: {
|
|
351
|
-
display: 'flex',
|
|
352
|
-
flex: 1,
|
|
353
|
-
flexDirection: 'column',
|
|
354
|
-
marginRight: theme.spacing.unit,
|
|
355
|
-
},
|
|
356
|
-
input: {
|
|
357
|
-
marginRight: 0,
|
|
358
|
-
},
|
|
359
|
-
errorText: {
|
|
360
|
-
fontSize: theme.typography.fontSize - 2,
|
|
361
|
-
color: theme.palette.error.main,
|
|
362
|
-
},
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
export default withStyles(styles)(ChoiceConfiguration);
|
|
370
|
+
export default ChoiceConfiguration;
|
|
@@ -1,70 +1,140 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import Adapter from 'enzyme-adapter-react-16';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen, within } from '@testing-library/react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
4
|
+
import { FeedbackConfig, buildDefaults } from '../index';
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
// Mock FeedbackSelector to simplify testing
|
|
7
|
+
jest.mock('../feedback-selector', () => {
|
|
8
|
+
return function FeedbackSelector({ label, feedback, onChange }) {
|
|
9
|
+
return (
|
|
10
|
+
<div data-testid="feedback-selector">
|
|
11
|
+
<label>{label}</label>
|
|
12
|
+
<select
|
|
13
|
+
aria-label={label}
|
|
14
|
+
value={feedback.type}
|
|
15
|
+
onChange={(e) => onChange({ ...feedback, type: e.target.value })}
|
|
16
|
+
>
|
|
17
|
+
<option value="default">Default</option>
|
|
18
|
+
<option value="custom">Custom</option>
|
|
19
|
+
<option value="none">None</option>
|
|
20
|
+
</select>
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
});
|
|
8
25
|
|
|
9
26
|
describe('FeedbackConfig', () => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
const onChange = jest.fn();
|
|
28
|
+
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
onChange.mockClear();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('rendering', () => {
|
|
34
|
+
it('renders with default feedback types', () => {
|
|
35
|
+
const feedback = buildDefaults();
|
|
36
|
+
|
|
37
|
+
render(<FeedbackConfig feedback={feedback} onChange={onChange} />);
|
|
38
|
+
|
|
39
|
+
expect(screen.getByText('Feedback')).toBeInTheDocument();
|
|
40
|
+
expect(screen.getByText('If correct, show')).toBeInTheDocument();
|
|
41
|
+
expect(screen.getByText('If partially correct, show')).toBeInTheDocument();
|
|
42
|
+
expect(screen.getByText('If incorrect, show')).toBeInTheDocument();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('renders all three feedback selectors by default', () => {
|
|
46
|
+
const feedback = buildDefaults();
|
|
47
|
+
|
|
48
|
+
render(<FeedbackConfig feedback={feedback} onChange={onChange} />);
|
|
49
|
+
|
|
50
|
+
const selectors = screen.getAllByTestId('feedback-selector');
|
|
51
|
+
expect(selectors).toHaveLength(3);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('does not render partial feedback selector when allowPartial is false', () => {
|
|
55
|
+
const feedback = buildDefaults();
|
|
56
|
+
|
|
57
|
+
render(<FeedbackConfig allowPartial={false} feedback={feedback} onChange={onChange} />);
|
|
58
|
+
|
|
59
|
+
expect(screen.getByText('If correct, show')).toBeInTheDocument();
|
|
60
|
+
expect(screen.queryByText('If partially correct, show')).not.toBeInTheDocument();
|
|
61
|
+
expect(screen.getByText('If incorrect, show')).toBeInTheDocument();
|
|
62
|
+
|
|
63
|
+
const selectors = screen.getAllByTestId('feedback-selector');
|
|
64
|
+
expect(selectors).toHaveLength(2);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('user interactions', () => {
|
|
69
|
+
it('calls onChange when correct feedback type changes', async () => {
|
|
70
|
+
const user = userEvent.setup();
|
|
71
|
+
const feedback = buildDefaults();
|
|
72
|
+
|
|
73
|
+
render(<FeedbackConfig feedback={feedback} onChange={onChange} />);
|
|
74
|
+
|
|
75
|
+
const correctSelect = screen.getByLabelText('If correct, show');
|
|
76
|
+
await user.selectOptions(correctSelect, 'custom');
|
|
77
|
+
|
|
78
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
79
|
+
expect.objectContaining({
|
|
80
|
+
correct: expect.objectContaining({ type: 'custom' }),
|
|
81
|
+
}),
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('calls onChange when incorrect feedback type changes', async () => {
|
|
86
|
+
const user = userEvent.setup();
|
|
87
|
+
const feedback = buildDefaults();
|
|
88
|
+
|
|
89
|
+
render(<FeedbackConfig feedback={feedback} onChange={onChange} />);
|
|
90
|
+
|
|
91
|
+
const incorrectSelect = screen.getByLabelText('If incorrect, show');
|
|
92
|
+
await user.selectOptions(incorrectSelect, 'none');
|
|
93
|
+
|
|
94
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
95
|
+
expect.objectContaining({
|
|
96
|
+
incorrect: expect.objectContaining({ type: 'none' }),
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('calls onChange when partial feedback type changes', async () => {
|
|
102
|
+
const user = userEvent.setup();
|
|
103
|
+
const feedback = buildDefaults();
|
|
104
|
+
|
|
105
|
+
render(<FeedbackConfig feedback={feedback} onChange={onChange} />);
|
|
106
|
+
|
|
107
|
+
const partialSelect = screen.getByLabelText('If partially correct, show');
|
|
108
|
+
await user.selectOptions(partialSelect, 'custom');
|
|
109
|
+
|
|
110
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
111
|
+
expect.objectContaining({
|
|
112
|
+
partial: expect.objectContaining({ type: 'custom' }),
|
|
113
|
+
}),
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('buildDefaults helper', () => {
|
|
119
|
+
it('returns default feedback configuration', () => {
|
|
120
|
+
const defaults = buildDefaults();
|
|
121
|
+
|
|
122
|
+
expect(defaults).toEqual({
|
|
123
|
+
correct: { type: 'default', default: 'Correct' },
|
|
124
|
+
incorrect: { type: 'default', default: 'Incorrect' },
|
|
125
|
+
partial: { type: 'default', default: 'Nearly' },
|
|
34
126
|
});
|
|
127
|
+
});
|
|
35
128
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<FeedbackConfig
|
|
40
|
-
allowPartial={false}
|
|
41
|
-
feedback={feedback}
|
|
42
|
-
defaults={defaults}
|
|
43
|
-
onChange={jest.fn()}
|
|
44
|
-
classes={{}}
|
|
45
|
-
/>,
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
selectors = component.find(FeedbackSelector);
|
|
49
|
-
|
|
50
|
-
expect(selectors.length).toEqual(2);
|
|
51
|
-
});
|
|
129
|
+
it('merges custom values with defaults', () => {
|
|
130
|
+
const defaults = buildDefaults({
|
|
131
|
+
correct: { type: 'custom', custom: 'Great job!' },
|
|
52
132
|
});
|
|
53
133
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
allowPartial={false}
|
|
59
|
-
feedback={feedback}
|
|
60
|
-
defaults={defaults}
|
|
61
|
-
onChange={jest.fn()}
|
|
62
|
-
classes={{}}
|
|
63
|
-
/>,
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
expect(component).toMatchSnapshot();
|
|
67
|
-
});
|
|
134
|
+
expect(defaults).toEqual({
|
|
135
|
+
correct: { type: 'custom', default: 'Correct', custom: 'Great job!' },
|
|
136
|
+
incorrect: { type: 'default', default: 'Incorrect' },
|
|
137
|
+
partial: { type: 'default', default: 'Nearly' },
|
|
68
138
|
});
|
|
69
139
|
});
|
|
70
140
|
});
|