Compare commits
11 commits
Author | SHA1 | Date | |
---|---|---|---|
e961d1509f | |||
201168cdb8 | |||
331be96310 | |||
7b12bd6cce | |||
1bd71fd953 | |||
5d4b0ed783 | |||
947412b0a2 | |||
8b70740186 | |||
f821ff2722 | |||
0d4f3ed683 | |||
eb7acf7fc6 |
1131
api/package-lock.json
generated
1131
api/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -31,7 +31,6 @@
|
||||||
"express": "4.17.1",
|
"express": "4.17.1",
|
||||||
"express-jwt": "^6.0.0",
|
"express-jwt": "^6.0.0",
|
||||||
"express-session": "1.17.1",
|
"express-session": "1.17.1",
|
||||||
"jest": "^26.6.3",
|
|
||||||
"joi": "^17.4.0",
|
"joi": "^17.4.0",
|
||||||
"jsonwebtoken": "8.5.1",
|
"jsonwebtoken": "8.5.1",
|
||||||
"method-override": "3.0.0",
|
"method-override": "3.0.0",
|
||||||
|
@ -46,6 +45,7 @@
|
||||||
"request": "2.88.2",
|
"request": "2.88.2",
|
||||||
"sanitize-filename": "^1.6.3",
|
"sanitize-filename": "^1.6.3",
|
||||||
"slug": "^3.5.2",
|
"slug": "^3.5.2",
|
||||||
|
"supertest": "^6.1.3",
|
||||||
"turf": "^3.0.14",
|
"turf": "^3.0.14",
|
||||||
"underscore": "^1.12.0"
|
"underscore": "^1.12.0"
|
||||||
},
|
},
|
||||||
|
@ -58,13 +58,16 @@
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"eslint-plugin-prettier": "^3.3.1",
|
"eslint-plugin-prettier": "^3.3.1",
|
||||||
"eslint-plugin-promise": "^4.3.1",
|
"eslint-plugin-promise": "^4.3.1",
|
||||||
|
"jest": "^26.6.3",
|
||||||
|
"mockingoose": "^2.15.2",
|
||||||
"nodemon": "^2.0.7",
|
"nodemon": "^2.0.7",
|
||||||
"prettier": "^2.2.1"
|
"prettier": "^2.2.1"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"modulePathIgnorePatterns": [
|
"modulePathIgnorePatterns": [
|
||||||
"local"
|
"local"
|
||||||
]
|
],
|
||||||
|
"testEnvironment": "node"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"useTabs": false,
|
"useTabs": false,
|
||||||
|
|
|
@ -13,41 +13,47 @@ router.get(
|
||||||
const trackCount = await Track.find().count();
|
const trackCount = await Track.find().count();
|
||||||
const publicTrackCount = await Track.find({ visible: true }).count();
|
const publicTrackCount = await Track.find({ visible: true }).count();
|
||||||
const userCount = await User.find().count();
|
const userCount = await User.find().count();
|
||||||
|
let trackLength = 0;
|
||||||
|
let publicTrackLength = 0;
|
||||||
|
let numEvents = 0;
|
||||||
|
let trackDuration = 0;
|
||||||
|
|
||||||
const [{ trackLength, publicTrackLength, numEvents, trackDuration }] = await Track.aggregate([
|
if (trackCount) {
|
||||||
{ $lookup: { from: 'trackdatas', localField: 'publicTrackData', foreignField: '_id', as: 'publicTrackDatas' } },
|
[{ trackLength, publicTrackLength, numEvents, trackDuration }] = await Track.aggregate([
|
||||||
{ $lookup: { from: 'trackdatas', localField: 'trackData', foreignField: '_id', as: 'trackDatas' } },
|
{ $lookup: { from: 'trackdatas', localField: 'publicTrackData', foreignField: '_id', as: 'publicTrackDatas' } },
|
||||||
{
|
{ $lookup: { from: 'trackdatas', localField: 'trackData', foreignField: '_id', as: 'trackDatas' } },
|
||||||
$addFields: {
|
{
|
||||||
publicTrackData: { $arrayElemAt: ['$publicTrackDatas', 0] },
|
$addFields: {
|
||||||
trackData: { $arrayElemAt: ['$trackDatas', 0] },
|
publicTrackData: { $arrayElemAt: ['$publicTrackDatas', 0] },
|
||||||
},
|
trackData: { $arrayElemAt: ['$trackDatas', 0] },
|
||||||
},
|
|
||||||
{
|
|
||||||
$addFields: {
|
|
||||||
publicTrackLength: '$publicTrackData.trackLength',
|
|
||||||
trackLength: '$trackData.trackLength',
|
|
||||||
numEvents: '$publicTrackData.numEvents',
|
|
||||||
trackDuration: {
|
|
||||||
$cond: [
|
|
||||||
{ $and: ['$publicTrackData.recordedUntil', '$publicTrackData.recordedAt'] },
|
|
||||||
{ $subtract: ['$publicTrackData.recordedUntil', '$publicTrackData.recordedAt'] },
|
|
||||||
0,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{ $project: { publicTrackLength: true, trackLength: true, numEvents: true, trackDuration: true } },
|
$addFields: {
|
||||||
{
|
publicTrackLength: '$publicTrackData.trackLength',
|
||||||
$group: {
|
trackLength: '$trackData.trackLength',
|
||||||
_id: 'sum',
|
numEvents: '$publicTrackData.numEvents',
|
||||||
trackLength: { $sum: '$trackLength' },
|
trackDuration: {
|
||||||
publicTrackLength: { $sum: '$publicTrackLength' },
|
$cond: [
|
||||||
numEvents: { $sum: '$numEvents' },
|
{ $and: ['$publicTrackData.recordedUntil', '$publicTrackData.recordedAt'] },
|
||||||
trackDuration: { $sum: '$trackDuration' },
|
{ $subtract: ['$publicTrackData.recordedUntil', '$publicTrackData.recordedAt'] },
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
{ $project: { publicTrackLength: true, trackLength: true, numEvents: true, trackDuration: true } },
|
||||||
]);
|
{
|
||||||
|
$group: {
|
||||||
|
_id: 'sum',
|
||||||
|
trackLength: { $sum: '$trackLength' },
|
||||||
|
publicTrackLength: { $sum: '$publicTrackLength' },
|
||||||
|
numEvents: { $sum: '$numEvents' },
|
||||||
|
trackDuration: { $sum: '$trackDuration' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
const trackLengthPrivatized = Math.floor(trackLength / TRACK_LENGTH_ROUNDING) * TRACK_LENGTH_ROUNDING;
|
const trackLengthPrivatized = Math.floor(trackLength / TRACK_LENGTH_ROUNDING) * TRACK_LENGTH_ROUNDING;
|
||||||
|
|
||||||
|
|
56
api/src/routes/api/stats.test.js
Normal file
56
api/src/routes/api/stats.test.js
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
const request = require('supertest');
|
||||||
|
const mockingoose = require('mockingoose');
|
||||||
|
const express = require('express');
|
||||||
|
|
||||||
|
const Track = require('../../models/Track');
|
||||||
|
const User = require('../../models/User');
|
||||||
|
|
||||||
|
const stats = require('./stats');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
app.use('/stats', stats);
|
||||||
|
|
||||||
|
describe('stats', () => {
|
||||||
|
it('checks for available trackCount', async () => {
|
||||||
|
mockingoose(Track).toReturn(undefined, 'find').toReturn(0, 'count');
|
||||||
|
mockingoose(User).toReturn({}, 'find');
|
||||||
|
|
||||||
|
await request(app).get('/stats').expect(200).expect({
|
||||||
|
publicTrackCount: 0,
|
||||||
|
publicTrackLength: 0,
|
||||||
|
trackLength: 0,
|
||||||
|
numEvents: 0,
|
||||||
|
trackCount: 0,
|
||||||
|
trackDuration: 0,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns with json', async () => {
|
||||||
|
mockingoose(Track)
|
||||||
|
.toReturn([{}], 'find')
|
||||||
|
.toReturn(1, 'count')
|
||||||
|
.toReturn(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
trackLength: 1900,
|
||||||
|
publicTrackLength: 500,
|
||||||
|
numEvents: 1,
|
||||||
|
trackDuration: 90,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'aggregate',
|
||||||
|
);
|
||||||
|
|
||||||
|
mockingoose(User).toReturn({}, 'find');
|
||||||
|
|
||||||
|
await request(app).get('/stats').expect(200).expect({
|
||||||
|
publicTrackCount: 1,
|
||||||
|
publicTrackLength: 500,
|
||||||
|
trackLength: 1000,
|
||||||
|
numEvents: 1,
|
||||||
|
trackCount: 1,
|
||||||
|
trackDuration: 0,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
181
frontend/package-lock.json
generated
181
frontend/package-lock.json
generated
|
@ -1869,6 +1869,7 @@
|
||||||
"version": "7.29.4",
|
"version": "7.29.4",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.29.4.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.29.4.tgz",
|
||||||
"integrity": "sha512-CtrJRiSYEfbtNGtEsd78mk1n1v2TUbeABlNIcOCJdDfkN5/JTOwQEbbQpoSRxGqzcWPgStMvJ4mNolSuBRv1NA==",
|
"integrity": "sha512-CtrJRiSYEfbtNGtEsd78mk1n1v2TUbeABlNIcOCJdDfkN5/JTOwQEbbQpoSRxGqzcWPgStMvJ4mNolSuBRv1NA==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/code-frame": "^7.10.4",
|
"@babel/code-frame": "^7.10.4",
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
|
@ -1884,6 +1885,7 @@
|
||||||
"version": "5.11.9",
|
"version": "5.11.9",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.11.9.tgz",
|
||||||
"integrity": "sha512-Mn2gnA9d1wStlAIT2NU8J15LNob0YFBVjs2aEQ3j8rsfRQo+lAs7/ui1i2TGaJjapLmuNPLTsrm+nPjmZDwpcQ==",
|
"integrity": "sha512-Mn2gnA9d1wStlAIT2NU8J15LNob0YFBVjs2aEQ3j8rsfRQo+lAs7/ui1i2TGaJjapLmuNPLTsrm+nPjmZDwpcQ==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.9.2",
|
"@babel/runtime": "^7.9.2",
|
||||||
"@types/testing-library__jest-dom": "^5.9.1",
|
"@types/testing-library__jest-dom": "^5.9.1",
|
||||||
|
@ -1899,6 +1901,7 @@
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
|
||||||
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
|
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-styles": "^4.1.0",
|
"ansi-styles": "^4.1.0",
|
||||||
"supports-color": "^7.1.0"
|
"supports-color": "^7.1.0"
|
||||||
|
@ -1910,6 +1913,7 @@
|
||||||
"version": "11.2.3",
|
"version": "11.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.3.tgz",
|
||||||
"integrity": "sha512-BirBUGPkTW28ULuCwIbYo0y2+0aavHczBT6N9r3LrsswEW3pg25l1wgoE7I8QBIy1upXWkwKpYdWY7NYYP0Bxw==",
|
"integrity": "sha512-BirBUGPkTW28ULuCwIbYo0y2+0aavHczBT6N9r3LrsswEW3pg25l1wgoE7I8QBIy1upXWkwKpYdWY7NYYP0Bxw==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"@testing-library/dom": "^7.28.1"
|
"@testing-library/dom": "^7.28.1"
|
||||||
|
@ -1919,6 +1923,7 @@
|
||||||
"version": "12.6.0",
|
"version": "12.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.6.0.tgz",
|
||||||
"integrity": "sha512-FNEH/HLmOk5GO70I52tKjs7WvGYckeE/SrnLX/ip7z2IGbffyd5zOUM1tZ10vsTphqm+VbDFI0oaXu0wcfQsAQ==",
|
"integrity": "sha512-FNEH/HLmOk5GO70I52tKjs7WvGYckeE/SrnLX/ip7z2IGbffyd5zOUM1tZ10vsTphqm+VbDFI0oaXu0wcfQsAQ==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.12.5"
|
"@babel/runtime": "^7.12.5"
|
||||||
}
|
}
|
||||||
|
@ -1928,10 +1933,17 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
|
||||||
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA=="
|
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA=="
|
||||||
},
|
},
|
||||||
|
"@types/arcgis-rest-api": {
|
||||||
|
"version": "10.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/arcgis-rest-api/-/arcgis-rest-api-10.4.4.tgz",
|
||||||
|
"integrity": "sha512-5NwSfj4po+03fauyr4F5AxYzu8pbbqmxay+pNr5ef2V3Mj+7OylvV48VKuVoO9m799jhZdH3EQgQBHm3Y6q1Sw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/aria-query": {
|
"@types/aria-query": {
|
||||||
"version": "4.2.1",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.1.tgz",
|
||||||
"integrity": "sha512-S6oPal772qJZHoRZLFc/XoZW2gFvwXusYUmXPXkgxJLuEk2vOt7jc4Yo6z/vtI0EBkbPBVrJJ0B+prLIKiWqHg=="
|
"integrity": "sha512-S6oPal772qJZHoRZLFc/XoZW2gFvwXusYUmXPXkgxJLuEk2vOt7jc4Yo6z/vtI0EBkbPBVrJJ0B+prLIKiWqHg==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/babel__core": {
|
"@types/babel__core": {
|
||||||
"version": "7.1.12",
|
"version": "7.1.12",
|
||||||
|
@ -1970,6 +1982,12 @@
|
||||||
"@babel/types": "^7.3.0"
|
"@babel/types": "^7.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/classnames": {
|
||||||
|
"version": "2.2.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.11.tgz",
|
||||||
|
"integrity": "sha512-2koNhpWm3DgWRp5tpkiJ8JGc1xTn2q0l+jUNUE7oMKXUf5NpI9AIdC4kbjGNFBdHtcxBD18LAksoudAVhFKCjw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/eslint": {
|
"@types/eslint": {
|
||||||
"version": "7.2.6",
|
"version": "7.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz",
|
||||||
|
@ -1984,6 +2002,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz",
|
||||||
"integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg=="
|
"integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg=="
|
||||||
},
|
},
|
||||||
|
"@types/geojson": {
|
||||||
|
"version": "7946.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz",
|
||||||
|
"integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/glob": {
|
"@types/glob": {
|
||||||
"version": "7.1.3",
|
"version": "7.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
|
||||||
|
@ -2047,6 +2071,7 @@
|
||||||
"version": "26.0.20",
|
"version": "26.0.20",
|
||||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.20.tgz",
|
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.20.tgz",
|
||||||
"integrity": "sha512-9zi2Y+5USJRxd0FsahERhBwlcvFh6D2GLQnY2FH2BzK8J9s9omvNHIbvABwIluXa0fD8XVKMLTO0aOEuUfACAA==",
|
"integrity": "sha512-9zi2Y+5USJRxd0FsahERhBwlcvFh6D2GLQnY2FH2BzK8J9s9omvNHIbvABwIluXa0fD8XVKMLTO0aOEuUfACAA==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"jest-diff": "^26.0.0",
|
"jest-diff": "^26.0.0",
|
||||||
"pretty-format": "^26.0.0"
|
"pretty-format": "^26.0.0"
|
||||||
|
@ -2068,6 +2093,12 @@
|
||||||
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==",
|
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/luxon": {
|
||||||
|
"version": "1.26.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-1.26.4.tgz",
|
||||||
|
"integrity": "sha512-OIvbVLZQUjyZofqSFpre2VsgvKy0V0JQdRgN0k3H1DTGRdxHiaQjT16+H2gyuhAS9r8B2PQEwrSiqP6/Zka3pQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/mdast": {
|
"@types/mdast": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.3.tgz",
|
||||||
|
@ -2091,6 +2122,17 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
|
||||||
"integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA=="
|
"integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA=="
|
||||||
},
|
},
|
||||||
|
"@types/ol": {
|
||||||
|
"version": "6.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ol/-/ol-6.4.2.tgz",
|
||||||
|
"integrity": "sha512-lSms1n5obkacAosby0U3HtnDkjhEXNCYNj0BYjQXyAZHz7+QkA3SuvUHiQ91DBUaAPptCrps3E2mtaPTGw74UA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/arcgis-rest-api": "*",
|
||||||
|
"@types/geojson": "*",
|
||||||
|
"@types/topojson-specification": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/parse-json": {
|
"@types/parse-json": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
|
||||||
|
@ -2104,7 +2146,8 @@
|
||||||
"@types/prop-types": {
|
"@types/prop-types": {
|
||||||
"version": "15.7.3",
|
"version": "15.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
|
||||||
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw=="
|
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/q": {
|
"@types/q": {
|
||||||
"version": "1.5.4",
|
"version": "1.5.4",
|
||||||
|
@ -2115,6 +2158,7 @@
|
||||||
"version": "17.0.1",
|
"version": "17.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.1.tgz",
|
||||||
"integrity": "sha512-w8t9f53B2ei4jeOqf/gxtc2Sswnc3LBK5s0DyJcg5xd10tMHXts2N31cKjWfH9IC/JvEPa/YF1U4YeP1t4R6HQ==",
|
"integrity": "sha512-w8t9f53B2ei4jeOqf/gxtc2Sswnc3LBK5s0DyJcg5xd10tMHXts2N31cKjWfH9IC/JvEPa/YF1U4YeP1t4R6HQ==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
|
@ -2124,6 +2168,7 @@
|
||||||
"version": "17.0.0",
|
"version": "17.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.0.tgz",
|
||||||
"integrity": "sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g==",
|
"integrity": "sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
|
@ -2161,6 +2206,29 @@
|
||||||
"@types/react-router": "*"
|
"@types/react-router": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/redux-localstorage": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/redux-localstorage/-/redux-localstorage-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-pt+w3Y2K4Xwx79exTFZO356buBCgCM6NnyMv/EmASWb03a81g/EMEhNgH6w9dOnhTs1Clnmf2ykaia0FWXjsbQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"redux": "^3.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"redux": {
|
||||||
|
"version": "3.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz",
|
||||||
|
"integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"lodash": "^4.2.1",
|
||||||
|
"lodash-es": "^4.2.1",
|
||||||
|
"loose-envify": "^1.1.0",
|
||||||
|
"symbol-observable": "^1.0.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/resolve": {
|
"@types/resolve": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
|
||||||
|
@ -2188,10 +2256,20 @@
|
||||||
"version": "5.9.5",
|
"version": "5.9.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.9.5.tgz",
|
||||||
"integrity": "sha512-ggn3ws+yRbOHog9GxnXiEZ/35Mow6YtPZpd7Z5mKDeZS/o7zx3yAle0ov/wjhVB5QT4N2Dt+GNoGCdqkBGCajQ==",
|
"integrity": "sha512-ggn3ws+yRbOHog9GxnXiEZ/35Mow6YtPZpd7Z5mKDeZS/o7zx3yAle0ov/wjhVB5QT4N2Dt+GNoGCdqkBGCajQ==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/jest": "*"
|
"@types/jest": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/topojson-specification": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/topojson-specification/-/topojson-specification-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-ZZYZUgkmUls9Uhxx2WZNt9f/h2+H3abUUjOVmq+AaaDFckC5oAwd+MDp95kBirk+XCXrYj0hfpI6DSUiJMrpYQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/geojson": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/uglify-js": {
|
"@types/uglify-js": {
|
||||||
"version": "3.11.1",
|
"version": "3.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.1.tgz",
|
||||||
|
@ -3381,6 +3459,15 @@
|
||||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"bindings": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"file-uri-to-path": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"block-stream": {
|
"block-stream": {
|
||||||
"version": "0.0.9",
|
"version": "0.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
|
||||||
|
@ -4378,6 +4465,7 @@
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz",
|
||||||
"integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==",
|
"integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"inherits": "^2.0.4",
|
"inherits": "^2.0.4",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1",
|
||||||
|
@ -4388,6 +4476,7 @@
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
|
||||||
"integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
|
"integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"atob": "^2.1.2",
|
"atob": "^2.1.2",
|
||||||
"decode-uri-component": "^0.2.0"
|
"decode-uri-component": "^0.2.0"
|
||||||
|
@ -4503,7 +4592,8 @@
|
||||||
"css.escape": {
|
"css.escape": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
|
||||||
"integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s="
|
"integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"csscolorparser": {
|
"csscolorparser": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
|
@ -4674,7 +4764,8 @@
|
||||||
"csstype": {
|
"csstype": {
|
||||||
"version": "3.0.6",
|
"version": "3.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz",
|
||||||
"integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw=="
|
"integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"currently-unhandled": {
|
"currently-unhandled": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
|
@ -5000,7 +5091,8 @@
|
||||||
"dom-accessibility-api": {
|
"dom-accessibility-api": {
|
||||||
"version": "0.5.4",
|
"version": "0.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz",
|
||||||
"integrity": "sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ=="
|
"integrity": "sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"dom-converter": {
|
"dom-converter": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
|
@ -5514,6 +5606,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"eslint-config-prettier": {
|
||||||
|
"version": "6.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz",
|
||||||
|
"integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"get-stdin": "^6.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"get-stdin": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"eslint-config-react-app": {
|
"eslint-config-react-app": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz",
|
||||||
|
@ -5707,6 +5816,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"eslint-plugin-prettier": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"prettier-linter-helpers": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"eslint-plugin-react": {
|
"eslint-plugin-react": {
|
||||||
"version": "7.21.5",
|
"version": "7.21.5",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz",
|
||||||
|
@ -6204,6 +6322,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||||
},
|
},
|
||||||
|
"fast-diff": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"fast-glob": {
|
"fast-glob": {
|
||||||
"version": "3.2.5",
|
"version": "3.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
|
||||||
|
@ -6285,6 +6409,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"file-uri-to-path": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"filesize": {
|
"filesize": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz",
|
||||||
|
@ -9173,7 +9303,8 @@
|
||||||
"lz-string": {
|
"lz-string": {
|
||||||
"version": "1.4.4",
|
"version": "1.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz",
|
||||||
"integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY="
|
"integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"magic-string": {
|
"magic-string": {
|
||||||
"version": "0.25.7",
|
"version": "0.25.7",
|
||||||
|
@ -9431,6 +9562,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"merge": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/merge/-/merge-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-TcuhVDV+e6X457MQAm7xIb19rWhZuEDEho7RrwxMpQ/3GhD5sDlnP188gjQQuweXHy9igdke5oUtVOXX1X8Sxg=="
|
||||||
|
},
|
||||||
"merge-descriptors": {
|
"merge-descriptors": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||||
|
@ -9521,7 +9657,8 @@
|
||||||
"min-indent": {
|
"min-indent": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
|
||||||
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="
|
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"mini-create-react-context": {
|
"mini-create-react-context": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
|
@ -11781,6 +11918,21 @@
|
||||||
"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.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-diff": "^1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"pretty-bytes": {
|
"pretty-bytes": {
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.5.0.tgz",
|
||||||
|
@ -12496,6 +12648,7 @@
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
|
||||||
"integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
|
"integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"indent-string": "^4.0.0",
|
"indent-string": "^4.0.0",
|
||||||
"strip-indent": "^3.0.0"
|
"strip-indent": "^3.0.0"
|
||||||
|
@ -12510,10 +12663,13 @@
|
||||||
"symbol-observable": "^1.2.0"
|
"symbol-observable": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"redux-localstorage": {
|
"redux-localstorage-simple": {
|
||||||
"version": "0.4.1",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/redux-localstorage/-/redux-localstorage-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/redux-localstorage-simple/-/redux-localstorage-simple-2.4.0.tgz",
|
||||||
"integrity": "sha1-+vbXGcWBOXKU2BFHP/zt7gZckzw="
|
"integrity": "sha512-Zj28elJtO4fqXXC+gikonbKhFUkiwlalScYRn3EGUU44Pika1995AqUgzjIcsSPlBhIDV2WudFqa/YI9+3aE9Q==",
|
||||||
|
"requires": {
|
||||||
|
"merge": "2.1.0"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"regenerate": {
|
"regenerate": {
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
|
@ -14368,6 +14524,7 @@
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
|
||||||
"integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
|
"integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"min-indent": "^1.0.0"
|
"min-indent": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -15532,6 +15689,7 @@
|
||||||
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
|
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"bindings": "^1.5.0",
|
||||||
"nan": "^2.12.1"
|
"nan": "^2.12.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -16129,6 +16287,7 @@
|
||||||
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
|
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"bindings": "^1.5.0",
|
||||||
"nan": "^2.12.1"
|
"nan": "^2.12.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,13 +3,6 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@testing-library/jest-dom": "^5.11.4",
|
|
||||||
"@testing-library/react": "^11.1.0",
|
|
||||||
"@testing-library/user-event": "^12.1.10",
|
|
||||||
"@types/jest": "^26.0.20",
|
|
||||||
"@types/node": "^14.14.25",
|
|
||||||
"@types/react": "^17.0.1",
|
|
||||||
"@types/react-dom": "^17.0.0",
|
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"luxon": "^1.25.0",
|
"luxon": "^1.25.0",
|
||||||
"node-sass": "^4.14.1",
|
"node-sass": "^4.14.1",
|
||||||
|
@ -22,7 +15,7 @@
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "4.0.1",
|
"react-scripts": "4.0.1",
|
||||||
"redux": "^4.0.5",
|
"redux": "^4.0.5",
|
||||||
"redux-localstorage": "^0.4.1",
|
"redux-localstorage-simple": "^2.4.0",
|
||||||
"rxjs": "^6.6.3",
|
"rxjs": "^6.6.3",
|
||||||
"rxjs-hooks": "^0.6.2",
|
"rxjs-hooks": "^0.6.2",
|
||||||
"semantic-ui-css": "^2.4.1",
|
"semantic-ui-css": "^2.4.1",
|
||||||
|
@ -39,8 +32,18 @@
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": [
|
"extends": [
|
||||||
"react-app",
|
"react-app",
|
||||||
"react-app/jest"
|
"react-app/jest",
|
||||||
]
|
"prettier"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"prettier"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"prettier/prettier": "warn",
|
||||||
|
"standard/array-bracket-even-spacing": 0,
|
||||||
|
"standard/computed-property-even-spacing": 0,
|
||||||
|
"standard/object-curly-even-spacing": 0
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
|
@ -56,8 +59,29 @@
|
||||||
},
|
},
|
||||||
"proxy": "http://api:3000",
|
"proxy": "http://api:3000",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@testing-library/jest-dom": "^5.11.4",
|
||||||
|
"@testing-library/react": "^11.1.0",
|
||||||
|
"@testing-library/user-event": "^12.1.10",
|
||||||
|
"@types/classnames": "^2.2.11",
|
||||||
|
"@types/jest": "^26.0.20",
|
||||||
"@types/lodash": "^4.14.168",
|
"@types/lodash": "^4.14.168",
|
||||||
|
"@types/luxon": "^1.26.4",
|
||||||
|
"@types/node": "^14.14.25",
|
||||||
|
"@types/ol": "^6.4.2",
|
||||||
|
"@types/react": "^17.0.1",
|
||||||
|
"@types/react-dom": "^17.0.0",
|
||||||
"@types/react-redux": "^7.1.16",
|
"@types/react-redux": "^7.1.16",
|
||||||
"@types/react-router-dom": "^5.1.7"
|
"@types/react-router-dom": "^5.1.7",
|
||||||
|
"eslint-config-prettier": "^6.15.0",
|
||||||
|
"eslint-plugin-prettier": "^3.3.1",
|
||||||
|
"prettier": "^2.2.1"
|
||||||
|
},
|
||||||
|
"prettier": {
|
||||||
|
"useTabs": false,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 120
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,6 @@ import classnames from 'classnames'
|
||||||
|
|
||||||
import styles from './Page.module.scss'
|
import styles from './Page.module.scss'
|
||||||
|
|
||||||
export default function Page({small, children}) {
|
export default function Page({children, small = false}: {children: React.ReactNode, small?: boolean }) {
|
||||||
return <main className={classnames(styles.page, small && styles.small)}>{children}</main>
|
return <main className={classnames(styles.page, small && styles.small)}>{children}</main>
|
||||||
}
|
}
|
|
@ -1,28 +1,45 @@
|
||||||
import React from 'react'
|
import React from 'react';
|
||||||
import {Form, Button} from 'semantic-ui-react'
|
import { Form, Button } from 'semantic-ui-react';
|
||||||
|
|
||||||
export default function RegistrationForm({onSubmit: onSubmitOuter}) {
|
type RegistrationFormSubmit = {
|
||||||
const [username, setUsername] = React.useState(null)
|
username: string | null;
|
||||||
const [email, setEmail] = React.useState(null)
|
email: string | null;
|
||||||
const [password, setPassword] = React.useState(null)
|
password: string | null;
|
||||||
const [password2, setPassword2] = React.useState(null)
|
};
|
||||||
|
|
||||||
const onChangeUsername = React.useCallback((e) => setUsername(e.target.value), [])
|
export default function RegistrationForm({
|
||||||
const onChangeEmail = React.useCallback((e) => setEmail(e.target.value), [])
|
onSubmit: onSubmitOuter,
|
||||||
const onChangePassword = React.useCallback((e) => setPassword(e.target.value), [])
|
}: {
|
||||||
const onChangePassword2 = React.useCallback((e) => setPassword2(e.target.value), [])
|
onSubmit: (data: RegistrationFormSubmit) => void;
|
||||||
|
}) {
|
||||||
|
const [username, setUsername] = React.useState('');
|
||||||
|
const [email, setEmail] = React.useState('');
|
||||||
|
const [password, setPassword] = React.useState('');
|
||||||
|
const [password2, setPassword2] = React.useState('');
|
||||||
|
|
||||||
|
const onChangeUsername = React.useCallback((e) => setUsername(e.target.value), []);
|
||||||
|
const onChangeEmail = React.useCallback((e) => setEmail(e.target.value), []);
|
||||||
|
const onChangePassword = React.useCallback((e) => setPassword(e.target.value), []);
|
||||||
|
const onChangePassword2 = React.useCallback((e) => setPassword2(e.target.value), []);
|
||||||
|
|
||||||
const onSubmit = React.useCallback(() => {
|
const onSubmit = React.useCallback(() => {
|
||||||
if (username && email && password && password2 === password) {
|
if (username && email && password && password2 === password) {
|
||||||
onSubmitOuter({username, email, password})
|
onSubmitOuter({ username, email, password });
|
||||||
}
|
}
|
||||||
}, [username, email, password, password2, onSubmitOuter])
|
}, [username, email, password, password2, onSubmitOuter]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form onSubmit={onSubmit}>
|
<Form onSubmit={onSubmit}>
|
||||||
<Form.Input label="Username" value={username} onChange={onChangeUsername} name="username" />
|
<Form.Input label="Username" value={username} onChange={onChangeUsername} name="username" />
|
||||||
<Form.Input label="e-Mail" value={email} onChange={onChangeEmail} name="email" />
|
<Form.Input label="e-Mail" value={email} onChange={onChangeEmail} name="email" />
|
||||||
<Form.Input label="Password" type="password" value={password} onChange={onChangePassword} name="password" />
|
<Form.Input
|
||||||
|
label="Password"
|
||||||
|
type="password"
|
||||||
|
value={password}
|
||||||
|
onChange={onChangePassword}
|
||||||
|
name="password"
|
||||||
|
minLength={6}
|
||||||
|
/>
|
||||||
<Form.Input
|
<Form.Input
|
||||||
label="Password (repeat)"
|
label="Password (repeat)"
|
||||||
type="password"
|
type="password"
|
||||||
|
@ -30,8 +47,9 @@ export default function RegistrationForm({onSubmit: onSubmitOuter}) {
|
||||||
onChange={onChangePassword2}
|
onChange={onChangePassword2}
|
||||||
name="password2"
|
name="password2"
|
||||||
error={password2 != null && password !== password2 ? 'Your passwords do not match.' : null}
|
error={password2 != null && password !== password2 ? 'Your passwords do not match.' : null}
|
||||||
|
minLength={6}
|
||||||
/>
|
/>
|
||||||
<Button type="submit">Submit</Button>
|
<Button type="submit">Submit</Button>
|
||||||
</Form>
|
</Form>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,15 +5,9 @@ import 'semantic-ui-css/semantic.min.css'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import App from './App'
|
import App from './App'
|
||||||
|
|
||||||
|
import { store } from './store';
|
||||||
|
|
||||||
import {Provider} from 'react-redux'
|
import {Provider} from 'react-redux'
|
||||||
import {compose, createStore} from 'redux'
|
|
||||||
import persistState from 'redux-localstorage'
|
|
||||||
|
|
||||||
import rootReducer from './reducers'
|
|
||||||
|
|
||||||
const enhancer = compose(persistState(['login']))
|
|
||||||
|
|
||||||
const store = createStore(rootReducer, undefined, enhancer)
|
|
||||||
|
|
||||||
// TODO: remove
|
// TODO: remove
|
||||||
Settings.defaultLocale = 'de-DE'
|
Settings.defaultLocale = 'de-DE'
|
||||||
|
|
|
@ -1,18 +1,36 @@
|
||||||
import React from 'react'
|
import React from 'react';
|
||||||
import {connect} from 'react-redux'
|
import { connect } from 'react-redux';
|
||||||
import {Redirect} from 'react-router-dom'
|
import { Redirect } from 'react-router-dom';
|
||||||
|
|
||||||
import {Page, RegistrationForm} from '../components'
|
import api from 'api';
|
||||||
|
import { Page, RegistrationForm } from 'components';
|
||||||
|
import type { RootState } from '../store';
|
||||||
|
|
||||||
const RegistrationPage = connect((state) => ({loggedIn: Boolean(state.login)}))(function RegistrationPage({loggedIn}) {
|
const RegistrationPage = connect((state: RootState) => ({ loggedIn: Boolean(state.login) }))(function RegistrationPage({
|
||||||
return loggedIn ? (
|
loggedIn,
|
||||||
<Redirect to="/" />
|
}) {
|
||||||
) : (
|
const [message, setMessage] = React.useState();
|
||||||
|
|
||||||
|
const onSubmit = React.useCallback(async ({ username, email, password }) => {
|
||||||
|
const response = await api.post(`/accounts/register`, {
|
||||||
|
body: { username, email, password, confirmPassword: password },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response && response.message) {
|
||||||
|
setMessage(response.message);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (loggedIn) {
|
||||||
|
return <Redirect to="/" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
<Page small>
|
<Page small>
|
||||||
<h2>Register</h2>
|
<h2>Register</h2>
|
||||||
<RegistrationForm />
|
{message ? message : <RegistrationForm onSubmit={onSubmit} />}
|
||||||
</Page>
|
</Page>
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
|
|
||||||
export default RegistrationPage
|
export default RegistrationPage;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {combineReducers} from 'redux'
|
import { combineReducers } from 'redux';
|
||||||
|
|
||||||
import login from './login'
|
import login from './login';
|
||||||
|
|
||||||
export default combineReducers({login})
|
export default combineReducers({ login });
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
const initialState = null
|
const initialState = null;
|
||||||
|
|
||||||
export function login(user) {
|
export function login(user) {
|
||||||
return {type: 'LOGIN.LOGIN', payload: {user}}
|
return { type: 'LOGIN.LOGIN', payload: { user } };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logout() {
|
export function logout() {
|
||||||
return {type: 'LOGIN.LOGOUT'}
|
return { type: 'LOGIN.LOGOUT' };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function loginReducer(state = initialState, action) {
|
export default function loginReducer(state = initialState, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'LOGIN.LOGIN':
|
case 'LOGIN.LOGIN':
|
||||||
return action.payload.user
|
return action.payload.user;
|
||||||
case 'LOGIN.LOGOUT':
|
case 'LOGIN.LOGOUT':
|
||||||
return null
|
return null;
|
||||||
default:
|
default:
|
||||||
return state
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
frontend/src/store.ts
Normal file
22
frontend/src/store.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { applyMiddleware, createStore, compose } from 'redux';
|
||||||
|
import { save, load } from 'redux-localstorage-simple';
|
||||||
|
|
||||||
|
import rootReducer from './reducers';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const composeEnhancers =
|
||||||
|
(process.env.NODE_ENV !== 'production' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose;
|
||||||
|
|
||||||
|
export const store = createStore(
|
||||||
|
rootReducer,
|
||||||
|
load({ states: ['login'], disableWarnings: true }),
|
||||||
|
composeEnhancers(applyMiddleware(save({ states: ['login'] }))),
|
||||||
|
);
|
||||||
|
|
||||||
|
export type AppDispatch = typeof store.dispatch;
|
||||||
|
export type RootState = ReturnType<typeof store.getState>;
|
Loading…
Reference in a new issue