import React, {useCallback, useContext, useEffect, useState} from 'react'; import {Link, useNavigate} from "react-router-dom"; import {LocaleContext} from "shared/locale"; import { Box, CssBaseline, Divider, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Select, Drawer, styled, MenuItem, Menu, useTheme, } from "@mui/material"; import { Dropdown } from '@mui/base/Dropdown'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; import ProfilePicture from "shared/elements/profile-picture"; import {Dns, Groups, People, QueryStats, Security, Settings, Route, ArrowBack, Translate} from "@mui/icons-material"; import useCurrentPath from "shared/hooks/current-path"; const drawerWidth = 240; const ProfileLink = styled(Link)((props) => ({ "& > div": { width: 30, height: 30, justifySelf: "center", }, color: "inherit", fontWeight: "bold", marginTop: props.theme.spacing(1), display: "grid", gridTemplateColumns: "35px auto", "& > span": { alignSelf: "center", marginLeft: props.theme.spacing(1) }, })); const DrawerHeader = styled('div')(({ theme }) => ({ display: 'flex', alignItems: 'center', justifyContent: "flex-start", padding: theme.spacing(0, 1), ...theme.mixins.toolbar, "& > button": { display: 'flex', marginLeft: "auto", }, "& > img": { width: 30, height: 30, }, "& > span": { marginLeft: theme.spacing(2), fontSize: "1.5em", } })); const openedMixin = (theme) => ({ width: drawerWidth, transition: theme.transitions.create('width', { easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.enteringScreen, }), overflowX: 'hidden', }); const closedMixin = (theme) => ({ transition: theme.transitions.create('width', { easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.leavingScreen, }), overflowX: 'hidden', width: `calc(${theme.spacing(7)} + 1px)`, [theme.breakpoints.up('sm')]: { width: `calc(${theme.spacing(8)} + 1px)`, }, }); const StyledDrawer = styled(Drawer, { shouldForwardProp: (prop) => prop !== 'open' })( ({ theme, open }) => ({ width: drawerWidth, flexShrink: 0, whiteSpace: 'nowrap', boxSizing: 'border-box', ...(open && { ...openedMixin(theme), '& .MuiDrawer-paper': openedMixin(theme), }), ...(!open && { ...closedMixin(theme), '& .MuiDrawer-paper': closedMixin(theme), }), }), ); export default function Sidebar(props) { const api = props.api; const showDialog = props.showDialog; const {translate: L, currentLocale, setLanguageByCode} = useContext(LocaleContext); const [languages, setLanguages] = useState(null); const [fetchLanguages, setFetchLanguages] = useState(true); const [drawerOpen, setDrawerOpen] = useState(window.screen.width >= 1000); const [anchorEl, setAnchorEl] = useState(null); const theme = useTheme(); const navigate = useNavigate(); const currentPath = useCurrentPath(); const onLogout = useCallback(() => { api.logout().then(obj => { if (obj.success) { document.location = "/admin"; } else { showDialog("Error logging out: " + obj.msg, "Error logging out"); } }); }, [api, showDialog]); const onSetLanguage = useCallback((code) => { setLanguageByCode(api, code).then((res) => { if (!res.success) { showDialog(res.msg, L("general.error_language_set")); } }); }, [api, showDialog]); const onFetchLanguages = useCallback((force = false) => { if (force || fetchLanguages) { setFetchLanguages(false); api.getLanguages().then((res) => { if (res.success) { setLanguages(res.languages); } else { setLanguages({}); showDialog(res.msg, L("general.error_language_fetch")); } }); } }, [api, fetchLanguages, showDialog]); useEffect(() => { onFetchLanguages(); }, []); const menuItems = { "dashboard": { "name": "admin.dashboard", "icon": }, "users": { "name": "admin.users", "icon": }, "groups": { "name": "admin.groups", "icon": }, "routes": { "name": "admin.page_routes", "icon": }, "settings": { "name": "admin.settings", "icon": }, "permissions": { "name": "admin.acl", "icon": }, "logs": { "name": "admin.logs", "icon": }, }; const NavbarItem = (props) => {props.icon} let li = []; for (const [id, menuItem] of Object.entries(menuItems)) { const match= /^\/admin\/(.*)$/.exec(currentPath); const active = match?.length >= 2 && match[1] === id; li.push( navigate(`/admin/${id}`)} />); } li.push(} onClick={onLogout}/>); return {drawerOpen && <> {"Logo"} WebBase } setDrawerOpen(!drawerOpen)}> {drawerOpen ? : } {L("account.logged_in_as")}: {drawerOpen && {api.user?.name || L("account.not_logged_in")}} {li} { drawerOpen ? : setAnchorEl(e.currentTarget)} sx={{ minWidth: 0, mr: 'auto', justifyContent: 'center', }}> setAnchorEl(null)} onClick={() => setAnchorEl(null)} transformOrigin={{ horizontal: 'left', vertical: 'bottom' }} anchorOrigin={{ horizontal: 'left', vertical: 'bottom' }}> {Object.values(languages || {}).map(language => onSetLanguage(language.code)}> {language.name} ) } } {props.children} }