1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-09 00:18:00 +01:00

Update admin menu (#4389)

## About the changes
- add divider
- reorder items
- add flag for project
https://linear.app/unleash/project/[high][s][none]-improved-menu-aefaca264034

Closes https://linear.app/unleash/issue/1-1101/improved-menu-enterprise
This commit is contained in:
Tymoteusz Czech 2023-08-03 09:01:49 +02:00 committed by GitHub
parent 5377243afc
commit a01aa7e355
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 84 additions and 32 deletions

View File

@ -123,6 +123,7 @@ const Header: VFC = () => {
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);
const showApiAccessInConfigure = !uiConfig?.flags?.frontendNavigationUpdate;
const toggleDrawer = () => setOpenDrawer(prev => !prev); const toggleDrawer = () => setOpenDrawer(prev => !prev);
const onAdminClose = () => setAdminRef(null); const onAdminClose = () => setAdminRef(null);
@ -141,23 +142,31 @@ const Header: VFC = () => {
const filteredMainRoutes = { const filteredMainRoutes = {
mainNavRoutes: getCondensedRoutes(routes.mainNavRoutes) mainNavRoutes: getCondensedRoutes(routes.mainNavRoutes)
.concat([ .concat(
{ showApiAccessInConfigure
path: '/admin/api', ? [
title: 'API access', {
menu: {}, path: '/admin/api',
}, title: 'API access',
]) menu: {},
},
]
: []
)
.filter(filterByConfig(uiConfig)) .filter(filterByConfig(uiConfig))
.map(mapRouteLink), .map(mapRouteLink),
mobileRoutes: getCondensedRoutes(routes.mobileRoutes) mobileRoutes: getCondensedRoutes(routes.mobileRoutes)
.concat([ .concat(
{ showApiAccessInConfigure
path: '/admin/api', ? [
title: 'API access', {
menu: {}, path: '/admin/api',
}, title: 'API access',
]) menu: {},
},
]
: []
)
.filter(filterByConfig(uiConfig)) .filter(filterByConfig(uiConfig))
.map(mapRouteLink), .map(mapRouteLink),
adminRoutes: adminMenuRoutes adminRoutes: adminMenuRoutes

View File

@ -1,4 +1,8 @@
import { Divider } from '@mui/material';
import { Menu, MenuItem, styled } from '@mui/material'; import { Menu, MenuItem, styled } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { Fragment } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
interface INavigationMenuProps { interface INavigationMenuProps {
@ -38,6 +42,9 @@ export const NavigationMenu = ({
anchorEl, anchorEl,
style, style,
}: INavigationMenuProps) => { }: INavigationMenuProps) => {
const { uiConfig } = useUiConfig();
const showDividers = uiConfig?.flags?.frontendNavigationUpdate;
return ( return (
<Menu <Menu
id={id} id={id}
@ -46,10 +53,17 @@ export const NavigationMenu = ({
open={Boolean(anchorEl)} open={Boolean(anchorEl)}
style={style} style={style}
> >
{options.map(option => { {options.map((option, i) => (
return ( <Fragment key={option.path}>
<ConditionallyRender
condition={Boolean(
showDividers &&
options[i - 1]?.group &&
options[i - 1]?.group !== option.group
)}
show={<Divider variant="middle" />}
/>
<MenuItem <MenuItem
key={option.path}
component={StyledLink} component={StyledLink}
to={option.path} to={option.path}
onClick={handleClose} onClick={handleClose}
@ -57,8 +71,8 @@ export const NavigationMenu = ({
<StyledSpan /> <StyledSpan />
{option.title} {option.title}
</MenuItem> </MenuItem>
); </Fragment>
})} ))}
</Menu> </Menu>
); );
}; };

View File

@ -457,69 +457,89 @@ export const adminMenuRoutes: INavigationMenuItem[] = [
path: '/admin/users', path: '/admin/users',
title: 'Users', title: 'Users',
menu: { adminSettings: true }, menu: { adminSettings: true },
group: 'users',
}, },
{ {
path: '/admin/service-accounts', path: '/admin/service-accounts',
title: 'Service accounts', title: 'Service accounts',
menu: { adminSettings: true, mode: ['enterprise'] }, menu: { adminSettings: true, mode: ['enterprise'] },
group: 'users',
}, },
{ {
path: '/admin/groups', path: '/admin/groups',
title: 'Groups', title: 'Groups',
menu: { adminSettings: true, mode: ['enterprise'] }, menu: { adminSettings: true, mode: ['enterprise'] },
flag: UG, flag: UG,
group: 'users',
}, },
{ {
path: '/admin/roles/*', path: '/admin/roles/*',
title: 'Roles', title: 'Roles',
menu: { adminSettings: true, mode: ['enterprise'] }, menu: { adminSettings: true, mode: ['enterprise'] },
group: 'users',
},
{
path: '/admin/api',
title: 'API access',
flag: 'frontendNavigationUpdate',
menu: { adminSettings: true },
group: 'access',
}, },
{ {
path: '/admin/cors', path: '/admin/cors',
title: 'CORS origins', title: 'CORS origins',
flag: 'embedProxyFrontend', flag: 'embedProxyFrontend',
menu: { adminSettings: true }, menu: { adminSettings: true },
group: 'access',
}, },
{ {
path: '/admin/auth', path: '/admin/auth',
title: 'Single sign-on', title: 'Single sign-on',
menu: { adminSettings: true }, menu: { adminSettings: true },
}, group: 'access',
{
path: '/admin/instance',
title: 'Instance stats',
menu: { adminSettings: true },
}, },
{ {
path: '/admin/network/*', path: '/admin/network/*',
title: 'Network', title: 'Network',
menu: { adminSettings: true, mode: ['pro', 'enterprise'] }, menu: { adminSettings: true, mode: ['pro', 'enterprise'] },
configFlag: 'networkViewEnabled', configFlag: 'networkViewEnabled',
group: 'instance',
}, },
{ {
path: '/admin/maintenance', path: '/admin/maintenance',
title: 'Maintenance', title: 'Maintenance',
menu: { adminSettings: true }, menu: { adminSettings: true },
group: 'instance',
}, },
{ {
path: '/admin/admin-invoices', path: '/admin/instance',
title: 'Billing & invoices', title: 'Instance stats',
menu: { adminSettings: true, mode: ['pro'] }, menu: { adminSettings: true },
group: 'instance',
}, },
{ {
path: '/admin/instance-privacy', path: '/admin/instance-privacy',
title: 'Instance privacy', title: 'Instance privacy',
menu: { adminSettings: true }, menu: { adminSettings: true },
group: 'instance',
}, },
{ {
path: '/history', path: '/admin/admin-invoices',
title: 'Event log', title: 'Billing & invoices',
menu: { adminSettings: true }, menu: { adminSettings: true, mode: ['pro'] },
group: 'instance',
}, },
{ {
path: '/admin/logins', path: '/admin/logins',
title: 'Login history', title: 'Login history',
menu: { adminSettings: true, mode: ['enterprise'] }, menu: { adminSettings: true, mode: ['enterprise'] },
group: 'log',
},
{
path: '/history',
title: 'Event log',
menu: { adminSettings: true },
group: 'log',
}, },
]; ];

View File

@ -22,6 +22,7 @@ export interface INavigationMenuItem {
menu: IRouteMenu; menu: IRouteMenu;
flag?: keyof IFlags; flag?: keyof IFlags;
configFlag?: keyof IUiConfig; configFlag?: keyof IUiConfig;
group?: string;
} }
interface IRouteMenu { interface IRouteMenu {

View File

@ -54,6 +54,7 @@ export interface IFlags {
strategyVariant?: boolean; strategyVariant?: boolean;
newProjectLayout?: boolean; newProjectLayout?: boolean;
configurableFeatureTypeLifetimes?: boolean; configurableFeatureTypeLifetimes?: boolean;
frontendNavigationUpdate?: boolean;
} }
export interface IVersionInfo { export interface IVersionInfo {

View File

@ -79,6 +79,7 @@ exports[`should create default config 1`] = `
"emitPotentiallyStaleEvents": false, "emitPotentiallyStaleEvents": false,
"featuresExportImport": true, "featuresExportImport": true,
"filterInvalidClientMetrics": false, "filterInvalidClientMetrics": false,
"frontendNavigationUpdate": false,
"googleAuthEnabled": false, "googleAuthEnabled": false,
"maintenanceMode": false, "maintenanceMode": false,
"messageBanner": { "messageBanner": {
@ -113,6 +114,7 @@ exports[`should create default config 1`] = `
"emitPotentiallyStaleEvents": false, "emitPotentiallyStaleEvents": false,
"featuresExportImport": true, "featuresExportImport": true,
"filterInvalidClientMetrics": false, "filterInvalidClientMetrics": false,
"frontendNavigationUpdate": false,
"googleAuthEnabled": false, "googleAuthEnabled": false,
"maintenanceMode": false, "maintenanceMode": false,
"messageBanner": { "messageBanner": {

View File

@ -26,7 +26,8 @@ export type IFlagKey =
| 'slackAppAddon' | 'slackAppAddon'
| 'emitPotentiallyStaleEvents' | 'emitPotentiallyStaleEvents'
| 'configurableFeatureTypeLifetimes' | 'configurableFeatureTypeLifetimes'
| 'filterInvalidClientMetrics'; | 'filterInvalidClientMetrics'
| 'frontendNavigationUpdate';
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>; export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
@ -115,7 +116,6 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_EMIT_POTENTIALLY_STALE_EVENTS, process.env.UNLEASH_EXPERIMENTAL_EMIT_POTENTIALLY_STALE_EVENTS,
false, false,
), ),
configurableFeatureTypeLifetimes: parseEnvVarBoolean( configurableFeatureTypeLifetimes: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_CONFIGURABLE_FEATURE_TYPE_LIFETIMES, process.env.UNLEASH_EXPERIMENTAL_CONFIGURABLE_FEATURE_TYPE_LIFETIMES,
false, false,
@ -124,6 +124,10 @@ const flags: IFlags = {
process.env.FILTER_INVALID_CLIENT_METRICS, process.env.FILTER_INVALID_CLIENT_METRICS,
false, false,
), ),
frontendNavigationUpdate: parseEnvVarBoolean(
process.env.UNLEASH_NAVIGATION_UPDATE,
false,
),
}; };
export const defaultExperimentalOptions: IExperimentalOptions = { export const defaultExperimentalOptions: IExperimentalOptions = {

View File

@ -42,6 +42,7 @@ process.nextTick(async () => {
emitPotentiallyStaleEvents: true, emitPotentiallyStaleEvents: true,
slackAppAddon: true, slackAppAddon: true,
configurableFeatureTypeLifetimes: true, configurableFeatureTypeLifetimes: true,
frontendNavigationUpdate: true,
}, },
}, },
authentication: { authentication: {