From 20d5e1c3fe132971c8350e4affc066a4a0e38f69 Mon Sep 17 00:00:00 2001 From: denkondratiev Date: Wed, 29 Jul 2020 06:49:09 +0300 Subject: [PATCH 1/3] first with typescript --- package-lock.json | 147 +++++++++++++++++- package.json | 7 + src/{App.jsx => App.tsx} | 4 +- src/components/AverageRow/AverageRow.jsx | 24 --- src/components/AverageRow/AverageRow.tsx | 18 +++ .../{ButtonAdd.jsx => ButtonAdd.tsx} | 9 +- .../{ButtonDelete.jsx => ButtonDelete.tsx} | 9 +- src/components/Buttons/Buttons.jsx | 58 ------- src/components/Buttons/Buttons.tsx | 39 +++++ src/components/Form/{Form.jsx => Form.tsx} | 73 ++++----- src/components/Table/Table.jsx | 76 --------- src/components/Table/Table.tsx | 61 ++++++++ .../{TableCell.jsx => TableCell.tsx} | 20 ++- .../{TableCellSum.jsx => TableCellSum.tsx} | 10 +- .../TableRow/{TableRow.jsx => TableRow.tsx} | 25 ++- src/helpers/generate.js | 25 --- src/helpers/generate.tsx | 26 ++++ ...getLightClosest.js => getLightClosest.tsx} | 6 +- src/helpers/interface.tsx | 27 ++++ src/helpers/{selectors.js => selectors.tsx} | 17 +- src/helpers/shapes.js | 66 -------- src/{index.jsx => index.tsx} | 0 src/react-app-env.d.ts | 1 + src/store/actions.js | 50 ------ src/store/actions.tsx | 92 +++++++++++ src/store/{reducers.js => reducers.tsx} | 16 +- src/store/store.js | 9 -- src/store/store.tsx | 6 + tsconfig.json | 25 +++ 29 files changed, 535 insertions(+), 411 deletions(-) rename src/{App.jsx => App.tsx} (85%) delete mode 100644 src/components/AverageRow/AverageRow.jsx create mode 100644 src/components/AverageRow/AverageRow.tsx rename src/components/ButtonAdd/{ButtonAdd.jsx => ButtonAdd.tsx} (53%) rename src/components/ButtonDelete/{ButtonDelete.jsx => ButtonDelete.tsx} (57%) delete mode 100644 src/components/Buttons/Buttons.jsx create mode 100644 src/components/Buttons/Buttons.tsx rename src/components/Form/{Form.jsx => Form.tsx} (61%) delete mode 100644 src/components/Table/Table.jsx create mode 100644 src/components/Table/Table.tsx rename src/components/TableCell/{TableCell.jsx => TableCell.tsx} (57%) rename src/components/TableCellSum/{TableCellSum.jsx => TableCellSum.tsx} (65%) rename src/components/TableRow/{TableRow.jsx => TableRow.tsx} (70%) delete mode 100644 src/helpers/generate.js create mode 100644 src/helpers/generate.tsx rename src/helpers/{getLightClosest.js => getLightClosest.tsx} (61%) create mode 100644 src/helpers/interface.tsx rename src/helpers/{selectors.js => selectors.tsx} (58%) delete mode 100644 src/helpers/shapes.js rename src/{index.jsx => index.tsx} (100%) create mode 100644 src/react-app-env.d.ts delete mode 100644 src/store/actions.js create mode 100644 src/store/actions.tsx rename src/store/{reducers.js => reducers.tsx} (72%) delete mode 100644 src/store/store.js create mode 100644 src/store/store.tsx create mode 100644 tsconfig.json diff --git a/package-lock.json b/package-lock.json index 16c364c..758dee3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1643,6 +1643,15 @@ "@types/node": "*" } }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -1665,6 +1674,117 @@ "@types/istanbul-lib-report": "*" } }, + "@types/jest": { + "version": "26.0.7", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.7.tgz", + "integrity": "sha512-+x0077/LoN6MjqBcVOe1y9dpryWnfDZ+Xfo3EqGeBcfPRJlQp3Lw62RvNlWxuGv7kOEwlHriAa54updi3Jvvwg==", + "requires": { + "jest-diff": "^25.2.1", + "pretty-format": "^25.2.1" + }, + "dependencies": { + "@jest/types": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz", + "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "@types/yargs": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.5.tgz", + "integrity": "sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "diff-sequences": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", + "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-diff": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.5.0.tgz", + "integrity": "sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==", + "requires": { + "chalk": "^3.0.0", + "diff-sequences": "^25.2.6", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.5.0" + } + }, + "jest-get-type": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==" + }, + "pretty-format": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.5.0.tgz", + "integrity": "sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==", + "requires": { + "@jest/types": "^25.5.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "@types/json-schema": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", @@ -1682,9 +1802,9 @@ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, "@types/node": { - "version": "14.0.23", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.23.tgz", - "integrity": "sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw==" + "version": "14.0.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.26.tgz", + "integrity": "sha512-W+fpe5s91FBGE0pEa0lnqGLL4USgpLgs4nokw16SrBBco/gQxuua7KnArSEOd5iaMqbbSHV10vUDkJYJJqpXKA==" }, "@types/parse-json": { "version": "4.0.0", @@ -1718,6 +1838,17 @@ "@types/react": "*" } }, + "@types/react-redux": { + "version": "7.1.9", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.9.tgz", + "integrity": "sha512-mpC0jqxhP4mhmOl3P4ipRsgTgbNofMRXJb08Ms6gekViLj61v1hOZEKWDCyWsdONr6EjEA6ZHXC446wdywDe0w==", + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", @@ -1822,6 +1953,11 @@ } } }, + "@types/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-xSQfNcvOiE5f9dyd4Kzxbof1aTrLobL278pGLKOZI6esGfZ7ts9Ka16CzIN6Y8hFHE1C7jIBZokULhK1bOgjRw==" + }, "@types/yargs": { "version": "13.0.9", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.9.tgz", @@ -12961,6 +13097,11 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, + "typescript": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==" + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", diff --git a/package.json b/package.json index cb93c1e..b0ecaa0 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,12 @@ "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", + "@types/jest": "^26.0.7", + "@types/node": "^14.0.26", + "@types/react": "^16.9.43", + "@types/react-dom": "^16.9.8", + "@types/react-redux": "^7.1.9", + "@types/uuid": "^8.0.0", "bootstrap": "^4.5.0", "react": "^16.13.1", "react-dom": "^16.13.1", @@ -15,6 +21,7 @@ "redux": "^4.0.5", "redux-devtools-extension": "^2.13.8", "reselect": "^4.0.0", + "typescript": "^3.9.7", "uuid": "^8.2.0" }, "scripts": { diff --git a/src/App.jsx b/src/App.tsx similarity index 85% rename from src/App.jsx rename to src/App.tsx index 0ef4884..36358d5 100644 --- a/src/App.jsx +++ b/src/App.tsx @@ -4,11 +4,11 @@ import Table from './components/Table/Table' import Buttons from './components/Buttons/Buttons' import './App.css' -const App = () => ( +const App: React.FC = () => (
- +
) diff --git a/src/components/AverageRow/AverageRow.jsx b/src/components/AverageRow/AverageRow.jsx deleted file mode 100644 index dabb741..0000000 --- a/src/components/AverageRow/AverageRow.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react' -// import { v4 as uuidv4 } from 'uuid' -import { AverageRowShape } from '../../helpers/shapes' -import { connect } from 'react-redux' -import { getAverageRowSum } from '../../helpers/selectors' - -const AverageRow = ({ averageArray }) => { - return ( - <> - {{averageArray.map((item, index) => ( - - ))} - } - - ) -} - -AverageRow.propTypes = AverageRowShape.isRequired - -const mapStateToProps = (state) => ({ - averageArray: getAverageRowSum(state) -}) - -export default connect(mapStateToProps)(React.memo(AverageRow)) diff --git a/src/components/AverageRow/AverageRow.tsx b/src/components/AverageRow/AverageRow.tsx new file mode 100644 index 0000000..efb8435 --- /dev/null +++ b/src/components/AverageRow/AverageRow.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import { getAverageRowSum } from '../../helpers/selectors' +import { useSelector } from 'react-redux' + +const AverageRow: React.FC = () => { + const averageArray = useSelector(getAverageRowSum) + + return ( + <> + {{averageArray.map((item, index) => ( + + ))} + } + + ) +} + +export default React.memo(AverageRow) diff --git a/src/components/ButtonAdd/ButtonAdd.jsx b/src/components/ButtonAdd/ButtonAdd.tsx similarity index 53% rename from src/components/ButtonAdd/ButtonAdd.jsx rename to src/components/ButtonAdd/ButtonAdd.tsx index 4e01644..0dc0bdb 100644 --- a/src/components/ButtonAdd/ButtonAdd.jsx +++ b/src/components/ButtonAdd/ButtonAdd.tsx @@ -1,7 +1,10 @@ import React from 'react' -import { ButtonAddShape } from '../../helpers/shapes' -export const ButtonAdd = ({ addRow }) => { +interface Props { + addRow: () => void +} + +export const ButtonAdd: React.FC = ({ addRow }) => { return ( ) } - -ButtonAdd.propTypes = ButtonAddShape.isRequired diff --git a/src/components/ButtonDelete/ButtonDelete.jsx b/src/components/ButtonDelete/ButtonDelete.tsx similarity index 57% rename from src/components/ButtonDelete/ButtonDelete.jsx rename to src/components/ButtonDelete/ButtonDelete.tsx index d8c3bca..8aec76e 100644 --- a/src/components/ButtonDelete/ButtonDelete.jsx +++ b/src/components/ButtonDelete/ButtonDelete.tsx @@ -1,7 +1,10 @@ import React from 'react' -import { ButtonDeleteShape } from '../../helpers/shapes' -export const ButtonDelete = (props) => { +interface Props { + deleteRow: () => void +} + +export const ButtonDelete: React.FC = (props) => { const { deleteRow } = props return ( @@ -14,5 +17,3 @@ export const ButtonDelete = (props) => { ) } - -ButtonDelete.propTypes = ButtonDeleteShape.isRequired diff --git a/src/components/Buttons/Buttons.jsx b/src/components/Buttons/Buttons.jsx deleted file mode 100644 index 7a8a5cc..0000000 --- a/src/components/Buttons/Buttons.jsx +++ /dev/null @@ -1,58 +0,0 @@ -import React from 'react' -import { connect } from 'react-redux' -import { generateTable } from '../../helpers/generate' -import { ButtonsShape } from '../../helpers/shapes' -import { ButtonDelete } from '../ButtonDelete/ButtonDelete' -import { ButtonAdd } from '../ButtonAdd/ButtonAdd' -import { getColumnsAmount } from '../../helpers/selectors' -import './Buttons.css' -import { - setNewRow, - removeRow -} from '../../store/actions' - -const Buttons = (props) => { - const { - showButtons, - setNewRow, - removeRow, - columnsAmount, - table - } = props - - const addRow = () => { - const { table, rows, cells } = generateTable(1, columnsAmount) - setNewRow({ table, rows, cells }) - } - - const deleteRow = () => { - const lastIndex = table[table.length - 1] - removeRow({ lastIndex }) - } - - return ( - <> - {showButtons && ( -
- - -
- )} - - ) -} - -Buttons.propTypes = ButtonsShape.isRequired - -const mapStateToProps = state => ({ - showButtons: state.buttons, - columnsAmount: getColumnsAmount(state), - table: state.table -}) - -const mapDispatchToProps = dispatch => ({ - setNewRow: (table, rows, cells) => dispatch(setNewRow(table, rows, cells)), - removeRow: (lastRow) => dispatch(removeRow(lastRow)) -}) - -export default connect(mapStateToProps, mapDispatchToProps)(React.memo(Buttons)) diff --git a/src/components/Buttons/Buttons.tsx b/src/components/Buttons/Buttons.tsx new file mode 100644 index 0000000..37ac18c --- /dev/null +++ b/src/components/Buttons/Buttons.tsx @@ -0,0 +1,39 @@ +import React from 'react' +import { generateTable } from '../../helpers/generate' +import { ButtonDelete } from '../ButtonDelete/ButtonDelete' +import { ButtonAdd } from '../ButtonAdd/ButtonAdd' +import { getColumnsAmount, getTable, getShowButtons } from '../../helpers/selectors' +import './Buttons.css' +import { setNewRow, removeRow } from '../../store/actions' +import { useDispatch, useSelector } from 'react-redux' + +const Buttons: React.FC = () => { + const dispatch = useDispatch() + + const columnsAmount = useSelector(getColumnsAmount) + const table = useSelector(getTable) + const showButtons = useSelector(getShowButtons) + + const addRow = (): void => { + const { table, rows, cells } = generateTable(1, columnsAmount) + dispatch(setNewRow({ table, rows, cells})) + } + + const deleteRow = (): void => { + const lastRow = table[table.length - 1] + dispatch(removeRow({ lastRow })) + } + + return ( + <> + {showButtons && ( +
+ + +
+ )} + + ) +} + +export default Buttons diff --git a/src/components/Form/Form.jsx b/src/components/Form/Form.tsx similarity index 61% rename from src/components/Form/Form.jsx rename to src/components/Form/Form.tsx index 58b04fb..0ff96f2 100644 --- a/src/components/Form/Form.jsx +++ b/src/components/Form/Form.tsx @@ -1,52 +1,52 @@ import React, { useState } from 'react' -import { FormShape } from '../../helpers/shapes' import { generateTable } from '../../helpers/generate' -import { connect } from 'react-redux' +import { useDispatch } from 'react-redux' import './Form.css' import { setParams, setTable, setRows, setCells, - setShowButtons + setShowButtons, } from '../../store/actions' -const Form = (props) => { - const { - setParamsData, - setTableData, - setRowsData, - setCellsData, - setShowButtonsBoll - } = props +type InputValue = { + rowsAmount: string, + columnsAmount: string, + lightsAmount: string +} + +const Form: React.FC = () => { + + const dispatch = useDispatch() - const [inputValue, setInputValue] = useState({ + const [inputValue, setInputValue] = useState({ rowsAmount: '', columnsAmount: '', lightsAmount: '' }) - const [error, setError] = useState({ + const [error, setError] = useState<{ [name: string]: boolean }>({ rowsAmount: false, columnsAmount: false, lightsAmount: false }) - const handleGenerateTable = (event) => { + const handleGenerateTable = (event: React.FormEvent) => { event.preventDefault() const rowsAmount = inputValue.rowsAmount const columnsAmount = inputValue.columnsAmount const lightsAmount = inputValue.lightsAmount - if (rowsAmount > 0 && columnsAmount > 0 && lightsAmount > 0) { + if (Number(rowsAmount) > 0 && Number(columnsAmount) > 0 && Number(lightsAmount) > 0) { const { table, rows, cells } = generateTable(rowsAmount, columnsAmount) - setParamsData({ rowsAmount, columnsAmount, lightsAmount }) - setTableData(table) - setRowsData(rows) - setCellsData(cells) - setShowButtonsBoll(true) + dispatch(setParams({ rowsAmount, columnsAmount, lightsAmount })) + dispatch(setTable(table)) + dispatch(setRows(rows)) + dispatch(setCells(cells)) + dispatch(setShowButtons(true)) setInputValue({ rowsAmount: '', @@ -56,20 +56,20 @@ const Form = (props) => { } const errorObj = { - rowsAmount: null, - columnsAmount: null, - lightsAmount: null + rowsAmount: false, + columnsAmount: false, + lightsAmount: false } - if (!rowsAmount || rowsAmount <= 0) { + if (!rowsAmount || Number(rowsAmount) <= 0) { errorObj.rowsAmount = true } - if (!columnsAmount || columnsAmount <= 0) { + if (!columnsAmount || Number(columnsAmount) <= 0) { errorObj.columnsAmount = true } - if (!lightsAmount || lightsAmount <= 0) { + if (!lightsAmount || Number(lightsAmount) <= 0) { errorObj.lightsAmount = true } @@ -80,7 +80,8 @@ const Form = (props) => { }) } - const onChangeHandler = ({ name, value }) => { + const onChangeHandler = (event: React.FormEvent): void => { + const { name, value } = event.currentTarget setError({ [name]: false }) setInputValue({ ...inputValue, [name]: value }) } @@ -99,7 +100,7 @@ const Form = (props) => { name="rowsAmount" className={`form-control ${error.rowsAmount && 'error'}`} placeholder="Rows..." - onChange={(event) => onChangeHandler(event.target)} + onChange={(event) => onChangeHandler(event)} value={inputValue.rowsAmount} /> { @@ -114,7 +115,7 @@ const Form = (props) => { name="columnsAmount" className={`form-control ${error.columnsAmount && 'error'}`} placeholder="Columns..." - onChange={(event) => onChangeHandler(event.target)} + onChange={(event) => onChangeHandler(event)} value={inputValue.columnsAmount} /> { @@ -129,7 +130,7 @@ const Form = (props) => { name="lightsAmount" className={`form-control ${error.lightsAmount && 'error'}`} placeholder="Highlight cells..." - onChange={(event) => onChangeHandler(event.target)} + onChange={(event) => onChangeHandler(event)} value={inputValue.lightsAmount} />
Average sum: {item}
Average sum: {item}
- - {table.map((rowId, index) => ( - - ))} - - -
- )} - - ) -} - -Table.propTypes = TableShape.isRequired - -const mapStateToProps = state => ({ - table: state.table, - rows: state.rows, - cells: state.cells, - sumRowArray: getRowSum(state), - lightsAmount: getLightsAmount(state) -}) - -const mapDispatchToProps = (dispatch) => ({ - incrementCell: id => dispatch(increment(id)) -}) - -export default connect(mapStateToProps, mapDispatchToProps)(React.memo(Table)) diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx new file mode 100644 index 0000000..7a8062f --- /dev/null +++ b/src/components/Table/Table.tsx @@ -0,0 +1,61 @@ +import React, { useState, SyntheticEvent } from 'react' +import TableRow from '../TableRow/TableRow' +import AverageRow from '../AverageRow/AverageRow' +import { getLightClosest } from '../../helpers/getLightClosest' +import { getRowSum, getLightsAmount, getTable, getRows, getCells } from '../../helpers/selectors' +import { increment } from '../../store/actions' +import './Table.css' +import { useDispatch, useSelector } from 'react-redux' + +const Table: React.FC = () => { + const [lightList, setLightList] = useState({}) + const dispatch = useDispatch(); + + const table = useSelector(getTable); + const lightsAmount = useSelector(getLightsAmount); + const rows = useSelector(getRows); + const cells = useSelector(getCells); + const sumRowArray = useSelector(getRowSum) + + const onMouseEnterHandler = (event: SyntheticEvent) => { + const { id } = event.currentTarget + const obj = getLightClosest(id, cells, lightsAmount) + setLightList(obj) + } + + const onMouseLeaveHandler = (): void => { + setLightList({}) + } + + const onClickIncrement = (event: SyntheticEvent) => { + const { id } = event.currentTarget + dispatch(increment(id)) + } + + return ( + <> + {table.length > 0 && ( + + + {table.map((rowId: string, index: number) => ( + + ))} + + +
+ )} + + ) +} + +export default React.memo(Table) diff --git a/src/components/TableCell/TableCell.jsx b/src/components/TableCell/TableCell.tsx similarity index 57% rename from src/components/TableCell/TableCell.jsx rename to src/components/TableCell/TableCell.tsx index 99eb685..e1b0595 100644 --- a/src/components/TableCell/TableCell.jsx +++ b/src/components/TableCell/TableCell.tsx @@ -1,14 +1,14 @@ import React from 'react' -import { TableCellShape } from '../../helpers/shapes' +import { TableCellProps } from '../../helpers/interface' import './TableCell.css' -const areEqual = (prevProps, nextProps) => { - const { id, value, styleString } = prevProps +const areEqual = (prevProps: TableCellProps, nextProps: TableCellProps) => { + const { id, amount, styleString } = prevProps if (nextProps.styleString !== styleString) { return false } - if (nextProps.value !== value) { + if (nextProps.amount !== amount) { return false } if (nextProps.id !== id) { @@ -17,10 +17,10 @@ const areEqual = (prevProps, nextProps) => { return true } -const TableCell = (props) => { +const TableCell: React.FC = (props) => { const { id, - value, + amount, styleString, onMouseEnterHandler, onMouseLeaveHandler, @@ -34,16 +34,14 @@ const TableCell = (props) => { return ( onClickIncrement(event.target.id)} - onMouseEnter={(event) => onMouseEnterHandler(event.target.id)} + onClick={(event) => onClickIncrement(event)} + onMouseEnter={(event) => onMouseEnterHandler(event)} onMouseLeave={onMouseLeaveHandler} style={styleObj} > - {value} + {amount} ) } -TableCell.propTypes = TableCellShape.isRequired - export default React.memo(TableCell, areEqual) diff --git a/src/components/TableCellSum/TableCellSum.jsx b/src/components/TableCellSum/TableCellSum.tsx similarity index 65% rename from src/components/TableCellSum/TableCellSum.jsx rename to src/components/TableCellSum/TableCellSum.tsx index e71efb4..9a5d639 100644 --- a/src/components/TableCellSum/TableCellSum.jsx +++ b/src/components/TableCellSum/TableCellSum.tsx @@ -1,7 +1,7 @@ import React from 'react' -import { TableCellSumShape } from '../../helpers/shapes' +import { TableCellSumProps } from '../../helpers/interface' -const areEqual = (prevProps, nextProps) => { +const areEqual = (prevProps: TableCellSumProps, nextProps: TableCellSumProps) => { const { rowSum } = prevProps if (nextProps.rowSum !== rowSum) { @@ -10,9 +10,8 @@ const areEqual = (prevProps, nextProps) => { return true } -const TableCellSum = (props) => { +const TableCellSum: React.FC = (props) => { const { - id, rowSum, onMouseEnterPercent, onMouseLeavePercent @@ -20,7 +19,6 @@ const TableCellSum = (props) => { return ( @@ -30,6 +28,4 @@ const TableCellSum = (props) => { ) } -TableCellSum.propTypes = TableCellSumShape.isRequired - export default React.memo(TableCellSum, areEqual) diff --git a/src/components/TableRow/TableRow.jsx b/src/components/TableRow/TableRow.tsx similarity index 70% rename from src/components/TableRow/TableRow.jsx rename to src/components/TableRow/TableRow.tsx index 131d22f..dc98df3 100644 --- a/src/components/TableRow/TableRow.jsx +++ b/src/components/TableRow/TableRow.tsx @@ -1,30 +1,29 @@ import React, { useState } from 'react' -// import { v4 as uuidv4 } from 'uuid' -import { TableRowShape } from '../../helpers/shapes' +import { TableRowProps } from '../../helpers/interface' import TableCell from '../TableCell/TableCell' import TableCellSum from '../TableCellSum/TableCellSum' -const areEqual = (prevProps, nextProps) => { - const { row, cells, lightArray } = prevProps +const areEqual = (prevProps: TableRowProps, nextProps: TableRowProps) => { + const { row, cells, lightList } = prevProps for (const id of row) { if (nextProps.cells[id].amount !== cells[id].amount) { return false } - if (nextProps.lightArray[id] !== lightArray[id]) { + if (nextProps.lightList[id] !== lightList[id]) { return false } } return true } -const TableRow = (props) => { +const TableRow: React.FC = (props) => { const { id, row, cells, rowSum, - lightArray, + lightList, onMouseEnterHandler, onMouseLeaveHandler, onClickIncrement @@ -45,21 +44,21 @@ const TableRow = (props) => { id={id} > {row.map(cellId => { - let value = cells[cellId].amount + const value = cells[cellId].amount + const percent = (cells[cellId].amount / rowSum * 100).toFixed(2) let styleString = '' - if (lightArray[cellId]) { styleString += '#6c757d' } + if (lightList[cellId]) { styleString += '#6c757d' } if (showPercent) { - value = (cells[cellId].amount / rowSum * 100).toFixed(2) - styleString += `linear-gradient(90deg, rgba(220,53,69,1) ${value}%, rgba(108,117,125,1) ${value}%)` + styleString += `linear-gradient(90deg, rgba(220,53,69,1) ${percent}%, rgba(108,117,125,1) ${percent}%)` } return ( { ) } -TableRow.propTypes = TableRowShape.isRequired - export default React.memo(TableRow, areEqual) diff --git a/src/helpers/generate.js b/src/helpers/generate.js deleted file mode 100644 index 2a4dc14..0000000 --- a/src/helpers/generate.js +++ /dev/null @@ -1,25 +0,0 @@ -import { v4 as uuidv4 } from 'uuid' - -export const generateTable = (rowsAmount, columnsAmount) => { - const table = [] - const rows = {} - const cells = {} - - for (let i = 0; i < rowsAmount; i++) { - const rowId = uuidv4() - table[i] = rowId - rows[rowId] = [] - - for (let j = 0; j < columnsAmount; j++) { - const cellId = uuidv4() - rows[rowId][j] = cellId - - cells[cellId] = { - id: cellId, - amount: Math.floor(Math.random() * 999) - } - } - } - - return { table, rows, cells } -} diff --git a/src/helpers/generate.tsx b/src/helpers/generate.tsx new file mode 100644 index 0000000..825060d --- /dev/null +++ b/src/helpers/generate.tsx @@ -0,0 +1,26 @@ +import { v4 as uuidv4 } from 'uuid' +import { RowsParams, CellsParams } from '../store/actions' + +export const generateTable = (rowsAmount: string | number, columnsAmount: string) => { + const table: Array = [] + const rows: RowsParams = {} + const cells: CellsParams = {} + + for (let i = 0; i < Number(rowsAmount); i++) { + const rowId = uuidv4() + table[i] = rowId + rows[rowId] = [] + + for (let j = 0; j < Number(columnsAmount); j++) { + const cellId = uuidv4() + rows[rowId][j] = cellId + + cells[cellId] = { + id: cellId, + amount: Math.floor(Math.random() * 999) + } + } + } + + return { table, rows, cells } +} diff --git a/src/helpers/getLightClosest.js b/src/helpers/getLightClosest.tsx similarity index 61% rename from src/helpers/getLightClosest.js rename to src/helpers/getLightClosest.tsx index c4c08e5..8ebac5a 100644 --- a/src/helpers/getLightClosest.js +++ b/src/helpers/getLightClosest.tsx @@ -1,4 +1,6 @@ -export const getLightClosest = (id, cells, lightsAmount) => { +import { CellsParams } from '../store/actions' + +export const getLightClosest = (id: string, cells: CellsParams, lightsAmount: string) => { const arr = Object.values(cells).map(item => ({ ...item, difference: Math.abs(item.amount - cells[id].amount) @@ -6,7 +8,7 @@ export const getLightClosest = (id, cells, lightsAmount) => { .slice(0, Number(lightsAmount)) .map(item => item.id) - const obj = {} + const obj: { [name: string]: boolean } = {} for (const id of arr) { obj[id] = true diff --git a/src/helpers/interface.tsx b/src/helpers/interface.tsx new file mode 100644 index 0000000..a254440 --- /dev/null +++ b/src/helpers/interface.tsx @@ -0,0 +1,27 @@ +import { SyntheticEvent } from 'react'; + +export interface TableRowProps { + id: string + row: Array + cells: { [name: string]: { id: string, amount: number } } + lightList: { [name: string]: boolean } + rowSum: number + onMouseEnterHandler: (event: SyntheticEvent) => void + onMouseLeaveHandler: () => void + onClickIncrement: (event: SyntheticEvent) => void +} + +export interface TableCellProps { + id: string + amount: any + styleString: string + onMouseEnterHandler: (event: SyntheticEvent) => void + onMouseLeaveHandler: () => void + onClickIncrement: (event: SyntheticEvent) => void +} + +export interface TableCellSumProps { + rowSum: number + onMouseEnterPercent: () => void + onMouseLeavePercent: () => void +} diff --git a/src/helpers/selectors.js b/src/helpers/selectors.tsx similarity index 58% rename from src/helpers/selectors.js rename to src/helpers/selectors.tsx index 8ae5bf0..d6f55c4 100644 --- a/src/helpers/selectors.js +++ b/src/helpers/selectors.tsx @@ -1,18 +1,19 @@ import { createSelector } from 'reselect' +import type { State } from '../store/actions' -export const getRows = state => state.rows +export const getRows = (state: State) => state.rows -export const getCells = state => state.cells +export const getCells = (state: State) => state.cells -export const getColumns = state => state.columns +export const getTable = (state: State) => state.table -export const getTable = state => state.table +export const getRowsAmount = (state: State) => state.params.rowsAmount -export const getRowsAmount = state => state.params.rowsAmount +export const getColumnsAmount = (state: State) => state.params.columnsAmount -export const getColumnsAmount = state => state.params.columnsAmount +export const getLightsAmount = (state: State) => state.params.lightsAmount -export const getLightsAmount = state => state.params.lightsAmount +export const getShowButtons = (state: State) => state.buttons export const getRowSum = createSelector( [getRows, getCells], @@ -32,7 +33,7 @@ export const getAverageRowSum = createSelector( row.map(item => cells[item].amount) )) - const res = [] + const res: number[] = [] for (let i = 0; i < onlyAmount.length; i++) { for (let j = 0; j < onlyAmount[i].length; j++) { res[j] = (res[j] || 0) + Math.floor(onlyAmount[i][j] / onlyAmount.length) diff --git a/src/helpers/shapes.js b/src/helpers/shapes.js deleted file mode 100644 index b5f819c..0000000 --- a/src/helpers/shapes.js +++ /dev/null @@ -1,66 +0,0 @@ -import PropTypes from 'prop-types' - -export const TableShape = PropTypes.shape({ - rows: PropTypes.number, - columns: PropTypes.number, - table: PropTypes.array, - sumRowArray: PropTypes.number, - lightsAmount: PropTypes.number -}) - -export const TableCellShape = PropTypes.shape({ - id: PropTypes.number, - cell: PropTypes.number, - amount: PropTypes.number, - isLight: PropTypes.bool, - showPercent: PropTypes.bool, - percent: PropTypes.number, - incrementCell: PropTypes.func, - lightArray: PropTypes.array, - onMouseEnterHandler: PropTypes.func, - onMouseLeaveHandler: PropTypes.func -}) - -export const TableCellSumShape = PropTypes.shape({ - id: PropTypes.number, - rowSum: PropTypes.number, - onMouseEnterPercent: PropTypes.func, - onMouseLeavePercent: PropTypes.func -}) - -export const TableRowShape = PropTypes.shape({ - id: PropTypes.number, - row: PropTypes.array, - cells: PropTypes.array, - rowSum: PropTypes.number, - lightArray: PropTypes.array, - onMouseEnterHandler: PropTypes.func, - onMouseLeaveHandler: PropTypes.func -}) - -export const AverageRowShape = PropTypes.shape({ - averageArray: PropTypes.array -}) - -export const FormShape = PropTypes.shape({ - setParamsData: PropTypes.func, - setTableData: PropTypes.func, - setRowsData: PropTypes.func, - setCellsData: PropTypes.func, - setShowButtonsBoll: PropTypes.func -}) - -export const ButtonsShape = PropTypes.shape({ - showButtons: PropTypes.bool, - rows: PropTypes.number, - columns: PropTypes.number, - table: PropTypes.array -}) - -export const ButtonDeleteShape = PropTypes.shape({ - deleteRow: PropTypes.func -}) - -export const ButtonAddShape = PropTypes.shape({ - addRow: PropTypes.func -}) diff --git a/src/index.jsx b/src/index.tsx similarity index 100% rename from src/index.jsx rename to src/index.tsx diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts new file mode 100644 index 0000000..ece12df --- /dev/null +++ b/src/react-app-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/src/store/actions.js b/src/store/actions.js deleted file mode 100644 index 6886ede..0000000 --- a/src/store/actions.js +++ /dev/null @@ -1,50 +0,0 @@ -export const ACTION_TYPES = { - SET_PARAMS: 'SET::PARAMS', - SET_TABLE: 'SET::TABLE', - SET_ROWS: 'SET::ROWS', - SET_CELLS: 'SET::CELLS', - SHOW_BUTTONS: 'SHOW::BUTTONS', - INCREMENT: 'INCREMENT', - ADD_ROW: 'ADD_ROW', - REMOVE_ROW: 'REMOVE::ROW' -} - -export const setParams = params => ({ - payload: params, - type: ACTION_TYPES.SET_PARAMS -}) - -export const setTable = params => ({ - payload: params, - type: ACTION_TYPES.SET_TABLE -}) - -export const setRows = params => ({ - payload: params, - type: ACTION_TYPES.SET_ROWS -}) - -export const setCells = params => ({ - payload: params, - type: ACTION_TYPES.SET_CELLS -}) - -export const setShowButtons = params => ({ - payload: params, - type: ACTION_TYPES.SHOW_BUTTONS -}) - -export const increment = params => ({ - type: ACTION_TYPES.INCREMENT, - payload: params -}) - -export const setNewRow = params => ({ - type: ACTION_TYPES.ADD_ROW, - payload: params -}) - -export const removeRow = params => ({ - type: ACTION_TYPES.REMOVE_ROW, - payload: params -}) diff --git a/src/store/actions.tsx b/src/store/actions.tsx new file mode 100644 index 0000000..ff9700d --- /dev/null +++ b/src/store/actions.tsx @@ -0,0 +1,92 @@ +export const ACTION_TYPES = { + SET_PARAMS: 'SET::PARAMS', + SET_TABLE: 'SET::TABLE', + SET_ROWS: 'SET::ROWS', + SET_CELLS: 'SET::CELLS', + SHOW_BUTTONS: 'SHOW::BUTTONS', + INCREMENT: 'INCREMENT', + ADD_ROW: 'ADD::ROW', + REMOVE_ROW: 'REMOVE::ROW' +} + +// TYPES + +export type State = { + table: Array + rows: RowsParams + cells: CellsParams + params: Params + buttons: boolean +} + +export type Action = ( + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType +) + +export type Params = { + [name: string]: string +} + +export type RowsParams = { + [name: string]: Array +} + +export type CellsParams = { + [name: string]: { id: string, amount: number } +} + + +export type NewRowsParams = { + table: Array + rows: RowsParams | any + cells: CellsParams | any +} + +// ACTIONS + +export const setParams = (params: Params) => ({ + payload: params, + type: ACTION_TYPES.SET_PARAMS +}) + +export const setTable = (params: Array) => ({ + payload: params, + type: ACTION_TYPES.SET_TABLE +}) + +export const setRows = (params: RowsParams) => ({ + payload: params, + type: ACTION_TYPES.SET_ROWS +}) + +export const setCells = (params: CellsParams) => ({ + payload: params, + type: ACTION_TYPES.SET_CELLS +}) + +export const setShowButtons = (params: boolean) => ({ + payload: params, + type: ACTION_TYPES.SHOW_BUTTONS +}) + +export const increment = (params: string) => ({ + payload: params, + type: ACTION_TYPES.INCREMENT +}) + +export const setNewRow = (params: NewRowsParams) => ({ + payload: params, + type: ACTION_TYPES.ADD_ROW +}) + +export const removeRow = (params: any) => ({ + payload: params, + type: ACTION_TYPES.REMOVE_ROW +}) diff --git a/src/store/reducers.js b/src/store/reducers.tsx similarity index 72% rename from src/store/reducers.js rename to src/store/reducers.tsx index 1885a30..516f315 100644 --- a/src/store/reducers.js +++ b/src/store/reducers.tsx @@ -1,7 +1,8 @@ import { combineReducers } from 'redux' import { ACTION_TYPES } from './actions' +import { Action, Params, RowsParams, CellsParams } from './actions' -const paramsReducer = (state = {}, action) => { +const paramsReducer = (state: Params = {}, action: Action): Params => { const { SET_PARAMS } = ACTION_TYPES switch (action.type) { @@ -12,7 +13,7 @@ const paramsReducer = (state = {}, action) => { } } -function tableReducer (state = [], action) { +function tableReducer (state: Array = [], action: Action): Array { const { SET_TABLE, ADD_ROW, REMOVE_ROW } = ACTION_TYPES switch (action.type) { @@ -21,13 +22,13 @@ function tableReducer (state = [], action) { case ADD_ROW: return [...state, action.payload.table] case REMOVE_ROW: - return state.filter(id => id !== action.payload.lastIndex) + return state.filter(id => id !== action.payload.lastRow) default: return state } } -const rowsReducer = (state = {}, action) => { +const rowsReducer = (state: RowsParams = {}, action: Action): RowsParams => { const { SET_ROWS, ADD_ROW, REMOVE_ROW } = ACTION_TYPES switch (action.type) { @@ -36,14 +37,15 @@ const rowsReducer = (state = {}, action) => { case ADD_ROW: return { ...state, ...action.payload.rows } case REMOVE_ROW: - delete state[action.payload.lastIndex] + delete state[action.payload.lastRow] return state default: return state } } -const cellsReducer = (state = {}, action) => { + +const cellsReducer = (state: CellsParams = {}, action: Action): CellsParams => { const { SET_CELLS, INCREMENT, ADD_ROW } = ACTION_TYPES switch (action.type) { @@ -64,7 +66,7 @@ const cellsReducer = (state = {}, action) => { } } -const buttonsReducer = (state = false, action) => { +const buttonsReducer = (state: boolean = false, action: Action): boolean => { const { SHOW_BUTTONS } = ACTION_TYPES switch (action.type) { diff --git a/src/store/store.js b/src/store/store.js deleted file mode 100644 index 1e38b93..0000000 --- a/src/store/store.js +++ /dev/null @@ -1,9 +0,0 @@ -import { createStore } from 'redux' -import { rootReducer } from './reducers' - -const store = createStore( - rootReducer, - window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() -) - -export default store diff --git a/src/store/store.tsx b/src/store/store.tsx new file mode 100644 index 0000000..134f616 --- /dev/null +++ b/src/store/store.tsx @@ -0,0 +1,6 @@ +import { createStore } from 'redux' +import { rootReducer } from './reducers' + +const store = createStore(rootReducer) + +export default store diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9a05724 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react" + }, + "include": [ + "src" + ] +} From 8d3ba7f6fc76538447f49f1eb1e71fb1729a700c Mon Sep 17 00:00:00 2001 From: denkondratiev Date: Thu, 30 Jul 2020 12:54:03 +0300 Subject: [PATCH 2/3] after review --- coverage-ts/assets/source-file.css | 21 ++ coverage-ts/assets/source-file.js | 40 ++++ coverage-ts/files/src/App.tsx.html | 33 +++ .../components/AverageRow/AverageRow.tsx.html | 36 +++ .../components/ButtonAdd/ButtonAdd.tsx.html | 35 +++ .../ButtonDelete/ButtonDelete.tsx.html | 37 +++ .../src/components/Buttons/Buttons.tsx.html | 60 +++++ .../files/src/components/Form/Form.tsx.html | 156 +++++++++++++ .../files/src/components/Table/Table.tsx.html | 81 +++++++ .../components/TableCell/TableCell.tsx.html | 67 ++++++ .../TableCellSum/TableCellSum.tsx.html | 49 ++++ .../src/components/TableRow/TableRow.tsx.html | 93 ++++++++ .../files/src/helpers/generate.tsx.html | 50 +++++ .../src/helpers/getLightClosest.tsx.html | 32 +++ .../files/src/helpers/interface.tsx.html | 45 ++++ .../files/src/helpers/selectors.tsx.html | 59 +++++ coverage-ts/files/src/index.tsx.html | 33 +++ coverage-ts/files/src/react-app-env.d.ts.html | 19 ++ coverage-ts/files/src/store/actions.tsx.html | 110 +++++++++ coverage-ts/files/src/store/reducers.tsx.html | 113 ++++++++++ coverage-ts/files/src/store/store.tsx.html | 24 ++ coverage-ts/index.html | 14 ++ package-lock.json | 211 ++++++++++++++++++ package.json | 6 +- src/components/Buttons/Buttons.tsx | 9 +- src/components/Form/Form.tsx | 52 ++--- src/components/Table/Table.tsx | 2 + src/components/TableCell/TableCell.tsx | 4 +- src/components/TableRow/TableRow.tsx | 17 +- src/helpers/generate.tsx | 42 ++-- src/helpers/getLightClosest.tsx | 12 +- src/helpers/interface.tsx | 2 +- src/helpers/selectors.tsx | 24 +- src/store/actions.tsx | 6 +- src/store/reducers.tsx | 17 +- 35 files changed, 1516 insertions(+), 95 deletions(-) create mode 100644 coverage-ts/assets/source-file.css create mode 100644 coverage-ts/assets/source-file.js create mode 100644 coverage-ts/files/src/App.tsx.html create mode 100644 coverage-ts/files/src/components/AverageRow/AverageRow.tsx.html create mode 100644 coverage-ts/files/src/components/ButtonAdd/ButtonAdd.tsx.html create mode 100644 coverage-ts/files/src/components/ButtonDelete/ButtonDelete.tsx.html create mode 100644 coverage-ts/files/src/components/Buttons/Buttons.tsx.html create mode 100644 coverage-ts/files/src/components/Form/Form.tsx.html create mode 100644 coverage-ts/files/src/components/Table/Table.tsx.html create mode 100644 coverage-ts/files/src/components/TableCell/TableCell.tsx.html create mode 100644 coverage-ts/files/src/components/TableCellSum/TableCellSum.tsx.html create mode 100644 coverage-ts/files/src/components/TableRow/TableRow.tsx.html create mode 100644 coverage-ts/files/src/helpers/generate.tsx.html create mode 100644 coverage-ts/files/src/helpers/getLightClosest.tsx.html create mode 100644 coverage-ts/files/src/helpers/interface.tsx.html create mode 100644 coverage-ts/files/src/helpers/selectors.tsx.html create mode 100644 coverage-ts/files/src/index.tsx.html create mode 100644 coverage-ts/files/src/react-app-env.d.ts.html create mode 100644 coverage-ts/files/src/store/actions.tsx.html create mode 100644 coverage-ts/files/src/store/reducers.tsx.html create mode 100644 coverage-ts/files/src/store/store.tsx.html create mode 100644 coverage-ts/index.html diff --git a/coverage-ts/assets/source-file.css b/coverage-ts/assets/source-file.css new file mode 100644 index 0000000..9a9dd80 --- /dev/null +++ b/coverage-ts/assets/source-file.css @@ -0,0 +1,21 @@ +.uncovered { + background: rgba(235, 26, 26, 0.3); +} +.CodeMirror { + border: 1px solid #ccc; + border-radius: 3px; + height: auto; +} +.TS-lineuncovered { + background: rgba(255, 255, 255, 0.3); + width: 24px; +} +/* NOTE: I have to increase the specificity because of semantic-ui */ +p.footer-text { + text-align: center; + margin: 3em 0; +} +.gutter-marker { + text-align: center; + font-size: 0.6em; +} diff --git a/coverage-ts/assets/source-file.js b/coverage-ts/assets/source-file.js new file mode 100644 index 0000000..786b6d1 --- /dev/null +++ b/coverage-ts/assets/source-file.js @@ -0,0 +1,40 @@ +"use strict"; + +document.addEventListener("DOMContentLoaded", () => { + const myTextArea = document.getElementById("editor"); + const codeMirrorInstance = CodeMirror.fromTextArea(myTextArea, { + readOnly: true, + lineNumbers: true, + lineWrapping: false, + mode: "text/typescript", + gutters: ["TS-lineuncovered", "CodeMirror-linenumbers"] + }); + const annotations = JSON.parse( + document.getElementById("annotations").textContent + ); + const gutters = {}; + + annotations.forEach((annotation) => { + gutters[annotation.line] = (gutters[annotation.line] || 0) + 1; + codeMirrorInstance.markText( + { line: annotation.line, ch: annotation.character }, + { + line: annotation.line, + ch: annotation.character + annotation.text.length + }, + { + className: "uncovered" + } + ); + }); + + Object.entries(gutters).forEach(([line, count]) => { + const gutterMarker = document.createElement("div"); + + gutterMarker.textContent = count + "x"; + gutterMarker.classList.add("gutter-marker"); + gutterMarker.style.background = "rgba(255,0,0," + count * 0.2 + ")"; + + codeMirrorInstance.setGutterMarker(+line, "TS-lineuncovered", gutterMarker); + }); +}); diff --git a/coverage-ts/files/src/App.tsx.html b/coverage-ts/files/src/App.tsx.html new file mode 100644 index 0000000..6bdb251 --- /dev/null +++ b/coverage-ts/files/src/App.tsx.html @@ -0,0 +1,33 @@ + + + + + App.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\App.tsx100.00%80%14140
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/components/AverageRow/AverageRow.tsx.html b/coverage-ts/files/src/components/AverageRow/AverageRow.tsx.html new file mode 100644 index 0000000..a470fbb --- /dev/null +++ b/coverage-ts/files/src/components/AverageRow/AverageRow.tsx.html @@ -0,0 +1,36 @@ + + + + + AverageRow.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\components\AverageRow\AverageRow.tsx100.00%80%23230
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/components/ButtonAdd/ButtonAdd.tsx.html b/coverage-ts/files/src/components/ButtonAdd/ButtonAdd.tsx.html new file mode 100644 index 0000000..cc85215 --- /dev/null +++ b/coverage-ts/files/src/components/ButtonAdd/ButtonAdd.tsx.html @@ -0,0 +1,35 @@ + + + + + ButtonAdd.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\components\ButtonAdd\ButtonAdd.tsx100.00%80%14140
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/components/ButtonDelete/ButtonDelete.tsx.html b/coverage-ts/files/src/components/ButtonDelete/ButtonDelete.tsx.html new file mode 100644 index 0000000..7cb2dfd --- /dev/null +++ b/coverage-ts/files/src/components/ButtonDelete/ButtonDelete.tsx.html @@ -0,0 +1,37 @@ + + + + + ButtonDelete.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\components\ButtonDelete\ButtonDelete.tsx100.00%80%16160
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/components/Buttons/Buttons.tsx.html b/coverage-ts/files/src/components/Buttons/Buttons.tsx.html new file mode 100644 index 0000000..6224856 --- /dev/null +++ b/coverage-ts/files/src/components/Buttons/Buttons.tsx.html @@ -0,0 +1,60 @@ + + + + + Buttons.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\components\Buttons\Buttons.tsx100.00%80%56560
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/components/Form/Form.tsx.html b/coverage-ts/files/src/components/Form/Form.tsx.html new file mode 100644 index 0000000..8e070fb --- /dev/null +++ b/coverage-ts/files/src/components/Form/Form.tsx.html @@ -0,0 +1,156 @@ + + + + + Form.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\components\Form\Form.tsx100.00%80%1811810
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/components/Table/Table.tsx.html b/coverage-ts/files/src/components/Table/Table.tsx.html new file mode 100644 index 0000000..fce4ec9 --- /dev/null +++ b/coverage-ts/files/src/components/Table/Table.tsx.html @@ -0,0 +1,81 @@ + + + + + Table.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\components\Table\Table.tsx100.00%80%1061060
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/components/TableCell/TableCell.tsx.html b/coverage-ts/files/src/components/TableCell/TableCell.tsx.html new file mode 100644 index 0000000..f255511 --- /dev/null +++ b/coverage-ts/files/src/components/TableCell/TableCell.tsx.html @@ -0,0 +1,67 @@ + + + + + TableCell.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\components\TableCell\TableCell.tsx100.00%80%54540
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/components/TableCellSum/TableCellSum.tsx.html b/coverage-ts/files/src/components/TableCellSum/TableCellSum.tsx.html new file mode 100644 index 0000000..f509216 --- /dev/null +++ b/coverage-ts/files/src/components/TableCellSum/TableCellSum.tsx.html @@ -0,0 +1,49 @@ + + + + + TableCellSum.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\components\TableCellSum\TableCellSum.tsx100.00%80%32320
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/components/TableRow/TableRow.tsx.html b/coverage-ts/files/src/components/TableRow/TableRow.tsx.html new file mode 100644 index 0000000..c64c5cb --- /dev/null +++ b/coverage-ts/files/src/components/TableRow/TableRow.tsx.html @@ -0,0 +1,93 @@ + + + + + TableRow.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\components\TableRow\TableRow.tsx100.00%80%1051050
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/helpers/generate.tsx.html b/coverage-ts/files/src/helpers/generate.tsx.html new file mode 100644 index 0000000..9438261 --- /dev/null +++ b/coverage-ts/files/src/helpers/generate.tsx.html @@ -0,0 +1,50 @@ + + + + + generate.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\helpers\generate.tsx100.00%80%62620
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/helpers/getLightClosest.tsx.html b/coverage-ts/files/src/helpers/getLightClosest.tsx.html new file mode 100644 index 0000000..88bee04 --- /dev/null +++ b/coverage-ts/files/src/helpers/getLightClosest.tsx.html @@ -0,0 +1,32 @@ + + + + + getLightClosest.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\helpers\getLightClosest.tsx100.00%80%43430
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/helpers/interface.tsx.html b/coverage-ts/files/src/helpers/interface.tsx.html new file mode 100644 index 0000000..0be1ffd --- /dev/null +++ b/coverage-ts/files/src/helpers/interface.tsx.html @@ -0,0 +1,45 @@ + + + + + interface.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\helpers\interface.tsx100.00%80%38380
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/helpers/selectors.tsx.html b/coverage-ts/files/src/helpers/selectors.tsx.html new file mode 100644 index 0000000..886e31c --- /dev/null +++ b/coverage-ts/files/src/helpers/selectors.tsx.html @@ -0,0 +1,59 @@ + + + + + selectors.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\helpers\selectors.tsx100.00%80%1071070
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/index.tsx.html b/coverage-ts/files/src/index.tsx.html new file mode 100644 index 0000000..546fe3d --- /dev/null +++ b/coverage-ts/files/src/index.tsx.html @@ -0,0 +1,33 @@ + + + + + index.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\index.tsx100.00%80%14140
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/react-app-env.d.ts.html b/coverage-ts/files/src/react-app-env.d.ts.html new file mode 100644 index 0000000..9f3285b --- /dev/null +++ b/coverage-ts/files/src/react-app-env.d.ts.html @@ -0,0 +1,19 @@ + + + + + react-app-env.d.ts + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\react-app-env.d.ts100.00%80%000
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/store/actions.tsx.html b/coverage-ts/files/src/store/actions.tsx.html new file mode 100644 index 0000000..20c6062 --- /dev/null +++ b/coverage-ts/files/src/store/actions.tsx.html @@ -0,0 +1,110 @@ + + + + + actions.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\store\actions.tsx97.35%80%1131103
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/store/reducers.tsx.html b/coverage-ts/files/src/store/reducers.tsx.html new file mode 100644 index 0000000..4720e4d --- /dev/null +++ b/coverage-ts/files/src/store/reducers.tsx.html @@ -0,0 +1,113 @@ + + + + + reducers.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\store\reducers.tsx87.43%80%16714621
+ + + + \ No newline at end of file diff --git a/coverage-ts/files/src/store/store.tsx.html b/coverage-ts/files/src/store/store.tsx.html new file mode 100644 index 0000000..fbac02c --- /dev/null +++ b/coverage-ts/files/src/store/store.tsx.html @@ -0,0 +1,24 @@ + + + + + store.tsx + + + + + + + + +

TypeScript coverage report

FilenamePercentThresholdTotalCoveredUncovered
src\store\store.tsx100.00%80%660
+ + + + \ No newline at end of file diff --git a/coverage-ts/index.html b/coverage-ts/index.html new file mode 100644 index 0000000..b34ca95 --- /dev/null +++ b/coverage-ts/index.html @@ -0,0 +1,14 @@ + + + + + TypeScript coverage report + + + + +

TypeScript coverage report

Summary

PercentThresholdTotalCoveredUncovered
97.91%80%1151112724

Files

FilenamePercentTotalCoveredUncovered
src\store\actions.tsx97.35%1131103
src\helpers\generate.tsx100.00%62620
src\components\Form\Form.tsx100.00%1811810
src\helpers\interface.tsx100.00%38380
src\components\TableCell\TableCell.tsx100.00%54540
src\components\TableCellSum\TableCellSum.tsx100.00%32320
src\components\TableRow\TableRow.tsx100.00%1051050
src\helpers\selectors.tsx100.00%1071070
src\components\AverageRow\AverageRow.tsx100.00%23230
src\helpers\getLightClosest.tsx100.00%43430
src\components\Table\Table.tsx100.00%1061060
src\components\ButtonDelete\ButtonDelete.tsx100.00%16160
src\components\ButtonAdd\ButtonAdd.tsx100.00%14140
src\components\Buttons\Buttons.tsx100.00%56560
src\App.tsx100.00%14140
src\store\reducers.tsx87.43%16714621
src\store\store.tsx100.00%660
src\index.tsx100.00%14140
src\react-app-env.d.ts100.00%000
+ + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 758dee3..20efcfa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1347,11 +1347,42 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==" }, + "@semantic-ui-react/event-stack": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@semantic-ui-react/event-stack/-/event-stack-3.1.1.tgz", + "integrity": "sha512-SA7VOu/tY3OkooR++mm9voeQrJpYXjJaMHO1aFCcSouS2xhqMR9Gnz0LEGLOR0h9ueWPBKaQzKIrx3FTTJZmUQ==", + "dev": true, + "requires": { + "exenv": "^1.2.2", + "prop-types": "^15.6.2" + } + }, "@sheerun/mutationobserver-shim": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz", "integrity": "sha512-DetpxZw1fzPD5xUBrIAoplLChO2VB8DlL5Gg+I1IR9b2wPqYIca2WSUxL5g1vLeR4MsQq1NeWriXAVffV+U1Fw==" }, + "@stardust-ui/react-component-event-listener": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@stardust-ui/react-component-event-listener/-/react-component-event-listener-0.38.0.tgz", + "integrity": "sha512-sIP/e0dyOrrlb8K7KWumfMxj/gAifswTBC4o68Aa+C/GA73ccRp/6W1VlHvF/dlOR4KLsA+5SKnhjH36xzPsWg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.1.2", + "prop-types": "^15.7.2" + } + }, + "@stardust-ui/react-component-ref": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@stardust-ui/react-component-ref/-/react-component-ref-0.38.0.tgz", + "integrity": "sha512-xjs6WnvJVueSIXMWw0C3oWIgAPpcD03qw43oGOjUXqFktvpNkB73JoKIhS4sCrtQxBdct75qqr4ZL6JiyPcESw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.1.2", + "prop-types": "^15.7.2", + "react-is": "^16.6.3" + } + }, "@svgr/babel-plugin-add-jsx-attribute": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz", @@ -3601,6 +3632,12 @@ } } }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==", + "dev": true + }, "clean-css": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", @@ -3736,6 +3773,12 @@ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==" }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -4006,6 +4049,16 @@ "sha.js": "^2.4.8" } }, + "create-react-context": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.3.0.tgz", + "integrity": "sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw==", + "dev": true, + "requires": { + "gud": "^1.0.0", + "warning": "^4.0.3" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -4733,6 +4786,12 @@ } } }, + "eastasianwidth": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.1.1.tgz", + "integrity": "sha1-RNZW3p2kFWlEZzNTZfsxR7hXK3w=", + "dev": true + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -5557,6 +5616,12 @@ "strip-eof": "^1.0.0" } }, + "exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=", + "dev": true + }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -6455,6 +6520,12 @@ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" }, + "gud": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", + "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==", + "dev": true + }, "gzip-size": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", @@ -8047,6 +8118,12 @@ "object.assign": "^4.1.0" } }, + "keyboard-key": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keyboard-key/-/keyboard-key-1.1.0.tgz", + "integrity": "sha512-qkBzPTi3rlAKvX7k0/ub44sqOfXeLc/jcnGGmj5c7BJpU8eDrEVPyhCvNYAaoubbsLm9uGWwQJO1ytQK1a9/dQ==", + "dev": true + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -8717,6 +8794,12 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "dev": true + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -9471,6 +9554,12 @@ "ts-pnp": "^1.1.6" } }, + "popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "dev": true + }, "portfinder": { "version": "1.0.26", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz", @@ -10894,6 +10983,21 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-popper": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.7.tgz", + "integrity": "sha512-nmqYTx7QVjCm3WUZLeuOomna138R1luC4EqkW3hxJUrAe+3eNz3oFCLYdnPwILfn0mX1Ew2c3wctrjlUMYYUww==", + "dev": true, + "requires": { + "@babel/runtime": "^7.1.2", + "create-react-context": "^0.3.0", + "deep-equal": "^1.1.1", + "popper.js": "^1.14.4", + "prop-types": "^15.6.1", + "typed-styles": "^0.0.7", + "warning": "^4.0.2" + } + }, "react-redux": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", @@ -11763,6 +11867,25 @@ "node-forge": "0.9.0" } }, + "semantic-ui-react": { + "version": "0.88.2", + "resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-0.88.2.tgz", + "integrity": "sha512-+02kN2z8PuA/cMdvDUsHhbJmBzxxgOXVHMFr9XK7zGb0wkW9A6OPQMFokWz7ozlVtKjN6r7zsb+Qvjk/qq1OWw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.1.2", + "@semantic-ui-react/event-stack": "^3.1.0", + "@stardust-ui/react-component-event-listener": "~0.38.0", + "@stardust-ui/react-component-ref": "~0.38.0", + "classnames": "^2.2.6", + "keyboard-key": "^1.0.4", + "lodash": "^4.17.15", + "prop-types": "^15.7.2", + "react-is": "^16.8.6", + "react-popper": "^1.3.4", + "shallowequal": "^1.1.0" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -11952,6 +12075,12 @@ } } }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "dev": true + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -12741,6 +12870,16 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" }, + "terminal-table": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/terminal-table/-/terminal-table-0.0.12.tgz", + "integrity": "sha1-e1bQCapoKN/dEPEbZU55wGKWX6I=", + "dev": true, + "requires": { + "colors": "^1.0.3", + "eastasianwidth": "^0.1.0" + } + }, "terser": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", @@ -13006,6 +13145,16 @@ "escape-string-regexp": "^1.0.2" } }, + "ts-lib-utils": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/ts-lib-utils/-/ts-lib-utils-2.9.0.tgz", + "integrity": "sha512-N+hiB60c/Za3sXTCptnaTl6eS4U7PEHC6obf8jBsC4Paae0nKwtreh68CXp7JNLOKil4t/k1dIwL4cUATmMJMQ==", + "dev": true, + "requires": { + "glob": "7", + "tslib": "1 || 2" + } + }, "ts-pnp": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.6.tgz", @@ -13078,6 +13227,18 @@ "prelude-ls": "~1.1.2" } }, + "type-coverage-core": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/type-coverage-core/-/type-coverage-core-2.9.0.tgz", + "integrity": "sha512-99iPqoHnbat+8FKkQaHed5CztFTwNFa+33Pr975tokoHQRcBEvuFWTT8ZjdF3BbrWblYU4Or5YtZi/T7tk4VCA==", + "dev": true, + "requires": { + "minimatch": "3", + "ts-lib-utils": "^2.9.0", + "tslib": "1 || 2", + "tsutils": "3" + } + }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -13092,6 +13253,12 @@ "mime-types": "~2.1.24" } }, + "typed-styles": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz", + "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -13102,6 +13269,41 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==" }, + "typescript-coverage-report": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/typescript-coverage-report/-/typescript-coverage-report-0.1.3.tgz", + "integrity": "sha512-fvTlmz//XUZSZRc9BqpseymTJlpP6YlCj2dzYy10BZJJ6FbdXcvFSH3MNLi+HaAu4i+eAkuzjCWzqECCTKZeuQ==", + "dev": true, + "requires": { + "colors": "^1.4.0", + "commander": "^5.0.0", + "ncp": "^2.0.0", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "rimraf": "^3.0.2", + "semantic-ui-react": "^0.88.2", + "terminal-table": "^0.0.12", + "type-coverage-core": "^2.4.1", + "typescript": "^3.8.3" + }, + "dependencies": { + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -13388,6 +13590,15 @@ "makeerror": "1.0.x" } }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, "watchpack": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz", diff --git a/package.json b/package.json index b0ecaa0..1bb87cd 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,8 @@ "eject": "react-scripts eject", "predeploy": "npm run build", "deploy": "gh-pages -d build", - "lint": "eslint --ext .jsx,.js ./src/ --fix" + "lint": "eslint --ext .jsx,.js ./src/ --fix", + "ts-coverage": "typescript-coverage-report" }, "browserslist": { "production": [ @@ -53,6 +54,7 @@ "eslint-plugin-react": "^7.20.3", "eslint-plugin-standard": "^4.0.1", "gh-pages": "^3.1.0", - "redux-devtools": "^3.5.0" + "redux-devtools": "^3.5.0", + "typescript-coverage-report": "^0.1.3" } } diff --git a/src/components/Buttons/Buttons.tsx b/src/components/Buttons/Buttons.tsx index 37ac18c..ed3990f 100644 --- a/src/components/Buttons/Buttons.tsx +++ b/src/components/Buttons/Buttons.tsx @@ -8,20 +8,23 @@ import { setNewRow, removeRow } from '../../store/actions' import { useDispatch, useSelector } from 'react-redux' const Buttons: React.FC = () => { + const dispatch = useDispatch() const columnsAmount = useSelector(getColumnsAmount) - const table = useSelector(getTable) const showButtons = useSelector(getShowButtons) + const table = useSelector(getTable) const addRow = (): void => { const { table, rows, cells } = generateTable(1, columnsAmount) + dispatch(setNewRow({ table, rows, cells})) } const deleteRow = (): void => { - const lastRow = table[table.length - 1] - dispatch(removeRow({ lastRow })) + const lastRowKey = table[table.length - 1] + + dispatch(removeRow({ lastRowKey, columnsAmount })) } return ( diff --git a/src/components/Form/Form.tsx b/src/components/Form/Form.tsx index 0ff96f2..c5483a6 100644 --- a/src/components/Form/Form.tsx +++ b/src/components/Form/Form.tsx @@ -1,6 +1,7 @@ import React, { useState } from 'react' import { generateTable } from '../../helpers/generate' import { useDispatch } from 'react-redux' +import { batch } from 'react-redux' import './Form.css' import { setParams, @@ -16,6 +17,12 @@ type InputValue = { lightsAmount: string } +type ErrorValue = { + rowsAmount: boolean, + columnsAmount: boolean, + lightsAmount: boolean +} + const Form: React.FC = () => { const dispatch = useDispatch() @@ -26,7 +33,7 @@ const Form: React.FC = () => { lightsAmount: '' }) - const [error, setError] = useState<{ [name: string]: boolean }>({ + const [error, setError] = useState({ rowsAmount: false, columnsAmount: false, lightsAmount: false @@ -36,17 +43,19 @@ const Form: React.FC = () => { event.preventDefault() const rowsAmount = inputValue.rowsAmount - const columnsAmount = inputValue.columnsAmount + const columnsAmount =inputValue.columnsAmount const lightsAmount = inputValue.lightsAmount if (Number(rowsAmount) > 0 && Number(columnsAmount) > 0 && Number(lightsAmount) > 0) { const { table, rows, cells } = generateTable(rowsAmount, columnsAmount) - dispatch(setParams({ rowsAmount, columnsAmount, lightsAmount })) - dispatch(setTable(table)) - dispatch(setRows(rows)) - dispatch(setCells(cells)) - dispatch(setShowButtons(true)) + batch(() => { + dispatch(setParams({ rowsAmount, columnsAmount, lightsAmount })) + dispatch(setTable(table)) + dispatch(setRows(rows)) + dispatch(setCells(cells)) + dispatch(setShowButtons(true)) + }) setInputValue({ rowsAmount: '', @@ -55,34 +64,17 @@ const Form: React.FC = () => { }) } - const errorObj = { - rowsAmount: false, - columnsAmount: false, - lightsAmount: false - } - - if (!rowsAmount || Number(rowsAmount) <= 0) { - errorObj.rowsAmount = true - } - - if (!columnsAmount || Number(columnsAmount) <= 0) { - errorObj.columnsAmount = true - } - - if (!lightsAmount || Number(lightsAmount) <= 0) { - errorObj.lightsAmount = true - } - setError({ - rowsAmount: errorObj.rowsAmount, - columnsAmount: errorObj.columnsAmount, - lightsAmount: errorObj.lightsAmount + rowsAmount: (!rowsAmount || Number(rowsAmount) <= 0) ? true : false, + columnsAmount: (!columnsAmount || Number(columnsAmount) <= 0) ? true : false, + lightsAmount: (!lightsAmount || Number(lightsAmount) <= 0) ? true : false }) } const onChangeHandler = (event: React.FormEvent): void => { const { name, value } = event.currentTarget - setError({ [name]: false }) + + setError({ ...error, [name]: false }) setInputValue({ ...inputValue, [name]: value }) } @@ -143,4 +135,4 @@ const Form: React.FC = () => { ) } -export default React.memo(Form) +export default Form diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx index 7a8062f..a66563b 100644 --- a/src/components/Table/Table.tsx +++ b/src/components/Table/Table.tsx @@ -30,6 +30,8 @@ const Table: React.FC = () => { const onClickIncrement = (event: SyntheticEvent) => { const { id } = event.currentTarget dispatch(increment(id)) + const obj = getLightClosest(id, cells, lightsAmount) + setLightList(obj) } return ( diff --git a/src/components/TableCell/TableCell.tsx b/src/components/TableCell/TableCell.tsx index e1b0595..8fe3db7 100644 --- a/src/components/TableCell/TableCell.tsx +++ b/src/components/TableCell/TableCell.tsx @@ -34,8 +34,8 @@ const TableCell: React.FC = (props) => { return ( onClickIncrement(event)} - onMouseEnter={(event) => onMouseEnterHandler(event)} + onClick={onClickIncrement} + onMouseEnter={onMouseEnterHandler} onMouseLeave={onMouseLeaveHandler} style={styleObj} > diff --git a/src/components/TableRow/TableRow.tsx b/src/components/TableRow/TableRow.tsx index dc98df3..57fffc6 100644 --- a/src/components/TableRow/TableRow.tsx +++ b/src/components/TableRow/TableRow.tsx @@ -3,18 +3,15 @@ import { TableRowProps } from '../../helpers/interface' import TableCell from '../TableCell/TableCell' import TableCellSum from '../TableCellSum/TableCellSum' -const areEqual = (prevProps: TableRowProps, nextProps: TableRowProps) => { +const areEqual = (prevProps: TableRowProps, nextProps: TableRowProps): boolean => { const { row, cells, lightList } = prevProps - for (const id of row) { - if (nextProps.cells[id].amount !== cells[id].amount) { - return false - } - if (nextProps.lightList[id] !== lightList[id]) { - return false - } - } - return true + const equal = !row.some((id) => ( + nextProps.cells[id].amount !== cells[id].amount || + nextProps.lightList[id] !== lightList[id] + )) + + return equal } const TableRow: React.FC = (props) => { diff --git a/src/helpers/generate.tsx b/src/helpers/generate.tsx index 825060d..a17e858 100644 --- a/src/helpers/generate.tsx +++ b/src/helpers/generate.tsx @@ -1,26 +1,32 @@ import { v4 as uuidv4 } from 'uuid' import { RowsParams, CellsParams } from '../store/actions' -export const generateTable = (rowsAmount: string | number, columnsAmount: string) => { - const table: Array = [] - const rows: RowsParams = {} - const cells: CellsParams = {} +export const generateTable = (rowsAmount: string | number, columnsAmount: string | number) => { + const table: Array = new Array(+rowsAmount).fill(0).map((item: string) => item = uuidv4()) - for (let i = 0; i < Number(rowsAmount); i++) { - const rowId = uuidv4() - table[i] = rowId - rows[rowId] = [] + const preparedArray: Array = new Array(+rowsAmount * +columnsAmount).fill(0).map((item: string) => item = uuidv4()) - for (let j = 0; j < Number(columnsAmount); j++) { - const cellId = uuidv4() - rows[rowId][j] = cellId + const rows = table.reduce( + (acum: RowsParams, rowID, index) => ( + (acum[rowID] = preparedArray.slice( + +columnsAmount * index, + +columnsAmount * index + +columnsAmount + )), + acum + ), + {} + ) - cells[cellId] = { - id: cellId, - amount: Math.floor(Math.random() * 999) - } - } - } + const cells = preparedArray.reduce( + (acum: CellsParams, cellID: string) => ( + (acum[cellID] = { + id: cellID, + amount: Math.floor(Math.random() * 999) + }), + acum + ), + {} + ); - return { table, rows, cells } + return { table, rows, cells }; } diff --git a/src/helpers/getLightClosest.tsx b/src/helpers/getLightClosest.tsx index 8ebac5a..6a95e52 100644 --- a/src/helpers/getLightClosest.tsx +++ b/src/helpers/getLightClosest.tsx @@ -1,18 +1,14 @@ import { CellsParams } from '../store/actions' -export const getLightClosest = (id: string, cells: CellsParams, lightsAmount: string) => { +export const getLightClosest = (id: string, cells: CellsParams, lightsAmount: string | number) => { const arr = Object.values(cells).map(item => ({ ...item, difference: Math.abs(item.amount - cells[id].amount) })).sort((a, b) => a.difference - b.difference) - .slice(0, Number(lightsAmount)) + .slice(0, +lightsAmount) .map(item => item.id) - const obj: { [name: string]: boolean } = {} + const resObj: { [name: string]: boolean } = arr.reduce((prev, cur) => ( { ...prev, [cur]: true } ), {}); - for (const id of arr) { - obj[id] = true - } - - return obj + return resObj } diff --git a/src/helpers/interface.tsx b/src/helpers/interface.tsx index a254440..009f710 100644 --- a/src/helpers/interface.tsx +++ b/src/helpers/interface.tsx @@ -13,7 +13,7 @@ export interface TableRowProps { export interface TableCellProps { id: string - amount: any + amount: string | number styleString: string onMouseEnterHandler: (event: SyntheticEvent) => void onMouseLeaveHandler: () => void diff --git a/src/helpers/selectors.tsx b/src/helpers/selectors.tsx index d6f55c4..0c0fd08 100644 --- a/src/helpers/selectors.tsx +++ b/src/helpers/selectors.tsx @@ -27,19 +27,15 @@ export const getRowSum = createSelector( ) export const getAverageRowSum = createSelector( - [getRows, getCells], - (rows, cells) => { - const onlyAmount = Object.values(rows).map(row => ( - row.map(item => cells[item].amount) - )) - - const res: number[] = [] - for (let i = 0; i < onlyAmount.length; i++) { - for (let j = 0; j < onlyAmount[i].length; j++) { - res[j] = (res[j] || 0) + Math.floor(onlyAmount[i][j] / onlyAmount.length) - } - } - - return res + [getRows, getCells, getColumnsAmount], + (rows, cells, columnsAmount) => { + const onlyAmount = Object.values(rows).map(row => ( + row.map(item => cells[item].amount) + )) + + const averageRow = onlyAmount.reduce((acum, cur) => + cur.map((amount, index) => (acum[index] += amount)), new Array(+columnsAmount).fill(0) + ) + return averageRow.map((item: number) => Math.floor(item / onlyAmount.length)) } ) diff --git a/src/store/actions.tsx b/src/store/actions.tsx index ff9700d..f60666e 100644 --- a/src/store/actions.tsx +++ b/src/store/actions.tsx @@ -31,7 +31,7 @@ export type Action = ( ) export type Params = { - [name: string]: string + [name: string]: string | number } export type RowsParams = { @@ -45,8 +45,8 @@ export type CellsParams = { export type NewRowsParams = { table: Array - rows: RowsParams | any - cells: CellsParams | any + rows: RowsParams + cells: CellsParams } // ACTIONS diff --git a/src/store/reducers.tsx b/src/store/reducers.tsx index 516f315..0f056d0 100644 --- a/src/store/reducers.tsx +++ b/src/store/reducers.tsx @@ -22,7 +22,7 @@ function tableReducer (state: Array = [], action: Action): Array case ADD_ROW: return [...state, action.payload.table] case REMOVE_ROW: - return state.filter(id => id !== action.payload.lastRow) + return state.filter(id => id !== action.payload.lastRowKey) default: return state } @@ -37,22 +37,31 @@ const rowsReducer = (state: RowsParams = {}, action: Action): RowsParams => { case ADD_ROW: return { ...state, ...action.payload.rows } case REMOVE_ROW: - delete state[action.payload.lastRow] + delete state[action.payload.lastRowKey] return state default: return state } } - const cellsReducer = (state: CellsParams = {}, action: Action): CellsParams => { - const { SET_CELLS, INCREMENT, ADD_ROW } = ACTION_TYPES + const { SET_CELLS, INCREMENT, ADD_ROW, REMOVE_ROW } = ACTION_TYPES switch (action.type) { case SET_CELLS: return action.payload case ADD_ROW: return { ...state, ...action.payload.cells } + case REMOVE_ROW: + const { columnsAmount } = action.payload + const notDeleted = Object.keys(state).slice(0, -columnsAmount) + + const res = Object.values(state).filter((cellsItem, index) => ( + cellsItem.id === notDeleted[index] + )) + const resObj: CellsParams = {} + res.map((item: { id: string, amount: number }) => resObj[item.id] = { ...item }) + return resObj case INCREMENT: return { ...state, From 2f8c6756a78d797dfbcf8fa997f2a7288f3ed82b Mon Sep 17 00:00:00 2001 From: denkondratiev Date: Thu, 30 Jul 2020 14:49:50 +0300 Subject: [PATCH 3/3] update package --- package-lock.json | 160 +++++++++++++++++++++++----------------------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/package-lock.json b/package-lock.json index 20efcfa..46bca4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1833,9 +1833,9 @@ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, "@types/node": { - "version": "14.0.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.26.tgz", - "integrity": "sha512-W+fpe5s91FBGE0pEa0lnqGLL4USgpLgs4nokw16SrBBco/gQxuua7KnArSEOd5iaMqbbSHV10vUDkJYJJqpXKA==" + "version": "14.0.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz", + "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==" }, "@types/parse-json": { "version": "4.0.0", @@ -2342,9 +2342,9 @@ "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" }, "ajv-keywords": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.1.tgz", - "integrity": "sha512-KWcq3xN8fDjSB+IMoh2VaXVhRI0BBGxoYp3rx7Pkb6z0cFjYR9Q9l4yZqqals0/zsioCmocC5H6UvsGD4MoIBA==" + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" }, "alphanum-sort": { "version": "1.0.2", @@ -2783,9 +2783,9 @@ } }, "parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.1.tgz", + "integrity": "sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ==", "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -3487,9 +3487,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001100", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001100.tgz", - "integrity": "sha512-0eYdp1+wFCnMlCj2oudciuQn2B9xAFq3WpgpcBIZTxk/1HNA/O2YA7rpeYhnOqsqAJq1AHUgx6i1jtafg7m2zA==" + "version": "1.0.30001109", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001109.tgz", + "integrity": "sha512-4JIXRodHzdS3HdK8nSgIqXYLExOvG+D2/EenSvcub2Kp3QEADjo2v2oUn5g0n0D+UNwG9BtwKOyGcSq2qvQXvQ==" }, "capture-exit": { "version": "2.0.0", @@ -3525,9 +3525,9 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, "chokidar": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", - "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.1.tgz", + "integrity": "sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g==", "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", @@ -4343,9 +4343,9 @@ } }, "csstype": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.11.tgz", - "integrity": "sha512-l8YyEC9NBkSm783PFTvh0FmJy7s5pFKrDp49ZL7zBGX3fWkO+N4EEyan1qqp8cwPLDcD0OSdyY6hAMoxp34JFw==" + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==" }, "cyclist": { "version": "1.0.1", @@ -4807,9 +4807,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.498", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.498.tgz", - "integrity": "sha512-W1hGwaQEU8j9su2jeAr3aabkPuuXw+j8t73eajGAkEJWbfWiwbxBwQN/8Qmv2qCy3uCDm2rOAaZneYQM8VGC4w==" + "version": "1.3.514", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.514.tgz", + "integrity": "sha512-8vb8zKIeGlZigeDzNWWthmGeLzo5CC43Lc+CZshMs7UXFVMPNLtXJGa/txedpu3OJFrXXVheBwp9PqOJJlHQ8w==" }, "elliptic": { "version": "6.5.3", @@ -4862,9 +4862,9 @@ } }, "enhanced-resolve": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.2.0.tgz", - "integrity": "sha512-S7eiFb/erugyd1rLb6mQ3Vuq+EXHv5cpCkNqqIkYkBgN2QdFnyCZzFBleqwGEx4lgNGYij81BWnCrFNK7vxvjQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", "requires": { "graceful-fs": "^4.1.2", "memory-fs": "^0.5.0", @@ -5446,9 +5446,9 @@ "dev": true }, "eslint-plugin-react": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.20.3.tgz", - "integrity": "sha512-txbo090buDeyV0ugF3YMWrzLIUqpYTsWSDZV9xLSmExE1P/Kmgg9++PD931r+KEWS66O1c9R4srLVVHmeHpoAg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.20.5.tgz", + "integrity": "sha512-ajbJfHuFnpVNJjhyrfq+pH1C0gLc2y94OiCbAXT5O0J0YCKaFEHDV8+3+mDOr+w8WguRX+vSs1bM2BDG0VLvCw==", "dev": true, "requires": { "array-includes": "^3.1.1", @@ -5576,9 +5576,9 @@ "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==" }, "events": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", - "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==" }, "eventsource": { "version": "1.0.7", @@ -6553,11 +6553,11 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, @@ -7013,9 +7013,9 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.2.tgz", - "integrity": "sha512-DF4osh1FM6l0RJc5YWYhSDB6TawiBRlbV9Cox8MWlidU218Tb7fm3lQTULyUJDfJ0tjbzl0W4q651mrCCEM55w==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", "requires": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.0", @@ -7023,7 +7023,7 @@ "cli-width": "^3.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", - "lodash": "^4.17.16", + "lodash": "^4.17.19", "mute-stream": "0.0.8", "run-async": "^2.4.0", "rxjs": "^6.6.0", @@ -8660,9 +8660,9 @@ } }, "minipass-pipeline": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.3.tgz", - "integrity": "sha512-cFOknTvng5vqnwOpDsZTWhNll6Jf8o2x+/diplafmxpuIymAjzoOolZG0VvQf3V2HgqzJNhnuKHYp2BqDgz8IQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "requires": { "minipass": "^3.0.0" } @@ -8940,9 +8940,9 @@ } }, "node-releases": { - "version": "1.1.59", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.59.tgz", - "integrity": "sha512-H3JrdUczbdiwxN5FuJPyCHnGHIFqQ0wWxo+9j1kAXAzqNMAHlo+4I/sYYxpyK0irQ73HgdiyzD32oqQDcU2Osw==" + "version": "1.1.60", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", + "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==" }, "normalize-package-data": { "version": "2.5.0", @@ -9179,9 +9179,9 @@ } }, "open": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/open/-/open-7.0.4.tgz", - "integrity": "sha512-brSA+/yq+b08Hsr4c8fsEW2CRzk1BmfN3SAK/5VCHQ9bdoZJ4qa/+AfR0xHjlbbZUyPkUHs1b8x1RqdyZdkVqQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.1.0.tgz", + "integrity": "sha512-lLPI5KgOwEYCDKXf4np7y1PBEkj7HYIyP2DY8mVDRnx0VIIu6bNrRB0R66TuO7Mack6EnTNLm4uvcl1UoklTpA==", "requires": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" @@ -9561,13 +9561,13 @@ "dev": true }, "portfinder": { - "version": "1.0.26", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz", - "integrity": "sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==", + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", "requires": { "async": "^2.6.2", "debug": "^3.1.1", - "mkdirp": "^0.5.1" + "mkdirp": "^0.5.5" }, "dependencies": { "debug": { @@ -10078,14 +10078,14 @@ } }, "postcss-modules-local-by-default": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz", - "integrity": "sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", "requires": { "icss-utils": "^4.1.1", - "postcss": "^7.0.16", + "postcss": "^7.0.32", "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.0.0" + "postcss-value-parser": "^4.1.0" } }, "postcss-modules-scope": { @@ -10999,9 +10999,9 @@ } }, "react-redux": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", - "integrity": "sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.1.tgz", + "integrity": "sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg==", "requires": { "@babel/runtime": "^7.5.5", "hoist-non-react-statics": "^3.3.0", @@ -11311,9 +11311,9 @@ } }, "redux-devtools": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/redux-devtools/-/redux-devtools-3.5.0.tgz", - "integrity": "sha512-pGU8TZNvWxPaCCE432AGm6H6alQbAz80gQM5CzM3SjX9/oSNu/HPF17xFdPQJOXasqyih1Gv167kZDTRe7r0iQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/redux-devtools/-/redux-devtools-3.6.0.tgz", + "integrity": "sha512-tA/H0nhuD4NxNf2yX2gnd9uHclj7nWmMQKsgkCLSJohmb/IfaGIa6/kotLbTch1pfDuRzx1ojIIr0EoVi1QPuA==", "dev": true, "requires": { "lodash": "^4.2.0", @@ -11350,9 +11350,9 @@ } }, "regenerator-runtime": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, "regenerator-transform": { "version": "0.14.5", @@ -11530,19 +11530,19 @@ } }, "request-promise-core": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", - "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", "requires": { - "lodash": "^4.17.15" + "lodash": "^4.17.19" } }, "request-promise-native": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", - "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", "requires": { - "request-promise-core": "1.1.3", + "request-promise-core": "1.1.4", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" } @@ -13516,9 +13516,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", - "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==" + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==" }, "v8-compile-cache": { "version": "2.1.1", @@ -13600,11 +13600,11 @@ } }, "watchpack": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz", - "integrity": "sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", + "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", "requires": { - "chokidar": "^3.4.0", + "chokidar": "^3.4.1", "graceful-fs": "^4.1.2", "neo-async": "^2.5.0", "watchpack-chokidar2": "^2.0.0"