@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
|
@@ -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,31 +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 {
|
|
78
|
-
|
|
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
|
+
};
|
|
79
97
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
+
};
|
|
88
109
|
|
|
89
110
|
return (
|
|
90
111
|
<div className={classes.base}>
|
|
91
112
|
<layout.ConfigLayout
|
|
113
|
+
hideSettings={settingsPanelDisabled}
|
|
92
114
|
settings={
|
|
93
115
|
<Panel
|
|
94
116
|
model={model}
|
|
@@ -96,19 +118,8 @@ export class Root extends React.Component {
|
|
|
96
118
|
configuration={configuration}
|
|
97
119
|
onChangeConfiguration={onConfigurationChanged}
|
|
98
120
|
groups={{
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
multipleCorrect.settings && toggle(multipleCorrect.label),
|
|
102
|
-
partialScoring:
|
|
103
|
-
partialScoring.settings && toggle(partialScoring.label),
|
|
104
|
-
promptEnabled:
|
|
105
|
-
prompt.settings && toggle(prompt.label),
|
|
106
|
-
},
|
|
107
|
-
Properties: {
|
|
108
|
-
teacherInstructionsEnabled:
|
|
109
|
-
teacherInstructions.settings && toggle(teacherInstructions.label),
|
|
110
|
-
rationaleEnabled: rationale.settings && toggle(rationale.label)
|
|
111
|
-
}
|
|
121
|
+
Settings: panelSettings,
|
|
122
|
+
Properties: panelProperties,
|
|
112
123
|
}}
|
|
113
124
|
/>
|
|
114
125
|
}
|
|
@@ -122,9 +133,15 @@ export class Root extends React.Component {
|
|
|
122
133
|
imageSupport={imageSupport}
|
|
123
134
|
nonEmpty={false}
|
|
124
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' }]}
|
|
125
141
|
/>
|
|
126
142
|
</InputContainer>
|
|
127
143
|
)}
|
|
144
|
+
|
|
128
145
|
{promptEnabled && (
|
|
129
146
|
<InputContainer label={prompt.label} className={classes.prompt}>
|
|
130
147
|
<EditableHtml
|
|
@@ -133,45 +150,60 @@ export class Root extends React.Component {
|
|
|
133
150
|
imageSupport={imageSupport}
|
|
134
151
|
nonEmpty={false}
|
|
135
152
|
toolbarOpts={toolbarOpts}
|
|
153
|
+
spellCheck={spellCheckEnabled}
|
|
154
|
+
maxImageWidth={defaultImageMaxWidth}
|
|
155
|
+
maxImageHeight={defaultImageMaxHeight}
|
|
156
|
+
uploadSoundSupport={uploadSoundSupport}
|
|
157
|
+
languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
|
|
136
158
|
/>
|
|
137
159
|
</InputContainer>
|
|
138
160
|
)}
|
|
139
161
|
|
|
140
162
|
{rationaleEnabled && (
|
|
141
|
-
<InputContainer
|
|
142
|
-
label={rationale.label}
|
|
143
|
-
className={classes.prompt}
|
|
144
|
-
>
|
|
163
|
+
<InputContainer label={rationale.label} className={classes.prompt}>
|
|
145
164
|
<EditableHtml
|
|
146
165
|
markup={model.rationale || ''}
|
|
147
166
|
onChange={onRationaleChanged}
|
|
148
167
|
imageSupport={imageSupport}
|
|
149
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' }]}
|
|
150
174
|
/>
|
|
151
175
|
</InputContainer>
|
|
152
176
|
)}
|
|
153
177
|
|
|
154
|
-
<
|
|
155
|
-
|
|
156
|
-
|
|
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>
|
|
157
192
|
|
|
158
193
|
<HotspotPalette
|
|
159
194
|
hotspotColor={model.hotspotColor}
|
|
160
195
|
hotspotList={model.hotspotList}
|
|
161
196
|
outlineColor={model.outlineColor}
|
|
162
197
|
outlineList={model.outlineList}
|
|
163
|
-
onHotspotColorChange={color =>
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
onOutlineColorChange={color =>
|
|
167
|
-
this.handleColorChange('outline', color)
|
|
168
|
-
}
|
|
198
|
+
onHotspotColorChange={(color) => this.handleColorChange('hotspot', color)}
|
|
199
|
+
onOutlineColorChange={(color) => this.handleColorChange('outline', color)}
|
|
169
200
|
/>
|
|
170
201
|
|
|
171
202
|
<HotspotContainer
|
|
172
203
|
dimensions={model.dimensions}
|
|
173
204
|
imageUrl={model.imageUrl}
|
|
174
205
|
multipleCorrect={model.multipleCorrect}
|
|
206
|
+
hasErrors={!!shapesError || !!selectionsError}
|
|
175
207
|
hotspotColor={model.hotspotColor}
|
|
176
208
|
outlineColor={model.outlineColor}
|
|
177
209
|
onUpdateImageDimension={onUpdateImageDimension}
|
|
@@ -181,6 +213,8 @@ export class Root extends React.Component {
|
|
|
181
213
|
strokeWidth={model.strokeWidth}
|
|
182
214
|
preserveAspectRatioEnabled={preserveAspectRatio.enabled}
|
|
183
215
|
/>
|
|
216
|
+
{shapesError && <div className={classes.errorText}>{shapesError}</div>}
|
|
217
|
+
{selectionsError && <div className={classes.errorText}>{selectionsError}</div>}
|
|
184
218
|
|
|
185
219
|
{model.imageUrl && (
|
|
186
220
|
<div>
|
|
@@ -198,6 +232,7 @@ export class Root extends React.Component {
|
|
|
198
232
|
showErrorWhenOutsideRange
|
|
199
233
|
className={classes.field}
|
|
200
234
|
/>
|
|
235
|
+
|
|
201
236
|
<NumberTextField
|
|
202
237
|
key="hotspot-manual-height"
|
|
203
238
|
label="Height"
|
|
@@ -217,35 +252,52 @@ export class Root extends React.Component {
|
|
|
217
252
|
}
|
|
218
253
|
}
|
|
219
254
|
|
|
220
|
-
const styles = theme => ({
|
|
255
|
+
const styles = (theme) => ({
|
|
221
256
|
base: {
|
|
222
|
-
marginTop: theme.spacing.unit * 3
|
|
257
|
+
marginTop: theme.spacing.unit * 3,
|
|
223
258
|
},
|
|
224
259
|
container: {
|
|
225
260
|
display: 'flex',
|
|
226
|
-
marginTop: theme.spacing.unit
|
|
261
|
+
marginTop: theme.spacing.unit,
|
|
227
262
|
},
|
|
228
263
|
dimensions: {
|
|
229
|
-
display: 'flex'
|
|
264
|
+
display: 'flex',
|
|
230
265
|
},
|
|
231
266
|
field: {
|
|
232
267
|
flex: 1,
|
|
233
|
-
width: '90%'
|
|
268
|
+
width: '90%',
|
|
234
269
|
},
|
|
235
270
|
label: {
|
|
236
|
-
marginTop: theme.spacing.unit * 4
|
|
271
|
+
marginTop: theme.spacing.unit * 4,
|
|
237
272
|
},
|
|
238
273
|
prompt: {
|
|
239
274
|
paddingTop: theme.spacing.unit * 2,
|
|
240
|
-
width: '100%'
|
|
275
|
+
width: '100%',
|
|
276
|
+
},
|
|
277
|
+
subheading: {
|
|
278
|
+
marginRight: theme.spacing.unit,
|
|
241
279
|
},
|
|
242
280
|
regular: {
|
|
243
|
-
marginBottom: theme.spacing.unit * 3
|
|
281
|
+
marginBottom: theme.spacing.unit * 3,
|
|
244
282
|
},
|
|
245
283
|
switchElement: {
|
|
246
284
|
justifyContent: 'space-between',
|
|
247
|
-
margin: 0
|
|
248
|
-
}
|
|
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
|
+
},
|
|
249
301
|
});
|
|
250
302
|
|
|
251
303
|
Root.propTypes = {
|
|
@@ -254,7 +306,11 @@ Root.propTypes = {
|
|
|
254
306
|
model: PropTypes.object.isRequired,
|
|
255
307
|
imageSupport: PropTypes.shape({
|
|
256
308
|
add: PropTypes.func,
|
|
257
|
-
delete: PropTypes.func
|
|
309
|
+
delete: PropTypes.func,
|
|
310
|
+
}),
|
|
311
|
+
uploadSoundSupport: PropTypes.shape({
|
|
312
|
+
add: PropTypes.func,
|
|
313
|
+
delete: PropTypes.func,
|
|
258
314
|
}),
|
|
259
315
|
onImageUpload: PropTypes.func.isRequired,
|
|
260
316
|
onColorChanged: PropTypes.func.isRequired,
|