@pie-element/hotspot 4.8.4-next.133 → 4.8.4-next.1335

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/CHANGELOG.md +241 -0
  2. package/configure/CHANGELOG.md +214 -0
  3. package/configure/lib/defaults.js +20 -0
  4. package/configure/lib/defaults.js.map +1 -1
  5. package/configure/lib/hotspot-container.js +26 -12
  6. package/configure/lib/hotspot-container.js.map +1 -1
  7. package/configure/lib/hotspot-drawable.js +11 -5
  8. package/configure/lib/hotspot-drawable.js.map +1 -1
  9. package/configure/lib/hotspot-palette.js +1 -1
  10. package/configure/lib/hotspot-palette.js.map +1 -1
  11. package/configure/lib/hotspot-polygon.js +1 -1
  12. package/configure/lib/hotspot-polygon.js.map +1 -1
  13. package/configure/lib/hotspot-rectangle.js +1 -1
  14. package/configure/lib/hotspot-rectangle.js.map +1 -1
  15. package/configure/lib/index.js +17 -3
  16. package/configure/lib/index.js.map +1 -1
  17. package/configure/lib/root.js +107 -13
  18. package/configure/lib/root.js.map +1 -1
  19. package/configure/lib/utils.js +18 -4
  20. package/configure/lib/utils.js.map +1 -1
  21. package/configure/package.json +4 -4
  22. package/configure/src/__tests__/__snapshots__/hotspot-container.test.js.snap +1 -0
  23. package/configure/src/__tests__/__snapshots__/root.test.js.snap +53 -4
  24. package/configure/src/defaults.js +20 -0
  25. package/configure/src/hotspot-container.jsx +16 -5
  26. package/configure/src/hotspot-drawable.jsx +8 -2
  27. package/configure/src/index.js +14 -0
  28. package/configure/src/root.jsx +87 -9
  29. package/configure/src/utils.js +23 -1
  30. package/controller/CHANGELOG.md +28 -0
  31. package/controller/lib/index.js +44 -5
  32. package/controller/lib/index.js.map +1 -1
  33. package/controller/lib/utils.js.map +1 -1
  34. package/controller/package.json +1 -1
  35. package/controller/src/index.js +26 -0
  36. package/docs/config-schema.json +212 -0
  37. package/docs/config-schema.json.md +165 -0
  38. package/docs/demo/generate.js +1 -0
  39. package/docs/pie-schema.json +49 -0
  40. package/docs/pie-schema.json.md +36 -0
  41. package/lib/hotspot/container.js +25 -7
  42. package/lib/hotspot/container.js.map +1 -1
  43. package/lib/hotspot/image.js +1 -1
  44. package/lib/hotspot/image.js.map +1 -1
  45. package/lib/hotspot/index.js +72 -18
  46. package/lib/hotspot/index.js.map +1 -1
  47. package/lib/hotspot/polygon.js +46 -20
  48. package/lib/hotspot/polygon.js.map +1 -1
  49. package/lib/hotspot/rectangle.js +46 -20
  50. package/lib/hotspot/rectangle.js.map +1 -1
  51. package/lib/index.js +4 -1
  52. package/lib/index.js.map +1 -1
  53. package/lib/session-updater.js.map +1 -1
  54. package/package.json +6 -4
  55. package/src/__tests__/__snapshots__/{container-test.jsx.snap → container.test.jsx.snap} +8 -0
  56. package/src/__tests__/__snapshots__/image.test.jsx.snap +43 -0
  57. package/src/__tests__/__snapshots__/{polygon-test.jsx.snap → polygon.test.jsx.snap} +11 -0
  58. package/src/__tests__/__snapshots__/{rectangle-test.jsx.snap → rectangle.test.jsx.snap} +11 -0
  59. package/src/__tests__/{container-test.jsx → container.test.jsx} +57 -0
  60. package/src/__tests__/{image-test.jsx → image.test.jsx} +0 -0
  61. package/src/__tests__/polygon.test.jsx +224 -0
  62. package/src/__tests__/rectangle.test.jsx +233 -0
  63. package/src/__tests__/{session-updater-test.jsx → session-updater.test.jsx} +0 -0
  64. package/src/hotspot/container.jsx +23 -3
  65. package/src/hotspot/index.jsx +68 -8
  66. package/src/hotspot/polygon.jsx +40 -17
  67. package/src/hotspot/rectangle.jsx +40 -17
  68. package/src/index.js +5 -0
  69. package/src/__tests__/__snapshots__/image-test.jsx.snap +0 -21
  70. package/src/__tests__/polygon-test.jsx +0 -77
  71. 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
+ });
@@ -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
- strokeWidth
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);
@@ -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 { Collapsible, hasText } from '@pie-lib/render-ui';
5
- import Container from './container';
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
- <div dangerouslySetInnerHTML={{ __html: teacherInstructions }}/>
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
- <span dangerouslySetInnerHTML={{ __html: prompt }} />
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
- <div dangerouslySetInnerHTML={{ __html: rationale }} />
140
+ <PreviewPrompt
141
+ className="prompt"
142
+ prompt={rationale}
143
+ />
84
144
  </Collapsible>
85
145
  )
86
146
  }
@@ -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
- // Correctly selected hotspot: white checkmark in green circle (plus the selected hotspot will have a heavy outline, as on “Gather”)
82
- // Correctly not selected hotspot: none
83
- // Incorrectly selected hostpot: white “X” in red circle, plus the heavy outline around the selection should appear in red
84
- // Incorrectly not selected hotspot: white “X” in red circle
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 (selected) {
88
- if (isCorrect) {
100
+ if (showCorrectEnabled) {
101
+ if ((selected && isCorrect) || (!selected && !isCorrect)) {
89
102
  iconSrc = faCorrect;
90
- } else {
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
- // Correctly selected hotspot: white checkmark in green circle (plus the selected hotspot will have a heavy outline, as on “Gather”)
65
- // Correctly not selected hotspot: none
66
- // Incorrectly selected hostpot: white “X” in red circle, plus the heavy outline around the selection should appear in red
67
- // Incorrectly not selected hotspot: white “X” in red circle
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 (selected) {
71
- if (isCorrect) {
83
+ if (showCorrectEnabled) {
84
+ if ((selected && isCorrect) || (!selected && !isCorrect)) {
72
85
  iconSrc = faCorrect;
73
- } else {
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
- `;