From 68589cd00737b0790eb7348f740e80a7c7c5e987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Goalec?= Date: Mon, 21 Dec 2020 22:43:57 +0100 Subject: [PATCH 1/3] feat(partitions): fix partition creation and deletion, fix minor positioning issues --- .eslintcache | 1 + package.json | 12 +- src/App.js | 79 +- src/actions/index.js | 65 +- src/app.module.scss | 6 + src/components/ChargeForm.js | 9 +- src/components/PartForm.js | 46 +- src/components/SvgArms/Arms.js | 9 +- src/components/SvgArms/Part.js | 5 + src/constants/partitions.js | 42 +- src/reducers/parts.js | 46 +- yarn.lock | 10055 ++++++++++++++++--------------- 12 files changed, 5304 insertions(+), 5071 deletions(-) create mode 100644 .eslintcache diff --git a/.eslintcache b/.eslintcache new file mode 100644 index 0000000..384cdd9 --- /dev/null +++ b/.eslintcache @@ -0,0 +1 @@ +[{"/home/feelic/repositories/armorial/src/index.js":"1","/home/feelic/repositories/armorial/src/App.js":"2","/home/feelic/repositories/armorial/src/serviceWorker.js":"3","/home/feelic/repositories/armorial/src/store/configure-store.js":"4","/home/feelic/repositories/armorial/src/components/SvgArms/Arms.js":"5","/home/feelic/repositories/armorial/src/components/PartForm.js":"6","/home/feelic/repositories/armorial/src/actions/index.js":"7","/home/feelic/repositories/armorial/src/reducers/index.js":"8","/home/feelic/repositories/armorial/src/components/ChargeForm.js":"9","/home/feelic/repositories/armorial/src/components/SvgArms/BaseElements.js":"10","/home/feelic/repositories/armorial/src/components/SvgArms/Part.js":"11","/home/feelic/repositories/armorial/src/constants/index.js":"12","/home/feelic/repositories/armorial/src/constants/partitions.js":"13","/home/feelic/repositories/armorial/src/constants/action-types.js":"14","/home/feelic/repositories/armorial/src/reducers/parts.js":"15","/home/feelic/repositories/armorial/src/components/SvgArms/Charge.js":"16","/home/feelic/repositories/armorial/src/components/charges/index.js":"17","/home/feelic/repositories/armorial/src/components/charges/CerfCourant.js":"18"},{"size":591,"mtime":1569077615410,"results":"19","hashOfConfig":"20"},{"size":890,"mtime":1607452028746,"results":"21","hashOfConfig":"20"},{"size":4951,"mtime":1568993756910,"results":"22","hashOfConfig":"20"},{"size":589,"mtime":1569087293175,"results":"23","hashOfConfig":"20"},{"size":998,"mtime":1607365778826,"results":"24","hashOfConfig":"20"},{"size":2864,"mtime":1607455290500,"results":"25","hashOfConfig":"20"},{"size":2219,"mtime":1607453804024,"results":"26","hashOfConfig":"20"},{"size":110,"mtime":1569076477144,"results":"27","hashOfConfig":"20"},{"size":1384,"mtime":1607455358513,"results":"28","hashOfConfig":"20"},{"size":2602,"mtime":1589217289055,"results":"29","hashOfConfig":"20"},{"size":1064,"mtime":1607450032868,"results":"30","hashOfConfig":"20"},{"size":1443,"mtime":1590145570912,"results":"31","hashOfConfig":"20"},{"size":4501,"mtime":1607446569799,"results":"32","hashOfConfig":"20"},{"size":434,"mtime":1589389767483,"results":"33","hashOfConfig":"20"},{"size":2756,"mtime":1607453812160,"results":"34","hashOfConfig":"20"},{"size":1496,"mtime":1590141364014,"results":"35","hashOfConfig":"20"},{"size":92,"mtime":1589387819376,"results":"36","hashOfConfig":"20"},{"size":14535,"mtime":1589825566355,"results":"37","hashOfConfig":"20"},{"filePath":"38","messages":"39","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},"elta90",{"filePath":"41","messages":"42","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"43","messages":"44","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"45","messages":"46","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"47","messages":"48","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"49","messages":"50","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"51","usedDeprecatedRules":"40"},{"filePath":"52","messages":"53","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"54","messages":"55","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"56","messages":"57","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"58","usedDeprecatedRules":"40"},{"filePath":"59","messages":"60","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"61","messages":"62","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"63","messages":"64","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"65","messages":"66","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"67","messages":"68","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"69","messages":"70","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"71","messages":"72","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"40"},{"filePath":"73","messages":"74","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"75","usedDeprecatedRules":"40"},{"filePath":"76","messages":"77","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"78"},"/home/feelic/repositories/armorial/src/index.js",[],["79","80"],"/home/feelic/repositories/armorial/src/App.js",[],"/home/feelic/repositories/armorial/src/serviceWorker.js",[],"/home/feelic/repositories/armorial/src/store/configure-store.js",[],"/home/feelic/repositories/armorial/src/components/SvgArms/Arms.js",[],"/home/feelic/repositories/armorial/src/components/PartForm.js",["81","82"],"import React from \"react\";\nimport { fields, colours, metals } from \"../constants\";\nimport partitions from \"../constants/partitions\";\nimport ChargeForm from \"./ChargeForm\";\nimport styles from \"./PartForm.module.scss\";\nimport { useDispatch } from \"react-redux\";\nimport * as actions from \"../actions\";\n\nexport default function PartForm(props) {\n const dispatch = useDispatch();\n const { armsParts, part } = props;\n\n if (part.partitionType) {\n return (\n
\n {part.id}\n \n dispatch(actions.changePartition(part.id, value))\n }\n armsParts={armsParts}\n part={part}\n />\n \n {part.parts.map((partId) => {\n return (\n \n );\n })}\n
\n );\n }\n if (part.field) {\n return (\n
\n {part.id}\n \n \n \n
\n );\n }\n return (\n
\n {part.id}\n \n Or create partition\n dispatch(actions.createPartition(part.id))}\n armsParts={armsParts}\n part={part}\n />\n
\n );\n}\n\nfunction PartitionSelector(props) {\n const { onSelect, part } = props;\n\n return (\n
\n Select partition type\n onSelect(part.id, e.target.value)}\n value={part.partitionType}\n >\n \n {Object.values(partitions).map((partition) => {\n return (\n \n );\n })}\n \n
\n );\n}\n\nfunction FieldForm(props) {\n const dispatch = useDispatch();\n const { part } = props;\n\n return (\n
\n Select colour or metal\n dispatch(actions.changeField(part.id, e.target.value))}\n value={part.field}\n >\n \n {Object.keys(fields).map((field) => {\n return (\n \n );\n })}\n \n
\n );\n}\n","/home/feelic/repositories/armorial/src/actions/index.js",[],"/home/feelic/repositories/armorial/src/reducers/index.js",[],"/home/feelic/repositories/armorial/src/components/ChargeForm.js",["83","84"],"import React from \"react\";\nimport { colours, metals /*, charges*/ } from \"../constants\";\nimport styles from \"./PartForm.module.scss\";\nimport charges from \"./charges/index\";\nimport * as actions from \"../actions\";\nimport { useDispatch } from \"react-redux\";\n\nexport default function ChargeForm(props) {\n const dispatch = useDispatch();\n const { armsParts, part } = props;\n\n const fieldColour = part.field;\n const fieldColourType =\n (Object.keys(metals).includes(fieldColour) && \"metals\") || \"colours\";\n const chargeColours = (fieldColourType === \"metals\" && colours) || metals;\n\n return (\n
\n dispatch(actions.changeCharge(part.id, e.target.value))}\n value={part.charge}\n >\n \n {Object.keys(charges).map(charge => {\n return (\n \n );\n })}\n \n dispatch(actions.changeChargeColour(part.id, e.target.value))}\n value={part.chargeColour}\n >\n \n {Object.keys(chargeColours).map(colour => {\n return (\n \n );\n })}\n \n
\n );\n}\n","/home/feelic/repositories/armorial/src/components/SvgArms/BaseElements.js",[],"/home/feelic/repositories/armorial/src/components/SvgArms/Part.js",[],"/home/feelic/repositories/armorial/src/constants/index.js",[],"/home/feelic/repositories/armorial/src/constants/partitions.js",[],"/home/feelic/repositories/armorial/src/constants/action-types.js",[],"/home/feelic/repositories/armorial/src/reducers/parts.js",[],"/home/feelic/repositories/armorial/src/components/SvgArms/Charge.js",[],"/home/feelic/repositories/armorial/src/components/charges/index.js",["85"],"import CerfCourant from \"./CerfCourant\";\n\nexport default {\n \"cerf-courant\": CerfCourant\n};\n","/home/feelic/repositories/armorial/src/components/charges/CerfCourant.js",[],["86","87"],{"ruleId":"88","replacedBy":"89"},{"ruleId":"90","replacedBy":"91"},{"ruleId":"92","severity":1,"message":"93","line":2,"column":18,"nodeType":"94","messageId":"95","endLine":2,"endColumn":25},{"ruleId":"92","severity":1,"message":"96","line":2,"column":27,"nodeType":"94","messageId":"95","endLine":2,"endColumn":33},{"ruleId":"92","severity":1,"message":"97","line":3,"column":8,"nodeType":"94","messageId":"95","endLine":3,"endColumn":14},{"ruleId":"92","severity":1,"message":"98","line":10,"column":11,"nodeType":"94","messageId":"95","endLine":10,"endColumn":20},{"ruleId":"99","severity":1,"message":"100","line":3,"column":1,"nodeType":"101","endLine":5,"endColumn":3},{"ruleId":"88","replacedBy":"102"},{"ruleId":"90","replacedBy":"103"},"no-native-reassign",["104"],"no-negated-in-lhs",["105"],"no-unused-vars","'colours' is defined but never used.","Identifier","unusedVar","'metals' is defined but never used.","'styles' is defined but never used.","'armsParts' is assigned a value but never used.","import/no-anonymous-default-export","Assign object to a variable before exporting as module default","ExportDefaultDeclaration",["104"],["105"],"no-global-assign","no-unsafe-negation"] \ No newline at end of file diff --git a/package.json b/package.json index 2f66add..ea312af 100644 --- a/package.json +++ b/package.json @@ -3,14 +3,14 @@ "version": "0.1.0", "private": true, "dependencies": { - "node-sass": "^4.14.1", - "react": "^16.13.1", - "react-dom": "^16.13.1", - "react-redux": "^7.2.0", - "react-scripts": "3.4.1", + "react": "^17.0.1", + "react-dom": "^17.0.1", + "react-redux": "^7.2.2", + "react-scripts": "4.0.1", "redux": "^4.0.5", "redux-thunk": "^2.3.0", - "uuidv4": "^6.0.8" + "sass": "^1.30.0", + "uuidv4": "^6.2.5" }, "scripts": { "start": "react-scripts start", diff --git a/src/App.js b/src/App.js index a297943..2ce9047 100644 --- a/src/App.js +++ b/src/App.js @@ -1,59 +1,38 @@ -import React, {Component} from 'react'; +import React, {useEffect} from 'react'; -import * as appActions from './actions'; -import {bindActionCreators} from 'redux'; - -import {connect} from 'react-redux'; +import {useSelector, useDispatch} from 'react-redux'; import SvgArms from './components/SvgArms/Arms'; import PartForm from './components/PartForm'; import styles from './app.module.scss'; +import * as actions from './actions'; -class App extends Component { - - render () { - const {parts, actions} = this.props; - const root = parts.root; - - return ( -
-
- - -
-
-
-          {JSON.stringify(parts, null, 2)}
-          
-
-
- ); - } -} -/** - * Map all our state to the application - * - * @param {Object} state state of our application - * @return {Object} props - */ -function mapStateToProps (state) { - return {...state}; -} +export default function App() { + const parts = useSelector(state => state.parts); + const dispatch = useDispatch(); -/** - * Map all our actions to dispatch - * - * @param {Object} dispatch store dispatch function - * @return {Object} actions - */ -function mapDispatchToProps (dispatch) { - return { - 'actions': bindActionCreators(appActions, dispatch) - }; -} + useEffect(() => { + dispatch(actions.createPartition('root', 'perPale')) + }, [dispatch]); -export default connect( - mapStateToProps, - mapDispatchToProps -)(App); + const root = parts.root; + + if (!root) { + return 'loading'; + } + + return ( +
+
+ + +
+
+
+        {JSON.stringify(parts, null, 2)}
+        
+
+
+ ); +} diff --git a/src/actions/index.js b/src/actions/index.js index 8cb2457..23f3e9b 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,5 +1,5 @@ import partitions from "../constants/partitions"; -import { emptyPart,getChildrenIds } from "../reducers/parts"; +import { emptyPart, getChildrenIds } from "../reducers/parts"; import * as types from "../constants/action-types"; let partIdx = 0; @@ -13,16 +13,38 @@ export function changeCharge(partId, value) { export function changeChargeColour(partId, value) { return { type: types.CHANGE_CHARGE_COLOUR, partId, value }; } -export function changePartition(partId, value) { - // const partNb = partitions[value].partsNb; +export const changePartition = (partId, value) => (dispatch, getState) => { + if (!value) { + return clearPartition(partId); + } - return { + const state = getState(); + const currentParts = state.parts[partId].parts; + const partNb = partitions[value].partsNb; + const parts = new Array(partNb) + .fill(0) + .map((p, idx) => { + if (currentParts[idx]) { + return state.parts[currentParts[idx]]; + } + return makeNewPart(); + }) + .reduce((prev, curr) => { + return { ...prev, [curr.id]: curr }; + }, {}); + + if (currentParts.length > partNb) { + dispatch(deleteParts(currentParts.slice(partNb))); + } + + return dispatch({ type: types.CHANGE_PARTITION, partId, - value - }; -} -export function createPartition(partId, value) { + parts, + value, + }); +}; +export function createPartition(partId, value = 'perFess') { const partNb = partitions[value].partsNb; return { @@ -34,37 +56,42 @@ export function createPartition(partId, value) { .map(makeNewPart) .reduce((prev, curr) => { return { ...prev, [curr.id]: curr }; - }, {}) + }, {}), }; } export function makeNewPart() { return { ...emptyPart, - id: String((partIdx += 1)) + id: String((partIdx += 1)), }; } export function clearField(partId) { - return { - type: types.CLEAR_FIELD, - partId - }; + return { + type: types.CLEAR_FIELD, + partId, + }; +} +export function deleteParts(partIds) { + return { + type: types.DELETE_PARTS, + partIds, + }; } -export function clearPartition -(partId) { - return function(dispatch, getState) { +export function clearPartition(partId) { + return function (dispatch, getState) { const childrenIds = getChildrenIds(getState().parts, partId); return dispatch({ type: types.CLEAR_PARTITION, partId, - childrenIds + childrenIds, }); }; } export function clearCharge(partId) { return { type: types.CLEAR_CHARGE, - partId + partId, }; } diff --git a/src/app.module.scss b/src/app.module.scss index 69c4f0d..63b1d6c 100644 --- a/src/app.module.scss +++ b/src/app.module.scss @@ -18,3 +18,9 @@ body { max-width: 40%; margin-right: 40px; } + +pre { + background-color: #334; + color: #cdc; + padding: 15px 60px 15px 30px; +} diff --git a/src/components/ChargeForm.js b/src/components/ChargeForm.js index ccf9744..e8fffbb 100644 --- a/src/components/ChargeForm.js +++ b/src/components/ChargeForm.js @@ -2,9 +2,12 @@ import React from "react"; import { colours, metals /*, charges*/ } from "../constants"; import styles from "./PartForm.module.scss"; import charges from "./charges/index"; +import * as actions from "../actions"; +import { useDispatch } from "react-redux"; export default function ChargeForm(props) { - const { actions, armsParts, part } = props; + const dispatch = useDispatch(); + const { armsParts, part } = props; const fieldColour = part.field; const fieldColourType = @@ -14,7 +17,7 @@ export default function ChargeForm(props) { return (
onSelect(part.id, e.target.value)} + onChange={(e) => onSelect(part.id, e.target.value)} value={part.partitionType} > - {Object.values(partitions).map(partition => { + {Object.values(partitions).map((partition) => { return (