From 07270cd8d7bfd33ac09c042d4ab4edd191240462 Mon Sep 17 00:00:00 2001 From: Sebastian Ovide Date: Fri, 11 Sep 2020 18:02:32 +0100 Subject: [PATCH] added a custom page with reports (#609) --- package-lock.json | 370 +++++++++++++++++++---- package.json | 4 +- src/App.js | 2 + src/custom/components/AnonymousPage.js | 26 -- src/custom/components/AnonymousPage.scss | 20 -- src/custom/components/ReportsPage.js | 219 ++++++++++++++ src/custom/config.js | 16 +- 7 files changed, 541 insertions(+), 116 deletions(-) delete mode 100644 src/custom/components/AnonymousPage.js delete mode 100644 src/custom/components/AnonymousPage.scss create mode 100644 src/custom/components/ReportsPage.js diff --git a/package-lock.json b/package-lock.json index cb939f79..b450976c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1369,35 +1369,73 @@ "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" }, "@firebase/analytics": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.4.2.tgz", - "integrity": "sha512-WCoeUAO3lP6ikHJ3/XYptV90fpTidzTS9VpAfiVQK8gl9w1zvvKSavY9U3+EVG3frOPCFdE5DBO4MYrUw4gaqw==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.5.0.tgz", + "integrity": "sha512-WyQ8BT6JSoXpg4q7SV9Yg5EPXbGbG8FkkXAIhV/AnslCglhpxegO1FU33qbuT4Grzc525hZJA97oqtQS8tm4Wg==", "requires": { - "@firebase/analytics-types": "0.3.1", - "@firebase/component": "0.1.18", - "@firebase/installations": "0.4.16", + "@firebase/analytics-types": "0.4.0", + "@firebase/component": "0.1.19", + "@firebase/installations": "0.4.17", "@firebase/logger": "0.2.6", - "@firebase/util": "0.3.1", + "@firebase/util": "0.3.2", "tslib": "^1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.19.tgz", + "integrity": "sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ==", + "requires": { + "@firebase/util": "0.3.2", + "tslib": "^1.11.1" + } + }, + "@firebase/util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.2.tgz", + "integrity": "sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g==", + "requires": { + "tslib": "^1.11.1" + } + } } }, "@firebase/analytics-types": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.3.1.tgz", - "integrity": "sha512-63vVJ5NIBh/JF8l9LuPrQYSzFimk7zYHySQB4Dk9rVdJ8kV/vGQoVTvRu1UW05sEc2Ug5PqtEChtTHU+9hvPcA==" + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.4.0.tgz", + "integrity": "sha512-Jj2xW+8+8XPfWGkv9HPv/uR+Qrmq37NPYT352wf7MvE9LrstpLVmFg3LqG6MCRr5miLAom5sen2gZ+iOhVDeRA==" }, "@firebase/app": { - "version": "0.6.10", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.10.tgz", - "integrity": "sha512-USg/AbgqBERhY0LayrKmmp7pka08WPa7OlFI46kaNW1pA2mUNf/ifTaxhCr2hGg/eWI0zPhpbEvtGQhSJ/QqWg==", + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.11.tgz", + "integrity": "sha512-FH++PaoyTzfTAVuJ0gITNYEIcjT5G+D0671La27MU8Vvr6MTko+5YUZ4xS9QItyotSeRF4rMJ1KR7G8LSyySiA==", "requires": { "@firebase/app-types": "0.6.1", - "@firebase/component": "0.1.18", + "@firebase/component": "0.1.19", "@firebase/logger": "0.2.6", - "@firebase/util": "0.3.1", + "@firebase/util": "0.3.2", "dom-storage": "2.1.0", "tslib": "^1.11.1", "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.19.tgz", + "integrity": "sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ==", + "requires": { + "@firebase/util": "0.3.2", + "tslib": "^1.11.1" + } + }, + "@firebase/util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.2.tgz", + "integrity": "sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g==", + "requires": { + "tslib": "^1.11.1" + } + } } }, "@firebase/app-types": { @@ -1427,6 +1465,7 @@ "version": "0.1.18", "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.18.tgz", "integrity": "sha512-c8gd1k/e0sbBTR0xkLIYUN8nVkA0zWxcXGIvdfYtGEsNw6n7kh5HkcxKXOPB8S7bcPpqZkGgBIfvd94IyG2gaQ==", + "dev": true, "requires": { "@firebase/util": "0.3.1", "tslib": "^1.11.1" @@ -1436,6 +1475,7 @@ "version": "0.6.11", "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.11.tgz", "integrity": "sha512-QOHhB7+CdjVhEXG9CyX0roA9ARJcEuwbozz0Bix+ULuZqjQ58KUFHMH1apW6EEiUP22d/mYD7dNXsUGshjL9PA==", + "dev": true, "requires": { "@firebase/auth-interop-types": "0.1.5", "@firebase/component": "0.1.18", @@ -1455,19 +1495,38 @@ } }, "@firebase/firestore": { - "version": "1.16.6", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.16.6.tgz", - "integrity": "sha512-w04ZS0i8xclGNvwpxt7Q3M9nhUq6pL0G73ZpDizPKB+peTuY/bcks+zrfNKZwDEaM+i0/lg9UZKREr0HtZOJsw==", + "version": "1.16.7", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.16.7.tgz", + "integrity": "sha512-MrX7te1eUib2pUzD3dLWdRuM7EPcCxtPwO4M9og3IFYr1U3XlxybD7kxyYswltHcUm6+kba3VKL1rvkqZ1sn2g==", "requires": { - "@firebase/component": "0.1.18", + "@firebase/component": "0.1.19", "@firebase/firestore-types": "1.12.1", "@firebase/logger": "0.2.6", - "@firebase/util": "0.3.1", + "@firebase/util": "0.3.2", "@firebase/webchannel-wrapper": "0.3.0", "@grpc/grpc-js": "^1.0.0", "@grpc/proto-loader": "^0.5.0", "node-fetch": "2.6.0", "tslib": "^1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.19.tgz", + "integrity": "sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ==", + "requires": { + "@firebase/util": "0.3.2", + "tslib": "^1.11.1" + } + }, + "@firebase/util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.2.tgz", + "integrity": "sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g==", + "requires": { + "tslib": "^1.11.1" + } + } } }, "@firebase/firestore-types": { @@ -1476,15 +1535,34 @@ "integrity": "sha512-CpWcDriYnGDoAl0D9DcSuwX0b/fXqi7qOwuuTI1M0SYxau48G8cqhVjzjqPDgEM3kDGYJTnPN3ALS0Z4cnwERQ==" }, "@firebase/functions": { - "version": "0.4.50", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.50.tgz", - "integrity": "sha512-eBsNrUm/Jfc/xsQXmxQRSkEg6pwHlMd2hice8N90/EeqgwqS/SCvC+O9cJITLlXroAghb9jWDWRvAkDU/TOhpw==", + "version": "0.4.51", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.51.tgz", + "integrity": "sha512-PPx8eZcr4eoU9BITOUGUVurs4WZu8Thj3uCWx766dU3mV1W/7kRgtiptmW0XJUB18FZ1PT3+Hadd6V6vjtLgYw==", "requires": { - "@firebase/component": "0.1.18", + "@firebase/component": "0.1.19", "@firebase/functions-types": "0.3.17", "@firebase/messaging-types": "0.5.0", "isomorphic-fetch": "2.2.1", "tslib": "^1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.19.tgz", + "integrity": "sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ==", + "requires": { + "@firebase/util": "0.3.2", + "tslib": "^1.11.1" + } + }, + "@firebase/util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.2.tgz", + "integrity": "sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g==", + "requires": { + "tslib": "^1.11.1" + } + } } }, "@firebase/functions-types": { @@ -1493,15 +1571,34 @@ "integrity": "sha512-DGR4i3VI55KnYk4IxrIw7+VG7Q3gA65azHnZxo98Il8IvYLr2UTBlSh72dTLlDf25NW51HqvJgYJDKvSaAeyHQ==" }, "@firebase/installations": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.16.tgz", - "integrity": "sha512-gqv3IrBUmPWKpH8wLJ0fZcAH1NEXwQhqjqnK3cQXRcIkEARP430cmIAaj7CcPdgdemHX9HqwJG+So/yBHIYXPA==", + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.17.tgz", + "integrity": "sha512-AE/TyzIpwkC4UayRJD419xTqZkKzxwk0FLht3Dci8WI2OEKHSwoZG9xv4hOBZebe+fDzoV2EzfatQY8c/6Avig==", "requires": { - "@firebase/component": "0.1.18", + "@firebase/component": "0.1.19", "@firebase/installations-types": "0.3.4", - "@firebase/util": "0.3.1", + "@firebase/util": "0.3.2", "idb": "3.0.2", "tslib": "^1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.19.tgz", + "integrity": "sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ==", + "requires": { + "@firebase/util": "0.3.2", + "tslib": "^1.11.1" + } + }, + "@firebase/util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.2.tgz", + "integrity": "sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g==", + "requires": { + "tslib": "^1.11.1" + } + } } }, "@firebase/installations-types": { @@ -1515,16 +1612,35 @@ "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" }, "@firebase/messaging": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.7.0.tgz", - "integrity": "sha512-PTD5pQw9QremOjiWWZYOkzcX6OKByMvlG+NQXdTnyL3kLbE01Bdp9iWhkH6ipNpHYMiwcK1RZD4TLkYVBviBsw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.7.1.tgz", + "integrity": "sha512-iev/ST9v0xd/8YpGYrZtDcqdD9J6ZWzSuceRn8EKy5vIgQvW/rk2eTQc8axzvDpQ36ZfphMYuhW6XuNrR3Pd2Q==", "requires": { - "@firebase/component": "0.1.18", - "@firebase/installations": "0.4.16", + "@firebase/component": "0.1.19", + "@firebase/installations": "0.4.17", "@firebase/messaging-types": "0.5.0", - "@firebase/util": "0.3.1", + "@firebase/util": "0.3.2", "idb": "3.0.2", "tslib": "^1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.19.tgz", + "integrity": "sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ==", + "requires": { + "@firebase/util": "0.3.2", + "tslib": "^1.11.1" + } + }, + "@firebase/util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.2.tgz", + "integrity": "sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g==", + "requires": { + "tslib": "^1.11.1" + } + } } }, "@firebase/messaging-types": { @@ -1533,16 +1649,35 @@ "integrity": "sha512-QaaBswrU6umJYb/ZYvjR5JDSslCGOH6D9P136PhabFAHLTR4TWjsaACvbBXuvwrfCXu10DtcjMxqfhdNIB1Xfg==" }, "@firebase/performance": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.4.0.tgz", - "integrity": "sha512-LZG89G2wAjTRsIcuewIx152+DyRzQf8UtPCAjifkFiMcAY4GmZZKeIbIC3b4oQDwTgH5i0IKKd4EOv7dLD97gw==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.4.1.tgz", + "integrity": "sha512-eAqS3/456xnUwuTg4w58x2fYbvTtQpgt67lpBUX3DuhOqwiM8+JELRte52nDgum2lTaTZWiu5de9mPuAYx2WDg==", "requires": { - "@firebase/component": "0.1.18", - "@firebase/installations": "0.4.16", + "@firebase/component": "0.1.19", + "@firebase/installations": "0.4.17", "@firebase/logger": "0.2.6", "@firebase/performance-types": "0.0.13", - "@firebase/util": "0.3.1", + "@firebase/util": "0.3.2", "tslib": "^1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.19.tgz", + "integrity": "sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ==", + "requires": { + "@firebase/util": "0.3.2", + "tslib": "^1.11.1" + } + }, + "@firebase/util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.2.tgz", + "integrity": "sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g==", + "requires": { + "tslib": "^1.11.1" + } + } } }, "@firebase/performance-types": { @@ -1568,16 +1703,35 @@ } }, "@firebase/remote-config": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.27.tgz", - "integrity": "sha512-BGjmQomRKNf+yGJ/3/5Kw6zNLM5jY9oTVjLmYsQXf6U+HMgz6J2H6EVGc1bZW7YSsvak8f6DomxegQtvfvwaMw==", + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.28.tgz", + "integrity": "sha512-4zSdyxpt94jAnFhO8toNjG8oMKBD+xTuBIcK+Nw8BdQWeJhEamgXlupdBARUk1uf3AvYICngHH32+Si/dMVTbw==", "requires": { - "@firebase/component": "0.1.18", - "@firebase/installations": "0.4.16", + "@firebase/component": "0.1.19", + "@firebase/installations": "0.4.17", "@firebase/logger": "0.2.6", "@firebase/remote-config-types": "0.1.9", - "@firebase/util": "0.3.1", + "@firebase/util": "0.3.2", "tslib": "^1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.19.tgz", + "integrity": "sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ==", + "requires": { + "@firebase/util": "0.3.2", + "tslib": "^1.11.1" + } + }, + "@firebase/util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.2.tgz", + "integrity": "sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g==", + "requires": { + "tslib": "^1.11.1" + } + } } }, "@firebase/remote-config-types": { @@ -1586,14 +1740,33 @@ "integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA==" }, "@firebase/storage": { - "version": "0.3.42", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.42.tgz", - "integrity": "sha512-FqHDWZPhATQeOFBQUZPsQO7xhnGBxprYVDb9eIjCnh1yRl6WAv/OQGHOF+JU5+H+YkjsKTtr/5VjyDl3Y0UHxw==", + "version": "0.3.43", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.43.tgz", + "integrity": "sha512-Jp54jcuyimLxPhZHFVAhNbQmgTu3Sda7vXjXrNpPEhlvvMSq4yuZBR6RrZxe/OrNVprLHh/6lTCjwjOVSo3bWA==", "requires": { - "@firebase/component": "0.1.18", + "@firebase/component": "0.1.19", "@firebase/storage-types": "0.3.13", - "@firebase/util": "0.3.1", + "@firebase/util": "0.3.2", "tslib": "^1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.19.tgz", + "integrity": "sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ==", + "requires": { + "@firebase/util": "0.3.2", + "tslib": "^1.11.1" + } + }, + "@firebase/util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.2.tgz", + "integrity": "sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g==", + "requires": { + "tslib": "^1.11.1" + } + } } }, "@firebase/storage-types": { @@ -1605,6 +1778,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.1.tgz", "integrity": "sha512-zjVd9rfL08dRRdZILFn1RZTHb1euCcnD9N/9P56gdBcm2bvT5XsCC4G6t5toQBpE/H/jYe5h6MZMqfLu3EQLXw==", + "dev": true, "requires": { "tslib": "^1.11.1" } @@ -6953,6 +7127,32 @@ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" }, + "chart.js": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.3.tgz", + "integrity": "sha512-+2jlOobSk52c1VU6fzkh3UwqHMdSlgH1xFv9FKMqHiNCpXsGPQa/+81AFa+i3jZ253Mq9aAycPwDjnn1XbRNNw==", + "requires": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "chartjs-color": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", + "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", + "requires": { + "chartjs-color-string": "^0.6.0", + "color-convert": "^1.9.3" + } + }, + "chartjs-color-string": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", + "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", + "requires": { + "color-name": "^1.0.0" + } + }, "chokidar": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", @@ -10794,24 +10994,57 @@ } }, "firebase": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-7.19.1.tgz", - "integrity": "sha512-kZUbxN4amrKZc2pkmAMqQtWNkb608rCZLL61NC0X/UXI1euWhIFXdCGQNBlEdOlUwDLBGwNpyTBhQtL4UYHEZw==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-7.20.0.tgz", + "integrity": "sha512-ijgiUPB93UGWw2P2kgUQgghu5WOn/WR2J8C/V6ZSeI1PQqiEwsfn0kvw4iMJeqLQpA/FVeZz/+p0ubE5kzqhBA==", "requires": { - "@firebase/analytics": "0.4.2", - "@firebase/app": "0.6.10", + "@firebase/analytics": "0.5.0", + "@firebase/app": "0.6.11", "@firebase/app-types": "0.6.1", "@firebase/auth": "0.14.9", - "@firebase/database": "0.6.11", - "@firebase/firestore": "1.16.6", - "@firebase/functions": "0.4.50", - "@firebase/installations": "0.4.16", - "@firebase/messaging": "0.7.0", - "@firebase/performance": "0.4.0", + "@firebase/database": "0.6.12", + "@firebase/firestore": "1.16.7", + "@firebase/functions": "0.4.51", + "@firebase/installations": "0.4.17", + "@firebase/messaging": "0.7.1", + "@firebase/performance": "0.4.1", "@firebase/polyfill": "0.3.36", - "@firebase/remote-config": "0.1.27", - "@firebase/storage": "0.3.42", - "@firebase/util": "0.3.1" + "@firebase/remote-config": "0.1.28", + "@firebase/storage": "0.3.43", + "@firebase/util": "0.3.2" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.19.tgz", + "integrity": "sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ==", + "requires": { + "@firebase/util": "0.3.2", + "tslib": "^1.11.1" + } + }, + "@firebase/database": { + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.12.tgz", + "integrity": "sha512-OLUxp8TkXiML4X5LWM5IACsSDvo3fcf4mTbTe5RF+N6TRFv0Svzlet5OgGIa3ET1dQvNiisrMX7zzRa0OTLs7Q==", + "requires": { + "@firebase/auth-interop-types": "0.1.5", + "@firebase/component": "0.1.19", + "@firebase/database-types": "0.5.2", + "@firebase/logger": "0.2.6", + "@firebase/util": "0.3.2", + "faye-websocket": "0.11.3", + "tslib": "^1.11.1" + } + }, + "@firebase/util": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.2.tgz", + "integrity": "sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g==", + "requires": { + "tslib": "^1.11.1" + } + } } }, "firebase-admin": { @@ -16259,6 +16492,11 @@ "minimist": "^1.2.5" } }, + "moment": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" + }, "morgan": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", diff --git a/package.json b/package.json index 0c49fcc9..3a6d82de 100755 --- a/package.json +++ b/package.json @@ -59,13 +59,15 @@ "@turf/turf": "latest", "axios": "^0.20.0", "blueimp-load-image": "^5.14.0", + "chart.js": "^2.9.3", "classnames": "latest", "dms2dec": "latest", - "firebase": "^7.19.1", + "firebase": "^7.20.0", "localforage": "^1.9.0", "lodash": "^4.17.20", "mapbox-gl": "^1.12.0", "md5": "^2.3.0", + "moment": "^2.27.0", "prop-types": "^15.7.2", "react": "latest", "react-dom": "latest", diff --git a/src/App.js b/src/App.js index 1b73a932..187eb0dc 100644 --- a/src/App.js +++ b/src/App.js @@ -718,6 +718,8 @@ class App extends Component { {...props} handleClose={history.goBack} label={CustomPage.label} + geojson={this.state.geojson} + config={this.props.config} /> )} /> diff --git a/src/custom/components/AnonymousPage.js b/src/custom/components/AnonymousPage.js deleted file mode 100644 index 703d810e..00000000 --- a/src/custom/components/AnonymousPage.js +++ /dev/null @@ -1,26 +0,0 @@ -import React, { Component } from "react"; -import { Link } from "react-router-dom"; - -import Button from "@material-ui/core/Button"; -// import backButton from '../images/left-arrow.svg'; -import "./AnonymousPage.scss"; - -class AnonymousPage extends Component { - render() { - return ( -
-
- - - - -
Page for Anonymous
-
-
- ); - } -} - -export default AnonymousPage; diff --git a/src/custom/components/AnonymousPage.scss b/src/custom/components/AnonymousPage.scss deleted file mode 100644 index d17ada5e..00000000 --- a/src/custom/components/AnonymousPage.scss +++ /dev/null @@ -1,20 +0,0 @@ -.geovation-page1 { - display:flex; - flex:1; - flex-direction:column; - height:100vh; - - .headline { - display:flex; - height:50px; - align-items:center; - - .buttonback { - height:25px; - } - } - - .headtext { - display:flex; - } -} diff --git a/src/custom/components/ReportsPage.js b/src/custom/components/ReportsPage.js new file mode 100644 index 00000000..a01c3f8f --- /dev/null +++ b/src/custom/components/ReportsPage.js @@ -0,0 +1,219 @@ +import React, { Component } from "react"; + +import _ from "lodash"; +import moment from "moment"; +import Chart from "chart.js"; + +import { withStyles } from "@material-ui/core/styles"; + +// import StarsIcon from "@material-ui/icons/Stars"; + +import PageWrapper from "../../components/PageWrapper"; + +const styles = (theme) => ({}); + +class Reports extends Component { + constructor(props) { + super(props); + this.graphRef = React.createRef(); + this.brandsRef = React.createRef(); + this.categoryRef = React.createRef(); + } + + findCategoryLabel(branch, key) { + if (!branch) { + return null; + } + if (branch[key]) { + return branch[key].label; + } else { + let label = null; + _.find(branch, (child) => { + label = this.findCategoryLabel(child.children, key); + return !!label; + }); + + return label; + } + } + + componentDidMount(months, ctx) { + const { geojson, config } = this.props; + + if (geojson) { + const withCategories = _.filter( + geojson.features, + (f) => f.properties.categories + ); + + const brands = {}; + const categories = {}; + const days = {}; + const months = {}; + const years = {}; + + // reformat the info + _.forEach(withCategories, (entry) => { + const liveDate = entry.properties.moderated; + // const datePeriod = moment(liveDate).format("YYYYMMDD"); + const day = moment(liveDate).startOf("day").toDate(); + const month = moment(liveDate).startOf("month").toDate(); + const year = moment(liveDate).startOf("year").toDate(); + + _.forEach(entry.properties.categories, (category) => { + const number = Number(category.number); + + brands[category.brand] = brands[category.brand] + ? brands[category.brand] + number + : number; + + const catLabel = this.findCategoryLabel( + config.PHOTO_FIELDS.categories.data, + category.leafkey + ); + categories[catLabel] = categories[catLabel] + ? categories[catLabel] + number + : number; + + days[day] = days[day] ? days[day] + number : number; + months[month] = months[month] ? months[month] + number : number; + years[year] = years[year] ? years[year] + number : number; + }); + }); + + // draw by month + drawByMonth(months, this.graphRef.current); + drawByBrand(brands, this.brandsRef.current); + drawByCategory(categories, this.categoryRef.current); + } + + // local functions + function drawByMonth(months, ctx) { + let sortedMonths = _.map(months, (amount, date) => { + return { + date: new Date(date), + amount, + }; + }); + sortedMonths = _.sortBy(sortedMonths, "date"); + + new Chart(ctx, { + type: "line", + data: { + labels: _.map(sortedMonths, (month) => + moment(month.date).format("YYYY-MM") + ), + datasets: [ + { + label: "# of Pieces", + // data: _.map(sortedMonths, (month) => month.amount), + data: _.map(sortedMonths, (month) => ({ + t: month.date, + y: month.amount, + })), + borderWidth: 1, + backgroundColor: _.map(sortedMonths, randomColor), + }, + ], + options: { + scales: { + xAxes: [ + { + type: "time", + distribution: "linear", + time: { + unit: "month", + }, + }, + ], + }, + }, + }, + }); + } // drawByMonth + + function drawByBrand(brands, ctx) { + let sortedBrands = _.map(brands, (amount, brand) => { + return { + brand, + amount, + }; + }); + sortedBrands = _.sortBy(sortedBrands, "amount"); + sortedBrands = _.reverse(sortedBrands); + const allTheRest = _.sumBy( + _.slice(sortedBrands, 10, sortedBrands.length), + "amount" + ); + sortedBrands = _.slice(sortedBrands, 0, 10); + sortedBrands.push({ brand: "the others", amount: allTheRest }); + + new Chart(ctx, { + type: "bar", + data: { + labels: _.map(sortedBrands, (brand) => brand.brand), + datasets: [ + { + label: "Worst brands", + data: _.map(sortedBrands, (brand) => brand.amount), + borderWidth: 1, + backgroundColor: _.map(sortedBrands, randomColor), + }, + ], + }, + }); + } // drawByMonth + + function drawByCategory(categories, ctx) { + let sortedCategpries = _.map(categories, (amount, category) => { + return { + category, + amount, + }; + }); + sortedCategpries = _.sortBy(sortedCategpries, "amount"); + sortedCategpries = _.reverse(sortedCategpries); + const allTheRest = _.sumBy( + _.slice(sortedCategpries, 8, sortedCategpries.length), + "amount" + ); + sortedCategpries = _.slice(sortedCategpries, 0, 8); + sortedCategpries.push({ category: "the others", amount: allTheRest }); + + new Chart(ctx, { + type: "pie", + data: { + datasets: [ + { + data: _.map(sortedCategpries, (category) => category.amount), + backgroundColor: _.map(sortedCategpries, randomColor), + }, + ], + labels: _.map(sortedCategpries, (category) => category.category), + }, + options: {}, + }); + } + + function randomColor() { + const r = Math.floor(Math.random() * 255); + const g = Math.floor(Math.random() * 255); + const b = Math.floor(Math.random() * 255); + return "rgb(" + r + "," + g + "," + b + ")"; + } + } + + render() { + const { classes, label, handleClose } = this.props; + + return ( + + + + + + ); + } +} + +export default withStyles(styles)(Reports); diff --git a/src/custom/config.js b/src/custom/config.js index 56573651..2e57d9d8 100644 --- a/src/custom/config.js +++ b/src/custom/config.js @@ -11,6 +11,7 @@ import DashboardIcon from "@material-ui/icons/Dashboard"; import HelpIcon from "@material-ui/icons/Help"; import FeedbackIcon from "@material-ui/icons/Feedback"; import LibraryBooksIcon from "@material-ui/icons/LibraryBooks"; +import AssessmentIcon from "@material-ui/icons/Assessment"; import _ from "lodash"; @@ -22,6 +23,7 @@ import MultiFields from "../components/PhotoPage/MultiFields"; import { data } from "./categories"; import { CUSTOM_STRING } from "./strings.js"; +import ReportsPage from "./components/ReportsPage"; const primaryColor = styles.primary; const secondaryColor = styles.secondary; @@ -155,10 +157,10 @@ export default { placeholder: "eg. 1", regexValidation: "^[0-9]+", }, - multicategories: { + categories: { component: MultiFields.MultiFieldsWithStyles, nakedComponent: MultiFields.MultiFieldsOriginal, - name: "multicategories", + name: "categories", placeholder: "Add photo categories", data: data, noOptionsMessage: "No more categories", @@ -193,7 +195,15 @@ export default { }, }, PAGES, - CUSTOM_PAGES: [], + CUSTOM_PAGES: [ + { + path: "/reports", + page: ReportsPage, + label: "Reports", + icon: , + visible: (user, online) => true, + }, + ], getStats, SECURITY: { UPLOAD_REQUIRES_LOGIN: true,