diff --git a/package.json b/package.json index eeabbe19feb400c151450533a50b8e8ddaa34392..3429ec678e7a3c0e3f8ab6b843dcb33def970d82 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "eslint-plugin-react": "^7.0.1", "gh-pages": "^1.0.0", "html-webpack-plugin": "2.28.0", + "immutable": "3.8.1", "lodash.bindall": "4.4.0", "lodash.debounce": "4.0.8", "lodash.defaultsdeep": "4.6.0", diff --git a/src/components/monitor-list/monitor-list.jsx b/src/components/monitor-list/monitor-list.jsx index 9ee885036cbf8d7b99ee790f2c6032afb8905192..fd9631e23fa06939794773814e8114d447cfc65f 100644 --- a/src/components/monitor-list/monitor-list.jsx +++ b/src/components/monitor-list/monitor-list.jsx @@ -2,6 +2,8 @@ const React = require('react'); const Box = require('../box/box.jsx'); const Monitor = require('../../containers/monitor.jsx'); const PropTypes = require('prop-types'); +const {OrderedMap} = require('immutable'); + const styles = require('./monitor-list.css'); @@ -9,10 +11,14 @@ const MonitorList = props => ( <Box className={styles.monitorList} > - {props.monitors.map(monitorData => ( + {props.monitors.valueSeq().map((monitorData, index) => ( <Monitor - {...monitorData} + id={monitorData.id} + index={index} key={monitorData.id} + opcode={monitorData.opcode} + params={monitorData.params} + value={monitorData.value} onDragEnd={props.onMonitorChange} /> ))} @@ -20,13 +26,7 @@ const MonitorList = props => ( ); MonitorList.propTypes = { - monitors: PropTypes.arrayOf(PropTypes.shape({ - color: PropTypes.string, - label: PropTypes.string.isRequired, - value: PropTypes.string.isRequired, - x: PropTypes.number, - y: PropTypes.number - })), + monitors: PropTypes.instanceOf(OrderedMap), onMonitorChange: PropTypes.func.isRequired }; diff --git a/src/containers/monitor.jsx b/src/containers/monitor.jsx index 4ec8681572efc567f9a54443f86d5199a8754f60..9bed328d40542625e0634961fb7729669269931e 100644 --- a/src/containers/monitor.jsx +++ b/src/containers/monitor.jsx @@ -1,6 +1,8 @@ const bindAll = require('lodash.bindall'); const React = require('react'); +const PropTypes = require('prop-types'); +const monitorAdapter = require('../lib/monitor-adapter.js'); const MonitorComponent = require('../components/monitor/monitor.jsx'); class Monitor extends React.Component { @@ -18,15 +20,23 @@ class Monitor extends React.Component { ); } render () { + const monitorProps = monitorAdapter(this.props); return ( <MonitorComponent - {...this.props} + {...monitorProps} onDragEnd={this.handleDragEnd} /> ); } } -Monitor.propTypes = MonitorComponent.propTypes; +Monitor.propTypes = { + id: PropTypes.string.isRequired, + index: PropTypes.number.isRequired, // eslint-disable-line react/no-unused-prop-types + onDragEnd: PropTypes.func.isRequired, + opcode: PropTypes.string.isRequired, // eslint-disable-line react/no-unused-prop-types + params: PropTypes.object, // eslint-disable-line react/no-unused-prop-types, react/forbid-prop-types + value: PropTypes.string.isRequired // eslint-disable-line react/no-unused-prop-types +}; module.exports = Monitor; diff --git a/src/lib/monitor-adapter.js b/src/lib/monitor-adapter.js index 8dcc802a48e9414062431e6ca9137f8d2eef6cde..dc66fd0b88c8273624ef0a07b30767add579ef51 100644 --- a/src/lib/monitor-adapter.js +++ b/src/lib/monitor-adapter.js @@ -3,14 +3,14 @@ * - Convert opcode to a label and a category * - Add missing XY position data if needed */ -const OpcodeLabels = require('../lib/opcode-labels.js'); +const OpcodeLabels = require('./opcode-labels.js'); const PADDING = 5; const MONITOR_HEIGHT = 23; const isUndefined = a => typeof a === 'undefined'; -module.exports = function ({id, opcode, params, value, x, y}, monitorIndex) { +module.exports = function ({id, index, opcode, params, value, x, y}) { let {label, category, labelFn} = OpcodeLabels(opcode); // Use labelFn if provided for dynamic labelling (e.g. variables) @@ -20,7 +20,7 @@ module.exports = function ({id, opcode, params, value, x, y}, monitorIndex) { // @todo scratch2 has a more complex layout behavior we may want to adopt // @todo e.g. this does not work well when monitors have already been moved if (isUndefined(x)) x = PADDING; - if (isUndefined(y)) y = PADDING + (monitorIndex * (PADDING + MONITOR_HEIGHT)); + if (isUndefined(y)) y = PADDING + (index * (PADDING + MONITOR_HEIGHT)); return {id, label, category, value, x, y}; }; diff --git a/src/reducers/monitors.js b/src/reducers/monitors.js index 18e9529f4ad417645101a5cc85ed60b6b8adecf0..e21e67a0193a5a1d40a9690a877d05cd75ca0aa4 100644 --- a/src/reducers/monitors.js +++ b/src/reducers/monitors.js @@ -1,14 +1,13 @@ -const monitorAdapter = require('../lib/monitor-adapter.js'); - const UPDATE_MONITORS = 'scratch-gui/monitors/UPDATE_MONITORS'; +const {OrderedMap} = require('immutable'); -const initialState = []; +const initialState = OrderedMap(); const reducer = function (state, action) { if (typeof state === 'undefined') state = initialState; switch (action.type) { case UPDATE_MONITORS: - return action.monitors.map(monitorAdapter); + return action.monitors; default: return state; }