Major refactoring

This commit is contained in:
Maciek Głowacki 2020-08-12 04:13:14 +02:00
parent f6da0d9c72
commit f1cf374b07
35 changed files with 783 additions and 732 deletions

2
.env Normal file
View File

@ -0,0 +1,2 @@
REACT_APP_API_URL=http://localhost:5000/api
REACT_APP_API_HOST=http://localhost:5000

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
node_modules
build

28
.eslintrc.js Normal file
View File

@ -0,0 +1,28 @@
module.exports = {
parser: '@typescript-eslint/parser',
extends: [
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
'prettier/@typescript-eslint',
'plugin:prettier/recommended',
'plugin:react-hooks/recommended',
],
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
},
rules: {
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_|^req|^next' }],
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/explicit-function-return-type': 0,
'react/prop-types': 0,
},
settings: {
react: {
version: 'detect',
},
},
};

7
.prettierrc.js Normal file
View File

@ -0,0 +1,7 @@
module.exports = {
semi: true,
trailingComma: 'all',
singleQuote: true,
printWidth: 120,
tabWidth: 2,
};

516
package-lock.json generated
View File

@ -1165,6 +1165,29 @@
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
}, },
"@emotion/is-prop-valid": {
"version": "0.8.8",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
"integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
"requires": {
"@emotion/memoize": "0.7.4"
}
},
"@emotion/memoize": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
"integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="
},
"@emotion/stylis": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz",
"integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ=="
},
"@emotion/unitless": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
},
"@hapi/address": { "@hapi/address": {
"version": "2.1.4", "version": "2.1.4",
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
@ -1823,6 +1846,15 @@
"@types/node": "*" "@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": { "@types/istanbul-lib-coverage": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.2.tgz",
@ -1854,9 +1886,9 @@
} }
}, },
"@types/json-schema": { "@types/json-schema": {
"version": "7.0.4", "version": "7.0.5",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz",
"integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==" "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ=="
}, },
"@types/lru-cache": { "@types/lru-cache": {
"version": "4.1.2", "version": "4.1.2",
@ -1905,6 +1937,14 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"@types/react-native": {
"version": "0.63.7",
"resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.63.7.tgz",
"integrity": "sha512-TrtH69+HuWVxTERhoDDP2YtpznfH/Ra3/Fu2dCrssy+CkBZjvDlEESfWiAJWlOto3QtUzkTA7RT/S2jrO4WKkw==",
"requires": {
"@types/react": "*"
}
},
"@types/react-transition-group": { "@types/react-transition-group": {
"version": "4.4.0", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz",
@ -1918,6 +1958,24 @@
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
"integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==" "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw=="
}, },
"@types/styled-components": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.2.tgz",
"integrity": "sha512-HNocYLfrsnNNm8NTS/W53OERSjRA8dx5Bn6wBd2rXXwt4Z3s+oqvY6/PbVt3e6sgtzI63GX//WiWiRhWur08qQ==",
"requires": {
"@types/hoist-non-react-statics": "*",
"@types/react": "*",
"@types/react-native": "*",
"csstype": "^3.0.2"
},
"dependencies": {
"csstype": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.2.tgz",
"integrity": "sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw=="
}
}
},
"@types/styled-jsx": { "@types/styled-jsx": {
"version": "2.2.8", "version": "2.2.8",
"resolved": "https://registry.npmjs.org/@types/styled-jsx/-/styled-jsx-2.2.8.tgz", "resolved": "https://registry.npmjs.org/@types/styled-jsx/-/styled-jsx-2.2.8.tgz",
@ -2033,46 +2091,43 @@
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz",
"integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==" "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw=="
}, },
"@typescript-eslint/eslint-plugin": {
"version": "2.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz",
"integrity": "sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ==",
"requires": {
"@typescript-eslint/experimental-utils": "2.34.0",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^3.0.0",
"tsutils": "^3.17.1"
}
},
"@typescript-eslint/experimental-utils": { "@typescript-eslint/experimental-utils": {
"version": "2.34.0", "version": "3.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.9.0.tgz",
"integrity": "sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==", "integrity": "sha512-/vSHUDYizSOhrOJdjYxPNGfb4a3ibO8zd4nUKo/QBFOmxosT3cVUV7KIg8Dwi6TXlr667G7YPqFK9+VSZOorNA==",
"requires": { "requires": {
"@types/json-schema": "^7.0.3", "@types/json-schema": "^7.0.3",
"@typescript-eslint/typescript-estree": "2.34.0", "@typescript-eslint/types": "3.9.0",
"@typescript-eslint/typescript-estree": "3.9.0",
"eslint-scope": "^5.0.0", "eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0" "eslint-utils": "^2.0.0"
} }
}, },
"@typescript-eslint/parser": { "@typescript-eslint/parser": {
"version": "2.34.0", "version": "3.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.34.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.9.0.tgz",
"integrity": "sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA==", "integrity": "sha512-rDHOKb6uW2jZkHQniUQVZkixQrfsZGUCNWWbKWep4A5hGhN5dLHMUCNAWnC4tXRlHedXkTDptIpxs6e4Pz8UfA==",
"requires": { "requires": {
"@types/eslint-visitor-keys": "^1.0.0", "@types/eslint-visitor-keys": "^1.0.0",
"@typescript-eslint/experimental-utils": "2.34.0", "@typescript-eslint/experimental-utils": "3.9.0",
"@typescript-eslint/typescript-estree": "2.34.0", "@typescript-eslint/types": "3.9.0",
"@typescript-eslint/typescript-estree": "3.9.0",
"eslint-visitor-keys": "^1.1.0" "eslint-visitor-keys": "^1.1.0"
} }
}, },
"@typescript-eslint/types": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.9.0.tgz",
"integrity": "sha512-rb6LDr+dk9RVVXO/NJE8dT1pGlso3voNdEIN8ugm4CWM5w5GimbThCMiMl4da1t5u3YwPWEwOnKAULCZgBtBHg=="
},
"@typescript-eslint/typescript-estree": { "@typescript-eslint/typescript-estree": {
"version": "2.34.0", "version": "3.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.9.0.tgz",
"integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==", "integrity": "sha512-N+158NKgN4rOmWVfvKOMoMFV5n8XxAliaKkArm/sOypzQ0bUL8MSnOEBW3VFIeffb/K5ce/cAV0yYhR7U4ALAA==",
"requires": { "requires": {
"@typescript-eslint/types": "3.9.0",
"@typescript-eslint/visitor-keys": "3.9.0",
"debug": "^4.1.1", "debug": "^4.1.1",
"eslint-visitor-keys": "^1.1.0",
"glob": "^7.1.6", "glob": "^7.1.6",
"is-glob": "^4.0.1", "is-glob": "^4.0.1",
"lodash": "^4.17.15", "lodash": "^4.17.15",
@ -2087,6 +2142,14 @@
} }
} }
}, },
"@typescript-eslint/visitor-keys": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.9.0.tgz",
"integrity": "sha512-O1qeoGqDbu0EZUC/MZ6F1WHTIzcBVhGqDj3LhTnj65WUA548RXVxUHbYhAW9bZWfb2rnX9QsbbP5nmeJ5Z4+ng==",
"requires": {
"eslint-visitor-keys": "^1.1.0"
}
},
"@webassemblyjs/ast": { "@webassemblyjs/ast": {
"version": "1.8.5", "version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
@ -2275,9 +2338,9 @@
} }
}, },
"acorn": { "acorn": {
"version": "7.2.0", "version": "7.4.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
"integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==" "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w=="
}, },
"acorn-globals": { "acorn-globals": {
"version": "4.3.4", "version": "4.3.4",
@ -2980,6 +3043,22 @@
"resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.6.tgz", "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.6.tgz",
"integrity": "sha512-1aGDUfL1qOOIoqk9QKGIo2lANk+C7ko/fqH0uIyC71x3PEGz0uVP8ISgfEsFuG+FKmjHTvFK/nNM8dowpmUxLA==" "integrity": "sha512-1aGDUfL1qOOIoqk9QKGIo2lANk+C7ko/fqH0uIyC71x3PEGz0uVP8ISgfEsFuG+FKmjHTvFK/nNM8dowpmUxLA=="
}, },
"babel-plugin-styled-components": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.11.1.tgz",
"integrity": "sha512-YwrInHyKUk1PU3avIRdiLyCpM++18Rs1NgyMXEAQC33rIXs/vro0A+stf4sT0Gf22Got+xRWB8Cm0tw+qkRzBA==",
"requires": {
"@babel/helper-annotate-as-pure": "^7.0.0",
"@babel/helper-module-imports": "^7.0.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"lodash": "^4.17.11"
}
},
"babel-plugin-syntax-jsx": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
"integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
},
"babel-plugin-syntax-object-rest-spread": { "babel-plugin-syntax-object-rest-spread": {
"version": "6.13.0", "version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
@ -3620,6 +3699,11 @@
} }
} }
}, },
"camelize": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
"integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
},
"caniuse-api": { "caniuse-api": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
@ -4257,6 +4341,11 @@
"postcss": "^7.0.5" "postcss": "^7.0.5"
} }
}, },
"css-color-keywords": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
"integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
},
"css-color-names": { "css-color-names": {
"version": "0.0.4", "version": "0.0.4",
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
@ -4347,6 +4436,16 @@
"resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
}, },
"css-to-react-native": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz",
"integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==",
"requires": {
"camelize": "^1.0.0",
"css-color-keywords": "^1.0.0",
"postcss-value-parser": "^4.0.2"
}
},
"css-tree": { "css-tree": {
"version": "1.0.0-alpha.37", "version": "1.0.0-alpha.37",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
@ -5185,84 +5284,18 @@
} }
} }
}, },
"eslint": { "eslint-config-prettier": {
"version": "6.8.0", "version": "6.11.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz",
"integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==",
"requires": { "requires": {
"@babel/code-frame": "^7.0.0", "get-stdin": "^6.0.0"
"ajv": "^6.10.0",
"chalk": "^2.1.0",
"cross-spawn": "^6.0.5",
"debug": "^4.0.1",
"doctrine": "^3.0.0",
"eslint-scope": "^5.0.0",
"eslint-utils": "^1.4.3",
"eslint-visitor-keys": "^1.1.0",
"espree": "^6.1.2",
"esquery": "^1.0.1",
"esutils": "^2.0.2",
"file-entry-cache": "^5.0.1",
"functional-red-black-tree": "^1.0.1",
"glob-parent": "^5.0.0",
"globals": "^12.1.0",
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
"inquirer": "^7.0.0",
"is-glob": "^4.0.0",
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.3.0",
"lodash": "^4.17.14",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
"optionator": "^0.8.3",
"progress": "^2.0.0",
"regexpp": "^2.0.1",
"semver": "^6.1.2",
"strip-ansi": "^5.2.0",
"strip-json-comments": "^3.0.1",
"table": "^5.2.3",
"text-table": "^0.2.0",
"v8-compile-cache": "^2.0.3"
}, },
"dependencies": { "dependencies": {
"eslint-utils": { "get-stdin": {
"version": "1.4.3", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
"integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g=="
"requires": {
"eslint-visitor-keys": "^1.1.0"
}
},
"globals": {
"version": "12.4.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
"integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
"requires": {
"type-fest": "^0.8.1"
}
},
"import-fresh": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
"integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
"requires": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
}
},
"regexpp": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
"integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw=="
},
"resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
} }
} }
}, },
@ -5467,6 +5500,14 @@
} }
} }
}, },
"eslint-plugin-prettier": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz",
"integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==",
"requires": {
"prettier-linter-helpers": "^1.0.0"
}
},
"eslint-plugin-react": { "eslint-plugin-react": {
"version": "7.19.0", "version": "7.19.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz",
@ -5510,18 +5551,18 @@
"integrity": "sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA==" "integrity": "sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA=="
}, },
"eslint-scope": { "eslint-scope": {
"version": "5.0.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz",
"integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==",
"requires": { "requires": {
"esrecurse": "^4.1.0", "esrecurse": "^4.1.0",
"estraverse": "^4.1.1" "estraverse": "^4.1.1"
} }
}, },
"eslint-utils": { "eslint-utils": {
"version": "2.0.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
"integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
"requires": { "requires": {
"eslint-visitor-keys": "^1.1.0" "eslint-visitor-keys": "^1.1.0"
} }
@ -5531,16 +5572,6 @@
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
"integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==" "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A=="
}, },
"espree": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
"integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
"requires": {
"acorn": "^7.1.1",
"acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.1.0"
}
},
"esprima": { "esprima": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
@ -5555,9 +5586,9 @@
}, },
"dependencies": { "dependencies": {
"estraverse": { "estraverse": {
"version": "5.1.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
"integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==" "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ=="
} }
} }
}, },
@ -5878,6 +5909,11 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
"integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
}, },
"fast-diff": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w=="
},
"fast-glob": { "fast-glob": {
"version": "2.2.7", "version": "2.2.7",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz",
@ -6999,20 +7035,20 @@
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
}, },
"inquirer": { "inquirer": {
"version": "7.1.0", "version": "7.3.3",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
"integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
"requires": { "requires": {
"ansi-escapes": "^4.2.1", "ansi-escapes": "^4.2.1",
"chalk": "^3.0.0", "chalk": "^4.1.0",
"cli-cursor": "^3.1.0", "cli-cursor": "^3.1.0",
"cli-width": "^2.0.0", "cli-width": "^3.0.0",
"external-editor": "^3.0.3", "external-editor": "^3.0.3",
"figures": "^3.0.0", "figures": "^3.0.0",
"lodash": "^4.17.15", "lodash": "^4.17.19",
"mute-stream": "0.0.8", "mute-stream": "0.0.8",
"run-async": "^2.4.0", "run-async": "^2.4.0",
"rxjs": "^6.5.3", "rxjs": "^6.6.0",
"string-width": "^4.1.0", "string-width": "^4.1.0",
"strip-ansi": "^6.0.0", "strip-ansi": "^6.0.0",
"through": "^2.3.6" "through": "^2.3.6"
@ -7028,14 +7064,19 @@
} }
}, },
"chalk": { "chalk": {
"version": "3.0.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"requires": { "requires": {
"ansi-styles": "^4.1.0", "ansi-styles": "^4.1.0",
"supports-color": "^7.1.0" "supports-color": "^7.1.0"
} }
}, },
"cli-width": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
"integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw=="
},
"color-convert": { "color-convert": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@ -7054,6 +7095,19 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
}, },
"lodash": {
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
},
"rxjs": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
"integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
"requires": {
"tslib": "^1.9.0"
}
},
"strip-ansi": { "strip-ansi": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
@ -10957,6 +11011,19 @@
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
}, },
"prettier": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
"integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg=="
},
"prettier-linter-helpers": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
"requires": {
"fast-diff": "^1.1.2"
}
},
"pretty-bytes": { "pretty-bytes": {
"version": "5.3.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz",
@ -11547,6 +11614,153 @@
"webpack-dev-server": "3.10.3", "webpack-dev-server": "3.10.3",
"webpack-manifest-plugin": "2.2.0", "webpack-manifest-plugin": "2.2.0",
"workbox-webpack-plugin": "4.3.1" "workbox-webpack-plugin": "4.3.1"
},
"dependencies": {
"@typescript-eslint/eslint-plugin": {
"version": "2.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz",
"integrity": "sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ==",
"requires": {
"@typescript-eslint/experimental-utils": "2.34.0",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^3.0.0",
"tsutils": "^3.17.1"
}
},
"@typescript-eslint/experimental-utils": {
"version": "2.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz",
"integrity": "sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==",
"requires": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/typescript-estree": "2.34.0",
"eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0"
}
},
"@typescript-eslint/parser": {
"version": "2.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.34.0.tgz",
"integrity": "sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA==",
"requires": {
"@types/eslint-visitor-keys": "^1.0.0",
"@typescript-eslint/experimental-utils": "2.34.0",
"@typescript-eslint/typescript-estree": "2.34.0",
"eslint-visitor-keys": "^1.1.0"
}
},
"@typescript-eslint/typescript-estree": {
"version": "2.34.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz",
"integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==",
"requires": {
"debug": "^4.1.1",
"eslint-visitor-keys": "^1.1.0",
"glob": "^7.1.6",
"is-glob": "^4.0.1",
"lodash": "^4.17.15",
"semver": "^7.3.2",
"tsutils": "^3.17.1"
},
"dependencies": {
"semver": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
}
}
},
"eslint": {
"version": "6.8.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
"integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==",
"requires": {
"@babel/code-frame": "^7.0.0",
"ajv": "^6.10.0",
"chalk": "^2.1.0",
"cross-spawn": "^6.0.5",
"debug": "^4.0.1",
"doctrine": "^3.0.0",
"eslint-scope": "^5.0.0",
"eslint-utils": "^1.4.3",
"eslint-visitor-keys": "^1.1.0",
"espree": "^6.1.2",
"esquery": "^1.0.1",
"esutils": "^2.0.2",
"file-entry-cache": "^5.0.1",
"functional-red-black-tree": "^1.0.1",
"glob-parent": "^5.0.0",
"globals": "^12.1.0",
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
"inquirer": "^7.0.0",
"is-glob": "^4.0.0",
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.3.0",
"lodash": "^4.17.14",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
"optionator": "^0.8.3",
"progress": "^2.0.0",
"regexpp": "^2.0.1",
"semver": "^6.1.2",
"strip-ansi": "^5.2.0",
"strip-json-comments": "^3.0.1",
"table": "^5.2.3",
"text-table": "^0.2.0",
"v8-compile-cache": "^2.0.3"
},
"dependencies": {
"eslint-utils": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
"integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
"requires": {
"eslint-visitor-keys": "^1.1.0"
}
},
"regexpp": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
"integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw=="
}
}
},
"espree": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
"integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
"requires": {
"acorn": "^7.1.1",
"acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.1.0"
}
},
"globals": {
"version": "12.4.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
"integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
"requires": {
"type-fest": "^0.8.1"
}
},
"import-fresh": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
"integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
"requires": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
}
},
"resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
}
} }
}, },
"react-transition-group": { "react-transition-group": {
@ -12438,6 +12652,11 @@
} }
} }
}, },
"shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
},
"shebang-command": { "shebang-command": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@ -13133,9 +13352,9 @@
} }
}, },
"strip-json-comments": { "strip-json-comments": {
"version": "3.1.0", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==" "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="
}, },
"style-loader": { "style-loader": {
"version": "0.23.1", "version": "0.23.1",
@ -13158,6 +13377,23 @@
} }
} }
}, },
"styled-components": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.1.1.tgz",
"integrity": "sha512-1ps8ZAYu2Husx+Vz8D+MvXwEwvMwFv+hqqUwhNlDN5ybg6A+3xyW1ECrAgywhvXapNfXiz79jJyU0x22z0FFTg==",
"requires": {
"@babel/helper-module-imports": "^7.0.0",
"@babel/traverse": "^7.4.5",
"@emotion/is-prop-valid": "^0.8.8",
"@emotion/stylis": "^0.8.4",
"@emotion/unitless": "^0.7.4",
"babel-plugin-styled-components": ">= 1",
"css-to-react-native": "^3.0.0",
"hoist-non-react-statics": "^3.0.0",
"shallowequal": "^1.1.0",
"supports-color": "^5.5.0"
}
},
"stylehacks": { "stylehacks": {
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz",
@ -13877,9 +14113,9 @@
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}, },
"v8-compile-cache": { "v8-compile-cache": {
"version": "2.1.0", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
"integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==" "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ=="
}, },
"validate-npm-package-license": { "validate-npm-package-license": {
"version": "3.0.4", "version": "3.0.4",

View File

@ -20,15 +20,21 @@
"@types/node": "^12.12.42", "@types/node": "^12.12.42",
"@types/react": "^16.9.35", "@types/react": "^16.9.35",
"@types/react-dom": "^16.9.8", "@types/react-dom": "^16.9.8",
"@types/styled-components": "^5.1.2",
"@typescript-eslint/parser": "^3.9.0",
"axios": "^0.19.2", "axios": "^0.19.2",
"axios-extensions": "^3.1.3", "axios-extensions": "^3.1.3",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-prettier": "^3.1.4",
"immer": "^7.0.5", "immer": "^7.0.5",
"install": "^0.13.0", "install": "^0.13.0",
"node-sass": "^4.14.1", "node-sass": "^4.14.1",
"prettier": "^2.0.5",
"react": "^16.13.1", "react": "^16.13.1",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-scripts": "3.4.1", "react-scripts": "3.4.1",
"sass": "^1.26.5", "sass": "^1.26.5",
"styled-components": "^5.1.1",
"to": "^0.2.9", "to": "^0.2.9",
"typescript": "^3.9.3", "typescript": "^3.9.3",
"use-immer": "^0.4.0" "use-immer": "^0.4.0"

View File

@ -1,14 +0,0 @@
body {
margin: 0px;
padding: 0px;
}
body::-webkit-scrollbar {
display: none;
}
.wraper{
display: flex;
&__calendar{
flex-grow: 3;
}
}

View File

@ -1,55 +1,40 @@
import React, { useState } from "react"; import React, { useState, useContext } from 'react';
import TopBar from "./components/TopBar/"; import TopBar from './components/TopBar/';
import Transfer from "./components/Transfer/"; import Transfer from './components/Transfer/';
import "./App.scss"; import { Scheduler } from './components/Scheduler';
import {Scheduler} from "./components/Scheduler"; import RightBar from './components/RightBar';
import RightBar from "./components/RightBar"; import { CASContext } from './contexts/CASProvider';
import { lectures } from "./businesslogic/mockData/lectures"; import styled from 'styled-components';
import BusinessLogicContext from "./businesslogic/BusinessLogicContext"; const Wrapper = styled.div`
import { BuisnessProvided } from "./businesslogic/BusinessLogicProvider"; display: flex;
`;
function App() { export const App = () => {
const [isOpenTransfer, setOpenTransfer] = useState(false); const [isOpenTransfer, setOpenTransfer] = useState(false);
const { logout } = useContext(CASContext)!;
const handleCloseTransfer = () => {
setOpenTransfer(!isOpenTransfer);
};
const onLangChange = () => {
console.log('Language changed');
};
const onGroupMouseOver = () => {
console.log(`On groupmouse over`);
};
return ( return (
<div className="App"> <>
<BusinessLogicContext.Consumer> <TopBar handleTransfer={handleCloseTransfer} onLangChange={onLangChange} handleLogout={logout} />
{(context) => ( <Transfer isOpen={isOpenTransfer} handleClose={handleCloseTransfer} />
<TopBar <Wrapper>
handleTransfer={(e) => {
setOpenTransfer(!isOpenTransfer);
}}
onLangChange={(e) => {
console.log(e);
}}
handleLogout={() => {
(context as BuisnessProvided).reducers.userlogout();
}}
/>
)}
</BusinessLogicContext.Consumer>
<Transfer
isOpen={isOpenTransfer}
handleClose={(e) => {
setOpenTransfer(!isOpenTransfer);
}}
/>
<div className="wraper">
<div className="wraper__calendar">
<Scheduler /> <Scheduler />
</div> <RightBar onGroupMouseOver={onGroupMouseOver} />
<div className="wraper__rightbar"> </Wrapper>
<RightBar </>
lectures={lectures}
onGroupMouseOver={(id, name) => {
}}
/>
</div>
</div>
</div>
); );
} };
export default App;

View File

@ -1,5 +0,0 @@
import React from "react";
const BusinessLogicContext = React.createContext({});
export default BusinessLogicContext;

View File

@ -1,76 +0,0 @@
import BusinessLogicContext from "./BusinessLogicContext";
import React, { Component } from "react";
import { User } from "./types/user";
export interface BuisnessProvided {
states: BusinessState;
reducers: {
userlogout: () => void;
};
}
interface BusinessState {
user: User | null;
}
interface Props {}
class BusinessLogicProvider extends Component<Props, BusinessState> {
constructor(props: Props) {
super(props);
this.state = {
user: null,
};
}
componentDidMount() {
this.login();
}
login() {
const urlParams = new URLSearchParams(window.location.search);
const ticket = urlParams.get("ticket");
if (!ticket) {
this.redirectToCASLoginService();
}
if (ticket) {
this.setState({ user: { ticket } });
}
}
logout() {
this.redirectToCASLogoutService();
}
redirectToCASLogoutService() {
window.location.replace(
`https://cas.amu.edu.pl/cas/logout?service=${window.origin}`
);
}
redirectToCASLoginService() {
window.location.replace(
`https://cas.amu.edu.pl/cas/login?service=${window.origin}&locale=pl`
);
}
render() {
return (
<BusinessLogicContext.Provider
value={{
states: this.state,
reducers: {
userlogout: () => {
this.logout();
},
},
}}
>
{this.props.children}
</BusinessLogicContext.Provider>
);
}
}
export default BusinessLogicProvider;

View File

@ -1,33 +0,0 @@
import React, { useState } from "react";
import { Lecture } from "./types/lecture";
import { Group } from "./types/group";
interface ILectureContext {
lectures: Array<Lecture>;
addLecture: (lectures: Lecture) => void;
}
export const LecturesContext = React.createContext({
lectures: Array<Lecture>(),
choosenGroups: Array<Group>(),
addLecture: (lecture: Lecture) => {},
addGroup: (group : Group) => {}
});
export const LecturesProvider: React.FC = (props) => {
const [lectures, setLectures] = useState<Array<Lecture>>([]);
const [choosenGroups, setChoosenGroups] = useState<Array<Group>>([]);
const addLecture = (lecture: Lecture) => {
setLectures([...lectures, lecture]);
};
const addGroup = (group : Group) => {
setChoosenGroups([...choosenGroups, group]);
};
return (
<LecturesContext.Provider
value={{ lectures, choosenGroups, addLecture, addGroup }}
>
{props.children}
</LecturesContext.Provider>
);
};

View File

@ -1,42 +0,0 @@
import { Lecture } from "../types/lecture";
export const lectures: Array<Lecture> = [
{
name: "E-gospodarka - narzędzia i bezpieczeństwo",
groups: [
{
id: "1CB",
day: "Pn",
time: "10:00",
lecturer: "dr inż. Michał Ren",
room: "A2-01",
},
{
id: "1XD",
day: "Wt",
time: "12:00",
lecturer: "dr inż. Michał Ren",
room: "A3-01",
},
],
},
{
name: "Statystyka",
groups: [
{
id: "2CB",
day: "Pn",
time: "10:00",
lecturer: "dr inż. Michał Ren",
room: "A2-01",
},
{
id: "2XD",
day: "Wt",
time: "12:00",
lecturer: "dr inż. Michał Ren",
room: "A3-01",
},
],
},
];

View File

@ -1,7 +0,0 @@
export interface Group {
id: string;
day: string;
time: string;
lecturer: string;
room: string;
}

View File

@ -1,7 +0,0 @@
import { Group } from "./group";
export interface Lecture {
id?: number;
name: string;
groups: Array<Group>;
}

View File

@ -1,4 +0,0 @@
export interface LectureInit {
name: string;
id: number;
}

View File

@ -1,5 +0,0 @@
export interface User {
name?: string;
surname?: string;
ticket: string | null;
};

View File

@ -1,10 +1,9 @@
import React, {useContext} from "react"; import React, { useContext } from 'react';
import "./index.scss"; import './index.scss';
import Collapse from "@material-ui/core/Collapse"; import Collapse from '@material-ui/core/Collapse';
import ExpandIcon from "./expand.png"; import ExpandIcon from './expand.png';
import { Lecture } from "../../../businesslogic/types/lecture"; import { Lecture, Group } from '../../../types/index';
import { Group } from "../../../businesslogic/types/group"; import { LecturesContext } from '../../../contexts/LecturesProvider';
import { LecturesContext } from "../../../businesslogic/LecturesProvider";
interface LectureCardProps { interface LectureCardProps {
onGroupMouseOver: (id: string, name: string) => void; onGroupMouseOver: (id: string, name: string) => void;
@ -14,31 +13,17 @@ interface LectureCardProps {
isSelected: boolean; isSelected: boolean;
} }
export default function LectureCard({ export default function LectureCard({ onGroupMouseOver, onCardClick, lecture, id, isSelected }: LectureCardProps) {
onGroupMouseOver, const { addGroup } = useContext(LecturesContext)!;
onCardClick,
lecture,
id,
isSelected,
}: LectureCardProps) {
const {addGroup} = useContext(LecturesContext);
function onGroupClick(group: Group) { function onGroupClick(group: Group) {
addGroup(group); addGroup(group);
} }
return ( return (
<div className="class" onClick={onCardClick} id={id}> <div className="class" onClick={onCardClick} id={id}>
<div className="class__name">{lecture.name}</div> <div className="class__name">{lecture.name}</div>
<Collapse <Collapse className="expanded" in={isSelected} timeout="auto" unmountOnExit>
className="expanded"
in={isSelected}
timeout="auto"
unmountOnExit
>
{lecture.groups.map((group, index) => ( {lecture.groups.map((group, index) => (
<div <div
className="class__group" className="class__group"
@ -48,16 +33,12 @@ export default function LectureCard({
> >
<p> <p>
{group.time} {group.room} <br></br> {group.lecturer} {group.time} {group.room} <br></br> {group.lecturer}
</p>{" "} </p>{' '}
</div> </div>
))} ))}
</Collapse> </Collapse>
<div onClick={onCardClick} id={id}> <div onClick={onCardClick} id={id}>
<img <img alt="expand" src={ExpandIcon} className={`class__expandIcon${isSelected ? 'Rotate' : ''}`} />
alt="expand"
src={ExpandIcon}
className={`class__expandIcon${isSelected ? "Rotate" : ""}`}
/>
</div> </div>
</div> </div>
); );

View File

@ -1,27 +1,21 @@
import React, { useState, useContext } from "react"; import React, { useState, useContext } from 'react';
import "./index.scss"; import './index.scss';
import { Lecture } from "../../businesslogic/types/lecture"; import { Lecture } from '../../types';
import LectureCard from "./LectureCard"; import LectureCard from './LectureCard';
import { LecturesContext } from "../../businesslogic/LecturesProvider"; import { LecturesContext } from '../../contexts/LecturesProvider';
interface RightBarProps { interface RightBarProps {
onGroupMouseOver: (id: string, name: string) => void; onGroupMouseOver: (id: string, name: string) => void;
lectures: Array<Lecture>;
} }
export default function RightBar({ export default function RightBar({ onGroupMouseOver }: RightBarProps) {
lectures,
onGroupMouseOver,
}: RightBarProps) {
const [selectedCardId, setSelectedCardId] = useState<string | null>(null); const [selectedCardId, setSelectedCardId] = useState<string | null>(null);
const lecturesContext = useContext(LecturesContext); const lecturesContext = useContext(LecturesContext);
const onCardClick = (e: React.MouseEvent) => { const onCardClick = (e: React.MouseEvent) => {
const target = e.currentTarget as HTMLElement; const target = e.currentTarget as HTMLElement;
selectedCardId === target.id selectedCardId === target.id ? setSelectedCardId(null) : setSelectedCardId(target.id);
? setSelectedCardId(null)
: setSelectedCardId(target.id);
}; };
return ( return (
@ -30,7 +24,7 @@ export default function RightBar({
Hubert Wrzesiński<br></br> Hubert Wrzesiński<br></br>
Semestr zimowy 2020/2021 Semestr zimowy 2020/2021
</div> </div>
{lecturesContext.lectures.map((lecture, index) => ( {lecturesContext?.lectures.map((lecture, index) => (
<LectureCard <LectureCard
lecture={lecture} lecture={lecture}
key={index} key={index}

View File

@ -1,23 +0,0 @@
import React from "react";
interface CellProps {
colIndex: number;
index: number;
term?: string;
handleClick?: (e: React.MouseEvent) => void;
isEventable?: boolean;
}
export const Cell = ({
colIndex,
index,
term,
handleClick,
isEventable,
}: CellProps) => {
return (
<div id={`${colIndex} ${index}`} className="td" onClick={handleClick}>
{isEventable || term}
</div>
);
};

View File

@ -1,33 +0,0 @@
import React from "react";
import { Cell } from "../Cell";
interface ColumnProps {
hours: Array<string>;
handleClick?: (e: React.MouseEvent) => void;
children?: React.ReactNode;
colIndex?: number;
isEventable?: boolean;
}
export const Column = ({
hours,
colIndex,
isEventable,
children,
...rest
}: ColumnProps) => {
return (
<div className="tbody__column">
{hours.map((hour, index) => (
<Cell
{...rest}
index={index}
term={hour}
colIndex={colIndex || 0}
isEventable={isEventable}
/>
))}
{children}
</div>
);
};

View File

@ -1,86 +1,81 @@
import React, { useContext, useEffect, useState } from "react"; import React, { useContext, useEffect, useState } from 'react';
import { SchedulerRow } from "../SchedulerRow"; import { SchedulerRow } from '../SchedulerRow';
import { LecturesContext } from "../../../businesslogic/LecturesProvider"; import { LecturesContext } from '../../../contexts/LecturesProvider';
import { Group } from "../../../businesslogic/types/group"; import { Group } from '../../../types';
interface SchedulerEventsProps { interface SchedulerEventsProps {
cellTop: number; cellTop: number;
cellWidth: number; cellWidth: number;
} }
export const SchedulerEvents = ({ export const SchedulerEvents = ({ cellTop, cellWidth }: SchedulerEventsProps) => {
cellTop, const { choosenGroups } = useContext(LecturesContext)!;
cellWidth,
}: SchedulerEventsProps) => {
// const handleEventClick = (e: React.MouseEvent) => {
// const eventDiv = e.target as HTMLDivElement;
// eventDiv.style.backgroundColor = "#1547C5";
// };
const { choosenGroups } = useContext(LecturesContext);
const [groupsMappedToEvents, setGroupsMappedToEvents] = useState<any>([]); const [groupsMappedToEvents, setGroupsMappedToEvents] = useState<any>([]);
// const groups: Array<Group> = [{ id: "5", day: "4", time: "11.45", lecturer: "dr Dorota Blinkiewicz", room: "A2-3" }, // const groups: Array<Group> = [{ id: "5", day: "4", time: "11.45", lecturer: "dr Dorota Blinkiewicz", room: "A2-3" },
// { id: "28", day: "1", time: "13.45", lecturer: "dr Barbara Kołodziejczak", room: "D-3" }, // { id: "28", day: "1", time: "13.45", lecturer: "dr Barbara Kołodziejczak", room: "D-3" },
// { id: "69", day: "4", time: "15.30", lecturer: "dr Karol Gierszewski", room: "A2-3" }]; // { id: "69", day: "4", time: "15.30", lecturer: "dr Karol Gierszewski", room: "A2-3" }];
interface GroupTimeToEventRowMapping { interface GroupTimeToEventRowMapping {
[time: string]: number [time: string]: number;
} }
const groupTimeToEventRowMapping: GroupTimeToEventRowMapping = { const groupTimeToEventRowMapping: GroupTimeToEventRowMapping = {
"8.15": 0, '8.15': 0,
"10.00": 1, '10.00': 1,
"11.45": 2, '11.45': 2,
"13.45": 3, '13.45': 3,
"15.30": 4, '15.30': 4,
"17.15": 5, '17.15': 5,
} };
useEffect(() => { useEffect(() => {
function mapGroupTimeToEventRow(groups: Array<Group>) { function mapGroupTimeToEventRow(groups: Array<Group>) {
for (const group of groups) { for (const group of groups) {
console.log(group); console.log(group);
const groupTime = group.time const groupTime = group.time;
const eventRow: number = groupTimeToEventRowMapping[groupTime]; const eventRow: number = groupTimeToEventRowMapping[groupTime];
const groupMappedToEvent: any = { id: group.id, day: group.day, eventRow: eventRow, lecturer: group.lecturer, room: group.room }; const groupMappedToEvent: any = {
id: group.id,
day: group.day,
eventRow: eventRow,
lecturer: group.lecturer,
room: group.room,
};
setGroupsMappedToEvents((groupsMappedToEvents: any) => [...groupsMappedToEvents, groupMappedToEvent]); setGroupsMappedToEvents((groupsMappedToEvents: any) => [...groupsMappedToEvents, groupMappedToEvent]);
} }
function alternative(groups: Array<Group>) {
const groupsMapped = choosenGroups.map(({ id, day, lecturer, room, time }) => ({
id,
day,
lecturer,
room,
eventRow: groupTimeToEventRowMapping[time],
}));
setGroupsMappedToEvents(groupsMapped);
}
} }
mapGroupTimeToEventRow(choosenGroups); mapGroupTimeToEventRow(choosenGroups);
}, [choosenGroups]); }, [choosenGroups]);
useEffect(() => { useEffect(() => {
console.log(groupsMappedToEvents); console.log(groupsMappedToEvents);
}, [groupsMappedToEvents]); }, [groupsMappedToEvents]);
return ( return (
<div> <div>
{ {[...Array(6)].map((_, index) => (
[...Array(6)].map((_, index) => (
<SchedulerRow <SchedulerRow
key={index} key={index}
groups={groupsMappedToEvents.filter((group: any) => { return group.eventRow === index })} groups={groupsMappedToEvents.filter((group: any) => {
return group.eventRow === index;
})}
indexRow={index} indexRow={index}
cellTop={cellTop + (10 + 70 * index)} cellTop={cellTop + (10 + 70 * index)}
cellWidth={cellWidth} cellWidth={cellWidth}
/> />
)) ))}
}
</div> </div>
); );
}; };

View File

@ -1,5 +1,22 @@
import React from "react"; import React from 'react';
import { Group } from "../../../businesslogic/types/group"; import { Group } from '../../../types';
import styled from 'styled-components';
interface SchedulerEventProps {
eventIndex: number;
cellTop: number;
cellWidth: number;
}
const SchedulerEvent = styled.div<SchedulerEventProps>`
position: absolute;
top: ${(props) => props.cellTop}px;
left: ${(props) => props.cellWidth + 5 + props.cellWidth * props.eventIndex}px;
width: ${(props) => (props.cellWidth * 2) / 3}px;
height: 60px;
background-color: lightblue;
z-index: 2;
`;
interface SchedulerRowProps { interface SchedulerRowProps {
groups: Array<Group>; groups: Array<Group>;
@ -8,44 +25,24 @@ interface SchedulerRowProps {
cellWidth: number; cellWidth: number;
} }
export const SchedulerRow = ({ export const SchedulerRow = ({ groups, indexRow, cellTop, cellWidth }: SchedulerRowProps) => {
groups, console.log(`You passed me these of a groupzzz: ${groups}`);
indexRow,
cellTop,
cellWidth,
}: SchedulerRowProps) => {
// const handleEventClick = (e: React.MouseEvent) => {
// const eventDiv = e.target as HTMLDivElement;
// eventDiv.style.backgroundColor = "#1547C5";
// };
console.log(`You passed me these of a groupzzz: ${groups}`)
return ( return (
<div> <>
{[...Array(5)].map((value, eventIndex) => ( {[...Array(5)].map((value, eventIndex) => (
<div <SchedulerEvent
eventIndex={eventIndex}
cellTop={cellTop}
cellWidth={cellWidth}
key={`eventRow${indexRow}eventCol${eventIndex}`} key={`eventRow${indexRow}eventCol${eventIndex}`}
id={`eventRow${indexRow}eventCol${eventIndex}`} id={`eventRow${indexRow}eventCol${eventIndex}`}
style={{
position: "absolute",
top: cellTop,
left: cellWidth + 5 + cellWidth * eventIndex,
width: (cellWidth * 2) / 3,
height: 60,
backgroundColor: "lightblue",
zIndex: 2,
}}
> >
{groups.map((group, index) => {groups.map((group, index) =>
( parseInt(group.day) === eventIndex ? <div key={index}>{groups[index]?.lecturer}</div> : null,
parseInt(group.day) === eventIndex ? <div key={index}>{groups[index]?.lecturer}</div> )}
: null </SchedulerEvent>
))} ))}
</div> </>
))}
</div>
); );
}; };

View File

@ -1,26 +0,0 @@
.scheduler {
margin-top: 20px;
border-collapse: collapse;
.tbody {
display: flex;
&__column {
display: flex;
flex-direction: column;
position: relative;
flex: 1;
}
}
.td,
.th {
border: 1px solid #ddd;
padding: 10px;
text-align: center;
flex: 1;
}
.td:hover {
background-color: #ddd;
}
}

View File

@ -1,61 +1,45 @@
import React, { useEffect, useRef } from "react"; import React, { useEffect, useRef } from "react";
import { useState } from "react"; import { useState } from "react";
import "./index.scss";
import { SchedulerEvents } from "./SchedulerEvents"; import { SchedulerEvents } from "./SchedulerEvents";
const days = ["", "poniedziałek", "wtorek", "środa", "czwartek", "piątek"]; import { days, hours } from "../../constants/index";
import styled from "styled-components";
const hours = [ const SchedulerWrapper = styled.div`
"8:00", flex-grow: 3;
"9:00", margin-top: 20px;
"10:00", border-collapse: collapse;
"11:00", `;
"12:00",
"13:00",
"14:00",
"15:00",
"16:00",
"17:00",
"18:00",
"19:00",
];
let events: Array<number> = []; const TableBody = styled.div`
for (let i = 0; i < hours.length / 2; i++) { width: 100%;
events.push(i); height: 100%;
} display: flex;
flex-direction: column;
`;
let center: "center" = "center"; const TableRow = styled.div`
let row: "row" = "row"; display: flex;
let column: "column" = "column"; flex-direction: row;
// const collapse: "collapse" = "collapse"; `;
const tbodyStyles = {
width: "100%",
height: "100%",
display: "flex",
flexDirection: column,
};
const rowStyles = { const TableCell = styled.div`
display: "flex", border: 1px solid #ddd;
flexDirection: row, padding: 10px;
}; text-align: center;
flex: 1;
`;
const cellStyles = { const TableHead = styled.div`
border: "1px solid #ddd", display: flex;
padding: "10px", width: 100%;
textAlign: center, `;
flex: 1,
};
const theadStyles = { const TableHeadCell = styled.div`
display: "flex", border: 1px solid #ddd;
width: "100%", padding: 10px;
}; text-align: center;
flex: 1;
// const scheduler = { `;
// marginTop: "20px",
// borderCollapse: collapse,
// };
export const Scheduler = () => { export const Scheduler = () => {
const [currentEventsIds, setCurrentEventsIds] = useState<Array<string>>([]); const [currentEventsIds, setCurrentEventsIds] = useState<Array<string>>([]);
@ -63,7 +47,6 @@ export const Scheduler = () => {
const [cellWidth, setCellWidth] = useState(0); const [cellWidth, setCellWidth] = useState(0);
const [cellTop, setCellTop] = useState(0); const [cellTop, setCellTop] = useState(0);
useEffect(() => { useEffect(() => {
const handleResize = () => { const handleResize = () => {
if (cellRef.current) { if (cellRef.current) {
@ -98,29 +81,30 @@ export const Scheduler = () => {
return ( return (
<> <>
<div className="scheduler"> <SchedulerWrapper>
<div style={theadStyles}> <TableHead>
{days.map((day, index) => ( {days.map((day, index) => (
<div className="th" key={index}> <TableHeadCell key={index}>{day}</TableHeadCell>
{day}
</div>
))} ))}
</div> </TableHead>
<div style={tbodyStyles}> <TableBody>
{hours.map((hour, indexRow) => ( {hours.map((hour, indexRow) => (
<div key={indexRow} style={rowStyles}> <TableRow key={indexRow}>
{[hour, "", "", "", "", ""].map((value, indexCell) => {[hour, "", "", "", "", ""].map((value, indexCell) =>
indexRow === 0 && indexCell === 1 ? ( indexRow === 0 && indexCell === 1 ? (
<div key={`${indexRow}${indexCell}`} ref={cellRef} style={cellStyles}></div> <TableCell
key={`${indexRow}${indexCell}`}
ref={cellRef}
></TableCell>
) : ( ) : (
<div key={`${indexRow}${indexCell}`} style={cellStyles}>{value}</div> <TableCell key={`${indexRow}${indexCell}`}>{value}</TableCell>
) )
)} )}
</div> </TableRow>
))} ))}
</div> </TableBody>
<SchedulerEvents cellTop={cellTop} cellWidth={cellWidth} /> <SchedulerEvents cellTop={cellTop} cellWidth={cellWidth} />
</div> </SchedulerWrapper>
</> </>
); );
}; };

View File

@ -1,11 +1,10 @@
import React, { useState, useContext, useEffect } from "react"; import React, { useState, useContext, useEffect } from 'react';
import axios from "axios"; import axios from 'axios';
import { Input } from "@material-ui/core"; import { Input } from '@material-ui/core';
import "./index.scss"; import './index.scss';
import ClickAwayListener from "@material-ui/core/ClickAwayListener"; import ClickAwayListener from '@material-ui/core/ClickAwayListener';
import { LecturesContext } from "../../../businesslogic/LecturesProvider"; import { LecturesContext } from '../../../contexts/LecturesProvider';
import { Lecture } from "../../../businesslogic/types/lecture"; import { Lecture, Group } from '../../../types';
import { Group } from "../../../businesslogic/types/group";
interface LectureData { interface LectureData {
name: string; name: string;
@ -13,14 +12,12 @@ interface LectureData {
} }
export const Results: React.FC = () => { export const Results: React.FC = () => {
const [input, setInput] = useState<string>(""); const [input, setInput] = useState<string>('');
const [lecturesData, setLecturesData] = useState<Array<LectureData>>([]); const [lecturesData, setLecturesData] = useState<Array<LectureData>>([]);
const [filteredLecturesData, setFilteredLecturesData] = useState< const [filteredLecturesData, setFilteredLecturesData] = useState<Array<LectureData>>([]);
Array<LectureData>
>([]);
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const lecturesContext = useContext(LecturesContext); const lecturesContext = useContext(LecturesContext)!;
//fetch lectures ids and lectures names //fetch lectures ids and lectures names
// useEffect(() => { // useEffect(() => {
@ -36,12 +33,10 @@ export const Results: React.FC = () => {
useEffect(() => { useEffect(() => {
const fetchData = async () => { const fetchData = async () => {
const results = await axios.get(`http://localhost:1287/getCourses?name=`); const results = await axios.get(`http://localhost:1287/getCourses?name=`);
const lecturesData = results.data.map( const lecturesData = results.data.map((result: { id: number; name: string }) => ({
(result: { id: number; name: string }) => ({
id: result.id, id: result.id,
name: result.name, name: result.name,
}) }));
);
setLecturesData(lecturesData); setLecturesData(lecturesData);
}; };
@ -51,8 +46,8 @@ export const Results: React.FC = () => {
useEffect(() => { useEffect(() => {
const names = lecturesContext.lectures.map((lecture) => lecture.name); const names = lecturesContext.lectures.map((lecture) => lecture.name);
const filterLectures = (value: string) => { const filterLectures = (value: string) => {
let filteredLectures = lecturesData.filter((lecture) => let filteredLectures = lecturesData.filter(
lecture.name.toLowerCase().includes(value.toLowerCase()) && !names.includes(lecture.name) (lecture) => lecture.name.toLowerCase().includes(value.toLowerCase()) && !names.includes(lecture.name),
); );
setFilteredLecturesData(filteredLectures); setFilteredLecturesData(filteredLectures);
}; };
@ -60,9 +55,7 @@ export const Results: React.FC = () => {
}, [input, open]); }, [input, open]);
const getLecturesById = async (id: string) => { const getLecturesById = async (id: string) => {
const { data } = await axios.get( const { data } = await axios.get(`http://localhost:1287/getClassesByCourseId?id=${id}`);
`http://localhost:1287/getClassesByCourseId?id=${id}`
);
return data; return data;
}; };
@ -92,12 +85,7 @@ export const Results: React.FC = () => {
group.id = result[i].id; group.id = result[i].id;
group.day = result[i].day; group.day = result[i].day;
group.time = result[i].time; group.time = result[i].time;
group.lecturer = group.lecturer = result[i].lecturer.title + ' ' + result[i].lecturer.name + ' ' + result[i].lecturer.surname;
result[i].lecturer.title +
" " +
result[i].lecturer.name +
" " +
result[i].lecturer.surname;
group.room = result[i].room.trim(); group.room = result[i].room.trim();
lecture.groups.push(group); lecture.groups.push(group);
} }
@ -113,7 +101,7 @@ export const Results: React.FC = () => {
<div> <div>
<Input <Input
placeholder="Wyszukaj..." placeholder="Wyszukaj..."
inputProps={{ "aria-label": "description" }} inputProps={{ 'aria-label': 'description' }}
className="top-bar__input-field" className="top-bar__input-field"
onChange={handleChange} onChange={handleChange}
onClick={handleClick} onClick={handleClick}
@ -122,12 +110,7 @@ export const Results: React.FC = () => {
{open ? ( {open ? (
<div className="dropdown"> <div className="dropdown">
{filteredLecturesData.map((lecture, index) => ( {filteredLecturesData.map((lecture, index) => (
<div <div className="lecture" key={index} id={String(lecture.id)} onClick={onLectureClick}>
className="lecture"
key={index}
id={String(lecture.id)}
onClick={onLectureClick}
>
<p>{lecture.name} </p> <p>{lecture.name} </p>
</div> </div>
))} ))}

22
src/constants/index.ts Normal file
View File

@ -0,0 +1,22 @@
export const days = [
"",
"poniedziałek",
"wtorek",
"środa",
"czwartek",
"piątek",
];
export const hours = [
"8:00",
"9:00",
"10:00",
"11:00",
"12:00",
"13:00",
"14:00",
"15:00",
"16:00",
"17:00",
"18:00",
"19:00",
];

View File

@ -0,0 +1,48 @@
import React, { useState, useEffect } from 'react';
import { User } from '../types';
export interface CASContext {
user: User | null;
logout: () => void;
}
export const CASContext = React.createContext<CASContext | null>(null);
export interface CASProviderProps {
children: React.ReactNode;
}
export const CASProvider = ({ children }: CASProviderProps) => {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
login();
}, []);
function login() {
const urlParams = new URLSearchParams(window.location.search);
const ticket = urlParams.get('ticket');
if (!ticket) {
redirectToCASLoginService();
}
if (ticket) {
console.log(`Ticket is: ${ticket}`);
setUser({ ...user, ticket: ticket });
}
}
function logout() {
redirectToCASLogoutService();
}
function redirectToCASLogoutService() {
window.location.replace(`https://cas.amu.edu.pl/cas/logout?service=${window.origin}`);
}
function redirectToCASLoginService() {
window.location.replace(`https://cas.amu.edu.pl/cas/login?service=${window.origin}&locale=pl`);
}
return <CASContext.Provider value={{ user, logout }}>{children}</CASContext.Provider>;
};

View File

@ -0,0 +1,32 @@
import React, { useState, createContext } from 'react';
import { Lecture, Group } from '../types';
interface LectureContext {
lectures: Array<Lecture>;
choosenGroups: Array<Group>;
addLecture: (lectures: Lecture) => void;
addGroup: (group: Group) => void;
}
export const LecturesContext = createContext<LectureContext | null>(null);
interface LecturesProviderProps {
children: React.ReactNode;
}
export const LecturesProvider = ({ children }: LecturesProviderProps) => {
const [lectures, setLectures] = useState<Array<Lecture>>([]);
const [choosenGroups, setChoosenGroups] = useState<Array<Group>>([]);
const addLecture = (lecture: Lecture) => {
setLectures([...lectures, lecture]);
};
const addGroup = (group: Group) => {
setChoosenGroups([...choosenGroups, group]);
};
return (
<LecturesContext.Provider value={{ lectures, choosenGroups, addLecture, addGroup }}>
{children}
</LecturesContext.Provider>
);
};

8
src/contexts/reducers.ts Normal file
View File

@ -0,0 +1,8 @@
export enum Types {
addLecture = 'ADD_LECTURE',
removeLecture = 'REMOVE_LECTURE',
addGroup = 'ADD_GROUP',
removeGroup = 'ADD_GROUP',
addCourse = 'ADD_COURSE',
removeCourse = 'REMOVE_COURSE',
}

View File

@ -1,16 +1,18 @@
import React from "react"; import React from 'react';
import ReactDOM from "react-dom"; import ReactDOM from 'react-dom';
import App from "./App"; import { App } from './App';
import BuisnessLogicProvider from "./businesslogic/BusinessLogicProvider"; import { CASProvider } from './contexts/CASProvider';
import { LecturesProvider } from "./businesslogic/LecturesProvider"; import { LecturesProvider } from './contexts/LecturesProvider';
import { GlobalStyles } from './styles/GlobalStyles';
ReactDOM.render( ReactDOM.render(
<> <>
<LecturesProvider> <LecturesProvider>
<BuisnessLogicProvider> <CASProvider>
<GlobalStyles />
<App /> <App />
</BuisnessLogicProvider> </CASProvider>
</LecturesProvider> </LecturesProvider>
</>, </>,
document.getElementById("root") document.getElementById('root'),
); );

View File

@ -0,0 +1,20 @@
import { createGlobalStyle } from 'styled-components';
export const GlobalStyles = createGlobalStyle`
*, *::before, *::after {
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
margin: 0;
padding: 0;
line-height: 24px;
}
body::-webkit-scrollbar {
display: none;
}
`;

View File

@ -1,27 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
const styles = {
root: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
border: 0,
borderRadius: 3,
boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
color: 'white',
height: 48,
padding: '0 30px',
},
};
function HigherOrderComponent(props: { classes: any; }) {
const { classes } = props;
return <Button className={classes.root}>Higher-order component</Button>;
}
HigherOrderComponent.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(HigherOrderComponent);

21
src/types/index.ts Normal file
View File

@ -0,0 +1,21 @@
export interface Group {
id: string;
day: string;
time: string;
lecturer: string;
room: string;
}
export interface Lecture {
id?: number;
name: string;
groups: Array<Group>;
}
export interface LectureInit {
name: string;
id: number;
}
export interface User {
name?: string;
surname?: string;
ticket: string | null;
}