@pie-element/hotspot 4.10.10 → 4.10.11-beta.1443
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 +349 -0
- package/configure/CHANGELOG.md +311 -0
- package/configure/lib/button.js.map +1 -1
- package/configure/lib/defaults.js +23 -2
- package/configure/lib/defaults.js.map +1 -1
- package/configure/lib/hotspot-container.js +28 -19
- package/configure/lib/hotspot-container.js.map +1 -1
- package/configure/lib/hotspot-drawable.js +3 -3
- package/configure/lib/hotspot-drawable.js.map +1 -1
- package/configure/lib/hotspot-palette.js.map +1 -1
- package/configure/lib/hotspot-polygon.js.map +1 -1
- package/configure/lib/hotspot-rectangle.js.map +1 -1
- package/configure/lib/index.js +16 -2
- package/configure/lib/index.js.map +1 -1
- package/configure/lib/root.js +129 -38
- package/configure/lib/root.js.map +1 -1
- package/configure/lib/upload-control.js.map +1 -1
- package/configure/lib/utils.js +15 -3
- 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 -1
- package/configure/src/__tests__/__snapshots__/root.test.js.snap +56 -4
- package/configure/src/__tests__/hotspot-container.test.js +98 -71
- package/configure/src/__tests__/hotspot-drawable.test.js +48 -49
- package/configure/src/__tests__/index.test.js +28 -51
- package/configure/src/__tests__/root.test.js +162 -82
- package/configure/src/__tests__/utils.test.js +112 -98
- package/configure/src/button.jsx +4 -4
- package/configure/src/defaults.js +35 -18
- package/configure/src/hotspot-container.jsx +99 -98
- package/configure/src/hotspot-drawable.jsx +56 -56
- package/configure/src/hotspot-palette.jsx +12 -25
- package/configure/src/hotspot-polygon.jsx +20 -22
- package/configure/src/hotspot-rectangle.jsx +5 -15
- package/configure/src/index.js +32 -18
- package/configure/src/root.jsx +116 -60
- package/configure/src/upload-control.jsx +9 -20
- package/configure/src/utils.js +51 -22
- package/controller/CHANGELOG.md +23 -0
- package/controller/lib/defaults.js +2 -2
- package/controller/lib/defaults.js.map +1 -1
- package/controller/lib/index.js +39 -3
- package/controller/lib/index.js.map +1 -1
- package/controller/lib/utils.js.map +1 -1
- package/controller/package.json +2 -2
- package/controller/src/__tests__/index.test.js +29 -50
- package/controller/src/defaults.js +5 -9
- package/controller/src/index.js +47 -33
- package/controller/src/utils.js +9 -6
- package/docs/config-schema.json +217 -0
- package/docs/config-schema.json.md +169 -0
- package/docs/demo/config.js +2 -2
- package/docs/demo/generate.js +53 -35
- package/docs/demo/session.js +2 -2
- package/docs/pie-schema.json +49 -0
- package/docs/pie-schema.json.md +36 -0
- package/lib/hotspot/container.js +24 -6
- package/lib/hotspot/container.js.map +1 -1
- package/lib/hotspot/icons.js.map +1 -1
- package/lib/hotspot/image.js.map +1 -1
- package/lib/hotspot/index.js +65 -5
- package/lib/hotspot/index.js.map +1 -1
- package/lib/hotspot/polygon.js +45 -19
- package/lib/hotspot/polygon.js.map +1 -1
- package/lib/hotspot/rectangle.js +45 -19
- package/lib/hotspot/rectangle.js.map +1 -1
- package/lib/index.js +3 -0
- 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 +214 -0
- package/src/__tests__/{image-test.jsx → image.test.jsx} +2 -2
- package/src/__tests__/polygon.test.jsx +235 -0
- package/src/__tests__/rectangle.test.jsx +237 -0
- package/src/__tests__/{session-updater-test.jsx → session-updater.test.jsx} +22 -31
- package/src/hotspot/container.jsx +40 -23
- package/src/hotspot/icons.js +4 -2
- package/src/hotspot/image.jsx +4 -8
- package/src/hotspot/index.jsx +73 -33
- package/src/hotspot/polygon.jsx +48 -30
- package/src/hotspot/rectangle.jsx +48 -30
- package/src/index.js +10 -18
- package/src/session-updater.js +1 -1
- package/src/__tests__/__snapshots__/image-test.jsx.snap +0 -21
- package/src/__tests__/container-test.jsx +0 -143
- package/src/__tests__/polygon-test.jsx +0 -77
- package/src/__tests__/rectangle-test.jsx +0 -78
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { Component } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
+
import classNames from 'classnames';
|
|
3
4
|
import { withStyles } from '@material-ui/core/styles/index';
|
|
4
5
|
import Help from '@material-ui/icons/Help';
|
|
5
6
|
|
|
@@ -10,6 +11,7 @@ import { getAllShapes, groupShapes } from './utils';
|
|
|
10
11
|
|
|
11
12
|
const isImage = (file) => {
|
|
12
13
|
const imageType = /image.*/;
|
|
14
|
+
|
|
13
15
|
return file.type.match(imageType);
|
|
14
16
|
};
|
|
15
17
|
|
|
@@ -19,7 +21,7 @@ export class Container extends Component {
|
|
|
19
21
|
return {
|
|
20
22
|
...prevState,
|
|
21
23
|
shapes: getAllShapes(nextProps.shapes),
|
|
22
|
-
}
|
|
24
|
+
};
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
constructor(props) {
|
|
@@ -28,16 +30,18 @@ export class Container extends Component {
|
|
|
28
30
|
this.state = {
|
|
29
31
|
dragEnabled: true,
|
|
30
32
|
// always transform shapes map into shapes array at this level
|
|
31
|
-
shapes: getAllShapes(props.shapes)
|
|
32
|
-
}
|
|
33
|
+
shapes: getAllShapes(props.shapes),
|
|
34
|
+
};
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
handleFileRead = (file) => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
if (file instanceof Blob) {
|
|
39
|
+
const { onImageUpload } = this.props;
|
|
40
|
+
const reader = new FileReader();
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
reader.onloadend = () => onImageUpload(reader.result);
|
|
43
|
+
reader.readAsDataURL(file);
|
|
44
|
+
}
|
|
41
45
|
};
|
|
42
46
|
|
|
43
47
|
handleUploadImage = (e) => {
|
|
@@ -47,6 +51,7 @@ export class Container extends Component {
|
|
|
47
51
|
};
|
|
48
52
|
|
|
49
53
|
enableDropzone = () => this.setState({ dropzoneActive: true });
|
|
54
|
+
|
|
50
55
|
disableDropzone = () => this.setState({ dropzoneActive: false });
|
|
51
56
|
|
|
52
57
|
handleOnPaste = (e) => {
|
|
@@ -71,6 +76,7 @@ export class Container extends Component {
|
|
|
71
76
|
} else if (isImage(files[0])) {
|
|
72
77
|
this.handleFileRead(files[0]);
|
|
73
78
|
}
|
|
79
|
+
|
|
74
80
|
this.disableDropzone();
|
|
75
81
|
};
|
|
76
82
|
|
|
@@ -90,13 +96,13 @@ export class Container extends Component {
|
|
|
90
96
|
this.disableDropzone();
|
|
91
97
|
};
|
|
92
98
|
|
|
93
|
-
onUpdateShapes = newShapes => {
|
|
99
|
+
onUpdateShapes = (newShapes) => {
|
|
94
100
|
const { onUpdateShapes } = this.props;
|
|
95
101
|
|
|
96
102
|
this.setState(
|
|
97
103
|
{ shapes: newShapes },
|
|
98
104
|
// always transform shapes array back into shapes map when saving changes
|
|
99
|
-
() => onUpdateShapes(groupShapes(newShapes))
|
|
105
|
+
() => onUpdateShapes(groupShapes(newShapes)),
|
|
100
106
|
);
|
|
101
107
|
};
|
|
102
108
|
|
|
@@ -105,7 +111,7 @@ export class Container extends Component {
|
|
|
105
111
|
|
|
106
112
|
if (shapes && shapes.length) {
|
|
107
113
|
// sort by index value
|
|
108
|
-
let newShapes = shapes.sort((a, b) =>
|
|
114
|
+
let newShapes = shapes.sort((a, b) => parseInt(a.index) - parseInt(b.index));
|
|
109
115
|
|
|
110
116
|
newShapes = newShapes ? newShapes.slice(0, newShapes.length - 1) : [];
|
|
111
117
|
|
|
@@ -116,7 +122,9 @@ export class Container extends Component {
|
|
|
116
122
|
handleClearAll = () => this.onUpdateShapes([]);
|
|
117
123
|
|
|
118
124
|
handleEnableDrag = () => this.setState({ dragEnabled: true });
|
|
125
|
+
|
|
119
126
|
handleDisableDrag = () => this.setState({ dragEnabled: false });
|
|
127
|
+
|
|
120
128
|
handleInputClick = () => this.input.click();
|
|
121
129
|
|
|
122
130
|
toggleTooltip = () => this.setState({ showTooltip: !this.state.showTooltip });
|
|
@@ -125,31 +133,34 @@ export class Container extends Component {
|
|
|
125
133
|
const {
|
|
126
134
|
classes,
|
|
127
135
|
dimensions,
|
|
136
|
+
hasErrors,
|
|
128
137
|
hotspotColor,
|
|
129
138
|
imageUrl,
|
|
130
139
|
multipleCorrect,
|
|
131
140
|
onUpdateImageDimension,
|
|
132
141
|
outlineColor,
|
|
133
142
|
strokeWidth,
|
|
134
|
-
preserveAspectRatioEnabled
|
|
143
|
+
preserveAspectRatioEnabled,
|
|
135
144
|
} = this.props;
|
|
136
|
-
const {
|
|
137
|
-
dropzoneActive,
|
|
138
|
-
dragEnabled,
|
|
139
|
-
showTooltip
|
|
140
|
-
} = this.state;
|
|
145
|
+
const { dropzoneActive, dragEnabled, showTooltip } = this.state;
|
|
141
146
|
const { shapes } = this.state;
|
|
142
147
|
|
|
143
148
|
return (
|
|
144
149
|
<div className={classes.base}>
|
|
145
|
-
<div
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
<div
|
|
151
|
+
className={classNames(classes.box, {
|
|
152
|
+
[classes.boxError]: hasErrors && !dropzoneActive,
|
|
153
|
+
[classes.boxActive]: dropzoneActive,
|
|
154
|
+
})}
|
|
155
|
+
{...(dragEnabled
|
|
156
|
+
? {
|
|
157
|
+
onDragExit: this.handleOnDragExit,
|
|
158
|
+
onDragLeave: this.handleOnDragExit,
|
|
159
|
+
onDragOver: this.handleOnDragOver,
|
|
160
|
+
onDrop: this.handleOnDrop,
|
|
161
|
+
onPaste: this.handleOnPaste,
|
|
162
|
+
}
|
|
163
|
+
: {})}
|
|
153
164
|
>
|
|
154
165
|
<div className={classes.toolbar}>
|
|
155
166
|
{imageUrl && (
|
|
@@ -164,54 +175,46 @@ export class Container extends Component {
|
|
|
164
175
|
}}
|
|
165
176
|
/>
|
|
166
177
|
)}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
label="Undo"
|
|
171
|
-
/>
|
|
172
|
-
<Button
|
|
173
|
-
disabled={!(shapes && shapes.length)}
|
|
174
|
-
onClick={this.handleClearAll}
|
|
175
|
-
label="Clear all"
|
|
176
|
-
/>
|
|
178
|
+
|
|
179
|
+
<Button disabled={!(shapes && shapes.length)} onClick={this.handleUndo} label="Undo" />
|
|
180
|
+
<Button disabled={!(shapes && shapes.length)} onClick={this.handleClearAll} label="Clear all" />
|
|
177
181
|
</div>
|
|
178
182
|
|
|
179
183
|
<div
|
|
180
|
-
ref={ref => {
|
|
184
|
+
ref={(ref) => {
|
|
181
185
|
this.imageSection = ref;
|
|
182
186
|
}}
|
|
183
|
-
className={classes.drawableHeight}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
187
|
+
className={classes.drawableHeight}
|
|
188
|
+
>
|
|
189
|
+
{imageUrl ? (
|
|
190
|
+
<Drawable
|
|
191
|
+
dimensions={dimensions}
|
|
192
|
+
disableDrag={this.handleDisableDrag}
|
|
193
|
+
enableDrag={this.handleEnableDrag}
|
|
194
|
+
imageUrl={imageUrl}
|
|
195
|
+
hotspotColor={hotspotColor}
|
|
196
|
+
multipleCorrect={multipleCorrect}
|
|
197
|
+
onUpdateImageDimension={onUpdateImageDimension}
|
|
198
|
+
onUpdateShapes={this.onUpdateShapes}
|
|
199
|
+
outlineColor={outlineColor}
|
|
200
|
+
shapes={shapes}
|
|
201
|
+
strokeWidth={strokeWidth}
|
|
202
|
+
preserveAspectRatioEnabled={preserveAspectRatioEnabled}
|
|
203
|
+
/>
|
|
204
|
+
) : (
|
|
205
|
+
<div className={classNames(classes.drawableHeight, classes.centered)}>
|
|
206
|
+
<label>Drag and drop or upload image from computer</label>
|
|
207
|
+
<br />
|
|
208
|
+
<UploadControl
|
|
209
|
+
label="Upload Image"
|
|
210
|
+
onInputClick={this.handleInputClick}
|
|
211
|
+
onUploadImage={this.handleUploadImage}
|
|
212
|
+
setRef={(ref) => {
|
|
213
|
+
this.input = ref;
|
|
214
|
+
}}
|
|
199
215
|
/>
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
<div className={`${classes.drawableHeight} ${classes.centered}`}>
|
|
203
|
-
<label>Drag and drop or upload image from computer</label>
|
|
204
|
-
<br/>
|
|
205
|
-
<UploadControl
|
|
206
|
-
label="Upload Image"
|
|
207
|
-
onInputClick={this.handleInputClick}
|
|
208
|
-
onUploadImage={this.handleUploadImage}
|
|
209
|
-
setRef={(ref) => {
|
|
210
|
-
this.input = ref;
|
|
211
|
-
}}
|
|
212
|
-
/>
|
|
213
|
-
</div>
|
|
214
|
-
)}
|
|
216
|
+
</div>
|
|
217
|
+
)}
|
|
215
218
|
</div>
|
|
216
219
|
|
|
217
220
|
{imageUrl && (
|
|
@@ -219,60 +222,58 @@ export class Container extends Component {
|
|
|
219
222
|
{showTooltip && (
|
|
220
223
|
<div className={classes.tooltipContent}>
|
|
221
224
|
<label>
|
|
222
|
-
Click and drag to create a hotspot. Click the hotspot to mark correct. Click
|
|
223
|
-
again to unmark.
|
|
225
|
+
Click and drag to create a hotspot. Click the hotspot to mark correct. Click again to unmark.
|
|
224
226
|
</label>
|
|
225
|
-
<div className={classes.tooltipArrow}/>
|
|
227
|
+
<div className={classes.tooltipArrow} />
|
|
226
228
|
</div>
|
|
227
229
|
)}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
onMouseOut={this.toggleTooltip}
|
|
231
|
-
onMouseOver={this.toggleTooltip}
|
|
232
|
-
/>
|
|
230
|
+
|
|
231
|
+
<Help className={classes.icon} onMouseOut={this.toggleTooltip} onMouseOver={this.toggleTooltip} />
|
|
233
232
|
</div>
|
|
234
233
|
)}
|
|
235
234
|
</div>
|
|
236
235
|
</div>
|
|
237
|
-
|
|
238
236
|
);
|
|
239
237
|
}
|
|
240
238
|
}
|
|
241
239
|
|
|
242
|
-
const styles = theme => ({
|
|
240
|
+
const styles = (theme) => ({
|
|
243
241
|
base: {
|
|
244
|
-
marginTop: theme.spacing.unit * 2
|
|
242
|
+
marginTop: theme.spacing.unit * 2,
|
|
245
243
|
},
|
|
246
244
|
box: {
|
|
247
245
|
border: '1px solid #E0E1E6',
|
|
248
|
-
borderRadius: '5px'
|
|
246
|
+
borderRadius: '5px',
|
|
249
247
|
},
|
|
250
248
|
boxActive: {
|
|
251
|
-
border: '1px solid #0032C2'
|
|
249
|
+
border: '1px solid #0032C2',
|
|
250
|
+
},
|
|
251
|
+
boxError: {
|
|
252
|
+
border: '1px solid red',
|
|
252
253
|
},
|
|
253
254
|
centered: {
|
|
254
255
|
alignItems: 'center',
|
|
255
256
|
display: 'flex',
|
|
256
257
|
flexDirection: 'column',
|
|
257
|
-
justifyContent: 'center'
|
|
258
|
+
justifyContent: 'center',
|
|
258
259
|
},
|
|
259
260
|
drawableHeight: {
|
|
260
261
|
minHeight: 350,
|
|
261
|
-
paddingBottom:
|
|
262
|
-
paddingRight:
|
|
262
|
+
paddingBottom: theme.spacing.unit * 5,
|
|
263
|
+
paddingRight: theme.spacing.unit * 5,
|
|
263
264
|
},
|
|
264
265
|
icon: {
|
|
265
266
|
'&:hover': {
|
|
266
267
|
color: '#333131',
|
|
267
|
-
cursor: 'help'
|
|
268
|
+
cursor: 'help',
|
|
268
269
|
},
|
|
269
|
-
color: '#C1C1C1'
|
|
270
|
+
color: '#C1C1C1',
|
|
270
271
|
},
|
|
271
272
|
replaceButton: {
|
|
272
273
|
marginLeft: 0,
|
|
273
274
|
},
|
|
274
275
|
replaceSection: {
|
|
275
|
-
marginRight: 'auto'
|
|
276
|
+
marginRight: 'auto',
|
|
276
277
|
},
|
|
277
278
|
toolbar: {
|
|
278
279
|
backgroundColor: '#ECEDF1',
|
|
@@ -281,25 +282,25 @@ const styles = theme => ({
|
|
|
281
282
|
borderTopRightRadius: '5px',
|
|
282
283
|
display: 'flex',
|
|
283
284
|
justifyContent: 'flex-end',
|
|
284
|
-
padding:
|
|
285
|
+
padding: theme.spacing.unit,
|
|
285
286
|
},
|
|
286
287
|
tooltip: {
|
|
287
288
|
position: 'relative',
|
|
288
289
|
textAlign: 'right',
|
|
289
|
-
padding:
|
|
290
|
+
padding: theme.spacing.unit,
|
|
290
291
|
},
|
|
291
292
|
tooltipContent: {
|
|
292
293
|
background: '#333131',
|
|
293
294
|
borderRadius: '4px',
|
|
294
295
|
color: '#FFFFFF',
|
|
295
|
-
fontSize:
|
|
296
|
+
fontSize: theme.typography.fontSize,
|
|
296
297
|
lineHeight: '18px',
|
|
297
|
-
marginTop: '-
|
|
298
|
-
padding:
|
|
298
|
+
marginTop: '-60px',
|
|
299
|
+
padding: theme.spacing.unit,
|
|
299
300
|
position: 'absolute',
|
|
300
301
|
right: '5px',
|
|
301
302
|
textAlign: 'left',
|
|
302
|
-
width: '300px'
|
|
303
|
+
width: '300px',
|
|
303
304
|
},
|
|
304
305
|
tooltipArrow: {
|
|
305
306
|
width: 0,
|
|
@@ -308,10 +309,10 @@ const styles = theme => ({
|
|
|
308
309
|
borderRight: '10px solid transparent',
|
|
309
310
|
borderTop: '10px solid #333131',
|
|
310
311
|
marginBottom: -10,
|
|
311
|
-
marginTop: '
|
|
312
|
+
marginTop: '4px',
|
|
312
313
|
position: 'absolute',
|
|
313
|
-
right: '5px'
|
|
314
|
-
}
|
|
314
|
+
right: '5px',
|
|
315
|
+
},
|
|
315
316
|
});
|
|
316
317
|
|
|
317
318
|
Container.propTypes = {
|
|
@@ -326,14 +327,14 @@ Container.propTypes = {
|
|
|
326
327
|
outlineColor: PropTypes.string.isRequired,
|
|
327
328
|
shapes: PropTypes.shape({
|
|
328
329
|
rectangles: PropTypes.array,
|
|
329
|
-
polygons: PropTypes.array
|
|
330
|
+
polygons: PropTypes.array,
|
|
330
331
|
}).isRequired,
|
|
331
332
|
strokeWidth: PropTypes.number,
|
|
332
|
-
preserveAspectRatioEnabled: PropTypes.bool
|
|
333
|
+
preserveAspectRatioEnabled: PropTypes.bool,
|
|
333
334
|
};
|
|
335
|
+
|
|
334
336
|
Container.defaultProps = {
|
|
335
|
-
strokeWidth: 5
|
|
337
|
+
strokeWidth: 5,
|
|
336
338
|
};
|
|
337
339
|
|
|
338
|
-
|
|
339
340
|
export default withStyles(styles)(Container);
|
|
@@ -22,7 +22,7 @@ export class Drawable extends React.Component {
|
|
|
22
22
|
return {
|
|
23
23
|
...prevState,
|
|
24
24
|
dimensions: dimensions,
|
|
25
|
-
}
|
|
25
|
+
};
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
constructor(props) {
|
|
@@ -36,7 +36,7 @@ export class Drawable extends React.Component {
|
|
|
36
36
|
height: 0,
|
|
37
37
|
width: 0,
|
|
38
38
|
},
|
|
39
|
-
}
|
|
39
|
+
};
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/// start of handling HotSpots section
|
|
@@ -45,7 +45,7 @@ export class Drawable extends React.Component {
|
|
|
45
45
|
const { onUpdateShapes, shapes } = this.props;
|
|
46
46
|
// Add a new rectangle at the mouse position with 0 width and height
|
|
47
47
|
const newShapes = shapes.slice();
|
|
48
|
-
const value = max(newShapes.map(c => parseInt(c.id)).filter(id => !isNaN(id))) || 0;
|
|
48
|
+
const value = max(newShapes.map((c) => parseInt(c.id)).filter((id) => !isNaN(id))) || 0;
|
|
49
49
|
|
|
50
50
|
newShapes.push({
|
|
51
51
|
id: `${value + 1}`,
|
|
@@ -54,7 +54,7 @@ export class Drawable extends React.Component {
|
|
|
54
54
|
x: e.evt.layerX,
|
|
55
55
|
y: e.evt.layerY,
|
|
56
56
|
group: 'rectangles',
|
|
57
|
-
index: shapes.length
|
|
57
|
+
index: shapes.length,
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
this.setState({ isDrawing: true, isDrawingShapeId: `${value + 1}` });
|
|
@@ -86,7 +86,7 @@ export class Drawable extends React.Component {
|
|
|
86
86
|
const mouseX = e.evt.layerX;
|
|
87
87
|
const mouseY = e.evt.layerY;
|
|
88
88
|
|
|
89
|
-
const currShapeIndex = shapes.findIndex(shape => shape.id === isDrawingShapeId);
|
|
89
|
+
const currShapeIndex = shapes.findIndex((shape) => shape.id === isDrawingShapeId);
|
|
90
90
|
const currShape = shapes[currShapeIndex];
|
|
91
91
|
|
|
92
92
|
if (currShape) {
|
|
@@ -100,7 +100,7 @@ export class Drawable extends React.Component {
|
|
|
100
100
|
height: newHeight,
|
|
101
101
|
width: newWidth,
|
|
102
102
|
x: currShape.x,
|
|
103
|
-
y: currShape.y
|
|
103
|
+
y: currShape.y,
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
// On mouse move don't trigger any event. Put the shapes on this state instead.
|
|
@@ -111,12 +111,12 @@ export class Drawable extends React.Component {
|
|
|
111
111
|
|
|
112
112
|
handleOnDragEnd = (id, updatedProps) => {
|
|
113
113
|
const { shapes, onUpdateShapes } = this.props;
|
|
114
|
-
const newShapes = shapes.map(shape => {
|
|
114
|
+
const newShapes = shapes.map((shape) => {
|
|
115
115
|
if (shape.id === id) {
|
|
116
116
|
return {
|
|
117
117
|
...shape,
|
|
118
|
-
...updatedProps
|
|
119
|
-
}
|
|
118
|
+
...updatedProps,
|
|
119
|
+
};
|
|
120
120
|
}
|
|
121
121
|
return shape;
|
|
122
122
|
});
|
|
@@ -131,17 +131,17 @@ export class Drawable extends React.Component {
|
|
|
131
131
|
let newShapes = [];
|
|
132
132
|
|
|
133
133
|
if (multipleCorrect) {
|
|
134
|
-
newShapes = shapes.map(shape => {
|
|
134
|
+
newShapes = shapes.map((shape) => {
|
|
135
135
|
if (shape.id === id) {
|
|
136
136
|
shape.correct = !shape.correct;
|
|
137
137
|
}
|
|
138
138
|
return shape;
|
|
139
|
-
})
|
|
139
|
+
});
|
|
140
140
|
} else {
|
|
141
|
-
newShapes = shapes.map(shape => {
|
|
141
|
+
newShapes = shapes.map((shape) => {
|
|
142
142
|
shape.correct = shape.id === id;
|
|
143
143
|
return shape;
|
|
144
|
-
})
|
|
144
|
+
});
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
onUpdateShapes(cloneDeep(newShapes));
|
|
@@ -157,17 +157,18 @@ export class Drawable extends React.Component {
|
|
|
157
157
|
const newWidth = parseFloat(elementStyle.width);
|
|
158
158
|
const aspectWidth = newWidth / IMAGE_MAX_WIDTH;
|
|
159
159
|
|
|
160
|
-
const dimensions =
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
160
|
+
const dimensions =
|
|
161
|
+
newWidth > IMAGE_MAX_WIDTH
|
|
162
|
+
? {
|
|
163
|
+
height: newHeight / aspectWidth,
|
|
164
|
+
width: IMAGE_MAX_WIDTH,
|
|
165
|
+
}
|
|
166
|
+
: {
|
|
167
|
+
height: newHeight,
|
|
168
|
+
width: newWidth,
|
|
169
|
+
};
|
|
167
170
|
|
|
168
|
-
this.setState(
|
|
169
|
-
{ dimensions },
|
|
170
|
-
() => onUpdateImageDimension(dimensions));
|
|
171
|
+
this.setState({ dimensions }, () => onUpdateImageDimension(dimensions));
|
|
171
172
|
|
|
172
173
|
resizeHandle.addEventListener('mousedown', this.initialiseResize, false);
|
|
173
174
|
};
|
|
@@ -182,47 +183,43 @@ export class Drawable extends React.Component {
|
|
|
182
183
|
let drawable = true;
|
|
183
184
|
|
|
184
185
|
// Do not allow resizing over the hotspots
|
|
185
|
-
shapes &&
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
186
|
+
shapes &&
|
|
187
|
+
shapes.forEach((shape) => {
|
|
188
|
+
const right = shape.x + shape.width + 5;
|
|
189
|
+
const bottom = shape.y + shape.height + 5;
|
|
190
|
+
if (x <= right || y <= bottom) {
|
|
191
|
+
drawable = false;
|
|
192
|
+
}
|
|
193
|
+
});
|
|
192
194
|
return drawable;
|
|
193
195
|
}
|
|
194
196
|
|
|
195
197
|
startResizing = (e) => {
|
|
196
198
|
const bounds = e.target.getBoundingClientRect();
|
|
197
199
|
const box = this.image;
|
|
198
|
-
const {
|
|
199
|
-
disableDrag,
|
|
200
|
-
preserveAspectRatioEnabled,
|
|
201
|
-
dimensions,
|
|
202
|
-
shapes
|
|
203
|
-
} = this.props;
|
|
200
|
+
const { disableDrag, preserveAspectRatioEnabled, dimensions, shapes } = this.props;
|
|
204
201
|
|
|
205
202
|
// todo previously we had state.dimensions, is it needed?
|
|
206
203
|
const { width, height } = updateImageDimensions(
|
|
207
204
|
dimensions,
|
|
208
205
|
{
|
|
209
206
|
width: e.clientX - bounds.left,
|
|
210
|
-
height: e.clientY - bounds.top
|
|
207
|
+
height: e.clientY - bounds.top,
|
|
211
208
|
},
|
|
212
|
-
preserveAspectRatioEnabled
|
|
209
|
+
preserveAspectRatioEnabled,
|
|
213
210
|
);
|
|
214
211
|
|
|
215
212
|
const resizeValid = this.checkIfResizeValid(width, height);
|
|
216
213
|
const hasMinimumWidth = width > 150 && height > 150;
|
|
217
214
|
|
|
218
|
-
if (resizeValid && hasMinimumWidth) {
|
|
215
|
+
if (resizeValid && hasMinimumWidth && box) {
|
|
219
216
|
box.style.width = `${width}px`;
|
|
220
217
|
box.style.height = `${height}px`;
|
|
221
218
|
|
|
222
219
|
this.setState({
|
|
223
220
|
resizing: true,
|
|
224
221
|
dimensions: { height: height, width: width },
|
|
225
|
-
stateShapes: getUpdatedShapes(dimensions, { width, height }, shapes)
|
|
222
|
+
stateShapes: getUpdatedShapes(dimensions, { width, height }, shapes),
|
|
226
223
|
});
|
|
227
224
|
}
|
|
228
225
|
|
|
@@ -256,12 +253,12 @@ export class Drawable extends React.Component {
|
|
|
256
253
|
hotspotColor,
|
|
257
254
|
outlineColor,
|
|
258
255
|
shapes,
|
|
259
|
-
strokeWidth
|
|
256
|
+
strokeWidth,
|
|
260
257
|
} = this.props;
|
|
261
258
|
const {
|
|
262
259
|
stateShapes,
|
|
263
260
|
isDrawing,
|
|
264
|
-
dimensions: { height: heightFromState, width: widthFromState }
|
|
261
|
+
dimensions: { height: heightFromState, width: widthFromState },
|
|
265
262
|
} = this.state;
|
|
266
263
|
const shapesToUse = stateShapes || shapes;
|
|
267
264
|
|
|
@@ -272,15 +269,18 @@ export class Drawable extends React.Component {
|
|
|
272
269
|
<img
|
|
273
270
|
className={classes.image}
|
|
274
271
|
onLoad={this.handleOnImageLoad}
|
|
275
|
-
ref={ref => {
|
|
272
|
+
ref={(ref) => {
|
|
276
273
|
this.image = ref;
|
|
277
274
|
}}
|
|
278
275
|
src={imageUrl}
|
|
279
|
-
{...height && width ? { style: { height, width } } : {}}
|
|
276
|
+
{...(height && width ? { style: { height, width } } : {})}
|
|
277
|
+
/>
|
|
278
|
+
<div
|
|
279
|
+
ref={(ref) => {
|
|
280
|
+
this.resize = ref;
|
|
281
|
+
}}
|
|
282
|
+
className={classes.resize}
|
|
280
283
|
/>
|
|
281
|
-
<div ref={ref => {
|
|
282
|
-
this.resize = ref;
|
|
283
|
-
}} className={classes.resize}/>
|
|
284
284
|
</div>
|
|
285
285
|
)}
|
|
286
286
|
|
|
@@ -288,9 +288,9 @@ export class Drawable extends React.Component {
|
|
|
288
288
|
className={classes.stage}
|
|
289
289
|
height={heightFromState || height}
|
|
290
290
|
width={widthFromState || width}
|
|
291
|
-
onMouseDown={this.handleOnMouseDown
|
|
292
|
-
onMouseUp={this.handleOnMouseUp
|
|
293
|
-
onMouseMove={this.handleMouseMove
|
|
291
|
+
onMouseDown={this.handleOnMouseDown}
|
|
292
|
+
onMouseUp={this.handleOnMouseUp}
|
|
293
|
+
onMouseMove={this.handleMouseMove}
|
|
294
294
|
>
|
|
295
295
|
<Layer>
|
|
296
296
|
{shapesToUse.map((shape, index) => {
|
|
@@ -324,7 +324,7 @@ export class Drawable extends React.Component {
|
|
|
324
324
|
|
|
325
325
|
const styles = () => ({
|
|
326
326
|
base: {
|
|
327
|
-
position: 'relative'
|
|
327
|
+
position: 'relative',
|
|
328
328
|
},
|
|
329
329
|
image: {
|
|
330
330
|
alignItems: 'center',
|
|
@@ -333,7 +333,7 @@ const styles = () => ({
|
|
|
333
333
|
},
|
|
334
334
|
imageContainer: {
|
|
335
335
|
position: 'relative',
|
|
336
|
-
width: 'fit-content'
|
|
336
|
+
width: 'fit-content',
|
|
337
337
|
},
|
|
338
338
|
resize: {
|
|
339
339
|
borderBottom: '1px solid #727272',
|
|
@@ -343,13 +343,13 @@ const styles = () => ({
|
|
|
343
343
|
height: '10px',
|
|
344
344
|
position: 'absolute',
|
|
345
345
|
right: '-10px',
|
|
346
|
-
width: '10px'
|
|
346
|
+
width: '10px',
|
|
347
347
|
},
|
|
348
348
|
stage: {
|
|
349
349
|
left: 0,
|
|
350
350
|
top: 0,
|
|
351
|
-
position: 'absolute'
|
|
352
|
-
}
|
|
351
|
+
position: 'absolute',
|
|
352
|
+
},
|
|
353
353
|
});
|
|
354
354
|
|
|
355
355
|
Drawable.propTypes = {
|
|
@@ -365,7 +365,7 @@ Drawable.propTypes = {
|
|
|
365
365
|
outlineColor: PropTypes.string.isRequired,
|
|
366
366
|
shapes: PropTypes.array.isRequired,
|
|
367
367
|
strokeWidth: PropTypes.number,
|
|
368
|
-
preserveAspectRatioEnabled: PropTypes.bool
|
|
368
|
+
preserveAspectRatioEnabled: PropTypes.bool,
|
|
369
369
|
};
|
|
370
370
|
|
|
371
371
|
export default withStyles(styles)(Drawable);
|