more improvements (coloring, themes)
This commit is contained in:
parent
5abbbac2b6
commit
c4037684ba
@ -8,7 +8,7 @@ import {LocaleContext} from "shared/locale";
|
||||
|
||||
// views
|
||||
import View404 from "./views/404";
|
||||
import clsx from "clsx";
|
||||
import {createTheme, CssBaseline, ThemeProvider} from "@mui/material";
|
||||
const Overview = lazy(() => import('./views/overview'));
|
||||
const UserListView = lazy(() => import('./views/user/user-list'));
|
||||
const UserEditView = lazy(() => import('./views/user/user-edit'));
|
||||
@ -58,25 +58,43 @@ export default function AdminDashboard(props) {
|
||||
hideDialog: hideDialog
|
||||
};
|
||||
|
||||
const lightTheme = createTheme({
|
||||
palette: {
|
||||
mode: 'light',
|
||||
},
|
||||
});
|
||||
|
||||
const darkTheme = createTheme({
|
||||
palette: {
|
||||
mode: 'dark',
|
||||
background: {
|
||||
paper: '#343a40',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return <BrowserRouter>
|
||||
<Sidebar {...controlObj}>
|
||||
<Suspense fallback={<div>{L("general.loading")}... </div>}>
|
||||
<Routes>
|
||||
<Route path={"/admin"} element={<Navigate to={"/admin/dashboard"} />}/>
|
||||
<Route path={"/admin/dashboard"} element={<Overview {...controlObj} />}/>
|
||||
<Route path={"/admin/users"} element={<UserListView {...controlObj} />}/>
|
||||
<Route path={"/admin/user/:userId"} element={<UserEditView {...controlObj} />}/>
|
||||
<Route path={"/admin/groups"} element={<GroupListView {...controlObj} />}/>
|
||||
<Route path={"/admin/group/:groupId"} element={<EditGroupView {...controlObj} />}/>
|
||||
<Route path={"/admin/logs"} element={<LogView {...controlObj} />}/>
|
||||
<Route path={"/admin/permissions"} element={<AccessControlList {...controlObj} />}/>
|
||||
<Route path={"/admin/routes"} element={<RouteListView {...controlObj} />}/>
|
||||
<Route path={"/admin/routes/:routeId"} element={<RouteEditView {...controlObj} />}/>
|
||||
<Route path={"/admin/settings"} element={<SettingsView {...controlObj} />}/>
|
||||
<Route path={"/admin/profile"} element={<ProfileView {...controlObj} />}/>
|
||||
<Route path={"*"} element={<View404 />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
<Sidebar theme={darkTheme} {...controlObj}>
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<CssBaseline />
|
||||
<Suspense fallback={<div>{L("general.loading")}... </div>}>
|
||||
<Routes>
|
||||
<Route path={"/admin"} element={<Navigate to={"/admin/dashboard"} />}/>
|
||||
<Route path={"/admin/dashboard"} element={<Overview {...controlObj} />}/>
|
||||
<Route path={"/admin/users"} element={<UserListView {...controlObj} />}/>
|
||||
<Route path={"/admin/user/:userId"} element={<UserEditView {...controlObj} />}/>
|
||||
<Route path={"/admin/groups"} element={<GroupListView {...controlObj} />}/>
|
||||
<Route path={"/admin/group/:groupId"} element={<EditGroupView {...controlObj} />}/>
|
||||
<Route path={"/admin/logs"} element={<LogView {...controlObj} />}/>
|
||||
<Route path={"/admin/permissions"} element={<AccessControlList {...controlObj} />}/>
|
||||
<Route path={"/admin/routes"} element={<RouteListView {...controlObj} />}/>
|
||||
<Route path={"/admin/routes/:routeId"} element={<RouteEditView {...controlObj} />}/>
|
||||
<Route path={"/admin/settings"} element={<SettingsView {...controlObj} />}/>
|
||||
<Route path={"/admin/profile"} element={<ProfileView {...controlObj} />}/>
|
||||
<Route path={"*"} element={<View404 />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</ThemeProvider>
|
||||
<Footer info={info} />
|
||||
</Sidebar>
|
||||
<Dialog {...dialog}/>
|
||||
|
@ -62,37 +62,6 @@ export default function App() {
|
||||
onInit();
|
||||
}, []);
|
||||
|
||||
/*
|
||||
const onTotp2FA = useCallback((code, callback) => {
|
||||
this.setState({ ...this.state, error: "" });
|
||||
return this.api.verifyTotp2FA(code).then((res) => {
|
||||
if (res.success) {
|
||||
this.api.fetchUser().then(() => {
|
||||
this.setState({ ...this.state, user: res });
|
||||
callback(res);
|
||||
})
|
||||
} else {
|
||||
callback(res);
|
||||
}
|
||||
});
|
||||
}, [api]);
|
||||
|
||||
onKey2FA(credentialID, clientDataJson, authData, signature, callback) {
|
||||
this.setState({ ...this.state, error: "" });
|
||||
return this.api.verifyKey2FA(credentialID, clientDataJson, authData, signature).then((res) => {
|
||||
if (res.success) {
|
||||
this.api.fetchUser().then(() => {
|
||||
this.setState({ ...this.state, user: res });
|
||||
callback(res);
|
||||
})
|
||||
} else {
|
||||
callback(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
if (!loaded) {
|
||||
if (error) {
|
||||
return <Alert severity={"error"} title={L("general.error_occurred")}>
|
||||
|
@ -2,10 +2,10 @@ import React, {useCallback, useContext, useEffect, useState} from 'react';
|
||||
import {Link, useNavigate} from "react-router-dom";
|
||||
import {LocaleContext} from "shared/locale";
|
||||
import {
|
||||
Box, CssBaseline, Divider,
|
||||
Box, Divider,
|
||||
IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText,
|
||||
Select, Drawer,
|
||||
styled, MenuItem, Menu, useTheme,
|
||||
styled, MenuItem, Menu, ThemeProvider, CssBaseline,
|
||||
} from "@mui/material";
|
||||
import { Dropdown } from '@mui/base/Dropdown';
|
||||
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
||||
@ -93,14 +93,13 @@ const StyledDrawer = styled(Drawer, { shouldForwardProp: (prop) => prop !== 'ope
|
||||
|
||||
export default function Sidebar(props) {
|
||||
|
||||
const api = props.api;
|
||||
const showDialog = props.showDialog;
|
||||
const {api, showDialog, theme, children, ...other} = props;
|
||||
|
||||
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();
|
||||
|
||||
@ -197,73 +196,75 @@ export default function Sidebar(props) {
|
||||
|
||||
li.push(<NavbarItem key={"logout"} name={"general.logout"} icon={<ArrowBack />} onClick={onLogout}/>);
|
||||
|
||||
return <Box sx={{ display: 'flex' }}>
|
||||
return <ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<StyledDrawer variant={"permanent"} open={drawerOpen}>
|
||||
<DrawerHeader>
|
||||
{drawerOpen && <>
|
||||
<img src={"/img/icons/logo.png"} alt={"Logo"} />
|
||||
<span>WebBase</span>
|
||||
</>}
|
||||
<IconButton onClick={() => setDrawerOpen(!drawerOpen)}>
|
||||
{drawerOpen ? <ChevronLeftIcon/> : <ChevronRightIcon/>}
|
||||
</IconButton>
|
||||
</DrawerHeader>
|
||||
<Divider/>
|
||||
<ListItem sx={{display: 'block'}}>
|
||||
<Box sx={{opacity: drawerOpen ? 1 : 0}}>{L("account.logged_in_as")}:</Box>
|
||||
<ProfileLink to={"/admin/profile"}>
|
||||
<ProfilePicture user={api.user}/>
|
||||
{drawerOpen && <span>{api.user?.name || L("account.not_logged_in")}</span>}
|
||||
</ProfileLink>
|
||||
</ListItem>
|
||||
<Divider/>
|
||||
<List>
|
||||
{li}
|
||||
</List>
|
||||
<Divider/>
|
||||
<ListItem sx={{display: 'block'}}>
|
||||
{ drawerOpen ?
|
||||
<Select native value={currentLocale} size={"small"} fullWidth={true}
|
||||
onChange={e => onSetLanguage(e.target.value)}>
|
||||
{Object.values(languages || {}).map(language =>
|
||||
<option key={language.code} value={language.code}>
|
||||
{language.name}
|
||||
</option>)
|
||||
}
|
||||
</Select>
|
||||
: <ListItemButton sx={{
|
||||
minHeight: 48,
|
||||
justifyContent: 'center',
|
||||
px: 2.5,
|
||||
}}>
|
||||
<Dropdown>
|
||||
<ListItemIcon onClick={e => setAnchorEl(e.currentTarget)} sx={{
|
||||
minWidth: 0,
|
||||
mr: 'auto',
|
||||
justifyContent: 'center',
|
||||
}}>
|
||||
<Translate />
|
||||
</ListItemIcon>
|
||||
<Menu open={!!anchorEl}
|
||||
anchorEl={anchorEl}
|
||||
onClose={() => setAnchorEl(null)}
|
||||
onClick={() => setAnchorEl(null)}
|
||||
transformOrigin={{ horizontal: 'left', vertical: 'bottom' }}
|
||||
anchorOrigin={{ horizontal: 'left', vertical: 'bottom' }}>
|
||||
{Object.values(languages || {}).map(language =>
|
||||
<MenuItem key={language.code} onClick={() => onSetLanguage(language.code)}>
|
||||
{language.name}
|
||||
</MenuItem>)
|
||||
}
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
</ListItemButton>
|
||||
}
|
||||
</ListItem>
|
||||
</StyledDrawer>
|
||||
<Box component="main" sx={{flexGrow: 1, p: 1}}>
|
||||
{props.children}
|
||||
<Box sx={{ display: 'flex' }} {...other}>
|
||||
<StyledDrawer variant={"permanent"} open={drawerOpen}>
|
||||
<DrawerHeader>
|
||||
{drawerOpen && <>
|
||||
<img src={"/img/icons/logo.png"} alt={"Logo"} />
|
||||
<span>WebBase</span>
|
||||
</>}
|
||||
<IconButton onClick={() => setDrawerOpen(!drawerOpen)}>
|
||||
{drawerOpen ? <ChevronLeftIcon/> : <ChevronRightIcon/>}
|
||||
</IconButton>
|
||||
</DrawerHeader>
|
||||
<Divider/>
|
||||
<ListItem sx={{display: 'block'}}>
|
||||
<Box sx={{opacity: drawerOpen ? 1 : 0}}>{L("account.logged_in_as")}:</Box>
|
||||
<ProfileLink to={"/admin/profile"}>
|
||||
<ProfilePicture user={api.user}/>
|
||||
{drawerOpen && <span>{api.user?.name || L("account.not_logged_in")}</span>}
|
||||
</ProfileLink>
|
||||
</ListItem>
|
||||
<Divider/>
|
||||
<List>
|
||||
{li}
|
||||
</List>
|
||||
<Divider/>
|
||||
<ListItem sx={{display: 'block'}}>
|
||||
{ drawerOpen ?
|
||||
<Select native value={currentLocale} size={"small"} fullWidth={true}
|
||||
onChange={e => onSetLanguage(e.target.value)}>
|
||||
{Object.values(languages || {}).map(language =>
|
||||
<option key={language.code} value={language.code}>
|
||||
{language.name}
|
||||
</option>)
|
||||
}
|
||||
</Select>
|
||||
: <ListItemButton sx={{
|
||||
minHeight: 48,
|
||||
justifyContent: 'center',
|
||||
px: 2.5,
|
||||
}}>
|
||||
<Dropdown>
|
||||
<ListItemIcon onClick={e => setAnchorEl(e.currentTarget)} sx={{
|
||||
minWidth: 0,
|
||||
mr: 'auto',
|
||||
justifyContent: 'center',
|
||||
}}>
|
||||
<Translate />
|
||||
</ListItemIcon>
|
||||
<Menu open={!!anchorEl}
|
||||
anchorEl={anchorEl}
|
||||
onClose={() => setAnchorEl(null)}
|
||||
onClick={() => setAnchorEl(null)}
|
||||
transformOrigin={{ horizontal: 'left', vertical: 'bottom' }}
|
||||
anchorOrigin={{ horizontal: 'left', vertical: 'bottom' }}>
|
||||
{Object.values(languages || {}).map(language =>
|
||||
<MenuItem key={language.code} onClick={() => onSetLanguage(language.code)}>
|
||||
{language.name}
|
||||
</MenuItem>)
|
||||
}
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
</ListItemButton>
|
||||
}
|
||||
</ListItem>
|
||||
</StyledDrawer>
|
||||
<Box component="main" sx={{flexGrow: 1, p: 1}}>
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</ThemeProvider>
|
||||
}
|
||||
|
@ -231,10 +231,10 @@ export default function AccessControlList(props) {
|
||||
</Box>
|
||||
<ButtonBar mb={2}>
|
||||
<Button variant={"outlined"} color={"primary"} size={"small"}
|
||||
startIcon={<Refresh/>} onClick={() => onFetchACL(true)}>
|
||||
startIcon={<Refresh />} onClick={() => onFetchACL(true)}>
|
||||
{L("general.reload")}
|
||||
</Button>
|
||||
<Button variant={"outlined"} startIcon={<Add/>} size={"small"}
|
||||
<Button variant={"outlined"} startIcon={<Add />} size={"small"} color={"success"}
|
||||
disabled={!props.api.hasGroup(USER_GROUP_ADMIN)}
|
||||
onClick={() => setDialogData({
|
||||
open: true,
|
||||
|
@ -274,7 +274,7 @@ export default function EditGroupView(props) {
|
||||
]}
|
||||
buttons={[{
|
||||
key: "btn-add-member",
|
||||
color: "primary",
|
||||
color: "success",
|
||||
startIcon: <Add />,
|
||||
disabled: !api.hasPermission("groups/addMember"),
|
||||
children: L("general.add"),
|
||||
|
@ -61,7 +61,7 @@ export default function GroupListView(props) {
|
||||
columns={columnDefinitions}
|
||||
buttons={[{
|
||||
key: "btn-create-group",
|
||||
color: "primary",
|
||||
color: "success",
|
||||
startIcon: <Add />,
|
||||
onClick: () => navigate("/admin/group/new"),
|
||||
disabled: !api.hasPermission("groups/create"),
|
||||
|
@ -129,12 +129,12 @@ export default function RouteListView(props) {
|
||||
startIcon={<Refresh />} onClick={() => onFetchRoutes(true)}>
|
||||
{L("general.reload")}
|
||||
</Button>
|
||||
<Button variant={"outlined"} startIcon={<Add />} size={"small"}
|
||||
<Button variant={"outlined"} color={"success"} startIcon={<Add />} size={"small"}
|
||||
disabled={!props.api.hasPermission("routes/add")}
|
||||
onClick={() => navigate("/admin/routes/new")} >
|
||||
{L("general.add")}
|
||||
</Button>
|
||||
<Button variant={"outlined"} startIcon={<Cached />} size={"small"}
|
||||
<Button variant={"outlined"} color={"info"} startIcon={<Cached />} size={"small"}
|
||||
disabled={!props.api.hasPermission("routes/generateCache") || isGeneratingCache}
|
||||
onClick={onRegenerateCache} >
|
||||
{isGeneratingCache ? L("routes.regenerating_cache") + "…" : L("routes.regenerate_cache")}
|
||||
|
@ -83,7 +83,7 @@ export default function UserListView(props) {
|
||||
columns={columnDefinitions}
|
||||
buttons={[{
|
||||
key: "btn-create",
|
||||
color: "primary",
|
||||
color: "success",
|
||||
startIcon: <Add />,
|
||||
children: L("general.create_new"),
|
||||
disabled: !api.hasPermission("user/create") && !api.hasPermission("user/invite"),
|
||||
|
Loading…
Reference in New Issue
Block a user