mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-17 01:17:29 +02:00
feat/admin menu reorganize (#4129)
## About the changes <!-- Describe the changes introduced. What are they and why are they being introduced? Feel free to also add screenshots or steps to view the changes if they're visual. --> Reorganizes the items in the menu to align with the tabs on the admin page. Also makes admin menu available to all users, they can get there anyways when using API access link, and all admin-only pages are disabled for non-admins. Also adds API access to the mobile drawer menu, in accordance with how the configure menu is laid out.
This commit is contained in:
parent
6145d9d71e
commit
aa7627bc0b
@ -7,7 +7,6 @@ import ExitToApp from '@mui/icons-material/ExitToApp';
|
|||||||
import { ReactComponent as UnleashLogo } from 'assets/img/logoDarkWithText.svg';
|
import { ReactComponent as UnleashLogo } from 'assets/img/logoDarkWithText.svg';
|
||||||
import { ReactComponent as UnleashLogoWhite } from 'assets/img/logoWithWhiteText.svg';
|
import { ReactComponent as UnleashLogoWhite } from 'assets/img/logoWithWhiteText.svg';
|
||||||
import NavigationLink from '../NavigationLink/NavigationLink';
|
import NavigationLink from '../NavigationLink/NavigationLink';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { basePath } from 'utils/formatPath';
|
import { basePath } from 'utils/formatPath';
|
||||||
import { IFlags } from 'interfaces/uiConfig';
|
import { IFlags } from 'interfaces/uiConfig';
|
||||||
import { INavigationMenuItem } from 'interfaces/route';
|
import { INavigationMenuItem } from 'interfaces/route';
|
||||||
@ -31,7 +30,6 @@ interface IDrawerMenuProps {
|
|||||||
title?: string;
|
title?: string;
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
toggleDrawer: () => void;
|
toggleDrawer: () => void;
|
||||||
admin?: boolean;
|
|
||||||
links: Array<{
|
links: Array<{
|
||||||
value: string;
|
value: string;
|
||||||
icon: ReactNode;
|
icon: ReactNode;
|
||||||
@ -51,7 +49,6 @@ export const DrawerMenu: VFC<IDrawerMenuProps> = ({
|
|||||||
flags = {},
|
flags = {},
|
||||||
open = false,
|
open = false,
|
||||||
toggleDrawer,
|
toggleDrawer,
|
||||||
admin = false,
|
|
||||||
routes,
|
routes,
|
||||||
}) => {
|
}) => {
|
||||||
const renderLinks = () => {
|
const renderLinks = () => {
|
||||||
@ -115,25 +112,18 @@ export const DrawerMenu: VFC<IDrawerMenuProps> = ({
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
<ConditionallyRender
|
<Divider />
|
||||||
condition={admin}
|
|
||||||
show={
|
|
||||||
<>
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
<List className={styles.drawerList}>
|
<List className={styles.drawerList}>
|
||||||
{routes.adminRoutes.map(item => (
|
{routes.adminRoutes.map(item => (
|
||||||
<NavigationLink
|
<NavigationLink
|
||||||
handleClose={() => toggleDrawer()}
|
handleClose={() => toggleDrawer()}
|
||||||
path={item.path}
|
path={item.path}
|
||||||
text={item.title}
|
text={item.title}
|
||||||
key={item.path}
|
key={item.path}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<div className={styles.iconLinkList}>
|
<div className={styles.iconLinkList}>
|
||||||
{renderLinks()}
|
{renderLinks()}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState, VFC } from 'react';
|
import { useState, VFC } from 'react';
|
||||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
@ -21,8 +21,6 @@ import { ReactComponent as UnleashLogoWhite } from 'assets/img/logoWithWhiteText
|
|||||||
import { DrawerMenu } from './DrawerMenu/DrawerMenu';
|
import { DrawerMenu } from './DrawerMenu/DrawerMenu';
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import { flexRow, focusable } from 'themes/themeStyles';
|
import { flexRow, focusable } from 'themes/themeStyles';
|
||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
|
||||||
import { IPermission } from 'interfaces/user';
|
|
||||||
import { NavigationMenu } from './NavigationMenu/NavigationMenu';
|
import { NavigationMenu } from './NavigationMenu/NavigationMenu';
|
||||||
import {
|
import {
|
||||||
getRoutes,
|
getRoutes,
|
||||||
@ -35,7 +33,6 @@ import {
|
|||||||
LightModeOutlined,
|
LightModeOutlined,
|
||||||
} from '@mui/icons-material';
|
} from '@mui/icons-material';
|
||||||
import { filterByConfig } from 'component/common/util';
|
import { filterByConfig } from 'component/common/util';
|
||||||
import { useAuthPermissions } from 'hooks/api/getters/useAuth/useAuthPermissions';
|
|
||||||
import { useId } from 'hooks/useId';
|
import { useId } from 'hooks/useId';
|
||||||
import { INavigationMenuItem } from 'interfaces/route';
|
import { INavigationMenuItem } from 'interfaces/route';
|
||||||
import { ThemeMode } from 'component/common/ThemeMode/ThemeMode';
|
import { ThemeMode } from 'component/common/ThemeMode/ThemeMode';
|
||||||
@ -118,8 +115,6 @@ const Header: VFC = () => {
|
|||||||
const [adminRef, setAdminRef] = useState<HTMLButtonElement | null>(null);
|
const [adminRef, setAdminRef] = useState<HTMLButtonElement | null>(null);
|
||||||
const [configRef, setConfigRef] = useState<HTMLButtonElement | null>(null);
|
const [configRef, setConfigRef] = useState<HTMLButtonElement | null>(null);
|
||||||
|
|
||||||
const [admin, setAdmin] = useState(false);
|
|
||||||
const { permissions } = useAuthPermissions();
|
|
||||||
const { uiConfig, isOss, isPro, isEnterprise } = useUiConfig();
|
const { uiConfig, isOss, isPro, isEnterprise } = useUiConfig();
|
||||||
const smallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
const smallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
@ -128,16 +123,6 @@ const Header: VFC = () => {
|
|||||||
const onAdminClose = () => setAdminRef(null);
|
const onAdminClose = () => setAdminRef(null);
|
||||||
const onConfigureClose = () => setConfigRef(null);
|
const onConfigureClose = () => setConfigRef(null);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const admin = permissions?.find(
|
|
||||||
(element: IPermission) => element.permission === ADMIN
|
|
||||||
);
|
|
||||||
|
|
||||||
if (admin) {
|
|
||||||
setAdmin(true);
|
|
||||||
}
|
|
||||||
}, [permissions]);
|
|
||||||
|
|
||||||
const routes = getRoutes();
|
const routes = getRoutes();
|
||||||
|
|
||||||
const filterByMode = (route: INavigationMenuItem): boolean => {
|
const filterByMode = (route: INavigationMenuItem): boolean => {
|
||||||
@ -159,9 +144,15 @@ const Header: VFC = () => {
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
.filter(filterByConfig(uiConfig)),
|
.filter(filterByConfig(uiConfig)),
|
||||||
mobileRoutes: getCondensedRoutes(routes.mobileRoutes).filter(
|
mobileRoutes: getCondensedRoutes(routes.mobileRoutes)
|
||||||
filterByConfig(uiConfig)
|
.concat([
|
||||||
),
|
{
|
||||||
|
path: '/admin/api',
|
||||||
|
title: 'API access',
|
||||||
|
menu: {},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.filter(filterByConfig(uiConfig)),
|
||||||
adminRoutes: adminMenuRoutes
|
adminRoutes: adminMenuRoutes
|
||||||
.filter(filterByConfig(uiConfig))
|
.filter(filterByConfig(uiConfig))
|
||||||
.filter(filterByMode)
|
.filter(filterByMode)
|
||||||
@ -191,7 +182,6 @@ const Header: VFC = () => {
|
|||||||
links={uiConfig.links}
|
links={uiConfig.links}
|
||||||
open={openDrawer}
|
open={openDrawer}
|
||||||
toggleDrawer={toggleDrawer}
|
toggleDrawer={toggleDrawer}
|
||||||
admin={admin}
|
|
||||||
routes={filteredMainRoutes}
|
routes={filteredMainRoutes}
|
||||||
/>
|
/>
|
||||||
<StyledUserContainer>
|
<StyledUserContainer>
|
||||||
@ -273,29 +263,18 @@ const Header: VFC = () => {
|
|||||||
<MenuBookIcon />
|
<MenuBookIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<ConditionallyRender
|
<Tooltip title="Settings" arrow>
|
||||||
condition={admin}
|
<StyledIconButton
|
||||||
show={
|
onClick={e => setAdminRef(e.currentTarget)}
|
||||||
<Tooltip title="Settings" arrow>
|
aria-controls={adminRef ? adminId : undefined}
|
||||||
<StyledIconButton
|
aria-expanded={Boolean(adminRef)}
|
||||||
onClick={e =>
|
size="large"
|
||||||
setAdminRef(e.currentTarget)
|
disableRipple
|
||||||
}
|
>
|
||||||
aria-controls={
|
<SettingsIcon />
|
||||||
adminRef ? adminId : undefined
|
<KeyboardArrowDown sx={styledIconProps} />
|
||||||
}
|
</StyledIconButton>
|
||||||
aria-expanded={Boolean(adminRef)}
|
</Tooltip>
|
||||||
size="large"
|
|
||||||
disableRipple
|
|
||||||
>
|
|
||||||
<SettingsIcon />
|
|
||||||
<KeyboardArrowDown
|
|
||||||
sx={styledIconProps}
|
|
||||||
/>
|
|
||||||
</StyledIconButton>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<NavigationMenu
|
<NavigationMenu
|
||||||
id={adminId}
|
id={adminId}
|
||||||
options={filteredMainRoutes.adminRoutes}
|
options={filteredMainRoutes.adminRoutes}
|
||||||
|
@ -442,21 +442,16 @@ export const routes: IRoute[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const adminMenuRoutes: INavigationMenuItem[] = [
|
export const adminMenuRoutes: INavigationMenuItem[] = [
|
||||||
{
|
|
||||||
path: '/history',
|
|
||||||
title: 'Event log',
|
|
||||||
menu: { adminSettings: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/logins',
|
|
||||||
title: 'Login history',
|
|
||||||
menu: { adminSettings: true, mode: ['enterprise'] },
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/admin/users',
|
path: '/admin/users',
|
||||||
title: 'Users',
|
title: 'Users',
|
||||||
menu: { adminSettings: true },
|
menu: { adminSettings: true },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/service-accounts',
|
||||||
|
title: 'Service accounts',
|
||||||
|
menu: { adminSettings: true, mode: ['enterprise'] },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/admin/groups',
|
path: '/admin/groups',
|
||||||
title: 'Groups',
|
title: 'Groups',
|
||||||
@ -468,6 +463,12 @@ export const adminMenuRoutes: INavigationMenuItem[] = [
|
|||||||
title: 'Roles',
|
title: 'Roles',
|
||||||
menu: { adminSettings: true, mode: ['enterprise'] },
|
menu: { adminSettings: true, mode: ['enterprise'] },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/cors',
|
||||||
|
title: 'CORS origins',
|
||||||
|
flag: 'embedProxyFrontend',
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/admin/auth',
|
path: '/admin/auth',
|
||||||
title: 'Single sign-on',
|
title: 'Single sign-on',
|
||||||
@ -478,11 +479,6 @@ export const adminMenuRoutes: INavigationMenuItem[] = [
|
|||||||
title: 'Instance stats',
|
title: 'Instance stats',
|
||||||
menu: { adminSettings: true },
|
menu: { adminSettings: true },
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/admin/service-accounts',
|
|
||||||
title: 'Service accounts',
|
|
||||||
menu: { adminSettings: true, mode: ['enterprise'] },
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/admin/network/*',
|
path: '/admin/network/*',
|
||||||
title: 'Network',
|
title: 'Network',
|
||||||
@ -494,12 +490,6 @@ export const adminMenuRoutes: INavigationMenuItem[] = [
|
|||||||
title: 'Maintenance',
|
title: 'Maintenance',
|
||||||
menu: { adminSettings: true },
|
menu: { adminSettings: true },
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/admin/cors',
|
|
||||||
title: 'CORS origins',
|
|
||||||
flag: 'embedProxyFrontend',
|
|
||||||
menu: { adminSettings: true },
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/admin/admin-invoices',
|
path: '/admin/admin-invoices',
|
||||||
title: 'Billing & invoices',
|
title: 'Billing & invoices',
|
||||||
@ -510,6 +500,16 @@ export const adminMenuRoutes: INavigationMenuItem[] = [
|
|||||||
title: 'Instance privacy',
|
title: 'Instance privacy',
|
||||||
menu: { adminSettings: true },
|
menu: { adminSettings: true },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/history',
|
||||||
|
title: 'Event log',
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/logins',
|
||||||
|
title: 'Login history',
|
||||||
|
menu: { adminSettings: true, mode: ['enterprise'] },
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const getRoute = (path: string) =>
|
export const getRoute = (path: string) =>
|
||||||
|
Loading…
Reference in New Issue
Block a user