@pie-element/image-cloze-association 3.5.0 → 3.5.1-beta.587
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 +478 -0
- package/configure/CHANGELOG.md +390 -0
- package/configure/lib/defaults.js +16 -0
- package/configure/lib/defaults.js.map +1 -1
- package/configure/lib/index.js +17 -3
- package/configure/lib/index.js.map +1 -1
- package/configure/lib/root.js +43 -13
- package/configure/lib/root.js.map +1 -1
- package/configure/package.json +4 -3
- package/configure/src/__tests__/index.test.js +12 -15
- package/configure/src/defaults.js +20 -4
- package/configure/src/index.js +23 -3
- package/configure/src/root.jsx +41 -25
- package/controller/CHANGELOG.md +63 -0
- package/controller/lib/index.js +9 -8
- package/controller/lib/index.js.map +1 -1
- package/controller/lib/utils.js +4 -4
- package/controller/lib/utils.js.map +1 -1
- package/controller/package.json +2 -2
- package/controller/src/__tests__/index.test.js +108 -62
- package/controller/src/index.js +40 -28
- package/controller/src/utils.js +10 -10
- package/docs/config-schema.json +160 -0
- package/docs/config-schema.json.md +127 -0
- package/docs/demo/config.js +2 -2
- package/docs/demo/generate.js +30 -25
- package/docs/demo/session.js +1 -1
- package/docs/pie-schema.json +378 -0
- package/docs/pie-schema.json.md +295 -0
- package/lib/constants.js.map +1 -1
- package/lib/evaluation-icon.js.map +1 -1
- package/lib/image-container.js +13 -6
- package/lib/image-container.js.map +1 -1
- package/lib/image-drop-target.js +7 -2
- package/lib/image-drop-target.js.map +1 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/interactive-section.js +1 -1
- package/lib/interactive-section.js.map +1 -1
- package/lib/possible-response.js +17 -5
- package/lib/possible-response.js.map +1 -1
- package/lib/possible-responses.js.map +1 -1
- package/lib/root.js +140 -19
- package/lib/root.js.map +1 -1
- package/lib/utils-correctness.js +33 -5
- package/lib/utils-correctness.js.map +1 -1
- package/package.json +8 -5
- package/src/__tests__/__snapshots__/{image-container-test.jsx.snap → image-container.test.jsx.snap} +20 -0
- package/src/__tests__/__snapshots__/possible-response.test.jsx.snap +5 -0
- package/src/__tests__/__snapshots__/root.test.jsx.snap +50 -0
- package/src/__tests__/{image-container-test.jsx → image-container.test.jsx} +12 -5
- package/src/__tests__/{possible-response-test.jsx → possible-response.test.jsx} +5 -3
- package/src/__tests__/{root-test.jsx → root.test.jsx} +4 -3
- package/src/__tests__/utils.test.js +207 -0
- package/src/constants.js +3 -3
- package/src/evaluation-icon.jsx +8 -17
- package/src/image-container.jsx +14 -19
- package/src/image-drop-target.jsx +45 -38
- package/src/index.js +10 -18
- package/src/interactive-section.jsx +15 -22
- package/src/possible-response.jsx +43 -23
- package/src/possible-responses.jsx +17 -25
- package/src/root.jsx +174 -100
- package/src/utils-correctness.js +44 -14
- package/src/__tests__/__snapshots__/possible-response-test.jsx.snap +0 -13
- package/src/__tests__/__snapshots__/root-test.jsx.snap +0 -38
- package/src/__tests__/utils-test.js +0 -211
|
@@ -3,7 +3,7 @@ import _ from 'lodash';
|
|
|
3
3
|
import { shallow } from 'enzyme';
|
|
4
4
|
import toJson from 'enzyme-to-json';
|
|
5
5
|
|
|
6
|
-
import PossibleResponse from '../possible-response';
|
|
6
|
+
import { PossibleResponse } from '../possible-response';
|
|
7
7
|
|
|
8
8
|
describe('Possible Response', () => {
|
|
9
9
|
let wrapper;
|
|
@@ -13,9 +13,11 @@ describe('Possible Response', () => {
|
|
|
13
13
|
{
|
|
14
14
|
canDrag: false,
|
|
15
15
|
containerStyle: {},
|
|
16
|
-
data: {}
|
|
16
|
+
data: {},
|
|
17
|
+
onDragBegin: jest.fn(),
|
|
18
|
+
onDragEnd: jest.fn(),
|
|
17
19
|
},
|
|
18
|
-
opts
|
|
20
|
+
opts,
|
|
19
21
|
);
|
|
20
22
|
|
|
21
23
|
return shallow(<PossibleResponse {...opts} />);
|
|
@@ -19,7 +19,8 @@ const model = {
|
|
|
19
19
|
responseContainers: [],
|
|
20
20
|
possibleResponses: [],
|
|
21
21
|
duplicateResponses: false,
|
|
22
|
-
maxResponsePerZone: 5
|
|
22
|
+
maxResponsePerZone: 5,
|
|
23
|
+
showDashedBorder: true,
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
describe('Root', () => {
|
|
@@ -29,9 +30,9 @@ describe('Root', () => {
|
|
|
29
30
|
opts = _.extend(
|
|
30
31
|
{
|
|
31
32
|
model,
|
|
32
|
-
updateAnswer: () => {}
|
|
33
|
+
updateAnswer: () => {},
|
|
33
34
|
},
|
|
34
|
-
opts
|
|
35
|
+
opts,
|
|
35
36
|
);
|
|
36
37
|
|
|
37
38
|
return shallow(<Root {...opts} />);
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { getAnswersCorrectness } from '../utils-correctness';
|
|
2
|
+
|
|
3
|
+
const rhomb = 'rhomb';
|
|
4
|
+
const trapeze = 'trapeze';
|
|
5
|
+
const hexagon = 'hexagon';
|
|
6
|
+
|
|
7
|
+
const answer1 = {
|
|
8
|
+
containerIndex: 0,
|
|
9
|
+
id: 1,
|
|
10
|
+
value: rhomb,
|
|
11
|
+
};
|
|
12
|
+
const answer2 = {
|
|
13
|
+
containerIndex: 0,
|
|
14
|
+
id: 2,
|
|
15
|
+
value: rhomb,
|
|
16
|
+
};
|
|
17
|
+
const answer3 = {
|
|
18
|
+
containerIndex: 0,
|
|
19
|
+
id: 3,
|
|
20
|
+
value: trapeze,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const answer4 = {
|
|
24
|
+
containerIndex: 1,
|
|
25
|
+
id: 4,
|
|
26
|
+
value: hexagon,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
describe('utils', () => {
|
|
30
|
+
let validResponses;
|
|
31
|
+
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
validResponses = {
|
|
34
|
+
validResponse: {
|
|
35
|
+
value: [{ images: [rhomb] }, { images: [rhomb, trapeze] }],
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('correctness', () => {
|
|
41
|
+
it('marks correct answers as correct', () => {
|
|
42
|
+
const result = getAnswersCorrectness(
|
|
43
|
+
[
|
|
44
|
+
answer1,
|
|
45
|
+
{
|
|
46
|
+
...answer3,
|
|
47
|
+
containerIndex: 1,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
validResponses,
|
|
51
|
+
);
|
|
52
|
+
expect(result).toEqual([
|
|
53
|
+
{
|
|
54
|
+
...answer1,
|
|
55
|
+
isCorrect: true,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
...answer3,
|
|
59
|
+
isCorrect: true,
|
|
60
|
+
containerIndex: 1,
|
|
61
|
+
},
|
|
62
|
+
]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('marks incorrect answers as incorrect', () => {
|
|
66
|
+
const result = getAnswersCorrectness([answer1, answer3], validResponses);
|
|
67
|
+
expect(result).toEqual([
|
|
68
|
+
{
|
|
69
|
+
...answer1,
|
|
70
|
+
isCorrect: true,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
...answer3,
|
|
74
|
+
isCorrect: false,
|
|
75
|
+
},
|
|
76
|
+
]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('marks duplicates as incorrect', () => {
|
|
80
|
+
const result = getAnswersCorrectness([answer1, answer2], validResponses);
|
|
81
|
+
expect(result).toEqual([
|
|
82
|
+
{
|
|
83
|
+
...answer1,
|
|
84
|
+
isCorrect: true,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
...answer2,
|
|
88
|
+
isCorrect: false,
|
|
89
|
+
},
|
|
90
|
+
]);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('marks duplicates and incorrect as incorrect', () => {
|
|
94
|
+
const result = getAnswersCorrectness([answer1, answer2, answer3], validResponses);
|
|
95
|
+
expect(result).toEqual([
|
|
96
|
+
{
|
|
97
|
+
...answer1,
|
|
98
|
+
isCorrect: true,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
...answer2,
|
|
102
|
+
isCorrect: false,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
...answer3,
|
|
106
|
+
isCorrect: false,
|
|
107
|
+
},
|
|
108
|
+
]);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('alternate correct answers', () => {
|
|
112
|
+
describe('handles one option', () => {
|
|
113
|
+
it('marks correct answers as correct', () => {
|
|
114
|
+
const result = getAnswersCorrectness([answer1, answer4], {
|
|
115
|
+
...validResponses,
|
|
116
|
+
altResponses: [
|
|
117
|
+
{
|
|
118
|
+
value: [{ images: [rhomb] }, { images: [hexagon] }],
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
});
|
|
122
|
+
expect(result).toEqual([
|
|
123
|
+
{
|
|
124
|
+
...answer1,
|
|
125
|
+
isCorrect: true,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
...answer4,
|
|
129
|
+
isCorrect: true,
|
|
130
|
+
},
|
|
131
|
+
]);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('marks incorrect answers as incorrect', () => {
|
|
135
|
+
const result = getAnswersCorrectness([answer1, answer4], {
|
|
136
|
+
...validResponses,
|
|
137
|
+
altResponses: [
|
|
138
|
+
{
|
|
139
|
+
value: [{ images: [hexagon] }, { images: [rhomb] }],
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
});
|
|
143
|
+
expect(result).toEqual([
|
|
144
|
+
{
|
|
145
|
+
...answer1,
|
|
146
|
+
isCorrect: false,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
...answer4,
|
|
150
|
+
isCorrect: false,
|
|
151
|
+
},
|
|
152
|
+
]);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe('handles multiple options', () => {
|
|
157
|
+
it('marks correct answers as correct', () => {
|
|
158
|
+
const result = getAnswersCorrectness([answer1, answer4], {
|
|
159
|
+
...validResponses,
|
|
160
|
+
altResponses: [
|
|
161
|
+
{
|
|
162
|
+
value: [{ images: [hexagon] }, { images: [rhomb] }],
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
value: [{ images: [rhomb] }, { images: [hexagon] }],
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
});
|
|
169
|
+
expect(result).toEqual([
|
|
170
|
+
{
|
|
171
|
+
...answer1,
|
|
172
|
+
isCorrect: true,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
...answer4,
|
|
176
|
+
isCorrect: true,
|
|
177
|
+
},
|
|
178
|
+
]);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('marks incorrect answers as incorrect', () => {
|
|
182
|
+
const result = getAnswersCorrectness([answer1, answer4], {
|
|
183
|
+
...validResponses,
|
|
184
|
+
altResponses: [
|
|
185
|
+
{
|
|
186
|
+
value: [{ images: [hexagon] }, { images: [rhomb] }],
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
value: [{ images: [hexagon] }, { images: [hexagon] }],
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
});
|
|
193
|
+
expect(result).toEqual([
|
|
194
|
+
{
|
|
195
|
+
...answer1,
|
|
196
|
+
isCorrect: false,
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
...answer4,
|
|
200
|
+
isCorrect: true,
|
|
201
|
+
},
|
|
202
|
+
]);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
});
|
package/src/constants.js
CHANGED
package/src/evaluation-icon.jsx
CHANGED
|
@@ -17,47 +17,38 @@ const EvaluationIcon = ({ classes, containerStyle, isCorrect, filled }) => {
|
|
|
17
17
|
const showCorrectness = isCorrect !== undefined;
|
|
18
18
|
const correctness = showCorrectness ? getCorrectnessClass(isCorrect, filled) : '';
|
|
19
19
|
|
|
20
|
-
return showCorrectness
|
|
21
|
-
? (
|
|
22
|
-
<Icon
|
|
23
|
-
className={`${classes.icon} ${classes[correctness]}`}
|
|
24
|
-
style={containerStyle}
|
|
25
|
-
/>
|
|
26
|
-
) : null
|
|
20
|
+
return showCorrectness ? <Icon className={`${classes.icon} ${classes[correctness]}`} style={containerStyle} /> : null;
|
|
27
21
|
};
|
|
28
22
|
|
|
29
23
|
EvaluationIcon.propTypes = {
|
|
30
24
|
classes: PropTypes.object,
|
|
31
25
|
containerStyle: PropTypes.object,
|
|
32
26
|
filled: PropTypes.bool,
|
|
33
|
-
isCorrect: PropTypes.oneOfType([
|
|
34
|
-
PropTypes.bool,
|
|
35
|
-
PropTypes.number
|
|
36
|
-
])
|
|
27
|
+
isCorrect: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
|
|
37
28
|
};
|
|
38
29
|
|
|
39
30
|
EvaluationIcon.defaultProps = {
|
|
40
31
|
classes: {},
|
|
41
32
|
containerStyle: {},
|
|
42
33
|
filled: false,
|
|
43
|
-
isCorrect: undefined
|
|
34
|
+
isCorrect: undefined,
|
|
44
35
|
};
|
|
45
36
|
|
|
46
37
|
const styles = () => ({
|
|
47
38
|
correctEmpty: {
|
|
48
|
-
color: color.correct()
|
|
39
|
+
color: color.correct(),
|
|
49
40
|
},
|
|
50
41
|
correctFilled: {
|
|
51
42
|
color: color.background(),
|
|
52
|
-
backgroundColor: color.correct()
|
|
43
|
+
backgroundColor: color.correct(),
|
|
53
44
|
},
|
|
54
45
|
incorrectEmpty: {
|
|
55
|
-
color: color.incorrect()
|
|
46
|
+
color: color.incorrect(),
|
|
56
47
|
},
|
|
57
48
|
incorrectFilled: {
|
|
58
49
|
color: color.background(),
|
|
59
|
-
backgroundColor: color.incorrect()
|
|
60
|
-
}
|
|
50
|
+
backgroundColor: color.incorrect(),
|
|
51
|
+
},
|
|
61
52
|
});
|
|
62
53
|
|
|
63
54
|
export default withStyles(styles)(EvaluationIcon);
|
package/src/image-container.jsx
CHANGED
|
@@ -12,30 +12,23 @@ class ImageContainer extends Component {
|
|
|
12
12
|
classes,
|
|
13
13
|
draggingElement,
|
|
14
14
|
duplicateResponses,
|
|
15
|
-
image: {
|
|
16
|
-
height,
|
|
17
|
-
src,
|
|
18
|
-
width
|
|
19
|
-
},
|
|
15
|
+
image: { height, src, width },
|
|
20
16
|
onAnswerSelect,
|
|
21
17
|
onDragAnswerBegin,
|
|
22
18
|
onDragAnswerEnd,
|
|
23
|
-
responseContainers
|
|
19
|
+
responseContainers,
|
|
20
|
+
showDashedBorder,
|
|
24
21
|
} = this.props;
|
|
25
22
|
|
|
26
23
|
return (
|
|
27
24
|
<div className={classes.base}>
|
|
28
|
-
<img
|
|
29
|
-
src={src}
|
|
30
|
-
height={height}
|
|
31
|
-
width={width}
|
|
32
|
-
/>
|
|
25
|
+
<img src={src} height={height} width={width} />
|
|
33
26
|
{responseContainers.map((r, i) => {
|
|
34
27
|
const rHeight = (r.height.replace('%', '') / 100) * height;
|
|
35
28
|
const rWidth = (r.width.replace('%', '') / 100) * width;
|
|
36
29
|
const rLeft = (r.x / 100) * width;
|
|
37
30
|
const rTop = (r.y / 100) * height;
|
|
38
|
-
const answersParsed = answers.filter(a => a.containerIndex === r.index);
|
|
31
|
+
const answersParsed = answers.filter((a) => a.containerIndex === r.index);
|
|
39
32
|
|
|
40
33
|
return (
|
|
41
34
|
<ImageDropTarget
|
|
@@ -45,7 +38,7 @@ class ImageContainer extends Component {
|
|
|
45
38
|
height: rHeight,
|
|
46
39
|
width: rWidth,
|
|
47
40
|
left: rLeft,
|
|
48
|
-
top: rTop
|
|
41
|
+
top: rTop,
|
|
49
42
|
}}
|
|
50
43
|
duplicateResponses={duplicateResponses}
|
|
51
44
|
key={r.id + i}
|
|
@@ -53,11 +46,12 @@ class ImageContainer extends Component {
|
|
|
53
46
|
onDrop={(item) => onAnswerSelect(item, r.index)}
|
|
54
47
|
onDragAnswerBegin={onDragAnswerBegin}
|
|
55
48
|
onDragAnswerEnd={onDragAnswerEnd}
|
|
49
|
+
showDashedBorder={showDashedBorder}
|
|
56
50
|
/>
|
|
57
51
|
);
|
|
58
52
|
})}
|
|
59
53
|
</div>
|
|
60
|
-
)
|
|
54
|
+
);
|
|
61
55
|
}
|
|
62
56
|
}
|
|
63
57
|
|
|
@@ -71,18 +65,19 @@ ImageContainer.propTypes = {
|
|
|
71
65
|
onAnswerSelect: PropTypes.func.isRequired,
|
|
72
66
|
onDragAnswerBegin: PropTypes.func.isRequired,
|
|
73
67
|
onDragAnswerEnd: PropTypes.func.isRequired,
|
|
74
|
-
responseContainers: PropTypes.array.isRequired
|
|
68
|
+
responseContainers: PropTypes.array.isRequired,
|
|
69
|
+
showDashedBorder: PropTypes.bool,
|
|
75
70
|
};
|
|
76
71
|
|
|
77
72
|
ImageContainer.defaultProps = {
|
|
78
73
|
classes: {},
|
|
79
|
-
duplicateResponses: false
|
|
74
|
+
duplicateResponses: false,
|
|
80
75
|
};
|
|
81
76
|
|
|
82
|
-
const styles = theme => ({
|
|
77
|
+
const styles = (theme) => ({
|
|
83
78
|
base: {
|
|
84
79
|
margin: theme.spacing.unit * 2,
|
|
85
|
-
position: 'relative'
|
|
86
|
-
}
|
|
80
|
+
position: 'relative',
|
|
81
|
+
},
|
|
87
82
|
});
|
|
88
83
|
export default withStyles(styles)(ImageContainer);
|
|
@@ -16,41 +16,44 @@ const ImageDropTarget = ({
|
|
|
16
16
|
duplicateResponses,
|
|
17
17
|
onDragAnswerBegin,
|
|
18
18
|
onDragAnswerEnd,
|
|
19
|
+
showDashedBorder,
|
|
19
20
|
// dnd-related props
|
|
20
21
|
connectDropTarget,
|
|
21
|
-
isOverCurrent
|
|
22
|
-
}) =>
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
isOverCurrent,
|
|
23
|
+
}) =>
|
|
24
|
+
connectDropTarget(
|
|
25
|
+
<div
|
|
26
|
+
className={`
|
|
25
27
|
${classes.responseContainer}
|
|
28
|
+
${showDashedBorder && !draggingElement.id ? classes.responseContainerDashed : ''}
|
|
26
29
|
${draggingElement.id ? classes.responseContainerActive : ''}
|
|
27
30
|
`}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
style={containerStyle}
|
|
32
|
+
>
|
|
33
|
+
{/* HOVER */}
|
|
34
|
+
{isOverCurrent && !duplicateResponses ? (
|
|
35
|
+
<div className={classes.dragOverContainer}>
|
|
36
|
+
<span dangerouslySetInnerHTML={{ __html: draggingElement.value }} />
|
|
37
|
+
</div>
|
|
38
|
+
) : null}
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
);
|
|
40
|
+
{/* EXISTING ANSWERS */}
|
|
41
|
+
{(!isOverCurrent && answers.length) || (duplicateResponses && answers.length) ? (
|
|
42
|
+
<div className={classes.answers}>
|
|
43
|
+
{answers.map((answer) => (
|
|
44
|
+
<PossibleResponse
|
|
45
|
+
canDrag={canDrag}
|
|
46
|
+
containerStyle={answer.isCorrect === undefined ? { borderWidth: 0 } : {}}
|
|
47
|
+
key={answer.id}
|
|
48
|
+
data={answer}
|
|
49
|
+
onDragBegin={() => onDragAnswerBegin(answer)}
|
|
50
|
+
onDragEnd={onDragAnswerEnd}
|
|
51
|
+
/>
|
|
52
|
+
))}
|
|
53
|
+
</div>
|
|
54
|
+
) : null}
|
|
55
|
+
</div>,
|
|
56
|
+
);
|
|
54
57
|
|
|
55
58
|
ImageDropTarget.propTypes = {
|
|
56
59
|
answer: PropTypes.object,
|
|
@@ -60,31 +63,35 @@ ImageDropTarget.propTypes = {
|
|
|
60
63
|
draggingElement: PropTypes.object.isRequired,
|
|
61
64
|
onDragAnswerBegin: PropTypes.func.isRequired,
|
|
62
65
|
onDragAnswerEnd: PropTypes.func.isRequired,
|
|
63
|
-
onDrop: PropTypes.func.isRequired
|
|
66
|
+
onDrop: PropTypes.func.isRequired,
|
|
67
|
+
showDashedBorder: PropTypes.bool,
|
|
64
68
|
};
|
|
65
69
|
|
|
66
70
|
ImageDropTarget.defaultProps = {
|
|
67
71
|
answer: {},
|
|
68
|
-
classes: {}
|
|
72
|
+
classes: {},
|
|
69
73
|
};
|
|
70
74
|
|
|
71
75
|
const styles = () => ({
|
|
72
76
|
answers: {
|
|
73
77
|
display: 'flex',
|
|
74
|
-
flexWrap: 'wrap'
|
|
78
|
+
flexWrap: 'wrap',
|
|
75
79
|
},
|
|
76
80
|
dragOverContainer: {
|
|
77
81
|
backgroundColor: color.background(),
|
|
78
82
|
pointerEvents: 'none',
|
|
79
|
-
width: 'fit-content'
|
|
83
|
+
width: 'fit-content',
|
|
80
84
|
},
|
|
81
85
|
responseContainer: {
|
|
82
|
-
position: 'absolute'
|
|
86
|
+
position: 'absolute',
|
|
83
87
|
},
|
|
84
88
|
responseContainerActive: {
|
|
85
89
|
border: `2px solid ${color.text()}`,
|
|
86
|
-
backgroundColor: 'rgba(230, 242, 252, .8)'
|
|
87
|
-
}
|
|
90
|
+
backgroundColor: 'rgba(230, 242, 252, .8)',
|
|
91
|
+
},
|
|
92
|
+
responseContainerDashed: {
|
|
93
|
+
border: `2px dashed ${color.text()}`,
|
|
94
|
+
},
|
|
88
95
|
});
|
|
89
96
|
|
|
90
97
|
const Styled = withStyles(styles)(ImageDropTarget);
|
|
@@ -96,10 +103,10 @@ const tileSource = {
|
|
|
96
103
|
drop(props, monitor) {
|
|
97
104
|
const item = monitor.getItem();
|
|
98
105
|
props.onDrop(item);
|
|
99
|
-
}
|
|
106
|
+
},
|
|
100
107
|
};
|
|
101
108
|
|
|
102
109
|
export default DropTarget(c.types.response, tileSource, (connect, monitor) => ({
|
|
103
110
|
connectDropTarget: connect.dropTarget(),
|
|
104
|
-
isOverCurrent: monitor.isOver({ shallow: true })
|
|
111
|
+
isOverCurrent: monitor.isOver({ shallow: true }),
|
|
105
112
|
}))(Styled);
|
package/src/index.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import ReactDOM from 'react-dom';
|
|
3
3
|
import { renderMath } from '@pie-lib/math-rendering';
|
|
4
|
-
import {
|
|
5
|
-
ModelSetEvent,
|
|
6
|
-
SessionChangedEvent
|
|
7
|
-
} from '@pie-framework/pie-player-events';
|
|
4
|
+
import { ModelSetEvent, SessionChangedEvent } from '@pie-framework/pie-player-events';
|
|
8
5
|
|
|
9
6
|
import ImageClozeAssociationComponent from './root';
|
|
10
7
|
|
|
@@ -12,13 +9,7 @@ export default class ImageClozeAssociation extends HTMLElement {
|
|
|
12
9
|
set model(m) {
|
|
13
10
|
this._model = m;
|
|
14
11
|
|
|
15
|
-
this.dispatchEvent(
|
|
16
|
-
new ModelSetEvent(
|
|
17
|
-
this.tagName.toLowerCase(),
|
|
18
|
-
this.isComplete(),
|
|
19
|
-
!!this._model
|
|
20
|
-
)
|
|
21
|
-
);
|
|
12
|
+
this.dispatchEvent(new ModelSetEvent(this.tagName.toLowerCase(), this.isComplete(), !!this._model));
|
|
22
13
|
this._render();
|
|
23
14
|
}
|
|
24
15
|
|
|
@@ -27,9 +18,7 @@ export default class ImageClozeAssociation extends HTMLElement {
|
|
|
27
18
|
return false;
|
|
28
19
|
}
|
|
29
20
|
|
|
30
|
-
return (
|
|
31
|
-
Array.isArray(this._session.answers) && this._session.answers.length > 0
|
|
32
|
-
);
|
|
21
|
+
return Array.isArray(this._session.answers) && this._session.answers.length > 0;
|
|
33
22
|
}
|
|
34
23
|
|
|
35
24
|
set session(s) {
|
|
@@ -41,12 +30,14 @@ export default class ImageClozeAssociation extends HTMLElement {
|
|
|
41
30
|
this._render();
|
|
42
31
|
}
|
|
43
32
|
|
|
33
|
+
get session() {
|
|
34
|
+
return this._session;
|
|
35
|
+
}
|
|
36
|
+
|
|
44
37
|
updateAnswer(data) {
|
|
45
38
|
this._session.answers = data;
|
|
46
39
|
|
|
47
|
-
this.dispatchEvent(
|
|
48
|
-
new SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete())
|
|
49
|
-
);
|
|
40
|
+
this.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));
|
|
50
41
|
|
|
51
42
|
this._render();
|
|
52
43
|
}
|
|
@@ -60,8 +51,9 @@ export default class ImageClozeAssociation extends HTMLElement {
|
|
|
60
51
|
const el = React.createElement(ImageClozeAssociationComponent, {
|
|
61
52
|
model: this._model,
|
|
62
53
|
session: this._session,
|
|
63
|
-
updateAnswer: this.updateAnswer.bind(this)
|
|
54
|
+
updateAnswer: this.updateAnswer.bind(this),
|
|
64
55
|
});
|
|
56
|
+
|
|
65
57
|
ReactDOM.render(el, this, () => {
|
|
66
58
|
renderMath(this);
|
|
67
59
|
});
|
|
@@ -12,11 +12,14 @@ class InteractiveSection extends React.Component {
|
|
|
12
12
|
|
|
13
13
|
switch (responseCorrect) {
|
|
14
14
|
case undefined:
|
|
15
|
-
styleProp = 'interactiveDefault';
|
|
15
|
+
styleProp = 'interactiveDefault';
|
|
16
|
+
break;
|
|
16
17
|
case true:
|
|
17
|
-
styleProp = 'interactiveCorrect';
|
|
18
|
+
styleProp = 'interactiveCorrect';
|
|
19
|
+
break;
|
|
18
20
|
default:
|
|
19
|
-
styleProp = 'interactiveIncorrect';
|
|
21
|
+
styleProp = 'interactiveIncorrect';
|
|
22
|
+
break;
|
|
20
23
|
}
|
|
21
24
|
return classes[styleProp];
|
|
22
25
|
}
|
|
@@ -27,16 +30,12 @@ class InteractiveSection extends React.Component {
|
|
|
27
30
|
const evaluationStyle = {
|
|
28
31
|
display: 'flex',
|
|
29
32
|
margin: '0 auto',
|
|
30
|
-
marginTop: -14
|
|
33
|
+
marginTop: -14,
|
|
31
34
|
};
|
|
32
35
|
|
|
33
36
|
return (
|
|
34
37
|
<div className={classname}>
|
|
35
|
-
<EvaluationIcon
|
|
36
|
-
containerStyle={evaluationStyle}
|
|
37
|
-
filled
|
|
38
|
-
isCorrect={responseCorrect}
|
|
39
|
-
/>
|
|
38
|
+
<EvaluationIcon containerStyle={evaluationStyle} filled isCorrect={responseCorrect} />
|
|
40
39
|
{children}
|
|
41
40
|
</div>
|
|
42
41
|
);
|
|
@@ -45,31 +44,25 @@ class InteractiveSection extends React.Component {
|
|
|
45
44
|
|
|
46
45
|
InteractiveSection.propTypes = {
|
|
47
46
|
classes: PropTypes.object,
|
|
48
|
-
children: PropTypes.oneOfType([
|
|
49
|
-
|
|
50
|
-
PropTypes.array
|
|
51
|
-
]).isRequired,
|
|
52
|
-
responseCorrect: PropTypes.oneOfType([
|
|
53
|
-
PropTypes.bool,
|
|
54
|
-
PropTypes.number
|
|
55
|
-
])
|
|
47
|
+
children: PropTypes.oneOfType([PropTypes.element, PropTypes.array]).isRequired,
|
|
48
|
+
responseCorrect: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
|
|
56
49
|
};
|
|
57
50
|
|
|
58
51
|
InteractiveSection.defaultProps = {
|
|
59
52
|
classes: {},
|
|
60
|
-
responseCorrect: undefined
|
|
53
|
+
responseCorrect: undefined,
|
|
61
54
|
};
|
|
62
55
|
|
|
63
56
|
const styles = () => ({
|
|
64
57
|
interactiveDefault: {
|
|
65
|
-
border: `1px solid ${color.disabled()}
|
|
58
|
+
border: `1px solid ${color.disabled()}`,
|
|
66
59
|
},
|
|
67
60
|
interactiveCorrect: {
|
|
68
|
-
border: `2px solid ${color.correct()}
|
|
61
|
+
border: `2px solid ${color.correct()}`,
|
|
69
62
|
},
|
|
70
63
|
interactiveIncorrect: {
|
|
71
|
-
border: `2px solid ${color.incorrect()}
|
|
72
|
-
}
|
|
64
|
+
border: `2px solid ${color.incorrect()}`,
|
|
65
|
+
},
|
|
73
66
|
});
|
|
74
67
|
|
|
75
68
|
export default withStyles(styles)(InteractiveSection);
|