import React, { useState, useEffect, JSXElementConstructor, Key, ReactElement, } from "react"; // react-router components 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"; import CssBaseline from "@mui/material/CssBaseline"; import Icon from "@mui/material/Icon"; // Material Dashboard 2 PRO React TS components import MDBox from "components/MDBox"; // Material Dashboard 2 PRO React TS exampless import Sidenav from "examples/Sidenav"; import Configurator from "examples/Configurator"; // Material Dashboard 2 PRO React TS themes import theme from "assets/theme"; // Material Dashboard 2 PRO React TS Dark Mode themes import themeDark from "assets/theme-dark"; // Material Dashboard 2 PRO React TS contexts import {useMaterialUIController, setMiniSidenav, setOpenConfigurator} from "context"; // Images import nfLogo from "assets/images/nutrifresh_one_icon_white.png"; import {Md5} from "ts-md5/dist/md5"; import {useCookies} from "react-cookie"; import EntityCreate from "./qqq/pages/entity-create"; import EntityList from "./qqq/pages/entity-list"; import EntityView from "./qqq/pages/entity-view"; import EntityEdit from "./qqq/pages/entity-edit"; import ProcessRun from "./qqq/pages/process-run"; import MDAvatar from "./components/MDAvatar"; import ProfileOverview from "./layouts/pages/profile/profile-overview"; import Settings from "./layouts/pages/account/settings"; import Analytics from "./layouts/dashboards/analytics"; import Sales from "./layouts/dashboards/sales"; import QClient from "./qqq/utils/QClient"; /////////////////////////////////////////////////////////////////////////////////////////////// // define the parts of the nav that are static - before the qqq tables etc get dynamic added // /////////////////////////////////////////////////////////////////////////////////////////////// function getStaticRoutes() { return [ {type: "divider", key: "divider-0"}, { type: "collapse", name: "Dashboards", key: "dashboards", icon: dashboard, collapse: [ { name: "Analytics", key: "analytics", route: "/dashboards/analytics", component: , }, { name: "Sales", key: "sales", route: "/dashboards/sales", component: , }, ], }, {type: "divider", key: "divider-1"}, {type: "title", title: "Tables", key: "title-docs"}, ]; } export const SESSION_ID_COOKIE_NAME = "sessionId"; LicenseInfo.setLicenseKey(process.env.REACT_APP_MATERIAL_UI_LICENSE_KEY); export default function App() { const [, setCookie] = useCookies([SESSION_ID_COOKIE_NAME]); const { user, getAccessTokenSilently, getIdTokenClaims, logout, loginWithRedirect, } = useAuth0(); const [loadingToken, setLoadingToken] = useState(false); const [isFullyAuthenticated, setIsFullyAuthenticated] = useState(false); useEffect(() => { if (loadingToken) { return; } setLoadingToken(true); (async () => { try { console.log("Loading token..."); 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, direction, layout, openConfigurator, sidenavColor, darkMode, } = controller; const [onMouseEnter, setOnMouseEnter] = useState(false); const {pathname} = useLocation(); const [needToLoadRoutes, setNeedToLoadRoutes] = useState(true); const [routes, setRoutes] = useState(getStaticRoutes()); //////////////////////////////////////////// // load qqq meta data to make more routes // //////////////////////////////////////////// useEffect(() => { if (!needToLoadRoutes || !isFullyAuthenticated) { return; } setNeedToLoadRoutes(false); (async () => { try { const metaData = await QClient.getInstance().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) { 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: , }, ], }; 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(); } } })(); }, [needToLoadRoutes, isFullyAuthenticated]); // Open sidenav when mouse enter on mini sidenav const handleOnMouseEnter = () => { if (miniSidenav && !onMouseEnter) { setMiniSidenav(dispatch, false); setOnMouseEnter(true); } }; // Close sidenav when mouse leave mini sidenav const handleOnMouseLeave = () => { if (onMouseEnter) { setMiniSidenav(dispatch, true); setOnMouseEnter(false); } }; // Change the openConfigurator state const handleConfiguratorOpen = () => setOpenConfigurator(dispatch, !openConfigurator); // Setting the dir attribute for the body element useEffect(() => { document.body.setAttribute("dir", direction); }, [direction]); // Setting page scroll to 0 when changing the route useEffect(() => { document.documentElement.scrollTop = 0; document.scrollingElement.scrollTop = 0; }, [pathname]); const getRoutes = (allRoutes: any[]): any => allRoutes.map( (route: { collapse: any; route: string; component: ReactElement>; key: Key; }) => { if (route.collapse) { return getRoutes(route.collapse); } if (route.route) { return ; } return null; }, ); const configsButton = ( settings ); const entityListElement = ; const entityCreateElement = ; const entityViewElement = ; const entityEditElement = ; const processRunElement = ; return ( {layout === "dashboard" && ( <> {configsButton} )} } /> {getRoutes(routes)} ); }