Merge remote-tracking branch 'remotes/origin/QQQ-27-build-support-for-auth-0-throughout-qqq' into feature/sprint-7-integration

This commit is contained in:
2022-07-25 08:56:00 -05:00
15 changed files with 445 additions and 91 deletions

3
.env-op Normal file
View File

@ -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"

View File

@ -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",

184
package-lock.json generated
View File

@ -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",

View File

@ -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",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

2
scripts/nodeWrapper.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
op run --env-file='.env-op' -- npm "$@"

View File

@ -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: <MDAvatar src={profilePicture} alt="Brooklyn Alice" size="sm" />,
collapse: [
{
name: "My Profile",
key: "my-profile",
route: "/pages/profile/profile-overview",
component: <ProfileOverview />,
},
{
name: "Settings",
key: "profile-settings",
route: "/pages/account/settings",
component: <Settings />,
},
{
name: "Logout",
key: "logout",
route: "/authentication/sign-in/basic",
component: <SignInBasic />,
},
],
},
{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: <EntityList table={table} />,
});
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: <EntityList table={table} />,
});
}
});
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: <MDAvatar src={profilePicture} alt="{user.name}" size="sm" />,
collapse: [
{
name: "My Profile",
key: "my-profile",
route: "/pages/profile/profile-overview",
component: <ProfileOverview />,
},
{
name: "Settings",
key: "profile-settings",
route: "/pages/account/settings",
component: <Settings />,
},
{
name: "Logout",
key: "logout",
route: "/authentication/sign-in/basic",
component: <SignInBasic />,
},
],
};
const tables = {
type: "collapse",
name: "Tables",
key: "tables",
icon: <Icon fontSize="medium">dashboard</Icon>,
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: <Icon fontSize="medium">dashboard</Icon>,
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 = (
<MDBox
display="flex"
justifyContent="center"
alignItems="center"
width="3.25rem"
height="3.25rem"
bgColor="white"
shadow="sm"
borderRadius="50%"
position="fixed"
right="2rem"
bottom="2rem"
zIndex={99}
color="dark"
sx={{cursor: "pointer"}}
>
<AuthenticationButton />
</MDBox>
);
const configsButton = (
<MDBox
display="flex"
@ -288,9 +360,9 @@ export default function App()
/>
<Configurator />
{configsButton}
{authButton}
</>
)}
{layout === "vr" && <Configurator />}
<Routes>
<Route path="*" element={<Navigate to="/dashboards/analytics" />} />
<Route path="/:tableName" element={entityListElement} key="entity-list" />

View File

@ -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(
<BrowserRouter>
<MaterialUIControllerProvider>
<App />
</MaterialUIControllerProvider>
</BrowserRouter>,
<Auth0Provider
domain={domain}
clientId={clientId}
redirectUri={`${window.location.origin}/dashboards/analytics`}
>
<BrowserRouter>
<MaterialUIControllerProvider>
<ProtectedRoute component={App} />
</MaterialUIControllerProvider>
</BrowserRouter>
</Auth0Provider>,
document.getElementById("root"),
);
export * from "components/MDButton";

View File

@ -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 (
<div className="code-snippet">
<span className="code-snippet__title">{title}</span>
<div className="code-snippet__container">
<div className="code-snippet__wrapper">
<pre className="code-snippet__body">{code}</pre>
</div>
</div>
</div>
);
}
CodeSnippet.defaultProps = {
title: undefined,
};
export default CodeSnippet;

14
src/qqq/auth0/loader.tsx Normal file
View File

@ -0,0 +1,14 @@
import React from "react";
function Loader() : JSX.Element
{
const loadingImg = "https://cdn.auth0.com/blog/hello-auth0/loader.svg";
return (
<div className="loader">
<img style={{height: "25px"}} src={loadingImg} alt="Loading..." />
</div>
);
}
export default Loader;

31
src/qqq/auth0/profile.tsx Normal file
View File

@ -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 (
<div className="content-layout">
<div className="content__body">
<div className="profile-grid">
<div className="profile__details">
<CodeSnippet
title="Decoded ID Token"
code={JSON.stringify(user, null, 2)}
/>
</div>
</div>
</div>
</div>
);
}
export default Profile;

View File

@ -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: () => <Loader />,
});
return <Component />;
}
export default ProtectedRoute;

View File

@ -59,7 +59,7 @@ function BaseLayout({stickyNavbar, children}: Props): JSX.Element
return (
<DashboardLayout>
<DashboardNavbar absolute={!stickyNavbar} isMini />
<Navbar />
<MDBox mt={stickyNavbar ? 3 : 10}>{children}</MDBox>
<Footer />
</DashboardLayout>

View File

@ -14,6 +14,8 @@
import React, {useEffect, useReducer, useState} from "react";
import {useParams, useSearchParams} from "react-router-dom";
import {useAuth0} from "@auth0/auth0-react";
// @mui material components
import Card from "@mui/material/Card";
import Icon from "@mui/material/Icon";
@ -57,6 +59,7 @@ import {QFilterCriteria} from "@kingsrook/qqq-frontend-core/lib/model/query/QFil
import {QCriteriaOperator} from "@kingsrook/qqq-frontend-core/lib/model/query/QCriteriaOperator";
import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
import QClient from "qqq/utils/QClient";
import Navbar from "qqq/components/Navbar";
import Footer from "../../components/Footer";
import QProcessUtils from "../../utils/QProcessUtils";
@ -461,7 +464,7 @@ function EntityList({table}: Props): JSX.Element
return (
<DashboardLayout>
<DashboardNavbar />
<Navbar />
<MDBox my={3}>
{alertContent ? (
<MDBox mb={3}>