@pie-element/hotspot 4.8.0 → 4.8.1-beta.587
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +474 -0
- package/configure/CHANGELOG.md +417 -0
- package/configure/lib/button.js.map +1 -1
- package/configure/lib/defaults.js +24 -2
- package/configure/lib/defaults.js.map +1 -1
- package/configure/lib/hotspot-container.js +44 -23
- 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 +133 -27
- package/configure/lib/root.js.map +1 -1
- package/configure/lib/upload-control.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 +2 -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 +36 -18
- package/configure/src/hotspot-container.jsx +107 -97
- package/configure/src/hotspot-drawable.jsx +59 -53
- 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 +120 -51
- package/configure/src/upload-control.jsx +9 -20
- package/configure/src/utils.js +51 -22
- package/controller/CHANGELOG.md +61 -0
- package/controller/lib/defaults.js +2 -2
- package/controller/lib/defaults.js.map +1 -1
- package/controller/lib/index.js +57 -9
- 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 +99 -55
- package/controller/src/defaults.js +5 -9
- package/controller/src/index.js +58 -34
- 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 +54 -35
- package/docs/demo/session.js +2 -2
- package/docs/pie-schema.json +59 -0
- package/docs/pie-schema.json.md +47 -0
- package/lib/hotspot/container.js +44 -7
- package/lib/hotspot/container.js.map +1 -1
- package/lib/hotspot/icons.js.map +1 -1
- package/lib/hotspot/image.js +35 -8
- 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 +51 -32
- package/lib/hotspot/polygon.js.map +1 -1
- package/lib/hotspot/rectangle.js +51 -32
- 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 +7 -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} +10 -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 +60 -23
- package/src/hotspot/icons.js +4 -2
- package/src/hotspot/image.jsx +26 -13
- package/src/hotspot/index.jsx +73 -33
- package/src/hotspot/polygon.jsx +51 -40
- package/src/hotspot/rectangle.jsx +51 -40
- 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 -76
- package/src/__tests__/rectangle-test.jsx +0 -77
|
@@ -6,14 +6,14 @@ import MenuItem from '@material-ui/core/MenuItem';
|
|
|
6
6
|
import { withStyles } from '@material-ui/core/styles';
|
|
7
7
|
|
|
8
8
|
class Palette extends React.Component {
|
|
9
|
-
onChange = (name) => event => {
|
|
9
|
+
onChange = (name) => (event) => {
|
|
10
10
|
const { value } = event.target;
|
|
11
11
|
const { onHotspotColorChange, onOutlineColorChange } = this.props;
|
|
12
12
|
|
|
13
13
|
if (name === 'hotspot') {
|
|
14
14
|
onHotspotColorChange(value);
|
|
15
15
|
} else {
|
|
16
|
-
onOutlineColorChange(value)
|
|
16
|
+
onOutlineColorChange(value);
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
19
|
|
|
@@ -23,18 +23,9 @@ class Palette extends React.Component {
|
|
|
23
23
|
return (
|
|
24
24
|
<div className={classes.base}>
|
|
25
25
|
<InputContainer label="Hot Spot" className={classes.input}>
|
|
26
|
-
<Select
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
value={hotspotColor}
|
|
30
|
-
>
|
|
31
|
-
{hotspotList.map(hotspot => (
|
|
32
|
-
<MenuItem
|
|
33
|
-
key={hotspot}
|
|
34
|
-
value={hotspot}
|
|
35
|
-
className={classes.item}
|
|
36
|
-
style={{ backgroundColor: hotspot }}
|
|
37
|
-
>
|
|
26
|
+
<Select className={classes.select} onChange={this.onChange('hotspot')} value={hotspotColor}>
|
|
27
|
+
{hotspotList.map((hotspot) => (
|
|
28
|
+
<MenuItem key={hotspot} value={hotspot} className={classes.item} style={{ backgroundColor: hotspot }}>
|
|
38
29
|
{hotspot}
|
|
39
30
|
</MenuItem>
|
|
40
31
|
))}
|
|
@@ -42,12 +33,8 @@ class Palette extends React.Component {
|
|
|
42
33
|
</InputContainer>
|
|
43
34
|
|
|
44
35
|
<InputContainer label="Response Outline" className={classes.input}>
|
|
45
|
-
<Select
|
|
46
|
-
|
|
47
|
-
onChange={this.onChange('outline')}
|
|
48
|
-
value={outlineColor}
|
|
49
|
-
>
|
|
50
|
-
{outlineList.map(outline => (
|
|
36
|
+
<Select className={classes.select} onChange={this.onChange('outline')} value={outlineColor}>
|
|
37
|
+
{outlineList.map((outline) => (
|
|
51
38
|
<MenuItem
|
|
52
39
|
key={outline}
|
|
53
40
|
value={outline}
|
|
@@ -64,21 +51,21 @@ class Palette extends React.Component {
|
|
|
64
51
|
}
|
|
65
52
|
}
|
|
66
53
|
|
|
67
|
-
const styles = theme => ({
|
|
54
|
+
const styles = (theme) => ({
|
|
68
55
|
base: {
|
|
69
56
|
marginTop: theme.spacing.unit * 2,
|
|
70
|
-
display: 'flex'
|
|
57
|
+
display: 'flex',
|
|
71
58
|
},
|
|
72
59
|
input: {
|
|
73
60
|
flex: 1,
|
|
74
|
-
width: '90%'
|
|
61
|
+
width: '90%',
|
|
75
62
|
},
|
|
76
63
|
item: {
|
|
77
64
|
borderRadius: '2px',
|
|
78
65
|
height: '22px',
|
|
79
66
|
marginLeft: theme.spacing.unit * 2,
|
|
80
67
|
marginRight: theme.spacing.unit * 2,
|
|
81
|
-
marginTop: theme.spacing.unit * 2
|
|
68
|
+
marginTop: theme.spacing.unit * 2,
|
|
82
69
|
},
|
|
83
70
|
});
|
|
84
71
|
|
|
@@ -89,7 +76,7 @@ Palette.propTypes = {
|
|
|
89
76
|
onHotspotColorChange: PropTypes.func.isRequired,
|
|
90
77
|
onOutlineColorChange: PropTypes.func.isRequired,
|
|
91
78
|
outlineColor: PropTypes.string.isRequired,
|
|
92
|
-
outlineList: PropTypes.array.isRequired
|
|
79
|
+
outlineList: PropTypes.array.isRequired,
|
|
93
80
|
};
|
|
94
81
|
|
|
95
82
|
export default withStyles(styles)(Palette);
|
|
@@ -6,8 +6,8 @@ import { withStyles } from '@material-ui/core/styles/index';
|
|
|
6
6
|
class PolComponent extends React.Component {
|
|
7
7
|
static getDerivedStateFromProps(nextProps) {
|
|
8
8
|
const { points } = nextProps;
|
|
9
|
-
const xList = points.map(p =>
|
|
10
|
-
const yList = points.map(p =>
|
|
9
|
+
const xList = points.map((p) => p.x);
|
|
10
|
+
const yList = points.map((p) => p.y);
|
|
11
11
|
|
|
12
12
|
const xOffset = Math.min(...xList);
|
|
13
13
|
const yOffset = Math.max(...yList);
|
|
@@ -16,14 +16,16 @@ class PolComponent extends React.Component {
|
|
|
16
16
|
return {
|
|
17
17
|
x: xOffset,
|
|
18
18
|
y: yOffset,
|
|
19
|
-
points: points.reduce((acc, point) => {
|
|
19
|
+
points: points.reduce((acc, point) => {
|
|
20
|
+
return acc.concat([point.x - xOffset, point.y - yOffset]);
|
|
21
|
+
}, []),
|
|
20
22
|
};
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
return {
|
|
24
26
|
x: 0,
|
|
25
27
|
y: 0,
|
|
26
|
-
points: []
|
|
28
|
+
points: [],
|
|
27
29
|
};
|
|
28
30
|
}
|
|
29
31
|
|
|
@@ -31,8 +33,8 @@ class PolComponent extends React.Component {
|
|
|
31
33
|
|
|
32
34
|
handleClick = (e) => {
|
|
33
35
|
const { points } = this.props;
|
|
34
|
-
const xList = points.map(p =>
|
|
35
|
-
const yList = points.map(p =>
|
|
36
|
+
const xList = points.map((p) => p.x);
|
|
37
|
+
const yList = points.map((p) => p.y);
|
|
36
38
|
|
|
37
39
|
const width = Math.max(...xList) - Math.min(...xList);
|
|
38
40
|
const height = Math.max(...yList) - Math.min(...yList);
|
|
@@ -63,7 +65,7 @@ class PolComponent extends React.Component {
|
|
|
63
65
|
if (index % 2 === 0 && index + 1 < points.length) {
|
|
64
66
|
acc.push({
|
|
65
67
|
x: currentPointCoordinate + e.target.x(),
|
|
66
|
-
y: points[index + 1]
|
|
68
|
+
y: points[index + 1] + e.target.y(),
|
|
67
69
|
});
|
|
68
70
|
|
|
69
71
|
return acc;
|
|
@@ -73,18 +75,12 @@ class PolComponent extends React.Component {
|
|
|
73
75
|
}, []);
|
|
74
76
|
|
|
75
77
|
onDragEnd(id, {
|
|
76
|
-
points: newPoints
|
|
77
|
-
})
|
|
78
|
+
points: newPoints,
|
|
79
|
+
});
|
|
78
80
|
};
|
|
79
81
|
|
|
80
82
|
render() {
|
|
81
|
-
const {
|
|
82
|
-
classes,
|
|
83
|
-
correct,
|
|
84
|
-
hotspotColor,
|
|
85
|
-
outlineColor,
|
|
86
|
-
strokeWidth = 5
|
|
87
|
-
} = this.props;
|
|
83
|
+
const { classes, correct, hotspotColor, outlineColor, strokeWidth = 5 } = this.props;
|
|
88
84
|
const { points, x, y } = this.state;
|
|
89
85
|
|
|
90
86
|
return (
|
|
@@ -113,7 +109,7 @@ class PolComponent extends React.Component {
|
|
|
113
109
|
const styles = () => ({
|
|
114
110
|
base: {
|
|
115
111
|
cursor: 'pointer',
|
|
116
|
-
opacity: 0.5
|
|
112
|
+
opacity: 0.5,
|
|
117
113
|
},
|
|
118
114
|
});
|
|
119
115
|
|
|
@@ -126,11 +122,13 @@ PolComponent.propTypes = {
|
|
|
126
122
|
onClick: PropTypes.func.isRequired,
|
|
127
123
|
onDragEnd: PropTypes.func.isRequired,
|
|
128
124
|
outlineColor: PropTypes.string.isRequired,
|
|
129
|
-
points: PropTypes.arrayOf(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
125
|
+
points: PropTypes.arrayOf(
|
|
126
|
+
PropTypes.shape({
|
|
127
|
+
x: PropTypes.number,
|
|
128
|
+
y: PropTypes.number,
|
|
129
|
+
}),
|
|
130
|
+
).isRequired,
|
|
131
|
+
strokeWidth: PropTypes.number,
|
|
134
132
|
};
|
|
135
133
|
|
|
136
134
|
PolComponent.defaultProps = {
|
|
@@ -26,22 +26,12 @@ class RectComponent extends React.Component {
|
|
|
26
26
|
|
|
27
27
|
onDragEnd(id, {
|
|
28
28
|
x: e.target.x(),
|
|
29
|
-
y: e.target.y()
|
|
30
|
-
})
|
|
29
|
+
y: e.target.y(),
|
|
30
|
+
});
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
render() {
|
|
34
|
-
const {
|
|
35
|
-
classes,
|
|
36
|
-
correct,
|
|
37
|
-
height,
|
|
38
|
-
hotspotColor,
|
|
39
|
-
outlineColor,
|
|
40
|
-
width,
|
|
41
|
-
x,
|
|
42
|
-
y,
|
|
43
|
-
strokeWidth = 5
|
|
44
|
-
} = this.props;
|
|
34
|
+
const { classes, correct, height, hotspotColor, outlineColor, width, x, y, strokeWidth = 5 } = this.props;
|
|
45
35
|
|
|
46
36
|
return (
|
|
47
37
|
<Group>
|
|
@@ -69,7 +59,7 @@ class RectComponent extends React.Component {
|
|
|
69
59
|
const styles = () => ({
|
|
70
60
|
base: {
|
|
71
61
|
cursor: 'pointer',
|
|
72
|
-
opacity: 0.5
|
|
62
|
+
opacity: 0.5,
|
|
73
63
|
},
|
|
74
64
|
});
|
|
75
65
|
|
|
@@ -86,7 +76,7 @@ RectComponent.propTypes = {
|
|
|
86
76
|
width: PropTypes.number.isRequired,
|
|
87
77
|
x: PropTypes.number.isRequired,
|
|
88
78
|
y: PropTypes.number.isRequired,
|
|
89
|
-
strokeWidth: PropTypes.number
|
|
79
|
+
strokeWidth: PropTypes.number,
|
|
90
80
|
};
|
|
91
81
|
|
|
92
82
|
RectComponent.defaultProps = {
|
package/configure/src/index.js
CHANGED
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
ModelUpdatedEvent,
|
|
6
6
|
DeleteImageEvent,
|
|
7
7
|
InsertImageEvent,
|
|
8
|
+
InsertSoundEvent,
|
|
9
|
+
DeleteSoundEvent,
|
|
8
10
|
} from '@pie-framework/pie-configure-events';
|
|
9
11
|
|
|
10
12
|
import Root from './root';
|
|
@@ -18,7 +20,7 @@ export default class HotspotConfigure extends HTMLElement {
|
|
|
18
20
|
...model,
|
|
19
21
|
hotspotList: model.hotspotList || [model.hotspotColor] || sensibleDefaults.model.hotspotList,
|
|
20
22
|
outlineList: model.outlineList || [model.outlineColor] || sensibleDefaults.model.outlineList,
|
|
21
|
-
shapes: model.shapes || sensibleDefaults.model.shapes || {}
|
|
23
|
+
shapes: model.shapes || sensibleDefaults.model.shapes || {},
|
|
22
24
|
});
|
|
23
25
|
|
|
24
26
|
constructor() {
|
|
@@ -61,8 +63,8 @@ export default class HotspotConfigure extends HTMLElement {
|
|
|
61
63
|
if (propertyType === 'multipleCorrect') {
|
|
62
64
|
const { rectangles = [], polygons = [] } = _model.shapes || {};
|
|
63
65
|
|
|
64
|
-
_model.shapes.rectangles = rectangles.map(shape => ({ ...shape, correct: false }));
|
|
65
|
-
_model.shapes.polygons = polygons.map(shape => ({ ...shape, correct: false }));
|
|
66
|
+
_model.shapes.rectangles = rectangles.map((shape) => ({ ...shape, correct: false }));
|
|
67
|
+
_model.shapes.polygons = polygons.map((shape) => ({ ...shape, correct: false }));
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
this.onModelChanged(_model);
|
|
@@ -71,53 +73,53 @@ export default class HotspotConfigure extends HTMLElement {
|
|
|
71
73
|
onColorChanged = (colorType, color) => {
|
|
72
74
|
this.onModelChanged({
|
|
73
75
|
...this._model,
|
|
74
|
-
[colorType]: color
|
|
76
|
+
[colorType]: color,
|
|
75
77
|
});
|
|
76
78
|
};
|
|
77
79
|
|
|
78
|
-
onPromptChanged = prompt => {
|
|
80
|
+
onPromptChanged = (prompt) => {
|
|
79
81
|
this.onModelChanged({
|
|
80
82
|
...this._model,
|
|
81
|
-
prompt
|
|
83
|
+
prompt,
|
|
82
84
|
});
|
|
83
85
|
};
|
|
84
86
|
|
|
85
|
-
onRationaleChanged = rationale => {
|
|
87
|
+
onRationaleChanged = (rationale) => {
|
|
86
88
|
this.onModelChanged({
|
|
87
89
|
...this._model,
|
|
88
|
-
rationale
|
|
90
|
+
rationale,
|
|
89
91
|
});
|
|
90
92
|
};
|
|
91
93
|
|
|
92
|
-
onTeacherInstructionsChanged = teacherInstructions => {
|
|
94
|
+
onTeacherInstructionsChanged = (teacherInstructions) => {
|
|
93
95
|
this.onModelChanged({
|
|
94
96
|
...this._model,
|
|
95
|
-
teacherInstructions
|
|
97
|
+
teacherInstructions,
|
|
96
98
|
});
|
|
97
99
|
};
|
|
98
100
|
|
|
99
|
-
onUpdateImageDimension = dimensions => {
|
|
101
|
+
onUpdateImageDimension = (dimensions) => {
|
|
100
102
|
this.onModelChanged({
|
|
101
103
|
...this._model,
|
|
102
|
-
dimensions
|
|
104
|
+
dimensions,
|
|
103
105
|
});
|
|
104
106
|
};
|
|
105
107
|
|
|
106
|
-
onUpdateShapes = shapes => {
|
|
108
|
+
onUpdateShapes = (shapes) => {
|
|
107
109
|
this.onModelChanged({
|
|
108
110
|
...this._model,
|
|
109
|
-
shapes
|
|
111
|
+
shapes,
|
|
110
112
|
});
|
|
111
113
|
};
|
|
112
114
|
|
|
113
|
-
onImageUpload = imageUrl => {
|
|
115
|
+
onImageUpload = (imageUrl) => {
|
|
114
116
|
this.onModelChanged({
|
|
115
117
|
...this._model,
|
|
116
|
-
imageUrl
|
|
118
|
+
imageUrl,
|
|
117
119
|
});
|
|
118
120
|
};
|
|
119
121
|
|
|
120
|
-
insertImage = handler => {
|
|
122
|
+
insertImage = (handler) => {
|
|
121
123
|
this.dispatchEvent(new InsertImageEvent(handler));
|
|
122
124
|
};
|
|
123
125
|
|
|
@@ -125,6 +127,14 @@ export default class HotspotConfigure extends HTMLElement {
|
|
|
125
127
|
this.dispatchEvent(new DeleteImageEvent(src, done));
|
|
126
128
|
};
|
|
127
129
|
|
|
130
|
+
insertSound(handler) {
|
|
131
|
+
this.dispatchEvent(new InsertSoundEvent(handler));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
onDeleteSound(src, done) {
|
|
135
|
+
this.dispatchEvent(new DeleteSoundEvent(src, done));
|
|
136
|
+
}
|
|
137
|
+
|
|
128
138
|
_render() {
|
|
129
139
|
log('_render');
|
|
130
140
|
let element = React.createElement(Root, {
|
|
@@ -138,7 +148,11 @@ export default class HotspotConfigure extends HTMLElement {
|
|
|
138
148
|
onUpdateImageDimension: this.onUpdateImageDimension,
|
|
139
149
|
imageSupport: {
|
|
140
150
|
add: this.insertImage,
|
|
141
|
-
delete: this.onDeleteImage
|
|
151
|
+
delete: this.onDeleteImage,
|
|
152
|
+
},
|
|
153
|
+
uploadSoundSupport: {
|
|
154
|
+
add: this.insertSound.bind(this),
|
|
155
|
+
delete: this.onDeleteSound.bind(this),
|
|
142
156
|
},
|
|
143
157
|
onUpdateShapes: this.onUpdateShapes,
|
|
144
158
|
onModelChangedByConfig: this.onModelChangedByConfig,
|
package/configure/src/root.jsx
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
settings,
|
|
4
|
-
layout,
|
|
5
|
-
InputContainer,
|
|
6
|
-
NumberTextField
|
|
7
|
-
} from '@pie-lib/config-ui';
|
|
2
|
+
import { settings, layout, InputContainer, NumberTextField } from '@pie-lib/config-ui';
|
|
8
3
|
import PropTypes from 'prop-types';
|
|
9
4
|
import EditableHtml from '@pie-lib/editable-html';
|
|
10
|
-
import Typography from '@material-ui/core/Typography';
|
|
11
5
|
import { withStyles } from '@material-ui/core/styles';
|
|
12
|
-
|
|
6
|
+
import Typography from '@material-ui/core/Typography';
|
|
7
|
+
import Info from '@material-ui/icons/Info';
|
|
8
|
+
import Tooltip from '@material-ui/core/Tooltip';
|
|
13
9
|
import HotspotPalette from './hotspot-palette';
|
|
14
10
|
import HotspotContainer from './hotspot-container';
|
|
15
|
-
import
|
|
11
|
+
import classNames from 'classnames';
|
|
12
|
+
import { updateImageDimensions, generateValidationMessage, getUpdatedShapes, getAllShapes, groupShapes } from './utils';
|
|
16
13
|
|
|
17
14
|
const { Panel, toggle } = settings;
|
|
18
15
|
|
|
@@ -39,7 +36,7 @@ export class Root extends React.Component {
|
|
|
39
36
|
dimensions,
|
|
40
37
|
nextImageDimensions,
|
|
41
38
|
preserveAspectRatio.enabled,
|
|
42
|
-
resizeType
|
|
39
|
+
resizeType,
|
|
43
40
|
);
|
|
44
41
|
// transform shapes map into shapes array
|
|
45
42
|
const shapesArray = getAllShapes(shapes);
|
|
@@ -57,6 +54,7 @@ export class Root extends React.Component {
|
|
|
57
54
|
configuration,
|
|
58
55
|
model,
|
|
59
56
|
imageSupport,
|
|
57
|
+
uploadSoundSupport,
|
|
60
58
|
onConfigurationChanged,
|
|
61
59
|
onImageUpload,
|
|
62
60
|
onModelChangedByConfig,
|
|
@@ -64,21 +62,55 @@ export class Root extends React.Component {
|
|
|
64
62
|
onRationaleChanged,
|
|
65
63
|
onUpdateImageDimension,
|
|
66
64
|
onTeacherInstructionsChanged,
|
|
67
|
-
onUpdateShapes
|
|
65
|
+
onUpdateShapes,
|
|
68
66
|
} = this.props;
|
|
69
67
|
const {
|
|
68
|
+
maxImageWidth = {},
|
|
69
|
+
maxImageHeight = {},
|
|
70
70
|
multipleCorrect = {},
|
|
71
71
|
partialScoring = {},
|
|
72
|
+
preserveAspectRatio = {},
|
|
72
73
|
prompt = {},
|
|
73
|
-
teacherInstructions = {},
|
|
74
74
|
rationale = {},
|
|
75
|
-
|
|
75
|
+
settingsPanelDisabled,
|
|
76
|
+
spellCheck = {},
|
|
77
|
+
teacherInstructions = {},
|
|
78
|
+
withRubric = {},
|
|
76
79
|
} = configuration || {};
|
|
77
|
-
const {
|
|
80
|
+
const {
|
|
81
|
+
errors,
|
|
82
|
+
promptEnabled,
|
|
83
|
+
rationaleEnabled,
|
|
84
|
+
spellCheckEnabled,
|
|
85
|
+
teacherInstructionsEnabled,
|
|
86
|
+
toolbarEditorPosition,
|
|
87
|
+
} = model || {};
|
|
88
|
+
const { shapesError, selectionsError } = errors || {};
|
|
89
|
+
const validationMessage = generateValidationMessage(configuration);
|
|
90
|
+
|
|
91
|
+
const defaultImageMaxWidth = maxImageWidth && maxImageWidth.prompt;
|
|
92
|
+
const defaultImageMaxHeight = maxImageHeight && maxImageHeight.prompt;
|
|
93
|
+
|
|
94
|
+
const toolbarOpts = {
|
|
95
|
+
position: toolbarEditorPosition === 'top' ? 'top' : 'bottom',
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const panelSettings = {
|
|
99
|
+
multipleCorrect: multipleCorrect.settings && toggle(multipleCorrect.label),
|
|
100
|
+
partialScoring: partialScoring.settings && toggle(partialScoring.label),
|
|
101
|
+
promptEnabled: prompt.settings && toggle(prompt.label),
|
|
102
|
+
};
|
|
103
|
+
const panelProperties = {
|
|
104
|
+
teacherInstructionsEnabled: teacherInstructions.settings && toggle(teacherInstructions.label),
|
|
105
|
+
rationaleEnabled: rationale.settings && toggle(rationale.label),
|
|
106
|
+
spellCheckEnabled: spellCheck.settings && toggle(spellCheck.label),
|
|
107
|
+
rubricEnabled: withRubric?.settings && toggle(withRubric?.label),
|
|
108
|
+
};
|
|
78
109
|
|
|
79
110
|
return (
|
|
80
111
|
<div className={classes.base}>
|
|
81
112
|
<layout.ConfigLayout
|
|
113
|
+
hideSettings={settingsPanelDisabled}
|
|
82
114
|
settings={
|
|
83
115
|
<Panel
|
|
84
116
|
model={model}
|
|
@@ -86,19 +118,8 @@ export class Root extends React.Component {
|
|
|
86
118
|
configuration={configuration}
|
|
87
119
|
onChangeConfiguration={onConfigurationChanged}
|
|
88
120
|
groups={{
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
multipleCorrect.settings && toggle(multipleCorrect.label),
|
|
92
|
-
partialScoring:
|
|
93
|
-
partialScoring.settings && toggle(partialScoring.label),
|
|
94
|
-
promptEnabled:
|
|
95
|
-
prompt.settings && toggle(prompt.label),
|
|
96
|
-
},
|
|
97
|
-
Properties: {
|
|
98
|
-
teacherInstructionsEnabled:
|
|
99
|
-
teacherInstructions.settings && toggle(teacherInstructions.label),
|
|
100
|
-
rationaleEnabled: rationale.settings && toggle(rationale.label)
|
|
101
|
-
}
|
|
121
|
+
Settings: panelSettings,
|
|
122
|
+
Properties: panelProperties,
|
|
102
123
|
}}
|
|
103
124
|
/>
|
|
104
125
|
}
|
|
@@ -111,9 +132,16 @@ export class Root extends React.Component {
|
|
|
111
132
|
onChange={onTeacherInstructionsChanged}
|
|
112
133
|
imageSupport={imageSupport}
|
|
113
134
|
nonEmpty={false}
|
|
135
|
+
toolbarOpts={toolbarOpts}
|
|
136
|
+
spellCheck={spellCheckEnabled}
|
|
137
|
+
maxImageWidth={(maxImageWidth && maxImageWidth.teacherInstructions) || defaultImageMaxWidth}
|
|
138
|
+
maxImageHeight={(maxImageHeight && maxImageHeight.teacherInstructions) || defaultImageMaxHeight}
|
|
139
|
+
uploadSoundSupport={uploadSoundSupport}
|
|
140
|
+
languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
|
|
114
141
|
/>
|
|
115
142
|
</InputContainer>
|
|
116
143
|
)}
|
|
144
|
+
|
|
117
145
|
{promptEnabled && (
|
|
118
146
|
<InputContainer label={prompt.label} className={classes.prompt}>
|
|
119
147
|
<EditableHtml
|
|
@@ -121,44 +149,61 @@ export class Root extends React.Component {
|
|
|
121
149
|
onChange={onPromptChanged}
|
|
122
150
|
imageSupport={imageSupport}
|
|
123
151
|
nonEmpty={false}
|
|
152
|
+
toolbarOpts={toolbarOpts}
|
|
153
|
+
spellCheck={spellCheckEnabled}
|
|
154
|
+
maxImageWidth={defaultImageMaxWidth}
|
|
155
|
+
maxImageHeight={defaultImageMaxHeight}
|
|
156
|
+
uploadSoundSupport={uploadSoundSupport}
|
|
157
|
+
languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
|
|
124
158
|
/>
|
|
125
159
|
</InputContainer>
|
|
126
160
|
)}
|
|
127
161
|
|
|
128
162
|
{rationaleEnabled && (
|
|
129
|
-
<InputContainer
|
|
130
|
-
label={rationale.label}
|
|
131
|
-
className={classes.prompt}
|
|
132
|
-
>
|
|
163
|
+
<InputContainer label={rationale.label} className={classes.prompt}>
|
|
133
164
|
<EditableHtml
|
|
134
165
|
markup={model.rationale || ''}
|
|
135
166
|
onChange={onRationaleChanged}
|
|
136
167
|
imageSupport={imageSupport}
|
|
168
|
+
toolbarOpts={toolbarOpts}
|
|
169
|
+
spellCheck={spellCheckEnabled}
|
|
170
|
+
maxImageWidth={(maxImageWidth && maxImageWidth.rationale) || defaultImageMaxWidth}
|
|
171
|
+
maxImageHeight={(maxImageHeight && maxImageHeight.rationale) || defaultImageMaxHeight}
|
|
172
|
+
uploadSoundSupport={uploadSoundSupport}
|
|
173
|
+
languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
|
|
137
174
|
/>
|
|
138
175
|
</InputContainer>
|
|
139
176
|
)}
|
|
140
177
|
|
|
141
|
-
<
|
|
142
|
-
|
|
143
|
-
|
|
178
|
+
<div className={classNames(classes.label, classes.flexContainer)}>
|
|
179
|
+
<Typography className={classes.subheading} variant="subheading">
|
|
180
|
+
Define Hotspot
|
|
181
|
+
</Typography>
|
|
182
|
+
<Tooltip
|
|
183
|
+
classes={{ tooltip: classes.tooltip }}
|
|
184
|
+
disableFocusListener
|
|
185
|
+
disableTouchListener
|
|
186
|
+
placement={'left'}
|
|
187
|
+
title={validationMessage}
|
|
188
|
+
>
|
|
189
|
+
<Info fontSize={'small'} color={'primary'} style={{ float: 'right' }} />
|
|
190
|
+
</Tooltip>
|
|
191
|
+
</div>
|
|
144
192
|
|
|
145
193
|
<HotspotPalette
|
|
146
194
|
hotspotColor={model.hotspotColor}
|
|
147
195
|
hotspotList={model.hotspotList}
|
|
148
196
|
outlineColor={model.outlineColor}
|
|
149
197
|
outlineList={model.outlineList}
|
|
150
|
-
onHotspotColorChange={color =>
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
onOutlineColorChange={color =>
|
|
154
|
-
this.handleColorChange('outline', color)
|
|
155
|
-
}
|
|
198
|
+
onHotspotColorChange={(color) => this.handleColorChange('hotspot', color)}
|
|
199
|
+
onOutlineColorChange={(color) => this.handleColorChange('outline', color)}
|
|
156
200
|
/>
|
|
157
201
|
|
|
158
202
|
<HotspotContainer
|
|
159
203
|
dimensions={model.dimensions}
|
|
160
204
|
imageUrl={model.imageUrl}
|
|
161
205
|
multipleCorrect={model.multipleCorrect}
|
|
206
|
+
hasErrors={!!shapesError || !!selectionsError}
|
|
162
207
|
hotspotColor={model.hotspotColor}
|
|
163
208
|
outlineColor={model.outlineColor}
|
|
164
209
|
onUpdateImageDimension={onUpdateImageDimension}
|
|
@@ -168,6 +213,8 @@ export class Root extends React.Component {
|
|
|
168
213
|
strokeWidth={model.strokeWidth}
|
|
169
214
|
preserveAspectRatioEnabled={preserveAspectRatio.enabled}
|
|
170
215
|
/>
|
|
216
|
+
{shapesError && <div className={classes.errorText}>{shapesError}</div>}
|
|
217
|
+
{selectionsError && <div className={classes.errorText}>{selectionsError}</div>}
|
|
171
218
|
|
|
172
219
|
{model.imageUrl && (
|
|
173
220
|
<div>
|
|
@@ -185,6 +232,7 @@ export class Root extends React.Component {
|
|
|
185
232
|
showErrorWhenOutsideRange
|
|
186
233
|
className={classes.field}
|
|
187
234
|
/>
|
|
235
|
+
|
|
188
236
|
<NumberTextField
|
|
189
237
|
key="hotspot-manual-height"
|
|
190
238
|
label="Height"
|
|
@@ -204,35 +252,52 @@ export class Root extends React.Component {
|
|
|
204
252
|
}
|
|
205
253
|
}
|
|
206
254
|
|
|
207
|
-
const styles = theme => ({
|
|
255
|
+
const styles = (theme) => ({
|
|
208
256
|
base: {
|
|
209
|
-
marginTop: theme.spacing.unit * 3
|
|
257
|
+
marginTop: theme.spacing.unit * 3,
|
|
210
258
|
},
|
|
211
259
|
container: {
|
|
212
260
|
display: 'flex',
|
|
213
|
-
marginTop: theme.spacing.unit
|
|
261
|
+
marginTop: theme.spacing.unit,
|
|
214
262
|
},
|
|
215
263
|
dimensions: {
|
|
216
|
-
display: 'flex'
|
|
264
|
+
display: 'flex',
|
|
217
265
|
},
|
|
218
266
|
field: {
|
|
219
267
|
flex: 1,
|
|
220
|
-
width: '90%'
|
|
268
|
+
width: '90%',
|
|
221
269
|
},
|
|
222
270
|
label: {
|
|
223
|
-
marginTop: theme.spacing.unit * 4
|
|
271
|
+
marginTop: theme.spacing.unit * 4,
|
|
224
272
|
},
|
|
225
273
|
prompt: {
|
|
226
274
|
paddingTop: theme.spacing.unit * 2,
|
|
227
|
-
width: '100%'
|
|
275
|
+
width: '100%',
|
|
276
|
+
},
|
|
277
|
+
subheading: {
|
|
278
|
+
marginRight: theme.spacing.unit,
|
|
228
279
|
},
|
|
229
280
|
regular: {
|
|
230
|
-
marginBottom: theme.spacing.unit * 3
|
|
281
|
+
marginBottom: theme.spacing.unit * 3,
|
|
231
282
|
},
|
|
232
283
|
switchElement: {
|
|
233
284
|
justifyContent: 'space-between',
|
|
234
|
-
margin: 0
|
|
235
|
-
}
|
|
285
|
+
margin: 0,
|
|
286
|
+
},
|
|
287
|
+
flexContainer: {
|
|
288
|
+
display: 'flex',
|
|
289
|
+
alignItems: 'center',
|
|
290
|
+
},
|
|
291
|
+
tooltip: {
|
|
292
|
+
fontSize: '12px',
|
|
293
|
+
whiteSpace: 'pre',
|
|
294
|
+
maxWidth: '500px',
|
|
295
|
+
},
|
|
296
|
+
errorText: {
|
|
297
|
+
fontSize: '12px',
|
|
298
|
+
color: theme.palette.error.main,
|
|
299
|
+
paddingTop: theme.spacing.unit,
|
|
300
|
+
},
|
|
236
301
|
});
|
|
237
302
|
|
|
238
303
|
Root.propTypes = {
|
|
@@ -241,7 +306,11 @@ Root.propTypes = {
|
|
|
241
306
|
model: PropTypes.object.isRequired,
|
|
242
307
|
imageSupport: PropTypes.shape({
|
|
243
308
|
add: PropTypes.func,
|
|
244
|
-
delete: PropTypes.func
|
|
309
|
+
delete: PropTypes.func,
|
|
310
|
+
}),
|
|
311
|
+
uploadSoundSupport: PropTypes.shape({
|
|
312
|
+
add: PropTypes.func,
|
|
313
|
+
delete: PropTypes.func,
|
|
245
314
|
}),
|
|
246
315
|
onImageUpload: PropTypes.func.isRequired,
|
|
247
316
|
onColorChanged: PropTypes.func.isRequired,
|