minor improvements

This commit is contained in:
Roman 2024-05-02 14:45:24 +02:00
parent fb353d1bc8
commit 5abbbac2b6
11 changed files with 44 additions and 43 deletions

@ -5,7 +5,7 @@ import {
Box, CssBaseline, Divider, Box, CssBaseline, Divider,
IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText,
Select, Drawer, Select, Drawer,
styled, MenuItem, Menu, styled, MenuItem, Menu, useTheme,
} from "@mui/material"; } from "@mui/material";
import { Dropdown } from '@mui/base/Dropdown'; import { Dropdown } from '@mui/base/Dropdown';
import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import ChevronRightIcon from '@mui/icons-material/ChevronRight';
@ -100,6 +100,7 @@ export default function Sidebar(props) {
const [fetchLanguages, setFetchLanguages] = useState(true); const [fetchLanguages, setFetchLanguages] = useState(true);
const [drawerOpen, setDrawerOpen] = useState(window.screen.width >= 1000); const [drawerOpen, setDrawerOpen] = useState(window.screen.width >= 1000);
const [anchorEl, setAnchorEl] = useState(null); const [anchorEl, setAnchorEl] = useState(null);
const theme = useTheme();
const navigate = useNavigate(); const navigate = useNavigate();
const currentPath = useCurrentPath(); const currentPath = useCurrentPath();

@ -159,9 +159,9 @@ export default function AccessControlList(props) {
rows.push( rows.push(
<TableRow key={"perm-" + index}> <TableRow key={"perm-" + index}>
<TableCell> <TableCell>
<div style={{display: "grid", gridTemplateColumns: "60px auto"}}> <Grid container>
<div style={{alignSelf: "center"}}> <Grid item xs={1} alignContent={"center"}>
<IconButton style={{padding: 0}} size={"small"} color={"primary"} <IconButton size={"small"} color={"primary"}
disabled={isRestricted(permission.method)} disabled={isRestricted(permission.method)}
onClick={() => setDialogData({ onClick={() => setDialogData({
open: true, open: true,
@ -172,25 +172,25 @@ export default function AccessControlList(props) {
{ type: "label", value: L("permissions.description") + ":" }, { type: "label", value: L("permissions.description") + ":" },
{ type: "text", name: "description", value: permission.description, maxLength: 128 } { type: "text", name: "description", value: permission.description, maxLength: 128 }
], ],
onOption: (option, inputData) => option === 0 ? onUpdatePermission(inputData, permission.groups) : true })} > onOption: (option, inputData) => option === 1 ? onUpdatePermission(inputData, permission.groups) : true })} >
<Edit /> <Edit />
</IconButton> </IconButton>
<IconButton style={{padding: 0}} size={"small"} color={"secondary"} <IconButton size={"small"} color={"error"}
disabled={isRestricted(permission.method)} disabled={isRestricted(permission.method)}
onClick={() => setDialogData({ onClick={() => setDialogData({
open: true, open: true,
title: L("permissions.delete_permission_confirm"), title: L("permissions.delete_permission_confirm"),
message: L("permissions.method") + ": " + permission.method, message: L("permissions.method") + ": " + permission.method,
onOption: (option) => option === 0 ? onDeletePermission(permission.method) : true onOption: (option) => option === 1 ? onDeletePermission(permission.method) : true
})} > })} >
<Delete /> <Delete />
</IconButton> </IconButton>
</div> </Grid>
<div> <Grid item>
<b>{permission.method}</b><br /> <b>{permission.method}</b><br />
<i>{permission.description}</i> <i>{permission.description}</i>
</div> </Grid>
</div> </Grid>
</TableCell> </TableCell>
<BorderedColumn key={"perm-" + index + "-everyone"} align={"center"}> <BorderedColumn key={"perm-" + index + "-everyone"} align={"center"}>
<Checkbox checked={!permission.groups.length} <Checkbox checked={!permission.groups.length}
@ -250,7 +250,7 @@ export default function AccessControlList(props) {
placeholder: L("permissions.description") placeholder: L("permissions.description")
} }
], ],
onOption: (option, inputData) => option === 0 ? onUpdatePermission(inputData, []) : true onOption: (option, inputData) => option === 1 ? onUpdatePermission(inputData, []) : true
})}> })}>
{L("general.add")} {L("general.add")}
</Button> </Button>
@ -279,6 +279,6 @@ export default function AccessControlList(props) {
message={dialogData.message} message={dialogData.message}
onOption={dialogData.onOption} onOption={dialogData.onOption}
inputs={dialogData.inputs} inputs={dialogData.inputs}
options={[L("general.ok"), L("general.cancel")]}/> options={[L("general.cancel"), L("general.ok")]}/>
</ViewContent> </ViewContent>
} }

@ -159,9 +159,9 @@ export default function EditGroupView(props) {
} }
], ],
onOption: (option) => { onOption: (option) => {
if(option === 0) { if(option === 1) {
onAddMember() onAddMember()
} else { } else {
selectedUserRef.current = null selectedUserRef.current = null
} }
} }
@ -227,12 +227,12 @@ export default function EditGroupView(props) {
</Button> </Button>
{ !isNewGroup && { !isNewGroup &&
<Button startIcon={<Delete/>} disabled={!api.hasPermission("groups/delete")} <Button startIcon={<Delete/>} disabled={!api.hasPermission("groups/delete")}
variant={"outlined"} color={"secondary"} variant={"outlined"} color={"error"}
onClick={() => setDialogData({ onClick={() => setDialogData({
open: true, open: true,
title: L("account.delete_group_title"), title: L("account.delete_group_title"),
message: L("account.delete_group_text"), message: L("account.delete_group_text"),
onOption: option => option === 0 ? onDeleteGroup() : true onOption: option => option === 1 ? onDeleteGroup() : true
})}> })}>
{L("general.delete")} {L("general.delete")}
</Button> </Button>
@ -262,12 +262,12 @@ export default function EditGroupView(props) {
label: L("general.remove"), label: L("general.remove"),
element: Delete, element: Delete,
disabled: !api.hasPermission("groups/removeMember"), disabled: !api.hasPermission("groups/removeMember"),
color: "secondary", color: "error",
onClick: (entry) => setDialogData({ onClick: (entry) => setDialogData({
open: true, open: true,
title: L("account.remove_group_member_title"), title: L("account.remove_group_member_title"),
message: sprintf(L("account.remove_group_member_text"), entry.fullName || entry.name), message: sprintf(L("account.remove_group_member_text"), entry.fullName || entry.name),
onOption: (option) => option === 0 ? onRemoveMember(entry.id) : true onOption: (option) => option === 1 ? onRemoveMember(entry.id) : true
}) })
} }
]), ]),
@ -293,6 +293,6 @@ export default function EditGroupView(props) {
message={dialogData.message} message={dialogData.message}
onOption={dialogData.onOption} onOption={dialogData.onOption}
inputs={dialogData.inputs} inputs={dialogData.inputs}
options={[L("general.ok"), L("general.cancel")]} /> options={[L("general.cancel"), L("general.ok")]} />
</> </>
} }

@ -76,12 +76,12 @@ const StatBox = (props) => <StyledStatBox variant={"filled"} icon={false}
const StatusLine = (props) => { const StatusLine = (props) => {
const {enabled, text, ...other} = props; const {enabled, text, ...other} = props;
if (enabled) { if (enabled) {
return <Box display="grid" gridTemplateColumns={"30px auto"}> return <Box display="grid" gridTemplateColumns={"30px auto"} alignItems={"center"}>
<CheckCircle color={"primary"} title={text} /> {text} <CheckCircle color={"primary"} title={text} /> {text}
</Box> </Box>
} else { } else {
return <Box display="grid" gridTemplateColumns={"30px auto"}> return <Box display="grid" gridTemplateColumns={"30px auto"} alignItems={"center"}>
<HighlightOff color={"secondary"} title={text} /> {text} <HighlightOff color={"error"} title={text} /> {text}
</Box> </Box>
} }
} }
@ -127,25 +127,25 @@ export default function Overview(props) {
<Link key={"home"} to={"/admin/dashboard"}>Home</Link> <Link key={"home"} to={"/admin/dashboard"}>Home</Link>
]}> ]}>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={3}> <Grid item xs={6} lg={3}>
<StatBox color={"info"} count={stats?.userCount} <StatBox color={"info"} count={stats?.userCount}
text={L("admin.users_registered")} text={L("admin.users_registered")}
icon={<People/>} icon={<People/>}
link={"/admin/users"}/> link={"/admin/users"}/>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={6} lg={3}>
<StatBox color={"success"} count={stats?.groupCount} <StatBox color={"success"} count={stats?.groupCount}
text={L("admin.available_groups")} text={L("admin.available_groups")}
icon={<Groups/>} icon={<Groups/>}
link={"/admin/groups"}/> link={"/admin/groups"}/>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={6} lg={3}>
<StatBox color={"warning"} count={stats?.pageCount} <StatBox color={"warning"} count={stats?.pageCount}
text={L("admin.routes_defined")} text={L("admin.routes_defined")}
icon={<LibraryBooks/>} icon={<LibraryBooks/>}
link={"/admin/routes"}/> link={"/admin/routes"}/>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={6} lg={3}>
<StatBox color={"error"} count={stats?.errorCount} <StatBox color={"error"} count={stats?.errorCount}
text={L("admin.error_count")} text={L("admin.error_count")}
icon={<BugReport />} icon={<BugReport />}

@ -76,7 +76,7 @@ export default function EditProfilePicture(props) {
}, },
], ],
onOption: (option) => { onOption: (option) => {
if (option === 0 && file) { if (option === 1 && file) {
onUploadPicture(file) onUploadPicture(file)
} }
@ -115,13 +115,13 @@ export default function EditProfilePicture(props) {
</Button> </Button>
{profile.profilePicture && {profile.profilePicture &&
<Button variant="outlined" size="small" <Button variant="outlined" size="small"
startIcon={<Delete />} color="secondary" startIcon={<Delete />} color={"error"}
onClick={() => setDialogData({ onClick={() => setDialogData({
show: true, show: true,
title: L("account.picture_remove_title"), title: L("account.picture_remove_title"),
message: L("account.picture_remove_text"), message: L("account.picture_remove_text"),
options: [L("general.confirm"), L("general.cancel")], options: [L("general.confirm"), L("general.cancel")],
onOption: (option) => option === 0 ? onRemoveImage() : true onOption: (option) => option === 1 ? onRemoveImage() : true
})}> })}>
{L("account.remove_picture")} {L("account.remove_picture")}
</Button> </Button>

@ -106,7 +106,7 @@ export default function GpgBox(props) {
<GpgFingerprintBox mb={2}> <GpgFingerprintBox mb={2}>
{ profile.gpgKey.confirmed ? { profile.gpgKey.confirmed ?
<CheckCircle color="info" title={L("account.gpg_key_confirmed")} /> : <CheckCircle color="info" title={L("account.gpg_key_confirmed")} /> :
<ErrorOutline color="secondary" title={L("account.gpg_key_pending")} /> <ErrorOutline color="error" title={L("account.gpg_key_pending")} />
} }
GPG-Fingerprint: <code title={L("general.click_to_copy")} GPG-Fingerprint: <code title={L("general.click_to_copy")}
onClick={() => navigator.clipboard.writeText(profile.gpgKey.fingerprint)}> onClick={() => navigator.clipboard.writeText(profile.gpgKey.fingerprint)}>
@ -124,7 +124,7 @@ export default function GpgBox(props) {
</FormControl> </FormControl>
</SpacedFormGroup> </SpacedFormGroup>
<Button startIcon={isGpgKeyRemoving ? <CircularProgress size={12} /> : <Remove />} <Button startIcon={isGpgKeyRemoving ? <CircularProgress size={12} /> : <Remove />}
color="secondary" onClick={onRemoveGpgKey} color="error" onClick={onRemoveGpgKey}
variant="outlined" size="small" variant="outlined" size="small"
disabled={isGpgKeyRemoving || !api.hasPermission("gpgKey/remove")}> disabled={isGpgKeyRemoving || !api.hasPermission("gpgKey/remove")}>
{isGpgKeyRemoving ? L("general.removing") + "…" : L("general.remove")} {isGpgKeyRemoving ? L("general.removing") + "…" : L("general.remove")}

@ -82,7 +82,7 @@ export default function MultiFactorBox(props) {
</FormControl> </FormControl>
</SpacedFormGroup> </SpacedFormGroup>
<Button startIcon={is2FARemoving ? <CircularProgress size={12} /> : <Remove />} <Button startIcon={is2FARemoving ? <CircularProgress size={12} /> : <Remove />}
color="secondary" onClick={onRemove2FA} color="danger" onClick={onRemove2FA}
variant="outlined" size="small" variant="outlined" size="small"
disabled={is2FARemoving || !api.hasPermission("tfa/remove")}> disabled={is2FARemoving || !api.hasPermission("tfa/remove")}>
{is2FARemoving ? L("general.removing") + "…" : L("general.remove")} {is2FARemoving ? L("general.removing") + "…" : L("general.remove")}

@ -37,8 +37,8 @@ export default function MfaTotp(props) {
sx: { "& input": { textAlign: "center", fontFamily: "monospace" } }, sx: { "& input": { textAlign: "center", fontFamily: "monospace" } },
} }
], ],
options: [L("general.ok"), L("general.cancel")], options: [L("general.cancel"), L("general.ok")],
onOption: (option, data) => option === 0 ? onConfirmTOTP(data.code) : true onOption: (option, data) => option === 1 ? onConfirmTOTP(data.code) : true
}) })
} }
}, [api, onConfirmTOTP]); }, [api, onConfirmTOTP]);

@ -104,9 +104,9 @@ export default function RouteForm(props) {
onChange={e => setRoute({...route, extra: minifyJson(e.target.value)})}/> onChange={e => setRoute({...route, extra: minifyJson(e.target.value)})}/>
<Box mt={1} fontStyle={"italic"} display={"grid"} gridTemplateColumns={"30px auto"}>{ <Box mt={1} fontStyle={"italic"} display={"grid"} gridTemplateColumns={"30px auto"}>{
extraArgs === null ? extraArgs === null ?
<><ErrorRounded color={"secondary"}/><span>{L("routes.json_err")}</span></> : <><ErrorRounded color={"error"}/><span>{L("routes.json_err")}</span></> :
(type !== "object" ? (type !== "object" ?
<><ErrorRounded color={"secondary"}/><span>{L("routes.json_not_object")}</span></> : <><ErrorRounded color={"error"}/><span>{L("routes.json_not_object")}</span></> :
<><CheckCircle color={"primary"} /><span>{L("routes.json_ok")}</span></>) <><CheckCircle color={"primary"} /><span>{L("routes.json_ok")}</span></>)
}</Box> }</Box>
</RouteFormControl> </RouteFormControl>

@ -178,7 +178,7 @@ export default function RouteListView(props) {
</IconButton> </IconButton>
<IconButton size={"small"} title={L("general.delete")} <IconButton size={"small"} title={L("general.delete")}
disabled={!api.hasPermission("routes/remove")} disabled={!api.hasPermission("routes/remove")}
color={"secondary"} color={"error"}
onClick={() => setDialogData({ onClick={() => setDialogData({
open: true, open: true,
title: L("routes.delete_route_title"), title: L("routes.delete_route_title"),
@ -186,8 +186,8 @@ export default function RouteListView(props) {
inputs: [ inputs: [
{ type: "text", name: "pattern", value: route.pattern, disabled: true} { type: "text", name: "pattern", value: route.pattern, disabled: true}
], ],
options: [L("general.ok"), L("general.cancel")], options: [L("general.cancel"), L("general.ok")],
onOption: btn => btn === 0 ? onDeleteRoute(route.id) : true onOption: btn => btn === 1 ? onDeleteRoute(route.id) : true
})}> })}>
<Delete /> <Delete />
</IconButton> </IconButton>
@ -207,6 +207,6 @@ export default function RouteListView(props) {
message={dialogData.message} message={dialogData.message}
onOption={dialogData.onOption} onOption={dialogData.onOption}
inputs={dialogData.inputs} inputs={dialogData.inputs}
options={[L("general.ok"), L("general.cancel")]} /> options={[L("general.cancel"), L("general.ok")]} />
</> </>
} }

@ -341,7 +341,7 @@ export default function SettingsView(props) {
</TableCell> </TableCell>
<TableCell align={"center"}> <TableCell align={"center"}>
<IconButton onClick={() => onDeleteKey(key)} <IconButton onClick={() => onDeleteKey(key)}
color={"secondary"}> color={"error"}>
<Delete /> <Delete />
</IconButton> </IconButton>
</TableCell> </TableCell>
@ -404,7 +404,7 @@ export default function SettingsView(props) {
variant={"outlined"} title={L(hasChanged ? "general.unsaved_changes" : "general.save")}> variant={"outlined"} title={L(hasChanged ? "general.unsaved_changes" : "general.save")}>
{isSaving ? L("general.saving") + "…" : (L("general.save") + (hasChanged ? " *" : ""))} {isSaving ? L("general.saving") + "…" : (L("general.save") + (hasChanged ? " *" : ""))}
</Button> </Button>
<Button color={"secondary"} <Button color={"error"}
onClick={onReset} onClick={onReset}
disabled={isSaving} disabled={isSaving}
startIcon={<RestartAlt />} startIcon={<RestartAlt />}