@pie-element/hotspot 4.8.4-next.1097 → 4.8.4-next.1115
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/configure/package.json +2 -2
- package/lib/hotspot/container.js +12 -4
- package/lib/hotspot/container.js.map +1 -1
- package/lib/hotspot/index.js +12 -2
- package/lib/hotspot/index.js.map +1 -1
- package/lib/hotspot/polygon.js +37 -17
- package/lib/hotspot/polygon.js.map +1 -1
- package/lib/hotspot/rectangle.js +37 -17
- package/lib/hotspot/rectangle.js.map +1 -1
- package/package.json +2 -2
- 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 +10 -2
- package/src/hotspot/index.jsx +14 -2
- package/src/hotspot/polygon.jsx +35 -15
- package/src/hotspot/rectangle.jsx +35 -15
- 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
|
|
@@ -43,7 +43,8 @@ export class Container extends React.Component {
|
|
|
43
43
|
onSelectChoice,
|
|
44
44
|
shapes: { rectangles, polygons },
|
|
45
45
|
scale: SCALE,
|
|
46
|
-
strokeWidth
|
|
46
|
+
strokeWidth,
|
|
47
|
+
showCorrect
|
|
47
48
|
} = this.props;
|
|
48
49
|
|
|
49
50
|
const width = withProp * SCALE;
|
|
@@ -78,6 +79,7 @@ export class Container extends React.Component {
|
|
|
78
79
|
const selected = this.isSelected(shape);
|
|
79
80
|
const isCorrect = isEvaluateMode ? this.correctness(shape.correct, selected) : undefined;
|
|
80
81
|
const evaluateText = isEvaluateMode ? this.getEvaluateText(shape.correct, selected) : null;
|
|
82
|
+
const markAsCorrect = !!(isEvaluateMode && showCorrect && shape.correct);
|
|
81
83
|
|
|
82
84
|
return (
|
|
83
85
|
<Rectangle
|
|
@@ -97,6 +99,8 @@ export class Container extends React.Component {
|
|
|
97
99
|
x={shape.x}
|
|
98
100
|
y={shape.y}
|
|
99
101
|
strokeWidth={strokeWidth}
|
|
102
|
+
markAsCorrect={markAsCorrect}
|
|
103
|
+
showCorrectEnabled={showCorrect}
|
|
100
104
|
/>
|
|
101
105
|
)
|
|
102
106
|
})}
|
|
@@ -104,6 +108,7 @@ export class Container extends React.Component {
|
|
|
104
108
|
const selected = this.isSelected(polygon);
|
|
105
109
|
const isCorrect = isEvaluateMode ? this.correctness(polygon.correct, selected) : undefined;
|
|
106
110
|
const evaluateText = isEvaluateMode ? this.getEvaluateText(polygon.correct, selected) : null;
|
|
111
|
+
const markAsCorrect = !!(isEvaluateMode && showCorrect && polygon.correct);
|
|
107
112
|
|
|
108
113
|
return (
|
|
109
114
|
<Polygon
|
|
@@ -120,6 +125,8 @@ export class Container extends React.Component {
|
|
|
120
125
|
outlineColor={outlineColor}
|
|
121
126
|
points={polygon.points}
|
|
122
127
|
strokeWidth={strokeWidth}
|
|
128
|
+
markAsCorrect={markAsCorrect}
|
|
129
|
+
showCorrectEnabled={showCorrect}
|
|
123
130
|
/>
|
|
124
131
|
)
|
|
125
132
|
})}
|
|
@@ -173,7 +180,8 @@ Container.propTypes = {
|
|
|
173
180
|
session:PropTypes.object.isRequired,
|
|
174
181
|
shapes:PropTypes.object.isRequired,
|
|
175
182
|
strokeWidth: PropTypes.number,
|
|
176
|
-
scale: PropTypes.number
|
|
183
|
+
scale: PropTypes.number,
|
|
184
|
+
showCorrect: PropTypes.bool
|
|
177
185
|
};
|
|
178
186
|
|
|
179
187
|
Container.defaultProps = {
|
package/src/hotspot/index.jsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import Typography from '@material-ui/core/Typography';
|
|
4
|
+
import CorrectAnswerToggle from '@pie-lib/correct-answer-toggle';
|
|
4
5
|
import {Collapsible, hasText, PreviewPrompt} from '@pie-lib/render-ui';
|
|
5
6
|
import { withStyles } from '@material-ui/core/styles';
|
|
6
7
|
|
|
@@ -71,16 +72,26 @@ class HotspotComponent extends React.Component {
|
|
|
71
72
|
dimensions,
|
|
72
73
|
rationale,
|
|
73
74
|
teacherInstructions,
|
|
74
|
-
strokeWidth
|
|
75
|
+
strokeWidth,
|
|
76
|
+
responseCorrect
|
|
75
77
|
},
|
|
76
78
|
onSelectChoice,
|
|
77
79
|
classes
|
|
78
80
|
} = this.props;
|
|
79
|
-
|
|
81
|
+
const { showCorrect } = this.state;
|
|
80
82
|
const isEvaluateMode = mode === 'evaluate';
|
|
83
|
+
const showCorrectAnswerToggle = isEvaluateMode && !responseCorrect;
|
|
81
84
|
|
|
82
85
|
return (
|
|
83
86
|
<div>
|
|
87
|
+
{showCorrectAnswerToggle && (
|
|
88
|
+
<CorrectAnswerToggle
|
|
89
|
+
show={showCorrectAnswerToggle}
|
|
90
|
+
toggled={showCorrect}
|
|
91
|
+
onToggle={this.onToggle.bind(this)}
|
|
92
|
+
/>
|
|
93
|
+
)}
|
|
94
|
+
{showCorrectAnswerToggle && <br />}
|
|
84
95
|
{
|
|
85
96
|
teacherInstructions && hasText(teacherInstructions) && (
|
|
86
97
|
<Collapsible
|
|
@@ -116,6 +127,7 @@ class HotspotComponent extends React.Component {
|
|
|
116
127
|
disabled={disabled}
|
|
117
128
|
strokeWidth={strokeWidth}
|
|
118
129
|
scale={this.state.scale}
|
|
130
|
+
showCorrect={showCorrect}
|
|
119
131
|
/>
|
|
120
132
|
) : null}
|
|
121
133
|
|
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 {
|
|
@@ -66,33 +66,51 @@ class PolygonComponent extends React.Component {
|
|
|
66
66
|
points,
|
|
67
67
|
evaluateText,
|
|
68
68
|
strokeWidth,
|
|
69
|
-
scale
|
|
69
|
+
scale,
|
|
70
|
+
markAsCorrect,
|
|
71
|
+
showCorrectEnabled
|
|
70
72
|
} = this.props;
|
|
71
73
|
|
|
72
74
|
const outlineColorParsed = isEvaluateMode
|
|
73
|
-
? this.getEvaluateOutlineColor(isCorrect, outlineColor)
|
|
75
|
+
? this.getEvaluateOutlineColor(isCorrect, markAsCorrect, outlineColor)
|
|
74
76
|
: outlineColor;
|
|
75
|
-
const outlineWidth = this.getOutlineWidth(selected, strokeWidth);
|
|
77
|
+
const outlineWidth = this.getOutlineWidth(showCorrectEnabled, selected, markAsCorrect, strokeWidth);
|
|
76
78
|
|
|
77
79
|
const pointsParsed = this.parsePointsForKonva(points);
|
|
78
80
|
const center = this.getPolygonCenter(points);
|
|
79
81
|
const iconX = center[0];
|
|
80
82
|
const iconY = center[1];
|
|
81
83
|
|
|
82
|
-
//
|
|
83
|
-
// Correctly
|
|
84
|
-
//
|
|
85
|
-
// 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
|
|
86
98
|
let iconSrc;
|
|
87
99
|
|
|
88
|
-
if (
|
|
89
|
-
if (isCorrect) {
|
|
100
|
+
if (showCorrectEnabled) {
|
|
101
|
+
if ((selected && isCorrect) || (!selected && !isCorrect)) {
|
|
90
102
|
iconSrc = faCorrect;
|
|
91
|
-
}
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
if (selected) {
|
|
106
|
+
if (isCorrect) {
|
|
107
|
+
iconSrc = faCorrect;
|
|
108
|
+
} else {
|
|
109
|
+
iconSrc = faWrong;
|
|
110
|
+
}
|
|
111
|
+
} else if (!isCorrect) {
|
|
92
112
|
iconSrc = faWrong;
|
|
93
113
|
}
|
|
94
|
-
} else if (!isCorrect) {
|
|
95
|
-
iconSrc = faWrong;
|
|
96
114
|
}
|
|
97
115
|
|
|
98
116
|
return (
|
|
@@ -144,7 +162,9 @@ PolygonComponent.propTypes = {
|
|
|
144
162
|
selected: PropTypes.bool.isRequired,
|
|
145
163
|
evaluateText: PropTypes.string,
|
|
146
164
|
strokeWidth: PropTypes.number,
|
|
147
|
-
scale: PropTypes.number
|
|
165
|
+
scale: PropTypes.number,
|
|
166
|
+
markAsCorrect: PropTypes.bool.isRequired,
|
|
167
|
+
showCorrectEnabled: PropTypes.bool.isRequired
|
|
148
168
|
};
|
|
149
169
|
|
|
150
170
|
PolygonComponent.defaultProps = {
|
|
@@ -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 {
|
|
@@ -50,32 +50,50 @@ class RectComponent extends React.Component {
|
|
|
50
50
|
y,
|
|
51
51
|
evaluateText,
|
|
52
52
|
strokeWidth,
|
|
53
|
-
scale
|
|
53
|
+
scale,
|
|
54
|
+
markAsCorrect,
|
|
55
|
+
showCorrectEnabled
|
|
54
56
|
} = this.props;
|
|
55
57
|
|
|
56
58
|
const outlineColorParsed = isEvaluateMode
|
|
57
|
-
? this.getEvaluateOutlineColor(isCorrect, outlineColor)
|
|
59
|
+
? this.getEvaluateOutlineColor(isCorrect, markAsCorrect, outlineColor)
|
|
58
60
|
: outlineColor;
|
|
59
61
|
|
|
60
|
-
const outlineWidth = this.getOutlineWidth(selected, strokeWidth);
|
|
62
|
+
const outlineWidth = this.getOutlineWidth(showCorrectEnabled, selected, markAsCorrect, strokeWidth);
|
|
61
63
|
|
|
62
64
|
const iconX = (x + (width / 2)) - 10;
|
|
63
65
|
const iconY = (y + (height / 2)) - 10;
|
|
64
66
|
|
|
65
|
-
//
|
|
66
|
-
// Correctly
|
|
67
|
-
//
|
|
68
|
-
// 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
|
|
69
81
|
let iconSrc;
|
|
70
82
|
|
|
71
|
-
if (
|
|
72
|
-
if (isCorrect) {
|
|
83
|
+
if (showCorrectEnabled) {
|
|
84
|
+
if ((selected && isCorrect) || (!selected && !isCorrect)) {
|
|
73
85
|
iconSrc = faCorrect;
|
|
74
|
-
}
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
if (selected) {
|
|
89
|
+
if (isCorrect) {
|
|
90
|
+
iconSrc = faCorrect;
|
|
91
|
+
} else {
|
|
92
|
+
iconSrc = faWrong;
|
|
93
|
+
}
|
|
94
|
+
} else if (!isCorrect) {
|
|
75
95
|
iconSrc = faWrong;
|
|
76
96
|
}
|
|
77
|
-
} else if (!isCorrect) {
|
|
78
|
-
iconSrc = faWrong;
|
|
79
97
|
}
|
|
80
98
|
|
|
81
99
|
return (
|
|
@@ -132,7 +150,9 @@ RectComponent.propTypes = {
|
|
|
132
150
|
y: PropTypes.number.isRequired,
|
|
133
151
|
evaluateText: PropTypes.string,
|
|
134
152
|
strokeWidth: PropTypes.number,
|
|
135
|
-
scale: PropTypes.number
|
|
153
|
+
scale: PropTypes.number,
|
|
154
|
+
markAsCorrect: PropTypes.bool.isRequired,
|
|
155
|
+
showCorrectEnabled: PropTypes.bool.isRequired
|
|
136
156
|
};
|
|
137
157
|
|
|
138
158
|
RectComponent.defaultProps = {
|
|
@@ -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
|
-
`;
|
|
@@ -1,77 +0,0 @@
|
|
|
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
|
-
|
|
7
|
-
import Polygon from '../hotspot/polygon';
|
|
8
|
-
|
|
9
|
-
Konva.isBrowser = false;
|
|
10
|
-
|
|
11
|
-
describe('Polygon', () => {
|
|
12
|
-
let onClick, wrapper;
|
|
13
|
-
|
|
14
|
-
const mkWrapper = (opts = {}) => {
|
|
15
|
-
opts = _.extend(
|
|
16
|
-
{
|
|
17
|
-
classes: {
|
|
18
|
-
base: 'base'
|
|
19
|
-
},
|
|
20
|
-
height: 200,
|
|
21
|
-
hotspotColor: 'rgba(137, 183, 244, 0.65)',
|
|
22
|
-
id: '1',
|
|
23
|
-
isCorrect: false,
|
|
24
|
-
isEvaluateMode: false,
|
|
25
|
-
evaluateText: null,
|
|
26
|
-
disabled: false,
|
|
27
|
-
outlineColor: 'blue',
|
|
28
|
-
selected: false,
|
|
29
|
-
points: [{ x: 94, y: 4 }, { x: 89, y: 4 }, { x: 36, y: 40 }]
|
|
30
|
-
},
|
|
31
|
-
opts
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
return shallow(<Polygon {...opts} onClick={onClick} />);
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
beforeEach(() => {
|
|
38
|
-
onClick = jest.fn();
|
|
39
|
-
wrapper = mkWrapper();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
describe('snapshots', () => {
|
|
43
|
-
describe('outline color', () => {
|
|
44
|
-
it('renders', () => {
|
|
45
|
-
const wrapper = mkWrapper({ outlineColor: 'red' });
|
|
46
|
-
expect(toJson(wrapper)).toMatchSnapshot();
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
describe('outline width', () => {
|
|
51
|
-
it('renders with default border width', () => {
|
|
52
|
-
const wrapper = mkWrapper();
|
|
53
|
-
expect(toJson(wrapper)).toMatchSnapshot();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('renders with given border width', () => {
|
|
57
|
-
const wrapper = mkWrapper({ strokeWidth: 10 });
|
|
58
|
-
expect(toJson(wrapper)).toMatchSnapshot();
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
describe('hotspot color', () => {
|
|
64
|
-
it('renders', () => {
|
|
65
|
-
const wrapper = mkWrapper({ hotspotColor: 'rgba(217, 30, 24, 0.65)' });
|
|
66
|
-
expect(toJson(wrapper)).toMatchSnapshot();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('evaluate with correct answer', () => {
|
|
71
|
-
it('renders', () => {
|
|
72
|
-
const wrapper = mkWrapper({ isEvaluateMode: true, isCorrect: true, evaluateText: 'Correctly\nselected' });
|
|
73
|
-
expect(toJson(wrapper)).toMatchSnapshot();
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
});
|
|
@@ -1,78 +0,0 @@
|
|
|
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
|
-
|
|
7
|
-
import Rectangle from '../hotspot/rectangle';
|
|
8
|
-
|
|
9
|
-
Konva.isBrowser = false;
|
|
10
|
-
|
|
11
|
-
describe('Rectangle', () => {
|
|
12
|
-
let onClick, wrapper;
|
|
13
|
-
|
|
14
|
-
const mkWrapper = (opts = {}) => {
|
|
15
|
-
opts = _.extend(
|
|
16
|
-
{
|
|
17
|
-
classes: {
|
|
18
|
-
base: 'base'
|
|
19
|
-
},
|
|
20
|
-
height: 200,
|
|
21
|
-
hotspotColor: 'rgba(137, 183, 244, 0.65)',
|
|
22
|
-
id: '1',
|
|
23
|
-
isCorrect: false,
|
|
24
|
-
isEvaluateMode: false,
|
|
25
|
-
evaluateText: null,
|
|
26
|
-
disabled: false,
|
|
27
|
-
outlineColor: 'blue',
|
|
28
|
-
selected: false,
|
|
29
|
-
width: 300,
|
|
30
|
-
x: 5,
|
|
31
|
-
y: 5
|
|
32
|
-
},
|
|
33
|
-
opts
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
return shallow(<Rectangle {...opts} onClick={onClick} />);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
beforeEach(() => {
|
|
40
|
-
onClick = jest.fn();
|
|
41
|
-
wrapper = mkWrapper();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
describe('snapshots', () => {
|
|
45
|
-
describe('outline color', () => {
|
|
46
|
-
it('renders', () => {
|
|
47
|
-
const wrapper = mkWrapper({ outlineColor: 'red' });
|
|
48
|
-
expect(toJson(wrapper)).toMatchSnapshot();
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe('outline width', () => {
|
|
53
|
-
it('renders with default border width', () => {
|
|
54
|
-
const wrapper = mkWrapper();
|
|
55
|
-
expect(toJson(wrapper)).toMatchSnapshot();
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('renders with given border width', () => {
|
|
59
|
-
const wrapper = mkWrapper({ strokeWidth: 10 });
|
|
60
|
-
expect(toJson(wrapper)).toMatchSnapshot();
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
describe('hotspot color', () => {
|
|
65
|
-
it('renders', () => {
|
|
66
|
-
const wrapper = mkWrapper({ hotspotColor: 'rgba(217, 30, 24, 0.65)' });
|
|
67
|
-
expect(toJson(wrapper)).toMatchSnapshot();
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
describe('evaluate with correct answer', () => {
|
|
72
|
-
it('renders', () => {
|
|
73
|
-
const wrapper = mkWrapper({ isEvaluateMode: true, isCorrect: true, evaluateText: 'Correctly\nselected' });
|
|
74
|
-
expect(toJson(wrapper)).toMatchSnapshot();
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
});
|