@pie-element/hotspot 4.8.4-next.135 → 4.8.4-next.1353
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 +263 -0
- package/configure/CHANGELOG.md +233 -0
- package/configure/lib/defaults.js +20 -0
- package/configure/lib/defaults.js.map +1 -1
- package/configure/lib/hotspot-container.js +26 -12
- package/configure/lib/hotspot-container.js.map +1 -1
- package/configure/lib/hotspot-drawable.js +11 -5
- package/configure/lib/hotspot-drawable.js.map +1 -1
- package/configure/lib/hotspot-palette.js +1 -1
- package/configure/lib/hotspot-palette.js.map +1 -1
- package/configure/lib/hotspot-polygon.js +1 -1
- package/configure/lib/hotspot-polygon.js.map +1 -1
- package/configure/lib/hotspot-rectangle.js +1 -1
- package/configure/lib/hotspot-rectangle.js.map +1 -1
- package/configure/lib/index.js +17 -3
- package/configure/lib/index.js.map +1 -1
- package/configure/lib/root.js +107 -13
- package/configure/lib/root.js.map +1 -1
- package/configure/lib/utils.js +18 -4
- package/configure/lib/utils.js.map +1 -1
- package/configure/package.json +4 -4
- package/configure/src/__tests__/__snapshots__/hotspot-container.test.js.snap +1 -0
- package/configure/src/__tests__/__snapshots__/root.test.js.snap +53 -4
- package/configure/src/defaults.js +20 -0
- package/configure/src/hotspot-container.jsx +16 -5
- package/configure/src/hotspot-drawable.jsx +8 -2
- package/configure/src/index.js +14 -0
- package/configure/src/root.jsx +87 -9
- package/configure/src/utils.js +23 -1
- package/controller/CHANGELOG.md +50 -0
- package/controller/lib/index.js +44 -5
- package/controller/lib/index.js.map +1 -1
- package/controller/lib/utils.js.map +1 -1
- package/controller/package.json +1 -1
- package/controller/src/index.js +26 -0
- package/docs/config-schema.json +212 -0
- package/docs/config-schema.json.md +165 -0
- package/docs/demo/generate.js +1 -0
- package/docs/pie-schema.json +49 -0
- package/docs/pie-schema.json.md +36 -0
- package/lib/hotspot/container.js +25 -7
- package/lib/hotspot/container.js.map +1 -1
- package/lib/hotspot/image.js +1 -1
- package/lib/hotspot/image.js.map +1 -1
- package/lib/hotspot/index.js +72 -18
- package/lib/hotspot/index.js.map +1 -1
- package/lib/hotspot/polygon.js +46 -20
- package/lib/hotspot/polygon.js.map +1 -1
- package/lib/hotspot/rectangle.js +46 -20
- package/lib/hotspot/rectangle.js.map +1 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/session-updater.js.map +1 -1
- package/package.json +6 -4
- package/src/__tests__/__snapshots__/{container-test.jsx.snap → container.test.jsx.snap} +8 -0
- package/src/__tests__/__snapshots__/image.test.jsx.snap +43 -0
- package/src/__tests__/__snapshots__/{polygon-test.jsx.snap → polygon.test.jsx.snap} +11 -0
- package/src/__tests__/__snapshots__/{rectangle-test.jsx.snap → rectangle.test.jsx.snap} +11 -0
- package/src/__tests__/{container-test.jsx → container.test.jsx} +57 -0
- package/src/__tests__/{image-test.jsx → image.test.jsx} +0 -0
- package/src/__tests__/polygon.test.jsx +224 -0
- package/src/__tests__/rectangle.test.jsx +233 -0
- package/src/__tests__/{session-updater-test.jsx → session-updater.test.jsx} +0 -0
- package/src/hotspot/container.jsx +23 -3
- package/src/hotspot/index.jsx +68 -8
- package/src/hotspot/polygon.jsx +40 -17
- package/src/hotspot/rectangle.jsx +40 -17
- package/src/index.js +5 -0
- package/src/__tests__/__snapshots__/image-test.jsx.snap +0 -21
- package/src/__tests__/polygon-test.jsx +0 -77
- package/src/__tests__/rectangle-test.jsx +0 -78
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import { shallow } from 'enzyme';
|
|
4
|
+
import toJson from 'enzyme-to-json';
|
|
5
|
+
import Konva from 'konva';
|
|
6
|
+
import { Rect } from 'react-konva';
|
|
7
|
+
|
|
8
|
+
import { shallowChild } from '@pie-lib/test-utils';
|
|
9
|
+
|
|
10
|
+
import Rectangle from '../hotspot/rectangle';
|
|
11
|
+
import Image from '../hotspot/image';
|
|
12
|
+
import { faCorrect, faWrong } from '../hotspot/icons';
|
|
13
|
+
|
|
14
|
+
global.MutationObserver = class {
|
|
15
|
+
constructor(callback) {}
|
|
16
|
+
disconnect() {}
|
|
17
|
+
observe(element, initObject) {}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
Konva.isBrowser = false;
|
|
21
|
+
|
|
22
|
+
describe('Rectangle', () => {
|
|
23
|
+
let onClick, wrapper;
|
|
24
|
+
|
|
25
|
+
const mkWrapper = (opts = {}) => {
|
|
26
|
+
opts = _.extend(
|
|
27
|
+
{
|
|
28
|
+
classes: {
|
|
29
|
+
base: 'base'
|
|
30
|
+
},
|
|
31
|
+
height: 200,
|
|
32
|
+
hotspotColor: 'rgba(137, 183, 244, 0.65)',
|
|
33
|
+
id: '1',
|
|
34
|
+
isCorrect: false,
|
|
35
|
+
isEvaluateMode: false,
|
|
36
|
+
evaluateText: null,
|
|
37
|
+
disabled: false,
|
|
38
|
+
outlineColor: 'blue',
|
|
39
|
+
selected: false,
|
|
40
|
+
width: 300,
|
|
41
|
+
x: 5,
|
|
42
|
+
y: 5
|
|
43
|
+
},
|
|
44
|
+
opts
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return shallow(<Rectangle {...opts} onClick={onClick} />);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
onClick = jest.fn();
|
|
52
|
+
wrapper = mkWrapper();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe('snapshots', () => {
|
|
56
|
+
describe('outline color', () => {
|
|
57
|
+
it('renders', () => {
|
|
58
|
+
const wrapper = mkWrapper({ outlineColor: 'red' });
|
|
59
|
+
expect(toJson(wrapper)).toMatchSnapshot();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('outline width', () => {
|
|
64
|
+
it('renders with default border width', () => {
|
|
65
|
+
const wrapper = mkWrapper();
|
|
66
|
+
expect(toJson(wrapper)).toMatchSnapshot();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('renders with given border width', () => {
|
|
70
|
+
const wrapper = mkWrapper({ strokeWidth: 10 });
|
|
71
|
+
expect(toJson(wrapper)).toMatchSnapshot();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('hotspot color', () => {
|
|
76
|
+
it('renders', () => {
|
|
77
|
+
const wrapper = mkWrapper({ hotspotColor: 'rgba(217, 30, 24, 0.65)' });
|
|
78
|
+
expect(toJson(wrapper)).toMatchSnapshot();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('evaluate with correct answer', () => {
|
|
83
|
+
it('renders', () => {
|
|
84
|
+
const wrapper = mkWrapper({ isEvaluateMode: true, isCorrect: true, evaluateText: 'Correctly\nselected' });
|
|
85
|
+
expect(toJson(wrapper)).toMatchSnapshot();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe('in evaluate mode', () => {
|
|
91
|
+
const defaultModel = {
|
|
92
|
+
onClick,
|
|
93
|
+
id: '1',
|
|
94
|
+
height: 200,
|
|
95
|
+
hotspotColor: 'rgba(137, 183, 244, 0.65)',
|
|
96
|
+
disabled: true,
|
|
97
|
+
width: 300,
|
|
98
|
+
x: 5,
|
|
99
|
+
y: 5,
|
|
100
|
+
selected: false,
|
|
101
|
+
isCorrect: false,
|
|
102
|
+
isEvaluateMode: true,
|
|
103
|
+
evaluateText: null,
|
|
104
|
+
strokeWidth: 5,
|
|
105
|
+
outlineColor: 'blue',
|
|
106
|
+
markAsCorrect: false,
|
|
107
|
+
showCorrectEnabled: false
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const getComponents = (model) => {
|
|
111
|
+
const testWrapper = shallowChild(Rectangle, {
|
|
112
|
+
...defaultModel,
|
|
113
|
+
...model
|
|
114
|
+
}, 1);
|
|
115
|
+
const rectangleComponent = testWrapper();
|
|
116
|
+
const rectComponent = rectangleComponent.find(Rect);
|
|
117
|
+
return {
|
|
118
|
+
rectangleComponent,
|
|
119
|
+
rectComponent
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
describe('when correctly selected', () => {
|
|
124
|
+
const { rectangleComponent, rectComponent } = getComponents({
|
|
125
|
+
selected: true,
|
|
126
|
+
isCorrect: true
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('should have a blue outline', () => {
|
|
130
|
+
expect(rectComponent.prop('stroke')).toEqual('blue');
|
|
131
|
+
expect(rectComponent.prop('strokeWidth')).toEqual(defaultModel.strokeWidth);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should have a green checkmark icon', () => {
|
|
135
|
+
const imgComponent = rectangleComponent.find(Image);
|
|
136
|
+
expect(imgComponent.length).toEqual(1);
|
|
137
|
+
expect(imgComponent.prop('src')).toEqual(faCorrect);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('when correctly not selected', () => {
|
|
142
|
+
const { rectangleComponent, rectComponent } = getComponents({
|
|
143
|
+
selected: false,
|
|
144
|
+
isCorrect: true
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should have no outline', () => {
|
|
148
|
+
expect(rectComponent.prop('strokeWidth')).toEqual(0);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should have no icon', () => {
|
|
152
|
+
const imgComponent = rectangleComponent.find(Image);
|
|
153
|
+
expect(imgComponent.length).toEqual(0);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe('when incorrectly selected', () => {
|
|
158
|
+
const { rectangleComponent, rectComponent } = getComponents({
|
|
159
|
+
selected: true,
|
|
160
|
+
isCorrect: false
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should have a red outline', () => {
|
|
164
|
+
expect(rectComponent.prop('stroke')).toEqual('red');
|
|
165
|
+
expect(rectComponent.prop('strokeWidth')).toEqual(defaultModel.strokeWidth);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should have a red x icon', () => {
|
|
169
|
+
const imgComponent = rectangleComponent.find(Image);
|
|
170
|
+
expect(imgComponent.length).toEqual(1);
|
|
171
|
+
expect(imgComponent.prop('src')).toEqual(faWrong);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe('when incorrectly not selected', () => {
|
|
176
|
+
const { rectangleComponent, rectComponent } = getComponents({
|
|
177
|
+
selected: false,
|
|
178
|
+
isCorrect: false
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should have no outline', () => {
|
|
182
|
+
expect(rectComponent.prop('strokeWidth')).toEqual(0);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('should have a red x icon', () => {
|
|
186
|
+
const imgComponent = rectangleComponent.find(Image);
|
|
187
|
+
expect(imgComponent.length).toEqual(1);
|
|
188
|
+
expect(imgComponent.prop('src')).toEqual(faWrong);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe('when showing correct answer (showCorrectEnabled = true)', () => {
|
|
193
|
+
it('should have a green outline', () => {
|
|
194
|
+
const { rectComponent } = getComponents({
|
|
195
|
+
showCorrectEnabled: true,
|
|
196
|
+
markAsCorrect: true
|
|
197
|
+
});
|
|
198
|
+
expect(rectComponent.prop('stroke')).toEqual('green');
|
|
199
|
+
expect(rectComponent.prop('strokeWidth')).toEqual(defaultModel.strokeWidth);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('should have a green checkmark icon', () => {
|
|
203
|
+
const { rectangleComponent } = getComponents({
|
|
204
|
+
showCorrectEnabled: true,
|
|
205
|
+
markAsCorrect: true
|
|
206
|
+
});
|
|
207
|
+
const imgComponent = rectangleComponent.find(Image);
|
|
208
|
+
expect(imgComponent.prop('src')).toEqual(faCorrect);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should not be selected if the answer is incorrect', () => {
|
|
212
|
+
const { rectComponent } = getComponents({
|
|
213
|
+
showCorrectEnabled: true,
|
|
214
|
+
markAsCorrect: false,
|
|
215
|
+
selected: true,
|
|
216
|
+
isCorrect: false
|
|
217
|
+
});
|
|
218
|
+
expect(rectComponent.prop('strokeWidth')).toEqual(0);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('should not render an icon if the answer is incorrect', () => {
|
|
222
|
+
const { rectangleComponent } = getComponents({
|
|
223
|
+
showCorrectEnabled: true,
|
|
224
|
+
markAsCorrect: false,
|
|
225
|
+
selected: true,
|
|
226
|
+
isCorrect: false
|
|
227
|
+
});
|
|
228
|
+
const imgComponent = rectangleComponent.find(Image);
|
|
229
|
+
expect(imgComponent.length).toEqual(0);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
});
|
|
File without changes
|
|
@@ -34,7 +34,7 @@ export class Container extends React.Component {
|
|
|
34
34
|
render() {
|
|
35
35
|
const {
|
|
36
36
|
classes,
|
|
37
|
-
dimensions: { width, height },
|
|
37
|
+
dimensions: { width: withProp, height: heightProp },
|
|
38
38
|
disabled,
|
|
39
39
|
hotspotColor,
|
|
40
40
|
imageUrl,
|
|
@@ -42,9 +42,14 @@ export class Container extends React.Component {
|
|
|
42
42
|
outlineColor,
|
|
43
43
|
onSelectChoice,
|
|
44
44
|
shapes: { rectangles, polygons },
|
|
45
|
-
|
|
45
|
+
scale: SCALE,
|
|
46
|
+
strokeWidth,
|
|
47
|
+
showCorrect
|
|
46
48
|
} = this.props;
|
|
47
49
|
|
|
50
|
+
const width = withProp * SCALE;
|
|
51
|
+
const height = heightProp * SCALE;
|
|
52
|
+
|
|
48
53
|
return (
|
|
49
54
|
<div
|
|
50
55
|
className={classes.base}
|
|
@@ -53,6 +58,7 @@ export class Container extends React.Component {
|
|
|
53
58
|
{imageUrl ? (
|
|
54
59
|
<div className={classes.imageContainer}>
|
|
55
60
|
<img
|
|
61
|
+
alt="hotspot-image"
|
|
56
62
|
className={classes.image}
|
|
57
63
|
height="auto"
|
|
58
64
|
src={imageUrl}
|
|
@@ -73,9 +79,11 @@ export class Container extends React.Component {
|
|
|
73
79
|
const selected = this.isSelected(shape);
|
|
74
80
|
const isCorrect = isEvaluateMode ? this.correctness(shape.correct, selected) : undefined;
|
|
75
81
|
const evaluateText = isEvaluateMode ? this.getEvaluateText(shape.correct, selected) : null;
|
|
82
|
+
const markAsCorrect = !!(isEvaluateMode && showCorrect && shape.correct);
|
|
76
83
|
|
|
77
84
|
return (
|
|
78
85
|
<Rectangle
|
|
86
|
+
scale={SCALE}
|
|
79
87
|
isEvaluateMode={isEvaluateMode}
|
|
80
88
|
isCorrect={isCorrect}
|
|
81
89
|
evaluateText={evaluateText}
|
|
@@ -91,6 +99,8 @@ export class Container extends React.Component {
|
|
|
91
99
|
x={shape.x}
|
|
92
100
|
y={shape.y}
|
|
93
101
|
strokeWidth={strokeWidth}
|
|
102
|
+
markAsCorrect={markAsCorrect}
|
|
103
|
+
showCorrectEnabled={showCorrect}
|
|
94
104
|
/>
|
|
95
105
|
)
|
|
96
106
|
})}
|
|
@@ -98,9 +108,11 @@ export class Container extends React.Component {
|
|
|
98
108
|
const selected = this.isSelected(polygon);
|
|
99
109
|
const isCorrect = isEvaluateMode ? this.correctness(polygon.correct, selected) : undefined;
|
|
100
110
|
const evaluateText = isEvaluateMode ? this.getEvaluateText(polygon.correct, selected) : null;
|
|
111
|
+
const markAsCorrect = !!(isEvaluateMode && showCorrect && polygon.correct);
|
|
101
112
|
|
|
102
113
|
return (
|
|
103
114
|
<Polygon
|
|
115
|
+
scale={SCALE}
|
|
104
116
|
isEvaluateMode={isEvaluateMode}
|
|
105
117
|
isCorrect={!!isCorrect}
|
|
106
118
|
evaluateText={evaluateText}
|
|
@@ -113,6 +125,8 @@ export class Container extends React.Component {
|
|
|
113
125
|
outlineColor={outlineColor}
|
|
114
126
|
points={polygon.points}
|
|
115
127
|
strokeWidth={strokeWidth}
|
|
128
|
+
markAsCorrect={markAsCorrect}
|
|
129
|
+
showCorrectEnabled={showCorrect}
|
|
116
130
|
/>
|
|
117
131
|
)
|
|
118
132
|
})}
|
|
@@ -165,7 +179,13 @@ Container.propTypes = {
|
|
|
165
179
|
outlineColor:PropTypes.string.isRequired,
|
|
166
180
|
session:PropTypes.object.isRequired,
|
|
167
181
|
shapes:PropTypes.object.isRequired,
|
|
168
|
-
strokeWidth: PropTypes.number
|
|
182
|
+
strokeWidth: PropTypes.number,
|
|
183
|
+
scale: PropTypes.number,
|
|
184
|
+
showCorrect: PropTypes.bool
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
Container.defaultProps = {
|
|
188
|
+
scale: 1
|
|
169
189
|
};
|
|
170
190
|
|
|
171
191
|
export default withStyles(styles)(Container);
|
package/src/hotspot/index.jsx
CHANGED
|
@@ -1,18 +1,57 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import Typography from '@material-ui/core/Typography';
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import CorrectAnswerToggle from '@pie-lib/correct-answer-toggle';
|
|
5
|
+
import {Collapsible, hasText, PreviewPrompt} from '@pie-lib/render-ui';
|
|
6
6
|
import { withStyles } from '@material-ui/core/styles';
|
|
7
7
|
|
|
8
|
+
import Container from './container';
|
|
9
|
+
|
|
8
10
|
class HotspotComponent extends React.Component {
|
|
9
11
|
constructor(props) {
|
|
10
12
|
super(props);
|
|
11
13
|
this.state = {
|
|
12
|
-
showCorrect: false
|
|
14
|
+
showCorrect: false,
|
|
15
|
+
observer: null,
|
|
16
|
+
scale: 1
|
|
13
17
|
};
|
|
14
18
|
}
|
|
15
19
|
|
|
20
|
+
componentDidMount() {
|
|
21
|
+
this.observer = new MutationObserver((mutations) => {
|
|
22
|
+
mutations.forEach(() => {
|
|
23
|
+
const target = document.getElementById('question-container')?.style?.cssText
|
|
24
|
+
const zoom = target?.substring(
|
|
25
|
+
target.indexOf('--pie-zoom') + 11,
|
|
26
|
+
target.lastIndexOf('%')
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const zoomParsed = zoom?.replace(/\s/g, '');
|
|
30
|
+
if (zoomParsed) {
|
|
31
|
+
const newScale = parseFloat(zoomParsed) / 100;
|
|
32
|
+
if (newScale !== this.state.scale) {
|
|
33
|
+
this.setState({
|
|
34
|
+
scale: parseFloat(zoomParsed) / 100,
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
} else if (!zoomParsed && this.state.scale !== 1) {
|
|
38
|
+
this.setState({
|
|
39
|
+
scale: 1,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const target = document.getElementById('question-container');
|
|
46
|
+
if (target) {
|
|
47
|
+
this.observer.observe(target, { attributes : true, attributeFilter : ['style'] })
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
componentWillUnmount() {
|
|
52
|
+
this.observer?.disconnect();
|
|
53
|
+
}
|
|
54
|
+
|
|
16
55
|
onToggle = () => {
|
|
17
56
|
const { showCorrect } = this.state;
|
|
18
57
|
this.setState({ showCorrect: !showCorrect });
|
|
@@ -33,29 +72,45 @@ class HotspotComponent extends React.Component {
|
|
|
33
72
|
dimensions,
|
|
34
73
|
rationale,
|
|
35
74
|
teacherInstructions,
|
|
36
|
-
strokeWidth
|
|
75
|
+
strokeWidth,
|
|
76
|
+
responseCorrect
|
|
37
77
|
},
|
|
38
78
|
onSelectChoice,
|
|
39
79
|
classes
|
|
40
80
|
} = this.props;
|
|
41
|
-
|
|
81
|
+
const { showCorrect } = this.state;
|
|
42
82
|
const isEvaluateMode = mode === 'evaluate';
|
|
83
|
+
const showCorrectAnswerToggle = isEvaluateMode && !responseCorrect;
|
|
43
84
|
|
|
44
85
|
return (
|
|
45
86
|
<div>
|
|
87
|
+
{showCorrectAnswerToggle && (
|
|
88
|
+
<CorrectAnswerToggle
|
|
89
|
+
show={showCorrectAnswerToggle}
|
|
90
|
+
toggled={showCorrect}
|
|
91
|
+
onToggle={this.onToggle.bind(this)}
|
|
92
|
+
/>
|
|
93
|
+
)}
|
|
94
|
+
{showCorrectAnswerToggle && <br />}
|
|
46
95
|
{
|
|
47
96
|
teacherInstructions && hasText(teacherInstructions) && (
|
|
48
97
|
<Collapsible
|
|
49
98
|
labels={{ hidden: 'Show Teacher Instructions', visible: 'Hide Teacher Instructions' }}
|
|
50
99
|
className={classes.collapsible}
|
|
51
100
|
>
|
|
52
|
-
<
|
|
101
|
+
<PreviewPrompt
|
|
102
|
+
className="prompt"
|
|
103
|
+
prompt={teacherInstructions}
|
|
104
|
+
/>
|
|
53
105
|
</Collapsible>
|
|
54
106
|
)
|
|
55
107
|
}
|
|
56
108
|
|
|
57
109
|
<Typography className={classes.prompt}>
|
|
58
|
-
<
|
|
110
|
+
<PreviewPrompt
|
|
111
|
+
className="prompt"
|
|
112
|
+
prompt={prompt}
|
|
113
|
+
/>
|
|
59
114
|
</Typography>
|
|
60
115
|
|
|
61
116
|
{imageUrl ? (
|
|
@@ -71,6 +126,8 @@ class HotspotComponent extends React.Component {
|
|
|
71
126
|
shapes={shapes}
|
|
72
127
|
disabled={disabled}
|
|
73
128
|
strokeWidth={strokeWidth}
|
|
129
|
+
scale={this.state.scale}
|
|
130
|
+
showCorrect={showCorrect}
|
|
74
131
|
/>
|
|
75
132
|
) : null}
|
|
76
133
|
|
|
@@ -80,7 +137,10 @@ class HotspotComponent extends React.Component {
|
|
|
80
137
|
labels={{ hidden: 'Show Rationale', visible: 'Hide Rationale' }}
|
|
81
138
|
className={classes.collapsible}
|
|
82
139
|
>
|
|
83
|
-
<
|
|
140
|
+
<PreviewPrompt
|
|
141
|
+
className="prompt"
|
|
142
|
+
prompt={rationale}
|
|
143
|
+
/>
|
|
84
144
|
</Collapsible>
|
|
85
145
|
)
|
|
86
146
|
}
|
package/src/hotspot/polygon.jsx
CHANGED
|
@@ -51,9 +51,9 @@ class PolygonComponent extends React.Component {
|
|
|
51
51
|
document.body.style.cursor = 'default';
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
-
getEvaluateOutlineColor = (isCorrect, outlineColor) => isCorrect ? outlineColor : 'red'
|
|
54
|
+
getEvaluateOutlineColor = (isCorrect, markAsCorrect, outlineColor) => markAsCorrect ? 'green' : (isCorrect ? outlineColor : 'red')
|
|
55
55
|
|
|
56
|
-
getOutlineWidth = (selected, strokeWidth) => selected ? strokeWidth : 0;
|
|
56
|
+
getOutlineWidth = (showCorrectEnabled, selected, markAsCorrect, strokeWidth) => markAsCorrect || (!markAsCorrect && !showCorrectEnabled && selected) ? strokeWidth : 0;
|
|
57
57
|
|
|
58
58
|
render() {
|
|
59
59
|
const {
|
|
@@ -65,37 +65,56 @@ class PolygonComponent extends React.Component {
|
|
|
65
65
|
selected,
|
|
66
66
|
points,
|
|
67
67
|
evaluateText,
|
|
68
|
-
strokeWidth
|
|
68
|
+
strokeWidth,
|
|
69
|
+
scale,
|
|
70
|
+
markAsCorrect,
|
|
71
|
+
showCorrectEnabled
|
|
69
72
|
} = this.props;
|
|
70
73
|
|
|
71
74
|
const outlineColorParsed = isEvaluateMode
|
|
72
|
-
? this.getEvaluateOutlineColor(isCorrect, outlineColor)
|
|
75
|
+
? this.getEvaluateOutlineColor(isCorrect, markAsCorrect, outlineColor)
|
|
73
76
|
: outlineColor;
|
|
74
|
-
const outlineWidth = this.getOutlineWidth(selected, strokeWidth);
|
|
77
|
+
const outlineWidth = this.getOutlineWidth(showCorrectEnabled, selected, markAsCorrect, strokeWidth);
|
|
75
78
|
|
|
76
79
|
const pointsParsed = this.parsePointsForKonva(points);
|
|
77
80
|
const center = this.getPolygonCenter(points);
|
|
78
81
|
const iconX = center[0];
|
|
79
82
|
const iconY = center[1];
|
|
80
83
|
|
|
81
|
-
//
|
|
82
|
-
// Correctly
|
|
83
|
-
//
|
|
84
|
-
// Incorrectly
|
|
84
|
+
// "Show Correct Answer" Enabled:
|
|
85
|
+
// - Correctly Selected: white checkmark in green circle
|
|
86
|
+
// - Correctly Not Selected: none
|
|
87
|
+
// - Incorrectly Selected: none
|
|
88
|
+
// - Incorrectly Not Selected: white checkmark in green circle
|
|
89
|
+
// "Show Correct Answer" Disabled:
|
|
90
|
+
// - Correctly Selected:
|
|
91
|
+
// - white checkmark in green circle
|
|
92
|
+
// - heavy outline, as on “Gather”
|
|
93
|
+
// - Correctly Not Selected: none
|
|
94
|
+
// - Incorrectly Selected:
|
|
95
|
+
// - white "X" in red circle
|
|
96
|
+
// - heavy outline around the selection should appear in red
|
|
97
|
+
// - Incorrectly Not Selected: white "X" in red circle
|
|
85
98
|
let iconSrc;
|
|
86
99
|
|
|
87
|
-
if (
|
|
88
|
-
if (isCorrect) {
|
|
100
|
+
if (showCorrectEnabled) {
|
|
101
|
+
if ((selected && isCorrect) || (!selected && !isCorrect)) {
|
|
89
102
|
iconSrc = faCorrect;
|
|
90
|
-
}
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
if (selected) {
|
|
106
|
+
if (isCorrect) {
|
|
107
|
+
iconSrc = faCorrect;
|
|
108
|
+
} else {
|
|
109
|
+
iconSrc = faWrong;
|
|
110
|
+
}
|
|
111
|
+
} else if (!isCorrect) {
|
|
91
112
|
iconSrc = faWrong;
|
|
92
113
|
}
|
|
93
|
-
} else if (!isCorrect) {
|
|
94
|
-
iconSrc = faWrong;
|
|
95
114
|
}
|
|
96
115
|
|
|
97
116
|
return (
|
|
98
|
-
<Group>
|
|
117
|
+
<Group scaleX={scale} scaleY={scale}>
|
|
99
118
|
<Line
|
|
100
119
|
points={pointsParsed}
|
|
101
120
|
closed={true}
|
|
@@ -142,12 +161,16 @@ PolygonComponent.propTypes = {
|
|
|
142
161
|
points: PropTypes.array.isRequired,
|
|
143
162
|
selected: PropTypes.bool.isRequired,
|
|
144
163
|
evaluateText: PropTypes.string,
|
|
145
|
-
strokeWidth: PropTypes.number
|
|
164
|
+
strokeWidth: PropTypes.number,
|
|
165
|
+
scale: PropTypes.number,
|
|
166
|
+
markAsCorrect: PropTypes.bool.isRequired,
|
|
167
|
+
showCorrectEnabled: PropTypes.bool.isRequired
|
|
146
168
|
};
|
|
147
169
|
|
|
148
170
|
PolygonComponent.defaultProps = {
|
|
149
171
|
evaluateText: null,
|
|
150
|
-
strokeWidth: 5
|
|
172
|
+
strokeWidth: 5,
|
|
173
|
+
scale: 1
|
|
151
174
|
};
|
|
152
175
|
|
|
153
176
|
export default withStyles(styles)(PolygonComponent);
|
|
@@ -32,9 +32,9 @@ class RectComponent extends React.Component {
|
|
|
32
32
|
document.body.style.cursor = 'default';
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
getEvaluateOutlineColor = (isCorrect, outlineColor) => isCorrect ? outlineColor : 'red'
|
|
35
|
+
getEvaluateOutlineColor = (isCorrect, markAsCorrect, outlineColor) => markAsCorrect ? 'green' : (isCorrect ? outlineColor : 'red')
|
|
36
36
|
|
|
37
|
-
getOutlineWidth = (selected, strokeWidth) => selected ? strokeWidth : 0;
|
|
37
|
+
getOutlineWidth = (showCorrectEnabled, selected, markAsCorrect, strokeWidth) => markAsCorrect || (!markAsCorrect && !showCorrectEnabled && selected) ? strokeWidth : 0;
|
|
38
38
|
|
|
39
39
|
render() {
|
|
40
40
|
const {
|
|
@@ -49,36 +49,55 @@ class RectComponent extends React.Component {
|
|
|
49
49
|
x,
|
|
50
50
|
y,
|
|
51
51
|
evaluateText,
|
|
52
|
-
strokeWidth
|
|
52
|
+
strokeWidth,
|
|
53
|
+
scale,
|
|
54
|
+
markAsCorrect,
|
|
55
|
+
showCorrectEnabled
|
|
53
56
|
} = this.props;
|
|
54
57
|
|
|
55
58
|
const outlineColorParsed = isEvaluateMode
|
|
56
|
-
? this.getEvaluateOutlineColor(isCorrect, outlineColor)
|
|
59
|
+
? this.getEvaluateOutlineColor(isCorrect, markAsCorrect, outlineColor)
|
|
57
60
|
: outlineColor;
|
|
58
61
|
|
|
59
|
-
const outlineWidth = this.getOutlineWidth(selected, strokeWidth);
|
|
62
|
+
const outlineWidth = this.getOutlineWidth(showCorrectEnabled, selected, markAsCorrect, strokeWidth);
|
|
60
63
|
|
|
61
64
|
const iconX = (x + (width / 2)) - 10;
|
|
62
65
|
const iconY = (y + (height / 2)) - 10;
|
|
63
66
|
|
|
64
|
-
//
|
|
65
|
-
// Correctly
|
|
66
|
-
//
|
|
67
|
-
// Incorrectly
|
|
67
|
+
// "Show Correct Answer" Enabled:
|
|
68
|
+
// - Correctly Selected: white checkmark in green circle
|
|
69
|
+
// - Correctly Not Selected: none
|
|
70
|
+
// - Incorrectly Selected: none
|
|
71
|
+
// - Incorrectly Not Selected: white checkmark in green circle
|
|
72
|
+
// "Show Correct Answer" Disabled:
|
|
73
|
+
// - Correctly Selected:
|
|
74
|
+
// - white checkmark in green circle
|
|
75
|
+
// - heavy outline, as on “Gather”
|
|
76
|
+
// - Correctly Not Selected: none
|
|
77
|
+
// - Incorrectly Selected:
|
|
78
|
+
// - white "X" in red circle
|
|
79
|
+
// - heavy outline around the selection should appear in red
|
|
80
|
+
// - Incorrectly Not Selected: white "X" in red circle
|
|
68
81
|
let iconSrc;
|
|
69
82
|
|
|
70
|
-
if (
|
|
71
|
-
if (isCorrect) {
|
|
83
|
+
if (showCorrectEnabled) {
|
|
84
|
+
if ((selected && isCorrect) || (!selected && !isCorrect)) {
|
|
72
85
|
iconSrc = faCorrect;
|
|
73
|
-
}
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
if (selected) {
|
|
89
|
+
if (isCorrect) {
|
|
90
|
+
iconSrc = faCorrect;
|
|
91
|
+
} else {
|
|
92
|
+
iconSrc = faWrong;
|
|
93
|
+
}
|
|
94
|
+
} else if (!isCorrect) {
|
|
74
95
|
iconSrc = faWrong;
|
|
75
96
|
}
|
|
76
|
-
} else if (!isCorrect) {
|
|
77
|
-
iconSrc = faWrong;
|
|
78
97
|
}
|
|
79
98
|
|
|
80
99
|
return (
|
|
81
|
-
<Group>
|
|
100
|
+
<Group scaleX={scale} scaleY={scale}>
|
|
82
101
|
<Rect
|
|
83
102
|
classes={classes.base}
|
|
84
103
|
width={width}
|
|
@@ -130,13 +149,17 @@ RectComponent.propTypes = {
|
|
|
130
149
|
x: PropTypes.number.isRequired,
|
|
131
150
|
y: PropTypes.number.isRequired,
|
|
132
151
|
evaluateText: PropTypes.string,
|
|
133
|
-
strokeWidth: PropTypes.number
|
|
152
|
+
strokeWidth: PropTypes.number,
|
|
153
|
+
scale: PropTypes.number,
|
|
154
|
+
markAsCorrect: PropTypes.bool.isRequired,
|
|
155
|
+
showCorrectEnabled: PropTypes.bool.isRequired
|
|
134
156
|
};
|
|
135
157
|
|
|
136
158
|
RectComponent.defaultProps = {
|
|
137
159
|
isCorrect: false,
|
|
138
160
|
evaluateText: null,
|
|
139
|
-
strokeWidth: 5
|
|
161
|
+
strokeWidth: 5,
|
|
162
|
+
scale: 1
|
|
140
163
|
};
|
|
141
164
|
|
|
142
165
|
export default withStyles(styles)(RectComponent);
|
package/src/index.js
CHANGED
|
@@ -42,6 +42,10 @@ export default class Hotspot extends HTMLElement {
|
|
|
42
42
|
this._render();
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
get session() {
|
|
46
|
+
return this._session;
|
|
47
|
+
}
|
|
48
|
+
|
|
45
49
|
onSelectChoice(data) {
|
|
46
50
|
updateSessionValue(this._session, this._model, data);
|
|
47
51
|
|
|
@@ -63,6 +67,7 @@ export default class Hotspot extends HTMLElement {
|
|
|
63
67
|
session: this._session,
|
|
64
68
|
onSelectChoice: this.onSelectChoice.bind(this)
|
|
65
69
|
});
|
|
70
|
+
|
|
66
71
|
ReactDOM.render(el, this, () => {
|
|
67
72
|
renderMath(this);
|
|
68
73
|
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`Image snapshots image renders 1`] = `
|
|
4
|
-
<Image
|
|
5
|
-
height={20}
|
|
6
|
-
image={null}
|
|
7
|
-
width={20}
|
|
8
|
-
x={5}
|
|
9
|
-
y={5}
|
|
10
|
-
/>
|
|
11
|
-
`;
|
|
12
|
-
|
|
13
|
-
exports[`Image snapshots x y position renders 1`] = `
|
|
14
|
-
<Image
|
|
15
|
-
height={20}
|
|
16
|
-
image={null}
|
|
17
|
-
width={20}
|
|
18
|
-
x={10}
|
|
19
|
-
y={10}
|
|
20
|
-
/>
|
|
21
|
-
`;
|