diff --git a/.env-op b/.env-op new file mode 100644 index 0000000..2a180dc --- /dev/null +++ b/.env-op @@ -0,0 +1,3 @@ +REACT_APP_AUTH0_DOMAIN="op://Kingsrook/Auth0 Developer Keys/domain" +REACT_APP_AUTH0_CLIENT_ID="op://Kingsrook/Auth0 Developer Keys/clientId" +MATERIAL_UI_LICENSE_KEY="op://Kingsrook/Material UI Licence/key" diff --git a/.eslintrc.json b/.eslintrc.json index 86d3b2b..1d1d0b2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -56,12 +56,14 @@ "devDependencies": true } ], + "import/order": "off", "max-len": "off", "no-console": "off", "no-constant-condition": "off", "no-shadow": "off", "no-unused-vars": "off", "no-plusplus": "off", + "no-underscore-dangle": "off", "spaced-comment": "off", "object-curly-spacing": [ "error", diff --git a/package-lock.json b/package-lock.json index 11ad173..7b5dae0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "@asseinfo/react-kanban": "2.2.0", + "@auth0/auth0-react": "1.10.2", "@emotion/cache": "11.7.1", "@emotion/react": "11.7.1", "@emotion/styled": "11.6.0", @@ -20,6 +21,7 @@ "@mui/icons-material": "5.4.1", "@mui/material": "5.4.1", "@mui/styled-engine": "5.4.1", + "@mui/x-data-grid": "5.13.0", "@mui/x-data-grid-pro": "5.13.0", "@mui/x-license-pro": "5.12.3", "@react-jvectormap/core": "1.0.1", @@ -39,6 +41,7 @@ "html-react-parser": "1.4.8", "react": "17.0.2", "react-chartjs-2": "3.0.4", + "react-cookie": "4.1.1", "react-dom": "17.0.2", "react-flatpickr": "3.10.7", "react-github-btn": "1.2.1", @@ -120,6 +123,32 @@ "react-dom": "^16.8.0 || ^17.0.0" } }, + "node_modules/@auth0/auth0-react": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@auth0/auth0-react/-/auth0-react-1.10.2.tgz", + "integrity": "sha512-s622ac/gLZ9pUX7d5dOhRggF4VI3MaLLCPVBFR5CKOGcPtPG80/4w2jMoBQtRRn6uKS6IVMWAUAFKWB7yATAoQ==", + "dependencies": { + "@auth0/auth0-spa-js": "^1.22.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17 || ^18", + "react-dom": "^16.11.0 || ^17 || ^18" + } + }, + "node_modules/@auth0/auth0-spa-js": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/@auth0/auth0-spa-js/-/auth0-spa-js-1.22.1.tgz", + "integrity": "sha512-l0FCmiN3XubpgCtB3U0ds4h+5WQNTnIF4eLT/fudHEtcyrT65QF/03LybGVdLyuvqdIF/D6OQsfjwYw0Ms605Q==", + "dependencies": { + "abortcontroller-polyfill": "^1.7.3", + "browser-tabs-lock": "^1.2.15", + "core-js": "^3.22.6", + "es-cookie": "^1.3.2", + "fast-text-encoding": "^1.0.3", + "promise-polyfill": "^8.2.3", + "unfetch": "^4.2.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -4131,6 +4160,11 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", + "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==" + }, "node_modules/@types/dropzone": { "version": "5.7.4", "resolved": "https://registry.npmjs.org/@types/dropzone/-/dropzone-5.7.4.tgz", @@ -4912,6 +4946,11 @@ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" }, + "node_modules/abortcontroller-polyfill": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.3.tgz", + "integrity": "sha512-zetDJxd89y3X99Kvo4qFx8GKlt6GsvN3UcRZHwU6iFA/0KiOmhkTVhe8oRoTBiTVPZu09x3vCra47+w8Yz1+2Q==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -5782,6 +5821,15 @@ "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" }, + "node_modules/browser-tabs-lock": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/browser-tabs-lock/-/browser-tabs-lock-1.2.15.tgz", + "integrity": "sha512-J8K9vdivK0Di+b8SBdE7EZxDr88TnATing7XoLw6+nFkXMQ6sVBh92K3NQvZlZU91AIkFRi0w3sztk5Z+vsswA==", + "hasInstallScript": true, + "dependencies": { + "lodash": ">=4.17.21" + } + }, "node_modules/browserslist": { "version": "4.21.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz", @@ -7399,6 +7447,11 @@ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" }, + "node_modules/es-cookie": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/es-cookie/-/es-cookie-1.3.2.tgz", + "integrity": "sha512-UTlYYhXGLOy05P/vKVT2Ui7WtC7NiRzGtJyAKKn32g5Gvcjn7KAClLPWlipCtxIus934dFg9o9jXiBL0nP+t9Q==" + }, "node_modules/es-module-lexer": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", @@ -8475,6 +8528,11 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "node_modules/fast-text-encoding": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.4.tgz", + "integrity": "sha512-x6lDDm/tBAzX9kmsPcZsNbvDs3Zey3+scsxaZElS8xWLgUMAg/oFLeewfUz0mu1CblHhhsu15jGkraldkFh8KQ==" + }, "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -13638,6 +13696,11 @@ "asap": "~2.0.6" } }, + "node_modules/promise-polyfill": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.3.tgz", + "integrity": "sha512-Og0+jCRQetV84U8wVjMNccfGCnMQ9mGs9Hv78QFe+pSDD3gWTpz0y+1QCuxy5d/vBFuZ3iwP2eycAkvqIMPmWg==" + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -13902,6 +13965,19 @@ "react": "^16.8.0 || ^17.0.0" } }, + "node_modules/react-cookie": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.1.1.tgz", + "integrity": "sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.0.1", + "hoist-non-react-statics": "^3.0.0", + "universal-cookie": "^4.0.0" + }, + "peerDependencies": { + "react": ">= 16.3.0" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -16105,6 +16181,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -16152,6 +16233,23 @@ "node": ">=8" } }, + "node_modules/universal-cookie": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz", + "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==", + "dependencies": { + "@types/cookie": "^0.3.3", + "cookie": "^0.4.0" + } + }, + "node_modules/universal-cookie/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -17196,6 +17294,28 @@ "react-beautiful-dnd": "^13.0.0" } }, + "@auth0/auth0-react": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@auth0/auth0-react/-/auth0-react-1.10.2.tgz", + "integrity": "sha512-s622ac/gLZ9pUX7d5dOhRggF4VI3MaLLCPVBFR5CKOGcPtPG80/4w2jMoBQtRRn6uKS6IVMWAUAFKWB7yATAoQ==", + "requires": { + "@auth0/auth0-spa-js": "^1.22.0" + } + }, + "@auth0/auth0-spa-js": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/@auth0/auth0-spa-js/-/auth0-spa-js-1.22.1.tgz", + "integrity": "sha512-l0FCmiN3XubpgCtB3U0ds4h+5WQNTnIF4eLT/fudHEtcyrT65QF/03LybGVdLyuvqdIF/D6OQsfjwYw0Ms605Q==", + "requires": { + "abortcontroller-polyfill": "^1.7.3", + "browser-tabs-lock": "^1.2.15", + "core-js": "^3.22.6", + "es-cookie": "^1.3.2", + "fast-text-encoding": "^1.0.3", + "promise-polyfill": "^8.2.3", + "unfetch": "^4.2.0" + } + }, "@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -19879,6 +19999,11 @@ "@types/node": "*" } }, + "@types/cookie": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", + "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==" + }, "@types/dropzone": { "version": "5.7.4", "resolved": "https://registry.npmjs.org/@types/dropzone/-/dropzone-5.7.4.tgz", @@ -20520,6 +20645,11 @@ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" }, + "abortcontroller-polyfill": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.3.tgz", + "integrity": "sha512-zetDJxd89y3X99Kvo4qFx8GKlt6GsvN3UcRZHwU6iFA/0KiOmhkTVhe8oRoTBiTVPZu09x3vCra47+w8Yz1+2Q==" + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -21173,6 +21303,14 @@ "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" }, + "browser-tabs-lock": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/browser-tabs-lock/-/browser-tabs-lock-1.2.15.tgz", + "integrity": "sha512-J8K9vdivK0Di+b8SBdE7EZxDr88TnATing7XoLw6+nFkXMQ6sVBh92K3NQvZlZU91AIkFRi0w3sztk5Z+vsswA==", + "requires": { + "lodash": ">=4.17.21" + } + }, "browserslist": { "version": "4.21.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz", @@ -22352,6 +22490,11 @@ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" }, + "es-cookie": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/es-cookie/-/es-cookie-1.3.2.tgz", + "integrity": "sha512-UTlYYhXGLOy05P/vKVT2Ui7WtC7NiRzGtJyAKKn32g5Gvcjn7KAClLPWlipCtxIus934dFg9o9jXiBL0nP+t9Q==" + }, "es-module-lexer": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", @@ -23127,6 +23270,11 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "fast-text-encoding": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.4.tgz", + "integrity": "sha512-x6lDDm/tBAzX9kmsPcZsNbvDs3Zey3+scsxaZElS8xWLgUMAg/oFLeewfUz0mu1CblHhhsu15jGkraldkFh8KQ==" + }, "fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -26691,6 +26839,11 @@ "asap": "~2.0.6" } }, + "promise-polyfill": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.3.tgz", + "integrity": "sha512-Og0+jCRQetV84U8wVjMNccfGCnMQ9mGs9Hv78QFe+pSDD3gWTpz0y+1QCuxy5d/vBFuZ3iwP2eycAkvqIMPmWg==" + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -26890,6 +27043,16 @@ "lodash": "^4.17.19" } }, + "react-cookie": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.1.1.tgz", + "integrity": "sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A==", + "requires": { + "@types/hoist-non-react-statics": "^3.0.1", + "hoist-non-react-statics": "^3.0.0", + "universal-cookie": "^4.0.0" + } + }, "react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -28541,6 +28704,11 @@ "which-boxed-primitive": "^1.0.2" } }, + "unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==" + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -28573,6 +28741,22 @@ "crypto-random-string": "^2.0.0" } }, + "universal-cookie": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz", + "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==", + "requires": { + "@types/cookie": "^0.3.3", + "cookie": "^0.4.0" + }, + "dependencies": { + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + } + } + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", diff --git a/package.json b/package.json index 660b569..33467e2 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@mui/icons-material": "5.4.1", "@mui/material": "5.4.1", "@mui/styled-engine": "5.4.1", + "@mui/x-data-grid": "5.13.0", "@mui/x-data-grid-pro": "5.13.0", "@mui/x-license-pro": "5.12.3", "@react-jvectormap/core": "1.0.1", @@ -36,6 +37,7 @@ "html-react-parser": "1.4.8", "react": "17.0.2", "react-chartjs-2": "3.0.4", + "react-cookie": "4.1.1", "react-dom": "17.0.2", "react-flatpickr": "3.10.7", "react-github-btn": "1.2.1", diff --git a/public/apple-icon.png b/public/apple-icon.png index a20470f..59c68b9 100644 Binary files a/public/apple-icon.png and b/public/apple-icon.png differ diff --git a/public/favicon.png b/public/favicon.png index 7d8b7d0..59c68b9 100644 Binary files a/public/favicon.png and b/public/favicon.png differ diff --git a/scripts/nodeWrapper.sh b/scripts/nodeWrapper.sh new file mode 100755 index 0000000..fab759d --- /dev/null +++ b/scripts/nodeWrapper.sh @@ -0,0 +1,2 @@ +#!/bin/bash +op run --env-file='.env-op' -- npm "$@" diff --git a/src/App.tsx b/src/App.tsx index 7014811..c518743 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,6 +11,8 @@ import { Routes, Route, Navigate, useLocation, } from "react-router-dom"; +import {useAuth0} from "@auth0/auth0-react"; + // @mui material components import {LicenseInfo} from "@mui/x-license-pro"; import {ThemeProvider} from "@mui/material/styles"; @@ -35,9 +37,10 @@ import {useMaterialUIController, setMiniSidenav, setOpenConfigurator} from "cont // Images import nfLogo from "assets/images/nutrifresh_one_icon_white.png"; -import brandWhite from "assets/images/logo-ct.png"; -import brandDark from "assets/images/logo-ct-dark.png"; import {Md5} from "ts-md5/dist/md5"; +import AuthenticationButton from "qqq/components/buttons/AuthenticationButton"; +import {useCookies} from "react-cookie"; +import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance"; import EntityCreate from "./qqq/pages/entity-create"; import EntityList from "./qqq/pages/entity-list"; import EntityView from "./qqq/pages/entity-view"; @@ -51,42 +54,12 @@ import Analytics from "./layouts/dashboards/analytics"; import Sales from "./layouts/dashboards/sales"; import QClient from "./qqq/utils/QClient"; -const gravatarBase = "http://www.gravatar.com/avatar/"; -const hash = Md5.hashStr("tim@nutrifreshservices.com"); -const profilePicture = `${gravatarBase}${hash}`; - /////////////////////////////////////////////////////////////////////////////////////////////// // define the parts of the nav that are static - before the qqq tables etc get dynamic added // /////////////////////////////////////////////////////////////////////////////////////////////// function getStaticRoutes() { return [ - { - type: "collapse", - name: "Tim Chamberlain", - key: "tim-chamberlain", - icon: , - collapse: [ - { - name: "My Profile", - key: "my-profile", - route: "/pages/profile/profile-overview", - component: , - }, - { - name: "Settings", - key: "profile-settings", - route: "/pages/account/settings", - component: , - }, - { - name: "Logout", - key: "logout", - route: "/authentication/sign-in/basic", - component: , - }, - ], - }, {type: "divider", key: "divider-0"}, { type: "collapse", @@ -113,10 +86,44 @@ function getStaticRoutes() ]; } -LicenseInfo.setLicenseKey("4ef48a0226ec7b5fb49d99f14c6b3170Tz00NzI0NyxFPTE2ODkyODU1NzUxMDYsUz1wcm8sTE09c3Vic2NyaXB0aW9uLEtWPTI="); +const SESSION_ID_COOKIE_NAME = "sessionId"; +LicenseInfo.setLicenseKey(process.env.MATERIAL_UI_LICENSE_KEY); export default function App() { + const [, setCookie] = useCookies([SESSION_ID_COOKIE_NAME]); + const { + user, getAccessTokenSilently, getIdTokenClaims, logout, + } = useAuth0(); + const [loadingToken, setLoadingToken] = useState(false); + const [isFullyAuthenticated, setIsFullyAuthenticated] = useState(false); + + useEffect(() => + { + if (loadingToken) + { + return; + } + setLoadingToken(true); + (async () => + { + try + { + console.log("Loading token..."); + const accessToken = await getAccessTokenSilently(); + const idToken = await getIdTokenClaims(); + setCookie(SESSION_ID_COOKIE_NAME, idToken.__raw, {path: "/"}); + setIsFullyAuthenticated(true); + console.log("Token load complete."); + } + catch (e) + { + console.log(`Error loading token: ${JSON.stringify(e)}`); + logout(); + } + })(); + }, [loadingToken]); + const [controller, dispatch] = useMaterialUIController(); const { miniSidenav, @@ -139,7 +146,7 @@ export default function App() //////////////////////////////////////////// useEffect(() => { - if (!needToLoadRoutes) + if (!needToLoadRoutes || !isFullyAuthenticated) { return; } @@ -147,43 +154,87 @@ export default function App() (async () => { - const metaData = await QClient.loadMetaData(); + try + { + console.log("ok now loading qqq things"); + const metaData = await QClient.loadMetaData(); - // get the keys sorted - const keys = [...metaData.tables.keys()].sort((a, b): number => - { - const labelA = metaData.tables.get(a).label; - const labelB = metaData.tables.get(b).label; - return (labelA.localeCompare(labelB)); - }); - const tableList = [] as any[]; - keys.forEach((key) => - { - const table = metaData.tables.get(key); - if (!table.isHidden) + // get the keys sorted + const keys = [...metaData.tables.keys()].sort((a, b): number => { - tableList.push({ - name: `${table.label}`, - key: table.name, - route: `/${table.name}`, - component: , - }); + const labelA = metaData.tables.get(a).label; + const labelB = metaData.tables.get(b).label; + return (labelA.localeCompare(labelB)); + }); + const tableList = [] as any[]; + keys.forEach((key) => + { + const table = metaData.tables.get(key); + if (!table.isHidden) + { + tableList.push({ + name: `${table.label}`, + key: table.name, + route: `/${table.name}`, + component: , + }); + } + }); + + let profileRoute = {}; + const gravatarBase = "http://www.gravatar.com/avatar/"; + const hash = Md5.hashStr(user.email); + const profilePicture = `${gravatarBase}${hash}`; + profileRoute = { + type: "collapse", + name: user.name, + key: user.name, + icon: , + collapse: [ + { + name: "My Profile", + key: "my-profile", + route: "/pages/profile/profile-overview", + component: , + }, + { + name: "Settings", + key: "profile-settings", + route: "/pages/account/settings", + component: , + }, + { + name: "Logout", + key: "logout", + route: "/authentication/sign-in/basic", + component: , + }, + ], + }; + + const tables = { + type: "collapse", + name: "Tables", + key: "tables", + icon: dashboard, + collapse: tableList, + }; + + const newDynamicRoutes = getStaticRoutes(); + // @ts-ignore + newDynamicRoutes.unshift(profileRoute); + newDynamicRoutes.push(tables); + setRoutes(newDynamicRoutes); + } + catch (e) + { + if (e.toString().indexOf("status code 401") !== -1) + { + logout(); } - }); - - const tables = { - type: "collapse", - name: "Tables", - key: "tables", - icon: dashboard, - collapse: tableList, - }; - - const newDynamicRoutes = getStaticRoutes(); - newDynamicRoutes.push(tables); - setRoutes(newDynamicRoutes); + } })(); - }, [needToLoadRoutes]); + }, [needToLoadRoutes, isFullyAuthenticated]); // Open sidenav when mouse enter on mini sidenav const handleOnMouseEnter = () => @@ -243,6 +294,27 @@ export default function App() }, ); + const authButton = ( + + + + ); + const configsButton = ( {configsButton} + {authButton} )} - {layout === "vr" && } } /> diff --git a/src/index.tsx b/src/index.tsx index 3a535ca..bc76917 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,33 +1,30 @@ -/** -========================================================= -* Material Dashboard 2 PRO React TS - v1.0.0 -========================================================= - -* Product Page: https://www.creative-tim.com/product/material-dashboard-2-pro-react-ts -* Copyright 2022 Creative Tim (https://www.creative-tim.com) - -Coded by www.creative-tim.com - - ========================================================= - -* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -*/ - import ReactDOM from "react-dom"; import {BrowserRouter} from "react-router-dom"; +import {Auth0Provider} from "@auth0/auth0-react"; import App from "App"; // Material Dashboard 2 PRO React TS Context Provider import {MaterialUIControllerProvider} from "context"; import "./qqq/styles/qqq-override-styles.css"; +import ProtectedRoute from "qqq/auth0/protected-route"; +import React from "react"; + +// Auth0 params from env +const domain = process.env.REACT_APP_AUTH0_DOMAIN; +const clientId = process.env.REACT_APP_AUTH0_CLIENT_ID; ReactDOM.render( - - - - - , + + + + + + + , document.getElementById("root"), ); - export * from "components/MDButton"; diff --git a/src/page.routes.tsx b/src/page.routes.tsx index 3974ada..01cefc6 100644 --- a/src/page.routes.tsx +++ b/src/page.routes.tsx @@ -1,39 +1,39 @@ /** -========================================================= -* Material Dashboard 2 PRO React TS - v1.0.0 -========================================================= + ========================================================= + * Material Dashboard 2 PRO React TS - v1.0.0 + ========================================================= -* Product Page: https://www.creative-tim.com/product/material-dashboard-2-pro-react-ts -* Copyright 2022 Creative Tim (https://www.creative-tim.com) + * Product Page: https://www.creative-tim.com/product/material-dashboard-2-pro-react-ts + * Copyright 2022 Creative Tim (https://www.creative-tim.com) -Coded by www.creative-tim.com + Coded by www.creative-tim.com ========================================================= -* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -*/ + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + */ /** - All of the routes for the Material Kit 2 PRO React React are added here, - You can add a new route, customize the routes and delete the routes here. + All of the routes for the Material Kit 2 PRO React React are added here, + You can add a new route, customize the routes and delete the routes here. - Once you add a new route on this file it will be visible automatically on - the Navbar. + Once you add a new route on this file it will be visible automatically on + the Navbar. - For adding a new route you can follow the existing routes in the routes array. - 1. The `name` key is used for the name of the route on the Navbar. - 2. The `icon` key is used for the icon of the route on the Navbar. - 3. The `collapse` key is used for making a collapsible item on the Navbar that contains other routes - inside (nested routes), you need to pass the nested routes inside an array as a value for the `collapse` key. - 4. The `route` key is used to store the route location which is used for the react router. - 5. The `href` key is used to store the external links location. - 7. The `dropdown` key is used to define that the item should open a dropdown for its collapse items . - 8. The `description` key is used to define the description of - a route under its name. - 9. The `columns` key is used to define that how the content should look inside the dropdown menu as columns, - you can set the columns amount based on this key. - 10. The `rowsPerColumn` key is used to define that how many rows should be in a column. -*/ + For adding a new route you can follow the existing routes in the routes array. + 1. The `name` key is used for the name of the route on the Navbar. + 2. The `icon` key is used for the icon of the route on the Navbar. + 3. The `collapse` key is used for making a collapsible item on the Navbar that contains other routes + inside (nested routes), you need to pass the nested routes inside an array as a value for the `collapse` key. + 4. The `route` key is used to store the route location which is used for the react router. + 5. The `href` key is used to store the external links location. + 7. The `dropdown` key is used to define that the item should open a dropdown for its collapse items . + 8. The `description` key is used to define the description of + a route under its name. + 9. The `columns` key is used to define that how the content should look inside the dropdown menu as columns, + you can set the columns amount based on this key. + 10. The `rowsPerColumn` key is used to define that how many rows should be in a column. + */ // @mui material components import Icon from "@mui/material/Icon"; @@ -76,9 +76,9 @@ const pageRoutes = [ name: "pricing page", route: "/pages/pricing-page", }, - { name: "RTL", route: "/pages/rtl" }, - { name: "widgets", route: "/pages/widgets" }, - { name: "charts", route: "/pages/charts" }, + {name: "RTL", route: "/pages/rtl"}, + {name: "widgets", route: "/pages/widgets"}, + {name: "charts", route: "/pages/charts"}, { name: "notfications", route: "/pages/notifications", diff --git a/src/qqq/auth0/code-snippet.tsx b/src/qqq/auth0/code-snippet.tsx new file mode 100644 index 0000000..e2d55e1 --- /dev/null +++ b/src/qqq/auth0/code-snippet.tsx @@ -0,0 +1,28 @@ +import React from "react"; + +interface CodeSnippetProps +{ + code: string; + title?: string; +} + +// eslint-disable-next-line react/function-component-definition +function CodeSnippet({title, code}: CodeSnippetProps): JSX.Element +{ + return ( +
+ {title} +
+
+
{code}
+
+
+
+ ); +} + +CodeSnippet.defaultProps = { + title: undefined, +}; + +export default CodeSnippet; diff --git a/src/qqq/auth0/loader.tsx b/src/qqq/auth0/loader.tsx new file mode 100644 index 0000000..b38d26e --- /dev/null +++ b/src/qqq/auth0/loader.tsx @@ -0,0 +1,14 @@ +import React from "react"; + +function Loader() : JSX.Element +{ + const loadingImg = "https://cdn.auth0.com/blog/hello-auth0/loader.svg"; + + return ( +
+ Loading... +
+ ); +} + +export default Loader; diff --git a/src/qqq/auth0/profile.tsx b/src/qqq/auth0/profile.tsx new file mode 100644 index 0000000..7d51b7a --- /dev/null +++ b/src/qqq/auth0/profile.tsx @@ -0,0 +1,31 @@ +import {useAuth0} from "@auth0/auth0-react"; +import React from "react"; +import CodeSnippet from "./code-snippet"; + +export function Profile() +{ + const {user} = useAuth0(); + + if (!user) + { + console.log("no user"); + return null; + } + + return ( +
+
+
+
+ +
+
+
+
+ ); +} + +export default Profile; diff --git a/src/qqq/auth0/protected-route.tsx b/src/qqq/auth0/protected-route.tsx new file mode 100644 index 0000000..2e66154 --- /dev/null +++ b/src/qqq/auth0/protected-route.tsx @@ -0,0 +1,16 @@ +import {withAuthenticationRequired} from "@auth0/auth0-react"; +import React from "react"; +import Loader from "./loader"; + +// @ts-ignore +function ProtectedRoute({component}) : JSX.Element +{ + const Component = withAuthenticationRequired(component, { + // eslint-disable-next-line react/no-unstable-nested-components + onRedirecting: () => , + }); + + return ; +} + +export default ProtectedRoute; diff --git a/src/qqq/components/BaseLayout/index.tsx b/src/qqq/components/BaseLayout/index.tsx index f8c8416..b0c4572 100644 --- a/src/qqq/components/BaseLayout/index.tsx +++ b/src/qqq/components/BaseLayout/index.tsx @@ -59,7 +59,7 @@ function BaseLayout({stickyNavbar, children}: Props): JSX.Element return ( - + {children}