Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintcache
Original file line number Diff line number Diff line change
@@ -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","/home/feelic/repositories/armorial/src/components/charges/BearRampant.js":"19","/home/feelic/repositories/armorial/src/components/charges/BearPassant.js":"20"},{"size":591,"mtime":1569077615410,"results":"21","hashOfConfig":"22"},{"size":890,"mtime":1607452028746,"results":"23","hashOfConfig":"22"},{"size":4951,"mtime":1568993756910,"results":"24","hashOfConfig":"22"},{"size":589,"mtime":1569087293175,"results":"25","hashOfConfig":"22"},{"size":998,"mtime":1607365778826,"results":"26","hashOfConfig":"22"},{"size":2864,"mtime":1607455290500,"results":"27","hashOfConfig":"22"},{"size":2219,"mtime":1607453804024,"results":"28","hashOfConfig":"22"},{"size":110,"mtime":1569076477144,"results":"29","hashOfConfig":"22"},{"size":1384,"mtime":1607455358513,"results":"30","hashOfConfig":"22"},{"size":2602,"mtime":1589217289055,"results":"31","hashOfConfig":"22"},{"size":1064,"mtime":1607450032868,"results":"32","hashOfConfig":"22"},{"size":1443,"mtime":1590145570912,"results":"33","hashOfConfig":"22"},{"size":4711,"mtime":1608588143721,"results":"34","hashOfConfig":"22"},{"size":434,"mtime":1589389767483,"results":"35","hashOfConfig":"22"},{"size":2756,"mtime":1607453812160,"results":"36","hashOfConfig":"22"},{"size":988,"mtime":1608595123783,"results":"37","hashOfConfig":"22"},{"size":262,"mtime":1608593252073,"results":"38","hashOfConfig":"22"},{"size":6365,"mtime":1608590370267,"results":"39","hashOfConfig":"22"},{"size":35124,"mtime":1608593285281,"results":"40","hashOfConfig":"22"},{"size":34666,"mtime":1608593281105,"results":"41","hashOfConfig":"22"},{"filePath":"42","messages":"43","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},"elta90",{"filePath":"45","messages":"46","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"47","messages":"48","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"49","messages":"50","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"51","messages":"52","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"53","messages":"54","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"55","usedDeprecatedRules":"44"},{"filePath":"56","messages":"57","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"58","messages":"59","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"60","messages":"61","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"62","usedDeprecatedRules":"44"},{"filePath":"63","messages":"64","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"65","messages":"66","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"67","messages":"68","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"69","messages":"70","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"71","messages":"72","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"73","messages":"74","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"44"},{"filePath":"75","messages":"76","errorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"77","messages":"78","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"79","messages":"80","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"81","messages":"82","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"83","messages":"84","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/home/feelic/repositories/armorial/src/index.js",[],["85","86"],"/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",["87","88"],"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 <div className={styles.partForm}>\n <b>{part.id}</b>\n <PartitionSelector\n onSelect={(id, value) =>\n dispatch(actions.changePartition(part.id, value))\n }\n armsParts={armsParts}\n part={part}\n />\n <button onClick={() => dispatch(actions.clearPartition(part.id))}>\n clear partition\n </button>\n {part.parts.map((partId) => {\n return (\n <PartForm\n key={partId}\n armsParts={armsParts}\n part={armsParts[partId]}\n />\n );\n })}\n </div>\n );\n }\n if (part.field) {\n return (\n <div className={styles.partForm}>\n <b>{part.id}</b>\n <FieldForm armsParts={armsParts} part={part} />\n <button onClick={() => dispatch(actions.clearField(part.id))}>\n clear field\n </button>\n <ChargeForm armsParts={armsParts} part={part} />\n </div>\n );\n }\n return (\n <div className={styles.partForm}>\n <b>{part.id}</b>\n <FieldForm armsParts={armsParts} part={part} />\n Or create partition\n <PartitionSelector\n onSelect={() => dispatch(actions.createPartition(part.id))}\n armsParts={armsParts}\n part={part}\n />\n </div>\n );\n}\n\nfunction PartitionSelector(props) {\n const { onSelect, part } = props;\n\n return (\n <div>\n Select partition type\n <select\n onChange={(e) => onSelect(part.id, e.target.value)}\n value={part.partitionType}\n >\n <option value={null}> </option>\n {Object.values(partitions).map((partition) => {\n return (\n <option key={partition.id} value={partition.id}>\n {partition.label}\n </option>\n );\n })}\n </select>\n </div>\n );\n}\n\nfunction FieldForm(props) {\n const dispatch = useDispatch();\n const { part } = props;\n\n return (\n <div>\n Select colour or metal\n <select\n onChange={(e) => dispatch(actions.changeField(part.id, e.target.value))}\n value={part.field}\n >\n <option value=\"\">select a field colour</option>\n {Object.keys(fields).map((field) => {\n return (\n <option key={field} value={field} style={{backgroundColor: fields[field]}}>\n {field}\n </option>\n );\n })}\n </select>\n </div>\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",["89","90"],"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 <div>\n <select\n onChange={e => dispatch(actions.changeCharge(part.id, e.target.value))}\n value={part.charge}\n >\n <option value={null}>none</option>\n {Object.keys(charges).map(charge => {\n return (\n <option key={charge} value={charge}>\n {charge}\n </option>\n );\n })}\n </select>\n <select\n onChange={e => dispatch(actions.changeChargeColour(part.id, e.target.value))}\n value={part.chargeColour}\n >\n <option value={null}> </option>\n {Object.keys(chargeColours).map(colour => {\n return (\n <option key={colour} value={colour}>\n {colour}\n </option>\n );\n })}\n </select>\n </div>\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",["91","92","93","94"],"/home/feelic/repositories/armorial/src/components/charges/index.js",[],"/home/feelic/repositories/armorial/src/components/charges/CerfCourant.js",[],"/home/feelic/repositories/armorial/src/components/charges/BearRampant.js",[],"/home/feelic/repositories/armorial/src/components/charges/BearPassant.js",[],{"ruleId":"95","replacedBy":"96"},{"ruleId":"97","replacedBy":"98"},{"ruleId":"99","severity":1,"message":"100","line":2,"column":18,"nodeType":"101","messageId":"102","endLine":2,"endColumn":25},{"ruleId":"99","severity":1,"message":"103","line":2,"column":27,"nodeType":"101","messageId":"102","endLine":2,"endColumn":33},{"ruleId":"99","severity":1,"message":"104","line":3,"column":8,"nodeType":"101","messageId":"102","endLine":3,"endColumn":14},{"ruleId":"99","severity":1,"message":"105","line":10,"column":11,"nodeType":"101","messageId":"102","endLine":10,"endColumn":20},{"ruleId":"99","severity":1,"message":"106","line":4,"column":10,"nodeType":"101","messageId":"102","endLine":4,"endColumn":16},{"ruleId":"99","severity":1,"message":"107","line":4,"column":18,"nodeType":"101","messageId":"102","endLine":4,"endColumn":23},{"ruleId":"99","severity":1,"message":"108","line":13,"column":11,"nodeType":"101","messageId":"102","endLine":13,"endColumn":30},{"ruleId":"99","severity":1,"message":"109","line":13,"column":32,"nodeType":"101","messageId":"102","endLine":13,"endColumn":46},"no-native-reassign",["110"],"no-negated-in-lhs",["111"],"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.","'HEIGHT' is defined but never used.","'WIDTH' is defined but never used.","'parentPartitionType' is assigned a value but never used.","'partitionIndex' is assigned a value but never used.","no-global-assign","no-unsafe-negation"]
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
79 changes: 29 additions & 50 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -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 (
<div className={styles.blasonContainer}>
<div className={styles.block}>
<SvgArms armsParts={parts} />
<PartForm actions={actions} armsParts={parts} part={root} />
</div>
<div className={styles.block}>
<pre>
{JSON.stringify(parts, null, 2)}
</pre>
</div>
</div>
);
}
}

/**
* 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 (
<div className={styles.blasonContainer}>
<div className={styles.block}>
<SvgArms armsParts={parts} />
<PartForm armsParts={parts} part={root} />
</div>
<div className={styles.block}>
<pre>
{JSON.stringify(parts, null, 2)}
</pre>
</div>
</div>
);
}
65 changes: 46 additions & 19 deletions src/actions/index.js
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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 {
Expand All @@ -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,
};
}
6 changes: 6 additions & 0 deletions src/app.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ body {
max-width: 40%;
margin-right: 40px;
}

pre {
background-color: #334;
color: #cdc;
padding: 15px 60px 15px 30px;
}
9 changes: 6 additions & 3 deletions src/components/ChargeForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand All @@ -14,7 +17,7 @@ export default function ChargeForm(props) {
return (
<div>
<select
onChange={e => actions.changeCharge(part.id, e.target.value)}
onChange={e => dispatch(actions.changeCharge(part.id, e.target.value))}
value={part.charge}
>
<option value={null}>none</option>
Expand All @@ -27,7 +30,7 @@ export default function ChargeForm(props) {
})}
</select>
<select
onChange={e => actions.changeChargeColour(part.id, e.target.value)}
onChange={e => dispatch(actions.changeChargeColour(part.id, e.target.value))}
value={part.chargeColour}
>
<option value={null}> </option>
Expand Down
Loading