\n auth.isAuthenticated() || publicRoute ? (\n \n \n \n ) : (\n \n )\n }\n />\n );\n};\n\nRouteWithLayout.propTypes = {\n component: PropTypes.any,\n layout: PropTypes.any,\n path: PropTypes.string\n};\n\nexport default RouteWithLayout;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { makeStyles } from '@material-ui/styles';\nimport { Link, Typography } from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(4)\n }\n}));\n\nconst Footer = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n return (\n \n \n ©{' '}\n \n NSD Insight Qore\n \n . {process.env.REACT_APP_VERSION}\n \n \n Operation data for NSD\n \n
\n );\n};\n\nFooter.propTypes = {\n className: PropTypes.string\n};\n\nexport default Footer;\n","import React from \"react\";\n\nconst AppContext = React.createContext({\n appData: {},\n setAppData: () => {}\n});\n\nexport default AppContext;\n","const getAccessToken = () => {\n const msData = localStorage.getItem('msData')\n ? JSON.parse(localStorage.getItem('msData'))\n : null;\n\n return msData\n ? msData.accessToken\n : null;\n};\n\nexport {\n getAccessToken\n};\n","export const ENVIRONMENT = {\n DEVELOPMENT: 'development',\n STAGING: 'staging',\n PRODUCTION: 'production'\n};\n\n// Check if we're in development or production. Staging uses prod db and functions\nexport const getCurrentEnv = () => {\n const currentHost = window.location.host;\n let currentEnv;\n\n if (currentHost.includes(`-${ENVIRONMENT.DEVELOPMENT}`)\n || currentHost.includes(`localhost`)\n ) {\n currentEnv = ENVIRONMENT.DEVELOPMENT;\n } else if (currentHost.includes(`-${ENVIRONMENT.STAGING}`)) {\n currentEnv = ENVIRONMENT.STAGING;\n } else {\n currentEnv = ENVIRONMENT.PRODUCTION;\n }\n\n return currentEnv;\n}\n","import { ENVIRONMENT, getCurrentEnv } from '../services/environmentService';\n\nconst getAzureFunctionUrl = () => {\n let azureFunctionUrl;\n const currentEnv = getCurrentEnv();\n switch (currentEnv) {\n case ENVIRONMENT.DEVELOPMENT:\n azureFunctionUrl = 'https://nsd-api-insight-qore-development.azurewebsites.net/api';\n break;\n case ENVIRONMENT.STAGING:\n azureFunctionUrl = 'https://nsd-api-insight-qore-staging.azurewebsites.net/api';\n break;\n case ENVIRONMENT.PRODUCTION:\n azureFunctionUrl = 'https://nsd-api-insight-qore.azurewebsites.net/api';\n break;\n default:\n break;\n }\n\n return azureFunctionUrl;\n};\n\nexport const API_URL = {\n AZURE_FUNCTION: getAzureFunctionUrl(),\n MICROSOFT_GRAPH: 'https://graph.microsoft.com/v1.0'\n};\n","import axios from 'axios';\nimport { getAccessToken } from './graphService';\nimport { API_URL } from '../constants/apiUrl';\n\nconst instance = axios.create({\n baseURL: API_URL.AZURE_FUNCTION,\n headers: {\n common: {\n 'Cache-Control': 'no-cache'\n },\n },\n});\n\ninstance.interceptors.request.use((config) => {\n config.params = {\n accessToken: getAccessToken(),\n code: process.env.REACT_APP_FUNCTION_CODE\n };\n return config;\n}, (error) => {\n return Promise.reject(error);\n});\n\nexport default instance;\n","import React, { useEffect, useState } from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport { Avatar, Typography } from '@material-ui/core';\nimport axios from '../../../../../../services/axiosService';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n minHeight: 'fit-content'\n },\n avatar: {\n width: 60,\n height: 60\n },\n name: {\n marginTop: theme.spacing(1)\n }\n}));\n\nconst Profile = props => {\n const { className, ...rest } = props;\n\n const [userName, setUserName] = useState(null);\n const [jobTitle, setJobTitle] = useState(null);\n const [avatar, setAvatar] = useState('');\n const classes = useStyles();\n\n const user = {\n name: userName,\n avatar: avatar,\n bio: jobTitle\n };\n\n useEffect(() => {\n (async() => {\n let msData = localStorage.getItem('msData') ? JSON.parse(localStorage.getItem('msData')) : null;\n if (msData) {\n setUserName(msData.account.name);\n const msAccesToken = msData.accessToken;\n\n try {\n const { data: meData } = await axios.get('/me');\n\n if (meData && meData.jobTitle) {\n setJobTitle(meData.jobTitle);\n }\n\n const { data: photoData } = await axios.get('/me/photo');\n\n setAvatar(URL.createObjectURL(photoData));\n } catch (err) {\n console.log('graph error', err);\n }\n\n }\n })();\n }, []);\n\n return (\n \n
\n
\n {user.name}\n \n
{user.bio} \n
\n );\n};\n\nProfile.propTypes = {\n className: PropTypes.string\n};\n\nexport default Profile;\n","import { createElement } from 'react';\nimport {\n AccountBalance,\n AirplanemodeActive,\n Assignment,\n AttachMoney,\n BlurLinear,\n CalendarToday,\n CenterFocusStrong,\n CreditCard,\n Dashboard,\n EmojiSymbols,\n FormatListNumbered,\n Group,\n HelpOutline,\n Language,\n LocalAtm,\n MonetizationOn,\n MonetizationOnOutlined,\n PermDataSetting,\n Phone,\n Settings,\n SpeakerNotes,\n SupervisedUserCircle,\n Timeline,\n TrendingUp,\n Widgets\n} from '@material-ui/icons';\n\nconst iconMap = {\n 'AccountBalance': AccountBalance,\n 'AirplanemodeActive': AirplanemodeActive,\n 'Assignment': Assignment,\n 'AttachMoney': AttachMoney,\n 'BlurLinear': BlurLinear,\n 'CalendarToday': CalendarToday,\n 'CenterFocusStrong': CenterFocusStrong,\n 'CreditCard': CreditCard,\n 'Dashboard': Dashboard,\n 'EmojiSymbols': EmojiSymbols,\n 'FormatListNumberedIcon': FormatListNumbered,\n 'Group': Group,\n 'HelpOutline': HelpOutline,\n 'Language': Language,\n 'LocalAtm': LocalAtm,\n 'MonetizationOn': MonetizationOn,\n 'MonetizationOnOutlined': MonetizationOnOutlined,\n 'PermDataSetting': PermDataSetting,\n 'Phone': Phone,\n 'Settings': Settings,\n 'SpeakerNotes' : SpeakerNotes,\n 'SupervisedUserCircle': SupervisedUserCircle,\n 'Timeline': Timeline,\n 'TrendingUp': TrendingUp,\n 'Widgets': Widgets\n};\n\n//dynamically load material icon\nconst DynamicMaterialIcon = ({ icon, ...rest }) => {\n return iconMap[icon] ? createElement(iconMap[icon]) : null;\n}\n\n//get all material icons\nconst getMaterialIcons = () => {\n if (localStorage.getItem('material_icons') === null) {\n localStorage.setItem(\n 'material_icons',\n JSON.stringify(Object.keys(iconMap))\n );\n }\n\n return JSON.parse(localStorage.getItem('material_icons'));\n}\n\nexport { DynamicMaterialIcon, getMaterialIcons }\n","import React, { forwardRef, useEffect, useState } from 'react';\nimport { NavLink as RouterLink } from 'react-router-dom';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport { List, ListItem, Button } from '@material-ui/core';\nimport {\n KeyboardArrowDown as ExpandMoreIcon,\n KeyboardArrowUp as ExpandLessIcon\n} from '@material-ui/icons';\nimport Collapse from '@material-ui/core/Collapse';\nimport find from 'lodash/find';\nimport each from 'lodash/each';\nimport { DynamicMaterialIcon } from '../../../../../../services/iconService';\n\nconst useStyles = makeStyles(theme => ({\n root: {},\n item: {\n display: 'flex',\n paddingTop: 0,\n paddingBottom: 0\n },\n button: {\n color: theme.palette.icon,\n padding: '10px 8px',\n justifyContent: 'flex-start',\n textTransform: 'none',\n letterSpacing: 0,\n width: '100%',\n fontWeight: theme.typography.fontWeightMedium\n },\n icon: {\n color: theme.palette.icon,\n width: 24,\n height: 24,\n display: 'flex',\n alignItems: 'center',\n marginRight: theme.spacing(1)\n },\n active: {\n color: theme.palette.background.contrastText,\n fontWeight: theme.typography.fontWeightMedium,\n '& $icon': {\n color: theme.palette.background.contrastText\n }\n }\n}));\n\nconst CustomRouterLink = forwardRef((props, ref) => (\n \n \n
\n));\n\nconst getChildMenu = (page, classes, toggleSideBar) => {\n return page.children.map(childPage => {\n return (\n \n \n \n \n
\n {childPage.name}\n \n \n );\n }\n );\n};\n\nconst SidebarNav = props => {\n const { pages, className, open, toggleSideBar, ...rest } = props;\n\n const classes = useStyles();\n const [navItemExpand, setNavItemExpand] = useState({});\n\n useEffect(() => {\n let href = window.location.pathname;\n each(pages, page => {\n if (find(page.children, { href: href })) {\n setNavItemExpand(navItemExpand => ({\n ...navItemExpand,\n [page.name]: true\n }));\n }\n });\n }, [pages]);\n\n return (\n \n {\n pages.map(page => {\n return (\n \n {\n !page.children ?\n \n \n \n
\n {page.name}\n \n :\n \n {\n page.children ?\n
\n {\n setNavItemExpand(navItemExpand => ({\n ...navItemExpand,\n [page.name]: !navItemExpand[page.name]\n }));\n }}\n >\n \n \n
\n {page.name}\n {navItemExpand[page.name] ? open ? : null : open ?\n : null}\n \n \n \n {getChildMenu(page, classes, toggleSideBar)}\n
\n \n \n :\n null\n }\n
\n }\n \n );\n }\n )\n }\n
\n );\n};\n\nSidebarNav.propTypes = {\n className: PropTypes.string,\n pages: PropTypes.array.isRequired\n};\n\nexport default SidebarNav;\n","import React from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport { Typography, Button, colors } from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n backgroundColor: colors.grey[50]\n },\n media: {\n paddingTop: theme.spacing(2),\n height: 80,\n textAlign: 'center',\n '& > img': {\n height: '100%',\n width: 'auto'\n }\n },\n content: {\n padding: theme.spacing(1, 2)\n },\n actions: {\n padding: theme.spacing(1, 2),\n display: 'flex',\n justifyContent: 'center'\n }\n}));\n\nconst UpgradePlan = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n return (\n \n
\n
\n
\n
\n \n Upgrade to PRO\n \n \n Upgrade to Devias Kit PRO and get even more components\n \n
\n
\n \n Upgrade\n \n
\n
\n );\n};\n\nUpgradePlan.propTypes = {\n className: PropTypes.string\n};\n\nexport default UpgradePlan;\n","import React from 'react';\nimport { makeStyles } from '@material-ui/styles';\nimport { ChevronLeft as ChevronLeftIcon, ChevronRight as ChevronRightIcon } from '@material-ui/icons';\nimport IconButton from '@material-ui/core/IconButton';\nimport clsx from 'clsx';\n\nconst useStyles = makeStyles(theme => ({\n collapser: {\n display: 'inline-block',\n position: 'absolute',\n right: 10,\n top: 10\n }\n}));\n\nconst SidebarCollapser = ({onClick, desktopCollapse}) => {\n const classes = useStyles();\n\n return (\n \n { desktopCollapse ? : }\n \n );\n};\n\nexport default SidebarCollapser;\n","import axios from './axiosService';\n\n// Sidebar links can have children. This adds all children to their parent links\nconst getChildren = (map, parent_id) => {\n let ans = [];\n map.forEach((val) => {\n if (val.parent_id === parent_id) {\n let { parent_id, ...temp } = val;\n let children = getChildren(map, val.id);\n ans.push({ ...temp, ...(children.length > 0 && {children}) });\n }\n });\n return ans;\n};\n\nconst getSidebar = () => {\n return localStorage.getItem('sidebar_links') !== null\n ? JSON.parse(localStorage.getItem('sidebar_links'))\n : [];\n}\n\nconst getSidebarMainLinks = (sidebar_links) => sidebar_links.filter(\n link => link.parent_id === null\n);\n\nconst getSidebarMainLinksWithIconComponents = (sidebar_links) =>\n getSidebarMainLinks(sidebar_links);\n\nconst getSidebarSubLinksByParentHref = (parent_href, sidebar_links) => {\n if (sidebar_links.length === 0) return [];\n const parent_id = sidebar_links.find(page => page.href === parent_href).id\n return sidebar_links.filter(page => page.parent_id === parent_id);\n}\n\nconst getParentLinkId = (parent_href, sidebar_links) => {\n return sidebar_links.find(page => page.href === parent_href).id;\n}\n\nconst getSidebarWithChildrenNested = (sidebar_links) => {\n if (sidebar_links.length === 0) return [];\n return getChildren(sidebar_links, null);\n}\n\nconst fetchSidebarAndSaveToLocalStorage = async () => {\n localStorage.setItem(\n 'sidebar_links',\n JSON.stringify((await getSidebarLinks())?.data?.rows)\n );\n\n return getSidebar();\n}\n\nconst getSidebarLinks = async () => {\n return await axios.get('SidebarLink');\n}\n\nconst addSidebarLink = async (\n { name, icon, view_permission, parent_id, tableau_url }\n) => {\n await axios.post(\n 'SidebarLink',\n { name, icon, view_permission, parent_id, tableau_url }\n )\n}\n\nconst updateSidebarLink = async ({ id, name, icon, view_permission, parent_id, tableau_url }) => {\n await axios.put(\n 'SidebarLink',\n { id, name, icon, view_permission, parent_id, tableau_url }\n )\n}\n\nconst deleteSidebarLink = async ({ id }) => {\n await axios.delete('SidebarLink', { data: { id } })\n}\n\nexport {\n fetchSidebarAndSaveToLocalStorage,\n getSidebarWithChildrenNested,\n getSidebarSubLinksByParentHref,\n getSidebar,\n getSidebarMainLinks,\n getSidebarMainLinksWithIconComponents,\n addSidebarLink,\n updateSidebarLink,\n deleteSidebarLink,\n getParentLinkId\n}\n","import axios from './axiosService';\nimport { getAccessToken } from './graphService';\n\nconst getLoggedInUserActiveDirectoryGroups = () => (localStorage.getItem('user_active_directory_groups') !== null\n ? JSON.parse(localStorage.getItem('user_active_directory_groups'))\n : []);\n\nconst getActiveDirectoryGroups = () => (localStorage.getItem('active_directory_groups') !== null\n ? JSON.parse(localStorage.getItem('active_directory_groups'))\n : []);\n\nconst hasAccessToApp = () => getLoggedInUserActiveDirectoryGroups()\n .some(({ displayName }) => displayName.startsWith('All InsightQore'));\n\nconst isAdmin = () => getLoggedInUserActiveDirectoryGroups()\n .some(({ displayName }) => displayName === 'All InsightQore Admin');\n\nconst fetchActiveDirectoryGroupsAndSaveToLocalStorage = async () => {\n const azureGroups = (\n await axios.get('/groups')\n ).data.value;\n\n const azureGroupsSorted = azureGroups.sort((a, b) => {\n if (a.displayName < b.displayName) { return -1; }\n if (a.displayName > b.displayName) { return 1; }\n return 0;\n });\n\n localStorage.setItem(\n 'active_directory_groups',\n JSON.stringify(azureGroupsSorted)\n );\n\n return getActiveDirectoryGroups();\n};\n\nexport {\n getAccessToken,\n fetchActiveDirectoryGroupsAndSaveToLocalStorage,\n getActiveDirectoryGroups,\n hasAccessToApp,\n isAdmin\n};\n","import React, { useEffect } from 'react';\nimport NProgress from 'nprogress';\nimport { Box, LinearProgress, makeStyles } from '@material-ui/core';\n\nconst useStyles = makeStyles((theme) => ({\n root: {\n alignItems: 'center',\n backgroundColor: theme.palette.background.default,\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n justifyContent: 'center',\n minHeight: '100%',\n padding: theme.spacing(3)\n }\n}));\n\nfunction LoadingScreen() {\n const classes = useStyles();\n\n useEffect(() => {\n NProgress.start();\n\n return () => {\n NProgress.done();\n };\n }, []);\n\n return (\n \n \n \n \n
\n );\n}\n\nexport default LoadingScreen;\n","import React, { useContext, useEffect, useState } from 'react';\nimport AppContext from '../../../../contexts/AppContext';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport axios from 'services/axiosService';\nimport { makeStyles, useTheme } from '@material-ui/styles';\nimport { Divider, Drawer, useMediaQuery } from '@material-ui/core';\nimport { Profile, SidebarNav } from './components';\nimport SidebarCollapser from './components/SidebarCollapser';\nimport { fetchSidebarAndSaveToLocalStorage, getSidebarWithChildrenNested } from '../../../../services/sidebarLinkService';\nimport { fetchActiveDirectoryGroupsAndSaveToLocalStorage } from 'services/microsoftGraphApiService';\nimport { useAutocomplete } from '@material-ui/lab';\nimport LoadingScreen from 'components/LoadingScreen';\n\nconst useStyles = makeStyles(theme => ({\n drawer: {\n width: 240,\n [theme.breakpoints.up('lg')]: {\n marginTop: 64,\n height: 'calc(100% - 64px)'\n }\n },\n root: {\n backgroundColor: theme.palette.white,\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n padding: theme.spacing(2)\n },\n divider: {\n margin: theme.spacing(2, 0)\n },\n nav: {\n marginBottom: theme.spacing(2)\n },\n desktopCollapse: {\n width: 50,\n overflowX: 'hidden'\n }\n}));\n\nconst Sidebar = props => {\n const { open, variant, onClose, onToggleDesktopCollapse, desktopCollapse, className, ...rest } = props;\n const theme = useTheme();\n const isDesktop = useMediaQuery(theme.breakpoints.up('lg'), {\n defaultMatches: true\n });\n\n const { appData, setAppData } = useContext(AppContext);\n const [isLoading, setIsLoading] = useState(false);\n const { sidebar_links } = appData;\n\n const classes = useStyles();\n\n useEffect(() => {\n const loadSidebar = async () => {\n try {\n setIsLoading(true);\n\n const { data: grpData } = await axios.get('/me/memberOf');\n\n localStorage.setItem(\n 'user_active_directory_groups',\n JSON.stringify(grpData.value.map(({ id, displayName }) => ({ id, displayName })))\n );\n\n const sidebar_links = await fetchSidebarAndSaveToLocalStorage();\n setAppData((prevAppData) => ({ ...prevAppData, sidebar_links }));\n\n const active_directory_groups = await fetchActiveDirectoryGroupsAndSaveToLocalStorage();\n setAppData((prevAppData) => ({ ...prevAppData, active_directory_groups }));\n } catch (error) {\n console.error(error);\n }\n\n setIsLoading(false);\n };\n\n loadSidebar();\n }, []);\n\n if (isLoading) return ;\n\n return (\n \n \n {isDesktop &&
\n }\n {!desktopCollapse &&\n [\n
,\n ,\n \n ]\n }\n \n \n );\n};\n\nSidebar.propTypes = {\n className: PropTypes.string,\n onClose: PropTypes.func,\n open: PropTypes.bool.isRequired,\n variant: PropTypes.string.isRequired\n};\n\nexport default Sidebar;\n","import React from 'react';\nimport {\n IconButton,\n Tooltip\n} from '@material-ui/core';\nimport { LockOpen as LockOpenIcon } from '@material-ui/icons';\nimport { Link as RouterLink } from 'react-router-dom';\n\nfunction Admin() {\n return (\n <>\n \n \n \n \n \n >\n );\n}\n\nexport default Admin;\n","/* eslint-disable no-empty */\nimport React, { createContext, useState, useEffect } from 'react';\nimport PropTypes from 'prop-types';\nimport * as msal from '@azure/msal-browser';\n\nconst msalConfig = {\n auth: {\n clientId: '4200006f-96c9-41d1-be91-7bfd3aa0a382',\n authority: 'https://login.microsoftonline.com/f797e736-cc74-4a7b-82b5-b7a09789eed2'\n },\n cache: {\n cacheLocation: 'sessionStorage',\n storeAuthStateInCookie: false\n }\n};\n\nconst AuthContext = createContext({});\n\nexport const AuthProvider = ({ children }) => {\n const [msalInstance] = useState(new msal.PublicClientApplication(msalConfig));\n const [authResponse, setAuthResponse] = useState(null);\n const [loginError, setLoginError] = useState(null);\n\n const deleteAllCookies = () => {\n const cookies = document.cookie.split(';');\n\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i];\n const eqPos = cookie.indexOf('=');\n const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;\n document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;\n }\n };\n\n const displayError = (error) => {\n console.error(error);\n setLoginError(error.message);\n };\n\n const loginWithMicrosoft = async () => {\n try {\n const token = await msalInstance.acquireTokenSilent({ scopes: ['User.Read'] });\n setAuthResponse(token);\n } catch (error) {\n if (error instanceof msal.InteractionRequiredAuthError || error instanceof msal.BrowserAuthError) {\n msalInstance.acquireTokenRedirect({ scopes: ['User.Read'] });\n return;\n }\n\n displayError(error);\n }\n };\n\n const logout = () => {\n setAuthResponse(null);\n sessionStorage.clear();\n localStorage.clear();\n deleteAllCookies();\n };\n\n useEffect(() => {\n // check if user is alrady logged in\n const setActiveAccount = async () => {\n try {\n const resp = await msalInstance.handleRedirectPromise();\n if (resp !== null) {\n msalInstance.setActiveAccount(resp.account);\n } else {\n const currentAccounts = msalInstance.getAllAccounts();\n if (currentAccounts.length >= 1) {\n const activeAccount = currentAccounts[0];\n msalInstance.setActiveAccount(activeAccount);\n }\n }\n } catch (error) {\n displayError(error);\n }\n\n try {\n const token = await msalInstance.acquireTokenSilent({ scopes: ['User.Read'] });\n setAuthResponse(token);\n } catch (error) {\n }\n };\n\n setActiveAccount();\n }, []);\n\n return (\n \n {children}\n \n );\n};\n\nAuthProvider.propTypes = {\n children: PropTypes.node\n};\n\nexport default AuthContext;\n","import { useContext } from 'react';\nimport AuthContext from '../contexts/AuthContext';\n\nexport default () => useContext(AuthContext);","import React, { useState } from 'react';\nimport { Link as RouterLink, withRouter } from 'react-router-dom';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport { AppBar, Toolbar, Badge, Hidden, IconButton } from '@material-ui/core';\nimport MenuIcon from '@material-ui/icons/Menu';\nimport NotificationsIcon from '@material-ui/icons/NotificationsOutlined';\nimport InputIcon from '@material-ui/icons/Input';\nimport { isAdmin } from 'services/microsoftGraphApiService';\nimport Admin from './Admin';\nimport useAuth from 'hooks/useAuth';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n boxShadow: 'none'\n },\n flexGrow: {\n flexGrow: 1\n },\n signOutButton: {\n marginLeft: theme.spacing(1)\n }\n}));\n\nconst Topbar = props => {\n const { className, onSidebarOpen, history, staticContext, ...rest } = props;\n\n const classes = useStyles();\n const {\n logout\n } = useAuth();\n\n const [notifications] = useState([]);\n\n const handleLogout = async () => {\n logout();\n history.push('/');\n };\n\n return (\n \n \n \n \n \n
\n \n {isAdmin() && }\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n );\n};\n\nTopbar.propTypes = {\n className: PropTypes.string,\n onSidebarOpen: PropTypes.func\n};\n\nexport default withRouter(Topbar);\n","import React, { useState } from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { makeStyles, useTheme } from '@material-ui/styles';\nimport { useMediaQuery } from '@material-ui/core';\nimport { Sidebar, Topbar, Footer } from './components';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n paddingTop: 56,\n height: '100%',\n [theme.breakpoints.up('sm')]: {\n paddingTop: 64\n }\n },\n shiftContent: {\n paddingLeft: 240\n },\n content: {\n height: '100%'\n },\n desktopCollapse: {\n paddingLeft: 40\n }\n}));\n\nconst Main = props => {\n const { children } = props;\n\n const classes = useStyles();\n const theme = useTheme();\n const isDesktop = useMediaQuery(theme.breakpoints.up('lg'), {\n defaultMatches: true\n });\n\n const [openSidebar, setOpenSidebar] = useState(false);\n const [desktopCollapse, setDesktopCollapse] = useState(false);\n\n const handleSidebarOpen = () => {\n setOpenSidebar(true);\n };\n\n const handleSidebarClose = () => {\n setOpenSidebar(false);\n };\n\n const handleToggleDesktopCollapse = () => {\n setDesktopCollapse(!desktopCollapse);\n };\n\n const shouldOpenSidebar = isDesktop ? true : openSidebar;\n\n return (\n \n \n \n \n {children}\n \n \n
\n );\n};\n\nMain.propTypes = {\n children: PropTypes.node\n};\n\nexport default Main;\n","import React from 'react';\nimport { Link as RouterLink } from 'react-router-dom';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport { AppBar, Toolbar } from '@material-ui/core';\n\nconst useStyles = makeStyles(() => ({\n root: {\n boxShadow: 'none'\n }\n}));\n\nconst Topbar = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n return (\n \n \n \n \n \n \n \n );\n};\n\nTopbar.propTypes = {\n className: PropTypes.string\n};\n\nexport default Topbar;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\n\nimport { Topbar } from './components';\n\nconst useStyles = makeStyles(() => ({\n root: {\n paddingTop: 64,\n height: '100%'\n },\n content: {\n height: '100%'\n }\n}));\n\nconst Minimal = props => {\n const { children } = props;\n\n const classes = useStyles();\n\n return (\n \n \n {children} \n
\n );\n};\n\nMinimal.propTypes = {\n children: PropTypes.node,\n className: PropTypes.string\n};\n\nexport default Minimal;\n","export default [\n '/board-of-directors',\n '/executive',\n '/claims',\n '/finance',\n '/it'\n];\n","import React, { useState } from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Card,\n CardHeader,\n CardContent,\n CardActions,\n Divider,\n Grid,\n Button,\n TextField\n} from '@material-ui/core';\n\nconst useStyles = makeStyles(() => ({\n root: {}\n}));\n\nconst AccountDetails = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n const [values, setValues] = useState({\n firstName: 'Shen',\n lastName: 'Zhi',\n email: 'shen.zhi@devias.io',\n phone: '',\n state: 'Alabama',\n country: 'USA'\n });\n\n const handleChange = event => {\n setValues({\n ...values,\n [event.target.name]: event.target.value\n });\n };\n\n const states = [\n {\n value: 'alabama',\n label: 'Alabama'\n },\n {\n value: 'new-york',\n label: 'New York'\n },\n {\n value: 'san-francisco',\n label: 'San Francisco'\n }\n ];\n\n return (\n \n \n \n );\n};\n\nAccountDetails.propTypes = {\n className: PropTypes.string\n};\n\nexport default AccountDetails;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport moment from 'moment';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Card,\n CardActions,\n CardContent,\n Avatar,\n Typography,\n Divider,\n Button,\n LinearProgress\n} from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n root: {},\n details: {\n display: 'flex'\n },\n avatar: {\n marginLeft: 'auto',\n height: 110,\n width: 100,\n flexShrink: 0,\n flexGrow: 0\n },\n progress: {\n marginTop: theme.spacing(2)\n },\n uploadButton: {\n marginRight: theme.spacing(2)\n }\n}));\n\nconst AccountProfile = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n const user = {\n name: 'Shen Zhi',\n city: 'Los Angeles',\n country: 'USA',\n timezone: 'GTM-7',\n avatar: '/images/avatars/avatar_11.png'\n };\n\n return (\n \n \n \n
\n \n John Doe\n \n \n {user.city}, {user.country}\n \n \n {moment().format('hh:mm A')} ({user.timezone})\n \n
\n
\n
\n \n Profile Completeness: 70% \n \n
\n \n \n \n \n Upload picture\n \n Remove picture \n \n \n );\n};\n\nAccountProfile.propTypes = {\n className: PropTypes.string\n};\n\nexport default AccountProfile;\n","import React from 'react';\nimport { makeStyles } from '@material-ui/styles';\nimport { Grid } from '@material-ui/core';\n\nimport { AccountProfile, AccountDetails } from './components';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(4)\n }\n}));\n\nconst Account = () => {\n const classes = useStyles();\n\n return (\n \n
\n \n \n \n \n \n \n \n
\n );\n};\n\nexport default Account;\n","import React from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport { Card, CardContent, Grid, Typography, Avatar } from '@material-ui/core';\nimport ArrowDownwardIcon from '@material-ui/icons/ArrowDownward';\nimport MoneyIcon from '@material-ui/icons/Money';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n height: '100%'\n },\n content: {\n alignItems: 'center',\n display: 'flex'\n },\n title: {\n fontWeight: 700\n },\n avatar: {\n backgroundColor: theme.palette.error.main,\n height: 56,\n width: 56\n },\n icon: {\n height: 32,\n width: 32\n },\n difference: {\n marginTop: theme.spacing(2),\n display: 'flex',\n alignItems: 'center'\n },\n differenceIcon: {\n color: theme.palette.error.dark\n },\n differenceValue: {\n color: theme.palette.error.dark,\n marginRight: theme.spacing(1)\n }\n}));\n\nconst Budget = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n return (\n \n \n \n \n \n BUDGET\n \n $24,000 \n \n \n \n \n \n \n \n \n
\n
\n 12%\n \n
\n Since last month\n \n
\n \n \n );\n};\n\nBudget.propTypes = {\n className: PropTypes.string\n};\n\nexport default Budget;\n","import uuid from 'uuid/v1';\n\nexport default [\n {\n id: uuid(),\n ref: 'CDD1049',\n amount: 30.5,\n customer: {\n name: 'Ekaterina Tankova'\n },\n createdAt: 1555016400000,\n status: 'pending'\n },\n {\n id: uuid(),\n ref: 'CDD1048',\n amount: 25.1,\n customer: {\n name: 'Cao Yu'\n },\n createdAt: 1555016400000,\n status: 'delivered'\n },\n {\n id: uuid(),\n ref: 'CDD1047',\n amount: 10.99,\n customer: {\n name: 'Alexa Richardson'\n },\n createdAt: 1554930000000,\n status: 'refunded'\n },\n {\n id: uuid(),\n ref: 'CDD1046',\n amount: 96.43,\n customer: {\n name: 'Anje Keizer'\n },\n createdAt: 1554757200000,\n status: 'pending'\n },\n {\n id: uuid(),\n ref: 'CDD1045',\n amount: 32.54,\n customer: {\n name: 'Clarke Gillebert'\n },\n createdAt: 1554670800000,\n status: 'delivered'\n },\n {\n id: uuid(),\n ref: 'CDD1044',\n amount: 16.76,\n customer: {\n name: 'Adam Denisov'\n },\n createdAt: 1554670800000,\n status: 'delivered'\n }\n];\n","import React, { useState } from 'react';\nimport clsx from 'clsx';\nimport moment from 'moment';\nimport PerfectScrollbar from 'react-perfect-scrollbar';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Card,\n CardActions,\n CardHeader,\n CardContent,\n Button,\n Divider,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n Tooltip,\n TableSortLabel\n} from '@material-ui/core';\nimport ArrowRightIcon from '@material-ui/icons/ArrowRight';\n\nimport mockData from './data';\nimport { StatusBullet } from 'components';\n\nconst useStyles = makeStyles(theme => ({\n root: {},\n content: {\n padding: 0\n },\n inner: {\n minWidth: 800\n },\n statusContainer: {\n display: 'flex',\n alignItems: 'center'\n },\n status: {\n marginRight: theme.spacing(1)\n },\n actions: {\n justifyContent: 'flex-end'\n }\n}));\n\nconst statusColors = {\n delivered: 'success',\n pending: 'info',\n refunded: 'danger'\n};\n\nconst LatestOrders = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n const [orders] = useState(mockData);\n\n return (\n \n \n New entry\n \n }\n title=\"Latest Orders\"\n />\n \n \n \n \n
\n \n \n Order Ref \n Customer \n \n \n \n Date\n \n \n \n Status \n \n \n \n {orders.map(order => (\n \n {order.ref} \n {order.customer.name} \n \n {moment(order.createdAt).format('DD/MM/YYYY')}\n \n \n \n \n {order.status}\n
\n \n \n ))}\n \n
\n
\n \n \n \n \n \n View all \n \n \n \n );\n};\n\nLatestOrders.propTypes = {\n className: PropTypes.string\n};\n\nexport default LatestOrders;\n","import uuid from 'uuid/v1';\nimport moment from 'moment';\n\nexport default [\n {\n id: uuid(),\n name: 'Dropbox',\n imageUrl: '/images/products/product_1.png',\n updatedAt: moment().subtract(2, 'hours')\n },\n {\n id: uuid(),\n name: 'Medium Corporation',\n imageUrl: '/images/products/product_2.png',\n updatedAt: moment().subtract(2, 'hours')\n },\n {\n id: uuid(),\n name: 'Slack',\n imageUrl: '/images/products/product_3.png',\n updatedAt: moment().subtract(3, 'hours')\n },\n {\n id: uuid(),\n name: 'Lyft',\n imageUrl: '/images/products/product_4.png',\n updatedAt: moment().subtract(5, 'hours')\n },\n {\n id: uuid(),\n name: 'GitHub',\n imageUrl: '/images/products/product_5.png',\n updatedAt: moment().subtract(9, 'hours')\n }\n];\n","import React, { useState } from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Card,\n CardHeader,\n CardContent,\n CardActions,\n Button,\n Divider,\n List,\n ListItem,\n ListItemAvatar,\n ListItemText,\n IconButton\n} from '@material-ui/core';\nimport ArrowRightIcon from '@material-ui/icons/ArrowRight';\nimport MoreVertIcon from '@material-ui/icons/MoreVert';\n\nimport mockData from './data';\n\nconst useStyles = makeStyles(() => ({\n root: {\n height: '100%'\n },\n content: {\n padding: 0\n },\n image: {\n height: 48,\n width: 48\n },\n actions: {\n justifyContent: 'flex-end'\n }\n}));\n\nconst LatestProducts = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n const [products] = useState(mockData);\n\n return (\n \n \n \n \n \n {products.map((product, i) => (\n \n \n \n \n \n \n \n \n \n ))}\n
\n \n \n \n \n View all \n \n \n \n );\n};\n\nLatestProducts.propTypes = {\n className: PropTypes.string\n};\n\nexport default LatestProducts;\n","import palette from 'theme/palette';\n\nexport const data = {\n labels: ['1 Aug', '2 Aug', '3 Aug', '4 Aug', '5 Aug', '6 Aug'],\n datasets: [\n {\n label: 'This year',\n backgroundColor: palette.primary.main,\n data: [18, 5, 19, 27, 29, 19, 20]\n },\n {\n label: 'Last year',\n backgroundColor: palette.neutral,\n data: [11, 20, 12, 29, 30, 25, 13]\n }\n ]\n};\n\nexport const options = {\n responsive: true,\n maintainAspectRatio: false,\n animation: false,\n legend: { display: false },\n cornerRadius: 20,\n tooltips: {\n enabled: true,\n mode: 'index',\n intersect: false,\n borderWidth: 1,\n borderColor: palette.divider,\n backgroundColor: palette.white,\n titleFontColor: palette.text.primary,\n bodyFontColor: palette.text.secondary,\n footerFontColor: palette.text.secondary\n },\n layout: { padding: 0 },\n scales: {\n xAxes: [\n {\n barThickness: 12,\n maxBarThickness: 10,\n barPercentage: 0.5,\n categoryPercentage: 0.5,\n ticks: {\n fontColor: palette.text.secondary\n },\n gridLines: {\n display: false,\n drawBorder: false\n }\n }\n ],\n yAxes: [\n {\n ticks: {\n fontColor: palette.text.secondary,\n beginAtZero: true,\n min: 0\n },\n gridLines: {\n borderDash: [2],\n borderDashOffset: [2],\n color: palette.divider,\n drawBorder: false,\n zeroLineBorderDash: [2],\n zeroLineBorderDashOffset: [2],\n zeroLineColor: palette.divider\n }\n }\n ]\n }\n};\n","import React from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { Bar } from 'react-chartjs-2';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Card,\n CardHeader,\n CardContent,\n CardActions,\n Divider,\n Button\n} from '@material-ui/core';\nimport ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';\nimport ArrowRightIcon from '@material-ui/icons/ArrowRight';\n\nimport { data, options } from './chart';\n\nconst useStyles = makeStyles(() => ({\n root: {},\n chartContainer: {\n height: 400,\n position: 'relative'\n },\n actions: {\n justifyContent: 'flex-end'\n }\n}));\n\nconst LatestSales = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n return (\n \n \n Last 7 days \n \n }\n title=\"Latest Sales\"\n />\n \n \n \n \n
\n \n \n \n \n Overview \n \n \n \n );\n};\n\nLatestSales.propTypes = {\n className: PropTypes.string\n};\n\nexport default LatestSales;\n","import React from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Card,\n CardContent,\n Grid,\n Typography,\n Avatar,\n LinearProgress\n} from '@material-ui/core';\nimport InsertChartIcon from '@material-ui/icons/InsertChartOutlined';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n height: '100%'\n },\n content: {\n alignItems: 'center',\n display: 'flex'\n },\n title: {\n fontWeight: 700\n },\n avatar: {\n backgroundColor: theme.palette.primary.main,\n color: theme.palette.primary.contrastText,\n height: 56,\n width: 56\n },\n icon: {\n height: 32,\n width: 32\n },\n progress: {\n marginTop: theme.spacing(3)\n }\n}));\n\nconst TasksProgress = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n return (\n \n \n \n \n \n TASKS PROGRESS\n \n 75.5% \n \n \n \n \n \n \n \n \n \n \n );\n};\n\nTasksProgress.propTypes = {\n className: PropTypes.string\n};\n\nexport default TasksProgress;\n","import React from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport { Card, CardContent, Grid, Typography, Avatar } from '@material-ui/core';\nimport AttachMoneyIcon from '@material-ui/icons/AttachMoney';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n height: '100%',\n backgroundColor: theme.palette.primary.main,\n color: theme.palette.primary.contrastText\n },\n content: {\n alignItems: 'center',\n display: 'flex'\n },\n title: {\n fontWeight: 700\n },\n avatar: {\n backgroundColor: theme.palette.white,\n color: theme.palette.primary.main,\n height: 56,\n width: 56\n },\n icon: {\n height: 32,\n width: 32\n }\n}));\n\nconst TotalProfit = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n return (\n \n \n \n \n \n TOTAL PROFIT\n \n \n $23,200\n \n \n \n \n \n \n \n \n \n \n );\n};\n\nTotalProfit.propTypes = {\n className: PropTypes.string\n};\n\nexport default TotalProfit;\n","import React from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport { Card, CardContent, Grid, Typography, Avatar } from '@material-ui/core';\nimport ArrowUpwardIcon from '@material-ui/icons/ArrowUpward';\nimport PeopleIcon from '@material-ui/icons/PeopleOutlined';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n height: '100%'\n },\n content: {\n alignItems: 'center',\n display: 'flex'\n },\n title: {\n fontWeight: 700\n },\n avatar: {\n backgroundColor: theme.palette.success.main,\n height: 56,\n width: 56\n },\n icon: {\n height: 32,\n width: 32\n },\n difference: {\n marginTop: theme.spacing(2),\n display: 'flex',\n alignItems: 'center'\n },\n differenceIcon: {\n color: theme.palette.success.dark\n },\n differenceValue: {\n color: theme.palette.success.dark,\n marginRight: theme.spacing(1)\n }\n}));\n\nconst TotalUsers = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n return (\n \n \n \n \n \n TOTAL USERS\n \n 1,600 \n \n \n \n \n \n \n \n \n
\n
\n 16%\n \n
\n Since last month\n \n
\n \n \n );\n};\n\nTotalUsers.propTypes = {\n className: PropTypes.string\n};\n\nexport default TotalUsers;\n","import React from 'react';\nimport { Doughnut } from 'react-chartjs-2';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { makeStyles, useTheme } from '@material-ui/styles';\nimport {\n Card,\n CardHeader,\n CardContent,\n IconButton,\n Divider,\n Typography\n} from '@material-ui/core';\nimport LaptopMacIcon from '@material-ui/icons/LaptopMac';\nimport PhoneIphoneIcon from '@material-ui/icons/PhoneIphone';\nimport RefreshIcon from '@material-ui/icons/Refresh';\nimport TabletMacIcon from '@material-ui/icons/TabletMac';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n height: '100%'\n },\n chartContainer: {\n position: 'relative',\n height: '300px'\n },\n stats: {\n marginTop: theme.spacing(2),\n display: 'flex',\n justifyContent: 'center'\n },\n device: {\n textAlign: 'center',\n padding: theme.spacing(1)\n },\n deviceIcon: {\n color: theme.palette.icon\n }\n}));\n\nconst UsersByDevice = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n const theme = useTheme();\n\n const data = {\n datasets: [\n {\n data: [63, 15, 22],\n backgroundColor: [\n theme.palette.primary.main,\n theme.palette.error.main,\n theme.palette.warning.main\n ],\n borderWidth: 8,\n borderColor: theme.palette.white,\n hoverBorderColor: theme.palette.white\n }\n ],\n labels: ['Desktop', 'Tablet', 'Mobile']\n };\n\n const options = {\n legend: {\n display: false\n },\n responsive: true,\n maintainAspectRatio: false,\n animation: false,\n cutoutPercentage: 80,\n layout: { padding: 0 },\n tooltips: {\n enabled: true,\n mode: 'index',\n intersect: false,\n borderWidth: 1,\n borderColor: theme.palette.divider,\n backgroundColor: theme.palette.white,\n titleFontColor: theme.palette.text.primary,\n bodyFontColor: theme.palette.text.secondary,\n footerFontColor: theme.palette.text.secondary\n }\n };\n\n const devices = [\n {\n title: 'Desktop',\n value: '63',\n icon: ,\n color: theme.palette.primary.main\n },\n {\n title: 'Tablet',\n value: '15',\n icon: ,\n color: theme.palette.error.main\n },\n {\n title: 'Mobile',\n value: '23',\n icon: ,\n color: theme.palette.warning.main\n }\n ];\n\n return (\n \n \n \n \n }\n title=\"Users By Device\"\n />\n \n \n \n \n
\n \n {devices.map(device => (\n
\n {device.icon} \n {device.title} \n \n {device.value}%\n \n
\n ))}\n
\n \n \n );\n};\n\nUsersByDevice.propTypes = {\n className: PropTypes.string\n};\n\nexport default UsersByDevice;\n","import React from 'react';\nimport { makeStyles } from '@material-ui/styles';\nimport { Grid } from '@material-ui/core';\n\nimport {\n Budget,\n TotalUsers,\n TasksProgress,\n TotalProfit,\n LatestSales,\n UsersByDevice,\n LatestProducts,\n LatestOrders\n} from './components';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(4)\n }\n}));\n\nconst Dashboard = () => {\n const classes = useStyles();\n\n return (\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n );\n};\n\nexport default Dashboard;\n","import React from 'react';\nimport { makeStyles } from '@material-ui/styles';\nimport { Grid, Typography } from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(4)\n },\n content: {\n paddingTop: 150,\n textAlign: 'center'\n },\n image: {\n marginTop: 50,\n display: 'inline-block',\n maxWidth: '100%',\n width: 560\n }\n}));\n\nconst NotFound = () => {\n const classes = useStyles();\n\n return (\n \n
\n \n \n
\n 404: The page you are looking for isn’t here\n \n
\n You either tried some shady route or you came here by mistake.\n Whichever it is, try using the navigation\n \n
\n
\n \n \n
\n );\n};\n\nexport default NotFound;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Card,\n CardContent,\n CardActions,\n Typography,\n Grid,\n Divider\n} from '@material-ui/core';\nimport AccessTimeIcon from '@material-ui/icons/AccessTime';\nimport GetAppIcon from '@material-ui/icons/GetApp';\n\nconst useStyles = makeStyles(theme => ({\n root: {},\n imageContainer: {\n height: 64,\n width: 64,\n margin: '0 auto',\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: '5px',\n overflow: 'hidden',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center'\n },\n image: {\n width: '100%'\n },\n statsItem: {\n display: 'flex',\n alignItems: 'center'\n },\n statsIcon: {\n color: theme.palette.icon,\n marginRight: theme.spacing(1)\n }\n}));\n\nconst ProductCard = props => {\n const { className, product, ...rest } = props;\n\n const classes = useStyles();\n\n return (\n \n \n \n
\n
\n \n {product.title}\n \n \n {product.description}\n \n \n \n \n \n \n \n \n Updated 2hr ago\n \n \n \n \n \n {product.totalDownloads} Downloads\n \n \n \n \n \n );\n};\n\nProductCard.propTypes = {\n className: PropTypes.string,\n product: PropTypes.object.isRequired\n};\n\nexport default ProductCard;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { makeStyles } from '@material-ui/styles';\nimport { Button } from '@material-ui/core';\n\nimport { SearchInput } from 'components';\n\nconst useStyles = makeStyles(theme => ({\n root: {},\n row: {\n height: '42px',\n display: 'flex',\n alignItems: 'center',\n marginTop: theme.spacing(1)\n },\n spacer: {\n flexGrow: 1\n },\n importButton: {\n marginRight: theme.spacing(1)\n },\n exportButton: {\n marginRight: theme.spacing(1)\n },\n searchInput: {\n marginRight: theme.spacing(1)\n }\n}));\n\nconst ProductsToolbar = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n return (\n \n
\n \n Import \n Export \n \n Add product\n \n
\n
\n \n
\n
\n );\n};\n\nProductsToolbar.propTypes = {\n className: PropTypes.string\n};\n\nexport default ProductsToolbar;\n","import uuid from 'uuid/v1';\n\nexport default [\n {\n id: uuid(),\n title: 'Dropbox',\n description:\n 'Dropbox is a file hosting service that offers cloud storage, file synchronization, a personal cloud.',\n imageUrl: '/images/products/product_1.png',\n totalDownloads: '594',\n updatedAt: '27/03/2019'\n },\n {\n id: uuid(),\n title: 'Medium Corporation',\n description:\n 'Medium is an online publishing platform developed by Evan Williams, and launched in August 2012.',\n imageUrl: '/images/products/product_2.png',\n totalDownloads: '625',\n createdAt: '31/03/2019'\n },\n {\n id: uuid(),\n title: 'Slack',\n description:\n 'Slack is a cloud-based set of team collaboration tools and services, founded by Stewart Butterfield.',\n imageUrl: '/images/products/product_3.png',\n totalDownloads: '857',\n createdAt: '03/04/2019'\n },\n {\n id: uuid(),\n title: 'Lyft',\n description:\n 'Lyft is an on-demand transportation company based in San Francisco, California.',\n imageUrl: '/images/products/product_4.png',\n totalDownloads: '406',\n createdAt: '04/04/2019'\n },\n {\n id: uuid(),\n title: 'GitHub',\n description:\n 'GitHub is a web-based hosting service for version control of code using Git.',\n imageUrl: '/images/products/product_5.png',\n totalDownloads: '835',\n createdAt: '04/04/2019'\n },\n {\n id: uuid(),\n title: 'Squarespace',\n description:\n 'Squarespace provides software as a service for website building and hosting. Headquartered in NYC.',\n imageUrl: '/images/products/product_6.png',\n totalDownloads: '835',\n createdAt: '04/04/2019'\n }\n];\n","import React, { useState } from 'react';\nimport { makeStyles } from '@material-ui/styles';\nimport { IconButton, Grid, Typography } from '@material-ui/core';\nimport ChevronRightIcon from '@material-ui/icons/ChevronRight';\nimport ChevronLeftIcon from '@material-ui/icons/ChevronLeft';\n\nimport { ProductsToolbar, ProductCard } from './components';\nimport mockData from './data';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(3)\n },\n content: {\n marginTop: theme.spacing(2)\n },\n pagination: {\n marginTop: theme.spacing(3),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end'\n }\n}));\n\nconst ProductList = () => {\n const classes = useStyles();\n\n const [products] = useState(mockData);\n\n return (\n \n
\n
\n
\n {products.map(product => (\n \n \n \n ))}\n \n
\n
\n 1-6 of 20 \n \n \n \n \n \n \n
\n
\n );\n};\n\nexport default ProductList;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Card,\n CardHeader,\n CardContent,\n CardActions,\n Grid,\n Divider,\n FormControlLabel,\n Checkbox,\n Typography,\n Button\n} from '@material-ui/core';\n\nconst useStyles = makeStyles(() => ({\n root: {},\n item: {\n display: 'flex',\n flexDirection: 'column'\n }\n}));\n\nconst Notifications = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n return (\n \n \n \n );\n};\n\nNotifications.propTypes = {\n className: PropTypes.string\n};\n\nexport default Notifications;\n","import React, { useState } from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Card,\n CardHeader,\n CardContent,\n CardActions,\n Divider,\n Button,\n TextField\n} from '@material-ui/core';\n\nconst useStyles = makeStyles(() => ({\n root: {}\n}));\n\nconst Password = props => {\n const { className, ...rest } = props;\n\n const classes = useStyles();\n\n const [values, setValues] = useState({\n password: '',\n confirm: ''\n });\n\n const handleChange = event => {\n setValues({\n ...values,\n [event.target.name]: event.target.value\n });\n };\n\n return (\n \n \n \n );\n};\n\nPassword.propTypes = {\n className: PropTypes.string\n};\n\nexport default Password;\n","import React from 'react';\nimport { makeStyles } from '@material-ui/styles';\nimport { Grid } from '@material-ui/core';\n\nimport { Notifications, Password } from './components';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(4)\n }\n}));\n\nconst Settings = () => {\n const classes = useStyles();\n\n return (\n \n
\n \n \n \n \n \n \n \n
\n );\n};\n\nexport default Settings;\n","import React from 'react';\nimport { makeStyles } from '@material-ui/core';\nimport SvgIcon from '@material-ui/core/SvgIcon';\n\nconst useStyles = makeStyles((theme) => ({\n icon: {\n color: 'white',\n width: 13,\n marginRight: theme.spacing(1)\n },\n path: {\n // fill:'#eb3c00',\n fillOpacity:1,\n strokeWidth:.31999999\n }\n}));\n\nconst Office365Logo = (props) => {\n const classes = useStyles();\n\n return (\n \n \n \n );\n}\n\nexport default Office365Logo;\n","import React, { useContext, useEffect, useState } from 'react';\nimport { withRouter } from 'react-router-dom';\nimport PropTypes from 'prop-types';\nimport validate from 'validate.js';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Button, Grid, Typography, useTheme\n} from '@material-ui/core';\nimport TextField from '@material-ui/core/TextField';\nimport useAuth from '../../hooks/useAuth';\nimport axios from '../../services/axiosService';\nimport {\n fetchActiveDirectoryGroupsAndSaveToLocalStorage,\n hasAccessToApp\n} from '../../services/microsoftGraphApiService';\nimport AppContext from '../../contexts/AppContext';\nimport {\n fetchSidebarAndSaveToLocalStorage,\n} from '../../services/sidebarLinkService';\nimport LoadingScreen from '../../components/LoadingScreen';\nimport Office365Logo from '../../icons/Office365';\n\nconst schema = {\n email: {\n presence: { allowEmpty: false, message: 'is required' },\n email: true,\n length: {\n maximum: 64\n }\n },\n password: {\n presence: { allowEmpty: false, message: 'is required' },\n length: {\n maximum: 128\n }\n }\n};\n\nconst useStyles = makeStyles((theme) => ({\n root: {\n backgroundColor: theme.palette.background.default,\n height: '100%'\n },\n grid: {\n height: '100%'\n },\n quoteContainer: {\n [theme.breakpoints.down('md')]: {\n display: 'none'\n }\n },\n quote: {\n backgroundColor: theme.palette.neutral,\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n backgroundImage: 'url(/images/login_bg.jpg)',\n backgroundSize: 'cover',\n backgroundRepeat: 'no-repeat',\n backgroundPosition: 'center'\n },\n quoteInner: {\n textAlign: 'center',\n flexBasis: '600px'\n },\n quoteText: {\n color: theme.palette.white,\n fontWeight: 300\n },\n name: {\n marginTop: theme.spacing(3),\n color: theme.palette.white\n },\n bio: {\n color: theme.palette.white\n },\n contentContainer: {},\n content: {\n height: '100%',\n display: 'flex',\n flexDirection: 'column'\n },\n contentHeader: {\n display: 'flex',\n alignItems: 'center',\n paddingTop: theme.spacing(5),\n paddingBototm: theme.spacing(2),\n paddingLeft: theme.spacing(2),\n paddingRight: theme.spacing(2)\n },\n logoImage: {\n marginLeft: theme.spacing(4)\n },\n contentBody: {\n flexGrow: 1,\n display: 'flex',\n alignItems: 'center',\n [theme.breakpoints.down('md')]: {\n justifyContent: 'center'\n }\n },\n form: {\n paddingLeft: 100,\n paddingRight: 100,\n paddingBottom: 125,\n flexBasis: 700,\n [theme.breakpoints.down('sm')]: {\n paddingLeft: theme.spacing(2),\n paddingRight: theme.spacing(2)\n }\n },\n title: {\n marginTop: theme.spacing(3)\n },\n socialButtons: {\n marginTop: theme.spacing(3)\n },\n socialIcon: {\n marginRight: theme.spacing(1)\n },\n sugestion: {\n marginTop: theme.spacing(2)\n },\n textField: {\n marginTop: theme.spacing(2)\n },\n signInButton: {\n margin: theme.spacing(2, 0)\n }\n}));\n\nconst SignIn = (props) => {\n const { history } = props;\n\n const theme = useTheme();\n const classes = useStyles();\n const {\n authResponse,\n loginWithMicrosoft,\n displayError,\n loginError\n } = useAuth();\n\n const { setAppData } = useContext(AppContext);\n const [isLoading, setIsLoading] = useState(false);\n const [formState, setFormState] = useState({\n isValid: false,\n values: {},\n touched: {},\n errors: {}\n });\n\n const hasError = (field) => !!(formState.touched[field] && formState.errors[field]);\n\n const handleChange = (event) => {\n event.persist();\n };\n\n useEffect(() => {\n const errors = validate(formState.values, schema);\n\n setFormState((formState) => ({\n ...formState,\n isValid: !errors,\n errors: errors || {}\n }));\n }, [formState.values]);\n\n const handleSignIn = (event) => {\n event.preventDefault();\n };\n\n useEffect(() => {\n // redirect from login with Microsoft comes with a hash in the url\n if (window.location.hash) {\n setIsLoading(true);\n }\n }, []);\n\n useEffect(() => {\n const login = async () => {\n try {\n setIsLoading(true);\n\n localStorage.setItem('id_token', '1');\n localStorage.setItem('msData', JSON.stringify(authResponse));\n const { data: grpData } = await axios.get('/me/memberOf');\n\n localStorage.setItem(\n 'user_active_directory_groups',\n JSON.stringify(grpData.value.map(({ id, displayName }) => ({ id, displayName })))\n );\n\n if (!hasAccessToApp()) {\n throw new Error('You are not authorized to access this application');\n }\n\n const sidebar_links = await fetchSidebarAndSaveToLocalStorage();\n setAppData((prevAppData) => ({ ...prevAppData, sidebar_links }));\n\n const active_directory_groups = await fetchActiveDirectoryGroupsAndSaveToLocalStorage();\n setAppData((prevAppData) => ({ ...prevAppData, active_directory_groups }));\n\n history.push('/');\n } catch (error) {\n displayError(error);\n }\n\n setIsLoading(false);\n };\n\n if (authResponse) {\n login();\n }\n }, [authResponse]);\n\n if (isLoading) return ;\n\n return (\n \n
\n \n \n
\n
\n It is a capital mistake to theorize before one has data.\n \n
\n \n (Sherlock Holmes)\n \n \n NSD Insight Qore\n \n
\n
\n
\n \n \n \n \n \n
\n );\n};\n\nSignIn.propTypes = {\n history: PropTypes.object\n};\n\nexport default withRouter(SignIn);\n","import React, { useState, useEffect } from 'react';\nimport { Link as RouterLink, withRouter } from 'react-router-dom';\nimport PropTypes from 'prop-types';\nimport validate from 'validate.js';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Grid,\n Button,\n IconButton,\n TextField,\n Link,\n FormHelperText,\n Checkbox,\n Typography\n} from '@material-ui/core';\nimport ArrowBackIcon from '@material-ui/icons/ArrowBack';\n\nconst schema = {\n firstName: {\n presence: { allowEmpty: false, message: 'is required' },\n length: {\n maximum: 32\n }\n },\n lastName: {\n presence: { allowEmpty: false, message: 'is required' },\n length: {\n maximum: 32\n }\n },\n email: {\n presence: { allowEmpty: false, message: 'is required' },\n email: true,\n length: {\n maximum: 64\n }\n },\n password: {\n presence: { allowEmpty: false, message: 'is required' },\n length: {\n maximum: 128\n }\n },\n policy: {\n presence: { allowEmpty: false, message: 'is required' },\n checked: true\n }\n};\n\nconst useStyles = makeStyles(theme => ({\n root: {\n backgroundColor: theme.palette.background.default,\n height: '100%'\n },\n grid: {\n height: '100%'\n },\n quoteContainer: {\n [theme.breakpoints.down('md')]: {\n display: 'none'\n }\n },\n quote: {\n backgroundColor: theme.palette.neutral,\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n backgroundImage: 'url(/images/auth.jpg)',\n backgroundSize: 'cover',\n backgroundRepeat: 'no-repeat',\n backgroundPosition: 'center'\n },\n quoteInner: {\n textAlign: 'center',\n flexBasis: '600px'\n },\n quoteText: {\n color: theme.palette.white,\n fontWeight: 300\n },\n name: {\n marginTop: theme.spacing(3),\n color: theme.palette.white\n },\n bio: {\n color: theme.palette.white\n },\n contentContainer: {},\n content: {\n height: '100%',\n display: 'flex',\n flexDirection: 'column'\n },\n contentHeader: {\n display: 'flex',\n alignItems: 'center',\n paddingTop: theme.spacing(5),\n paddingBototm: theme.spacing(2),\n paddingLeft: theme.spacing(2),\n paddingRight: theme.spacing(2)\n },\n logoImage: {\n marginLeft: theme.spacing(4)\n },\n contentBody: {\n flexGrow: 1,\n display: 'flex',\n alignItems: 'center',\n [theme.breakpoints.down('md')]: {\n justifyContent: 'center'\n }\n },\n form: {\n paddingLeft: 100,\n paddingRight: 100,\n paddingBottom: 125,\n flexBasis: 700,\n [theme.breakpoints.down('sm')]: {\n paddingLeft: theme.spacing(2),\n paddingRight: theme.spacing(2)\n }\n },\n title: {\n marginTop: theme.spacing(3)\n },\n textField: {\n marginTop: theme.spacing(2)\n },\n policy: {\n marginTop: theme.spacing(1),\n display: 'flex',\n alignItems: 'center'\n },\n policyCheckbox: {\n marginLeft: '-14px'\n },\n signUpButton: {\n margin: theme.spacing(2, 0)\n }\n}));\n\nconst SignUp = props => {\n const { history } = props;\n\n const classes = useStyles();\n\n const [formState, setFormState] = useState({\n isValid: false,\n values: {},\n touched: {},\n errors: {}\n });\n\n useEffect(() => {\n const errors = validate(formState.values, schema);\n\n setFormState(formState => ({\n ...formState,\n isValid: errors ? false : true,\n errors: errors || {}\n }));\n }, [formState.values]);\n\n const handleChange = event => {\n event.persist();\n\n setFormState(formState => ({\n ...formState,\n values: {\n ...formState.values,\n [event.target.name]:\n event.target.type === 'checkbox'\n ? event.target.checked\n : event.target.value\n },\n touched: {\n ...formState.touched,\n [event.target.name]: true\n }\n }));\n };\n\n const handleBack = () => {\n history.goBack();\n };\n\n const handleSignUp = event => {\n event.preventDefault();\n history.push('/');\n };\n\n const hasError = field =>\n formState.touched[field] && formState.errors[field] ? true : false;\n\n return (\n \n
\n \n \n
\n
\n Hella narwhal Cosby sweater McSweeney's, salvia kitsch before\n they sold out High Life.\n \n
\n \n Takamaru Ayako\n \n \n Manager at inVision\n \n
\n
\n
\n \n \n \n \n \n
\n );\n};\n\nSignUp.propTypes = {\n history: PropTypes.object\n};\n\nexport default withRouter(SignUp);\n","import React from 'react';\nimport { makeStyles } from '@material-ui/styles';\nimport { Grid, Typography } from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(4)\n },\n content: {\n paddingTop: 10,\n textAlign: 'center'\n },\n image: {\n marginTop: 50,\n display: 'inline-block',\n maxWidth: '100%',\n width: 350\n },\n topImage: {\n marginTop: 50,\n display: 'inline-block',\n maxWidth: '100%',\n width: 150\n }\n}));\n\nconst WorkingOnIt = () => {\n const classes = useStyles();\n\n return (\n \n
\n \n \n
\n
\n 204: This page isn't finished\n \n
\n We are working on it! Hang in there we will be done soon!!\n \n
\n
\n \n \n
\n );\n};\n\nexport default WorkingOnIt;\n","import React, { Fragment } from 'react';\nimport { makeStyles } from '@material-ui/styles';\nimport { Grid, Typography as MuiTypography } from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(4)\n }\n}));\n\nconst variants = {\n h1: 'Nisi euismod ante senectus consequat phasellus ut',\n h2: 'Nisi euismod ante senectus consequat phasellus ut',\n h3: 'Nisi euismod ante senectus consequat phasellus ut',\n h4: 'Nisi euismod ante senectus consequat phasellus ut',\n h5: 'Nisi euismod ante senectus consequat phasellus ut',\n h6: 'Nisi euismod ante senectus consequat phasellus ut',\n subtitle1: 'Leo varius justo aptent arcu urna felis pede nisl',\n subtitle2: 'Leo varius justo aptent arcu urna felis pede nisl',\n body1:\n 'Justo proin curabitur dictumst semper auctor, consequat tempor, nostra aenean neque turpis nunc. Leo. Sapien aliquet facilisi turpis, elit facilisi praesent porta metus leo. Dignissim amet dis nec ac integer inceptos erat dis Turpis sodales ad torquent. Dolor, erat convallis.Laoreet velit a fames commodo tristique hendrerit sociosqu rhoncus vel sapien penatibus facilisis faucibus ad. Mus purus vehicula imperdiet tempor lectus, feugiat Sapien erat viverra netus potenti mattis purus turpis. Interdum curabitur potenti tristique. Porta velit dignissim tristique ultrices primis.',\n body2:\n 'Justo proin curabitur dictumst semper auctor, consequat tempor, nostra aenean neque turpis nunc. Leo. Sapien aliquet facilisi turpis, elit facilisi praesent porta metus leo. Dignissim amet dis nec ac integer inceptos erat dis Turpis sodales ad torquent. Dolor, erat convallis.',\n caption: 'Accumsan leo pretium conubia ullamcorper.',\n overline: 'Accumsan leo pretium conubia ullamcorper.',\n button: 'Vivamus ultrices rutrum fames dictumst'\n};\n\nconst Typography = () => {\n const classes = useStyles();\n\n return (\n \n \n {Object.keys(variants).map((key, i) => (\n \n \n {key} \n \n \n {variants[key]} \n \n \n ))}\n \n
\n );\n};\n\nexport default Typography;\n","import React from 'react';\nimport { makeStyles } from '@material-ui/styles';\nimport { Typography, Grid, Hidden } from '@material-ui/core';\n\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(4)\n },\n image: {\n width: '100%'\n // maxHeight: 250\n }\n}));\n\nconst Home = (props) => {\n const classes = useStyles();\n\n return (\n \n );\n};\n\nexport default Home;\n","export default Object.freeze(\n {\n \"CREATE\": 0,\n \"UPDATE\": 1,\n \"DELETE\": 2\n }\n);\n","import React, { useContext, useEffect } from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '@material-ui/core/Button';\nimport Operation from './Operation';\nimport { makeStyles } from '@material-ui/styles';\nimport AppContext from '../../contexts/AppContext';\nimport { green, red } from '@material-ui/core/colors';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport clsx from 'clsx';\nimport Alert from '@material-ui/lab/Alert';\n\nconst useStyles = makeStyles((theme) => ({\n formControl: {\n width: 260\n },\n noLabel: {\n marginTop: theme.spacing(3),\n },\n root: {\n flexGrow: 1,\n },\n paper: {\n padding: theme.spacing(2),\n textAlign: 'center',\n color: theme.palette.text.secondary,\n },\n buttonProgress: {\n position: 'absolute',\n top: '50%',\n left: '50%',\n marginTop: -12,\n marginLeft: -12,\n },\n green: {\n color: green[500],\n },\n red: {\n color: red[500],\n },\n wrapper: {\n margin: theme.spacing(1),\n position: 'relative',\n },\n buttonSuccess: {\n backgroundColor: green[500],\n '&:hover': {\n backgroundColor: green[700],\n },\n },\n buttonError: {\n backgroundColor: red[500],\n '&:hover': {\n backgroundColor: red[700],\n },\n },\n alert: {\n marginTop: 8,\n },\n hide: {\n display: 'none'\n }\n}));\n\nconst CrudDialog = ({ settings, crudDialog, onClose }) => {\n const {\n create: {\n onSubmit: createOnSubmit,\n extraNonFormDataToSubmit,\n dialogContent: createDialogContent,\n dialogTitle: createDialogTitle,\n dialogInstructions: createDialogInstructions\n },\n update: { onSubmit: updateOnSubmit },\n delete: {\n onSubmit: deleteOnSubmit,\n dialogTitle: deleteDialogTitle,\n dialogInstructions: deleteDialogInstructions\n },\n fetchDataAfterSubmit,\n appDataToRefreshAfterSubmit\n } = settings;\n\n const { setAppData } = useContext(AppContext);\n const { open, operation, selected_item } = crudDialog;\n const [formData, setFormData] = React.useState({});\n const [loading, setLoading] = React.useState(false);\n const [alertMessage, setAlertMessage] = React.useState(null);\n\n useEffect(() => {\n if (open === true && operation === Operation.UPDATE) {\n setFormData({ ...formData, ...selected_item });\n } else if (open === false) {\n setFormData({});\n }\n }, [open, selected_item, operation]);\n\n const updateAppDataContext = async () => {\n let dataAfterSubmit = await fetchDataAfterSubmit();\n setAppData(prevAppData => {\n return { ...prevAppData, [appDataToRefreshAfterSubmit]: dataAfterSubmit };\n });\n }\n\n const handleSave = async () => {\n setLoading(true);\n const dataToSubmit = { ...formData, ...extraNonFormDataToSubmit };\n const { id, ...dataToSubmitWithoutId } = dataToSubmit;\n\n try {\n operation === Operation.CREATE\n ? await createOnSubmit(dataToSubmitWithoutId)\n : await updateOnSubmit(dataToSubmit);\n await updateAppDataContext();\n handleClose();\n } catch (e) {\n const {response: {data: {error}}} = e;\n setAlertMessage(error);\n }\n\n setLoading(false);\n };\n\n const handleDeleteConfirm = async () => {\n setLoading(true);\n const { id } = selected_item;\n\n try {\n await deleteOnSubmit({ id });\n await updateAppDataContext();\n handleClose();\n } catch (e) {\n const {response: {data: {error}}} = e;\n setAlertMessage(error);\n }\n\n setLoading(false);\n };\n\n const handleClose = () => {\n setAlertMessage(null);\n if (onClose) onClose();\n };\n\n const classes = useStyles();\n\n // update field with either what the user is typing or newVal\n const handleChange = (field, newVal) => {\n if (newVal !== undefined) {\n setFormData({ ...formData, [field]: newVal });\n } else {\n return (e) => {\n setFormData({ ...formData, [field]: e.target.value });\n }\n }\n };\n\n let dialog = {};\n switch(operation) {\n case Operation.CREATE:\n case Operation.UPDATE:\n dialog = {\n dialog_title: createDialogTitle(operation),\n dialog_instructions: createDialogInstructions(operation),\n dialog_content: createDialogContent(formData, handleChange, classes),\n dialog_actions: (\n <>\n \n Cancel\n \n \n \n Save\n \n {loading && \n }\n
\n >\n )\n };\n break;\n case Operation.DELETE:\n dialog = {\n dialog_title: deleteDialogTitle(),\n dialog_instructions: deleteDialogInstructions(operation, selected_item),\n dialog_actions: (\n <>\n \n Don't Delete\n \n \n \n Delete\n \n {loading && }\n
\n >\n )\n };\n break;\n default:\n break;\n }\n\n let {\n dialog_title,\n dialog_instructions,\n dialog_content,\n dialog_actions\n } = dialog;\n return (\n open === true\n ? \n \n \n { dialog_title }\n \n \n \n { dialog_instructions } \n { dialog_content }\n \n { dialog_actions } \n \n
\n : null\n );\n}\n\nfunction CrudAlert({message, setMessage}) {\n const useStyles = makeStyles((theme) => ({\n alert: {\n marginTop: 8,\n },\n hide: {\n display: 'none'\n }\n }));\n\n const classes = useStyles();\n\n return (\n {setMessage(null)}}\n severity=\"error\">\n { message }\n \n );\n}\n\nexport default CrudDialog;\n","import React, { cloneElement } from 'react';\nimport { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';\nimport { TableBody } from '@material-ui/core';\nimport { colors } from '@material-ui/core';\n\nconst DraggableTable = ({ tableData, tableRow, draggableSettings }) => {\n const getItemStyle = (isDragging, draggableStyle) => ({\n userSelect: \"none\",\n ...draggableStyle,\n ...(isDragging && { display: 'table', background: colors.grey[400] }),\n });\n\n const getListStyle = isDraggingOver => ({\n });\n\n const { onDragEnd } = draggableSettings;\n\n return (\n \n \n {(provided, snapshot) => (\n \n {tableData.map((row, index) => (\n \n {(provided, snapshot) => {\n const tRow = tableRow(row);\n return cloneElement(tRow, {\n ref: provided.innerRef,\n ...provided.draggableProps,\n ...provided.dragHandleProps,\n style: getItemStyle(\n snapshot.isDragging,\n provided.draggableProps.style\n )\n });\n }}\n \n ))}\n {provided.placeholder}\n \n )}\n \n \n );\n};\n\nDraggableTable.propTypes = {\n};\n\nexport default DraggableTable;\n","import React, { useContext, useEffect, useState } from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport PerfectScrollbar from 'react-perfect-scrollbar';\nimport { makeStyles } from '@material-ui/styles';\nimport {\n Card,\n CardActions,\n CardContent,\n Checkbox,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TablePagination\n} from '@material-ui/core';\nimport DraggableTable from './DraggableTable';\n\nconst useStyles = makeStyles(theme => ({\n root: {},\n content: {\n padding: 0\n },\n inner: {\n minWidth: 1050\n },\n nameContainer: {\n display: 'flex',\n alignItems: 'center'\n },\n avatar: {\n marginRight: theme.spacing(2)\n },\n actions: {\n justifyContent: 'flex-end'\n },\n tableRow: {\n cursor: 'pointer'\n },\n checkboxCell: {\n width:52\n }\n}));\n\nconst DataTable = ({ className, tableSettings, draggable, ...rest }) => {\n const classes = useStyles();\n const {\n tableHead,\n tableBody,\n onRowClick,\n tableData,\n draggableSettings\n } = tableSettings;\n\n const [selectedRows, setSelectedRows] = useState([]);\n const [rowsPerPage, setRowsPerPage] = useState(10);\n const [page, setPage] = useState(0);\n\n useEffect(() => {\n setPage(0);\n }, [tableSettings]);\n\n const applyPagination = (data, page, limit) => {\n return data.slice(page * limit, page * limit + limit);\n };\n\n const handleSelectAll = event => {\n\n let selectedRows;\n\n if (event.target.checked) {\n selectedRows = tableData.map(row => row.id);\n } else {\n selectedRows = [];\n }\n\n setSelectedRows(selectedRows);\n };\n\n const handleSelectOne = (event, id) => {\n const selectedIndex = selectedRows.indexOf(id);\n let newSelectedRows = [];\n\n if (selectedIndex === -1) {\n newSelectedRows = newSelectedRows.concat(selectedRows, id);\n } else if (selectedIndex === 0) {\n newSelectedRows = newSelectedRows.concat(selectedRows.slice(1));\n } else if (selectedIndex === selectedRows.length - 1) {\n newSelectedRows = newSelectedRows.concat(selectedRows.slice(0, -1));\n } else if (selectedIndex > 0) {\n newSelectedRows = newSelectedRows.concat(\n selectedRows.slice(0, selectedIndex),\n selectedRows.slice(selectedIndex + 1)\n );\n }\n\n setSelectedRows(newSelectedRows);\n };\n\n const handlePageChange = (event, page) => {\n setPage(page);\n };\n\n const handleRowsPerPageChange = event => {\n setRowsPerPage(event.target.value);\n };\n\n const handleRowClick = (event, row) => {\n if (onRowClick) onRowClick(event, row);\n };\n\n const handleClickCheckboxCell = (event) => {\n event.stopPropagation();\n };\n\n let currentTableData = applyPagination(tableData, page, rowsPerPage)\n .slice(0, rowsPerPage);\n\n const tableRow = (row) => (\n handleRowClick(event, row)}\n >\n \n handleSelectOne(event, row.id)}\n value=\"true\"\n />\n \n {\n tableBody(row).map((tableCell, idx) => (\n \n { tableCell.content ?? tableCell }\n \n ))\n }\n \n );\n\n return (\n \n \n \n \n
\n \n \n \n 0 &&\n selectedRows.length < currentTableData.length\n }\n onChange={handleSelectAll}\n />\n \n {\n tableHead().map((head) => (\n { head.title ?? head }\n \n ))\n }\n \n \n {\n draggableSettings ? (\n \n ) : (\n \n { currentTableData.map((row) => tableRow(row)) }\n \n )\n }\n
\n
\n \n \n \n \n \n \n );\n};\n\nDataTable.propTypes = {\n className: PropTypes.string,\n tableSettings: PropTypes.object.isRequired,\n draggable: PropTypes.bool\n};\n\nDataTable.defaultProps = {\n draggable: true\n}\n\nexport default DataTable;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { makeStyles } from '@material-ui/styles';\nimport NavigateNextIcon from '@material-ui/icons/NavigateNext';\nimport Grid from '@material-ui/core/Grid';\nimport Breadcrumbs from '@material-ui/core/Breadcrumbs';\nimport Typography from '@material-ui/core/Typography';\nimport Link from '@material-ui/core/Link';\nimport { Link as RouterLink } from 'react-router-dom';\nimport Button from '@material-ui/core/Button';\n\nconst useStyles = makeStyles(theme => ({\n root: {},\n row: {\n height: '42px',\n display: 'flex',\n alignItems: 'center',\n marginTop: theme.spacing(1)\n },\n spacer: {\n flexGrow: 1\n },\n importButton: {\n marginRight: theme.spacing(1)\n },\n exportButton: {\n marginRight: theme.spacing(1)\n },\n searchInput: {\n marginRight: theme.spacing(1)\n }\n}));\n\nconst CrudTableToolbar = ({\n className,\n toolbarSettings,\n onClickCreate,\n ...rest\n}) => {\n const classes = useStyles();\n const { breadcrumbs, buttonText, title } = toolbarSettings;\n\n const handleAddClick = () => {\n if (onClickCreate) onClickCreate();\n };\n\n return (\n \n \n }\n aria-label=\"breadcrumb\"\n >\n {\n breadcrumbs.map((breadcrumb) => (\n breadcrumb.href\n ? (\n \n { breadcrumb.title }\n \n )\n : (\n \n { breadcrumb.title }\n \n )\n ))\n }\n \n \n { title }\n \n \n \n \n { buttonText }\n \n \n \n );\n};\n\nCrudTableToolbar.propTypes = {\n className: PropTypes.string\n};\n\nexport default CrudTableToolbar;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport DataTable from '../DataTable';\nimport { CrudDialog } from '../CrudDialog';\nimport CrudTableToolbar from './CrudTableToolbar';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(3)\n },\n content: {\n marginTop: theme.spacing(2)\n }\n}));\n\nconst CrudTable = ({\n crudDialog,\n crudDialogSettings,\n onClickCloseCrudDialog,\n onClickCreate,\n tableSettings,\n toolbarSettings\n}) => {\n const classes = useStyles();\n\n const handleClickCreate = () => {\n if (onClickCreate) onClickCreate();\n }\n\n const handleClickCloseCrudDialog = () => {\n if (onClickCloseCrudDialog) onClickCloseCrudDialog();\n }\n\n return (\n \n );\n};\n\nCrudTable.propTypes = {\n className: PropTypes.string,\n toolbarSettings: PropTypes.object,\n tableSettings: PropTypes.object\n};\n\nexport default CrudTable;\n","import React, { useContext, useState } from 'react';\nimport { makeStyles } from '@material-ui/styles';\nimport { Operation } from '../../components/CrudDialog';\nimport {\n addSidebarLink, deleteSidebarLink, fetchSidebarAndSaveToLocalStorage, getParentLinkId, getSidebar,\n getSidebarMainLinksWithIconComponents, getSidebarSubLinksByParentHref, updateSidebarLink\n} from '../../services/sidebarLinkService';\nimport Grid from '@material-ui/core/Grid';\nimport TextField from '@material-ui/core/TextField';\nimport FormControl from '@material-ui/core/FormControl';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport Select from '@material-ui/core/Select';\nimport Input from '@material-ui/core/Input';\nimport { getMaterialIcons, DynamicMaterialIcon } from '../../services/iconService';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport Box from '@material-ui/core/Box';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport { getActiveDirectoryGroups } from '../../services/microsoftGraphApiService';\nimport { Delete as DeleteIcon, Edit as EditIcon } from '@material-ui/icons';\nimport { Typography } from '@material-ui/core';\nimport Chip from '@material-ui/core/Chip';\nimport IconButton from '@material-ui/core/IconButton';\nimport AppContext from '../../contexts/AppContext';\nimport Link from '@material-ui/core/Link';\nimport CrudTable from '../../components/CrudTable';\nimport axios from '../../services/axiosService';\nimport { useSnackbar } from 'notistack';\n\nconst useStyles = makeStyles(theme => ({\n permission: {\n margin: theme.spacing(1)\n },\n tableauLink: {\n wordBreak: 'break-all'\n }\n}));\n\nconst Sidebar = ({ match, location, history }) => {\n const classes = useStyles();\n const isSidebarChildrenPage = !!match.params.page;\n\n const { enqueueSnackbar } = useSnackbar();\n const { appData, setAppData } = useContext(AppContext);\n const { sidebar_links } = appData;\n\n let crudDialogSettings = {\n create: {\n onSubmit: addSidebarLink,\n dialogContent: (formData, handleChange, classes) => {\n const activeDirectoryGroups = getActiveDirectoryGroups();\n return (\n \n \n \n \n \n \n \n Icon \n }\n renderValue={(selected) => selected}\n MenuProps={{PaperProps: {\n style: {\n width: 250,\n },\n }}}\n >\n {getMaterialIcons().map((name) => (\n \n \n \n \n \n \n \n \n \n ))}\n \n \n \n \n \n View Permission \n }\n renderValue={\n selected => selected.map(id =>\n activeDirectoryGroups\n .find(group => group.id === id)\n ?.displayName\n ).join(', ')\n }\n MenuProps={{PaperProps: {\n style: {\n width: 250,\n },\n }}}\n >\n {activeDirectoryGroups.map(({id, displayName}) => (\n \n -1\n }\n />\n \n \n \n \n ))}\n \n \n \n \n
\n );\n },\n dialogTitle: (operation) => {\n return <>{ operation === Operation.CREATE ? 'Add' : 'Edit' } Link>;\n },\n dialogInstructions: (operation) => {\n return <>{ operation === Operation.CREATE ? 'Add' : 'Edit' } the details below to update the sidebar navigation>;\n }\n },\n update: {\n onSubmit: updateSidebarLink,\n },\n delete: {\n onSubmit: deleteSidebarLink,\n dialogTitle: () => {\n return <>Are you sure?>;\n },\n dialogInstructions: (operation, selected_item) => {\n return <>This will permanently delete the\n {selected_item.title} \n link.>;\n }\n },\n fetchDataAfterSubmit: fetchSidebarAndSaveToLocalStorage,\n appDataToRefreshAfterSubmit: 'sidebar_links'\n };\n\n if (isSidebarChildrenPage) {\n crudDialogSettings = {\n ...crudDialogSettings,\n ...{\n create: {\n ...(crudDialogSettings.create),\n extraNonFormDataToSubmit: {\n parent_id: getParentLinkId(match.params.page, sidebar_links)\n },\n dialogContent: (formData, handleChange, classes) => {\n return (\n \n \n \n \n \n \n \n Icon \n }\n renderValue={(selected) => selected}\n MenuProps={{PaperProps: {\n style: {\n width: 250,\n },\n }}}\n >\n {getMaterialIcons().map((name) => (\n \n \n \n \n \n \n \n \n \n ))}\n \n \n \n \n {\n // if user enters full url, remove the beginning\n let match = formData.tableau_url\n && formData\n .tableau_url\n .match(/^https?:(?:.*)views\\/(.*)/i);\n if (match !== null && typeof match !== 'undefined') {\n handleChange('tableau_url', match[1]);\n }\n }}\n fullWidth\n />\n \n \n
\n );\n }\n }\n }\n }\n }\n\n const links = isSidebarChildrenPage\n ? getSidebarSubLinksByParentHref(match.params.page, sidebar_links)\n : getSidebarMainLinksWithIconComponents(sidebar_links);\n\n // table settings\n const { active_directory_groups } = appData;\n\n const [crudDialog, setCrudDialog] = useState(\n { open: false, operation: null, link: null }\n );\n\n const handleClickCreate = () => {\n setCrudDialog({\n open: true,\n operation: Operation.CREATE,\n selected_item: null\n });\n };\n\n const handleCloseCrudDialog = () => {\n setCrudDialog({\n open: false,\n operation: null,\n selected_item: null\n });\n };\n\n const handleEditClick = (event, link) => {\n event.stopPropagation();\n setCrudDialog({\n open: true,\n operation: Operation.UPDATE,\n selected_item: link\n });\n };\n const handleDeleteClick = (event, link) => {\n event.stopPropagation();\n setCrudDialog({\n open: true,\n operation: Operation.DELETE,\n selected_item: link\n });\n };\n\n const tableBodyTitle = (link) => (\n \n {link.name} \n
\n );\n\n const tableBodyIcon = (link) => (\n \n );\n\n const tableActions = (link) => (\n <>\n handleEditClick(event, link)}>\n \n \n handleDeleteClick(event, link)}>\n \n \n >\n );\n\n let tableCellWidths = [\n '10%',\n '10%',\n '60%'\n ];\n\n const draggableSettings = {\n onDragEnd: (tableData) => async (result) => {\n // dropped outside the list\n if (!result.destination) {\n return;\n }\n\n const reorder = (list, startId, endId) => {\n const results = Array.from(list);\n const startIndex = results.findIndex((result) => result.id === tableData[startId].id);\n const endIndex = results.findIndex((result) => result.id === tableData[endId].id);\n const [removed] = results.splice(startIndex, 1);\n results.splice(endIndex, 0, removed);\n\n return results;\n };\n\n const sidebar_links_before_reorder = appData.sidebar_links;\n const sidebar_links = reorder(\n sidebar_links_before_reorder,\n result.source.index,\n result.destination.index\n );\n\n const sortOrders = sidebar_links\n .map(({id}, order_id) => ({ id, order_id }));\n\n setAppData(prevAppData => {\n return { ...prevAppData, sidebar_links };\n });\n\n try {\n await axios.patch(\n 'SidebarLink',\n { sortOrders }\n );\n\n localStorage.setItem('sidebar_links', JSON.stringify(sidebar_links));\n } catch (error) {\n // revert back to state before reorder on save error\n setAppData(prevAppData => {\n return { ...prevAppData, sidebar_links: sidebar_links_before_reorder };\n });\n\n enqueueSnackbar(\n \"Change wasn't saved\",\n { variant: 'error' }\n );\n }\n }\n };\n\n let tableSettings = {\n tableData: links,\n onRowClick: (event, link) => {\n history.push(`${location.pathname}/${link.href}`);\n },\n tableHead: () => {\n const tHead = [\n 'Name',\n 'Icon',\n 'View Permission',\n 'Actions'\n ];\n return tHead.map((entry, ind) => (\n {\n title: entry,\n ...(tableCellWidths[ind] && { width: tableCellWidths[ind] })\n }\n ))\n },\n tableBody: (link) => {\n const tBody = [\n tableBodyTitle(link),\n tableBodyIcon(link),\n link.view_permission.map(permission_id => {\n let display_name = null;\n if (active_directory_groups) {\n let group = active_directory_groups\n .find(group => group.id === permission_id);\n if (group) display_name = group.displayName;\n }\n return ;\n }),\n tableActions(link)\n ];\n return tBody.map((entry, ind) => (\n {\n content: entry,\n ...(tableCellWidths[ind] && { width: tableCellWidths[ind] })\n }\n ))\n },\n draggableSettings\n };\n\n let toolbarSettings = {\n breadcrumbs: [\n { title: 'Admin', href: '/admin' },\n { title: 'Sidebar Main Categories' }\n ],\n title: 'Sidebar Main Categories',\n buttonText: 'Add Sidebar Main Category'\n };\n\n if (isSidebarChildrenPage) {\n tableCellWidths = [\n '20%',\n '5%',\n '55%'\n ];\n\n tableSettings = {\n tableData: links,\n tableHead: () => {\n const tHead = [\n 'Name',\n 'Icon',\n 'Tableau URL',\n 'Actions',\n ];\n return tHead.map((entry, ind) => (\n {\n title: entry,\n ...(tableCellWidths[ind] && { width: tableCellWidths[ind] })\n }\n ))\n },\n tableBody: (link) => {\n const tBody = [\n tableBodyTitle(link),\n tableBodyIcon(link),\n (\n \n {link.tableau_url}\n \n ),\n tableActions(link)\n ];\n return tBody.map((entry, ind) => (\n {\n content: entry,\n ...(tableCellWidths[ind] && { width: tableCellWidths[ind] })\n }\n ))\n },\n draggableSettings\n };\n\n toolbarSettings = {\n breadcrumbs: [\n { title: 'Admin', href: '/admin' },\n { title: 'Sidebar Main Categories', href: '/admin/sidebar' },\n { title: getSidebar().find((sidebar_link) => sidebar_link.href === match.params.page)?.name }\n ],\n title: 'Tableau Page',\n buttonText: 'Add Tableau Page'\n };\n }\n\n return (\n \n );\n};\n\nexport default Sidebar;\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { makeStyles } from '@material-ui/styles';\nimport TableauReport from 'tableau-react';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(4)\n }\n}));\n\nconst options = {\n height: 'calc(100vh - 150px)',\n width: '100%',\n hideTabs: false\n};\nconst TableauDashboard = props => {\n const { url } = props;\n\n const classes = useStyles();\n\n return (\n \n );\n};\n\nTableauDashboard.propTypes = {\n url: PropTypes.string\n};\n\n\nexport default TableauDashboard;\n","import React, { useContext, useEffect, useState } from 'react';\nimport { makeStyles } from '@material-ui/styles';\nimport TableauDashboard from '../../components/Tableau';\nimport { withRouter } from 'react-router-dom';\nimport AppContext from '../../contexts/AppContext';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n padding: theme.spacing(0)\n }\n}));\n\n\nconst StandardTableauDashboard = (props) => {\n const { match } = props;\n const classes = useStyles();\n const [url, setUrl] = useState('');\n const { appData } = useContext(AppContext);\n const { sidebar_links } = appData;\n\n useEffect(() => {\n const sidebar_link = sidebar_links.find(page =>\n page.href === match.params.page\n );\n const { tableau_url } = sidebar_link;\n\n setUrl(tableau_url);\n }, [match.params.page, sidebar_links]);\n\n return (\n \n );\n};\n\nexport default withRouter(StandardTableauDashboard);\n","import { Redirect, Switch, useRouteMatch } from 'react-router-dom';\nimport { RouteWithLayout } from '../components';\nimport { StandardTableauDashboard as StandardTableauDashboardView, WorkingOnIt as WorkingOnItView } from '../views';\nimport { Main as MainLayout } from '../layouts';\nimport React from 'react';\n\nconst TableauRoutes = ({pages}) => {\n let { path } = useRouteMatch();\n\n return (\n \n \n {pages && (\n page.href).join('|')})`\n }\n />\n )}\n \n \n );\n}\n\nexport default TableauRoutes;\n","import { Redirect, Switch, useRouteMatch } from 'react-router-dom';\nimport React, { useContext } from 'react';\nimport AppContext from '../contexts/AppContext';\nimport { RouteWithLayout } from '../components';\nimport {\n Sidebar as SidebarView,\n} from '../views';\nimport { Main as MainLayout } from '../layouts';\nimport { getSidebarWithChildrenNested } from '../services/sidebarLinkService';\n\nconst AdminSidebarRoutes = () => {\n let { path } = useRouteMatch();\n const { appData } = useContext(AppContext);\n const { sidebar_links } = appData;\n\n return (\n \n \n page.href).join('|')})`\n }\n />\n \n \n );\n}\n\nexport default AdminSidebarRoutes;\n","import { Redirect, Switch, useRouteMatch } from 'react-router-dom';\nimport { RouteWithLayout } from '../components';\nimport { WorkingOnIt as WorkingOnItView } from '../views';\nimport { Main as MainLayout } from '../layouts';\nimport React from 'react';\nimport AdminSidebarRoutes from './AdminSidebarRoutes';\n\nconst AdminRoutes = () => {\n let { path } = useRouteMatch();\n\n return (\n \n \n \n \n \n \n \n );\n}\n\nexport default AdminRoutes;\n","import { Redirect, Switch, useRouteMatch } from 'react-router-dom';\nimport { RouteWithLayout } from '../components';\nimport {\n Account as AccountView,\n Dashboard as DashboardView,\n ProductList as ProductListView, Settings as SettingsView,\n WorkingOnIt as WorkingOnItView\n} from '../views';\nimport { Main as MainLayout } from '../layouts';\nimport React from 'react';\n\nconst ThemeRoutes = () => {\n let { path } = useRouteMatch();\n\n return (\n \n \n \n \n \n \n \n \n );\n}\n\nexport default ThemeRoutes;\n","import React, { Suspense, useContext } from 'react';\nimport { Redirect, Switch } from 'react-router-dom';\nimport { RouteWithLayout } from './components';\nimport { Main as MainLayout, Minimal as MinimalLayout } from './layouts';\nimport workingOnItPages from './content/workingOnItPages';\nimport {\n NotFound as NotFoundView,\n SignIn as SignInView,\n SignUp as SignUpView,\n WorkingOnIt as WorkingOnItView,\n Home as HomeView,\n} from './views';\nimport AppContext from './contexts/AppContext';\nimport { getSidebarWithChildrenNested } from './services/sidebarLinkService';\nimport TableauRoutes from './routes/TableauRoutes';\nimport AdminRoutes from './routes/AdminRoutes';\nimport { isAdmin } from './services/microsoftGraphApiService';\nimport ThemeRoutes from './routes/ThemeRoutes';\n\nconst Routes = () => {\n\n const { appData } = useContext(AppContext);\n const { sidebar_links } = appData;\n\n let routes = [];\n getSidebarWithChildrenNested(sidebar_links).forEach(page => {\n routes.push(\n \n \n \n );\n });\n\n return (\n \n \n \n {isAdmin() && (\n \n \n \n )}\n \n\n {/* dynamic tableau pages from db */}\n { getSidebarWithChildrenNested(sidebar_links).map(page =>\n \n \n \n ) }\n\n {/* working on it pages */}\n { workingOnItPages.map(path =>\n \n ) }\n\n {/* theme pages */}\n \n \n \n\n \n \n \n \n \n \n );\n};\n\nexport default Routes;\n","import React, { useState } from 'react';\nimport { Router } from 'react-router-dom';\nimport { createBrowserHistory } from 'history';\nimport { Chart } from 'react-chartjs-2';\nimport { ThemeProvider } from '@material-ui/styles';\nimport validate from 'validate.js';\nimport { chartjs } from './helpers';\nimport theme from './theme';\nimport 'react-perfect-scrollbar/dist/css/styles.css';\nimport './assets/scss/index.scss';\nimport validators from './common/validators';\nimport Routes from './Routes';\nimport './fontello/css/fontello.css';\nimport AppContext from './contexts/AppContext';\nimport { getSidebar } from './services/sidebarLinkService';\nimport {\n getActiveDirectoryGroups\n} from './services/microsoftGraphApiService';\nimport { SnackbarProvider } from 'notistack';\nimport { AuthProvider } from 'contexts/AuthContext';\n\nconst browserHistory = createBrowserHistory();\n\nChart.helpers.extend(Chart.elements.Rectangle.prototype, {\n draw: chartjs.draw\n});\n\nvalidate.validators = {\n ...validate.validators,\n ...validators\n};\n\nconst App = () => {\n const [appData, setAppData] = useState({\n sidebar_links: getSidebar(),\n active_directory_groups: getActiveDirectoryGroups(),\n });\n\n return (\n \n \n \n \n \n \n \n \n \n \n \n );\n};\n\nexport default App;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './fontello/css/fontello.css';\n\nimport * as serviceWorker from './serviceWorker';\nimport App from './App';\n\nif (window.location.protocol === 'http:' && window.location.hostname !== 'localhost') {\n window.location = `https://${window.location.host}${window.location.pathname}${window.location.search}$`;\n}\nReactDOM.render( , document.getElementById('root'));\n\nserviceWorker.unregister();\n"],"sourceRoot":""}