mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-10 01:16:39 +02:00
chore: categorize access overview (#9546)
https://linear.app/unleash/issue/2-3346/only-show-description-and-not-permission-first-column-and-group Categorizes the permissions in our Access Overview. 
This commit is contained in:
parent
e38a58d635
commit
76b3e06fe5
@ -12,6 +12,12 @@ import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
|||||||
import { AccessOverviewSelect } from './AccessOverviewSelect';
|
import { AccessOverviewSelect } from './AccessOverviewSelect';
|
||||||
import { useUserAccessOverview } from 'hooks/api/getters/useUserAccessOverview/useUserAccessOverview';
|
import { useUserAccessOverview } from 'hooks/api/getters/useUserAccessOverview/useUserAccessOverview';
|
||||||
import { AccessOverviewAccordion } from './AccessOverviewAccordion/AccessOverviewAccordion';
|
import { AccessOverviewAccordion } from './AccessOverviewAccordion/AccessOverviewAccordion';
|
||||||
|
import {
|
||||||
|
getCategorizedProjectPermissions,
|
||||||
|
getCategorizedRootPermissions,
|
||||||
|
} from 'utils/permissions';
|
||||||
|
import type { IAccessOverviewPermissionCategory } from './AccessOverviewAccordion/AccessOverviewList';
|
||||||
|
import { createProjectPermissionsStructure } from 'component/admin/roles/RoleForm/RolePermissionCategories/createProjectPermissionsStructure';
|
||||||
|
|
||||||
const StyledActionsContainer = styled('div')(({ theme }) => ({
|
const StyledActionsContainer = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -86,6 +92,21 @@ export const AccessOverview = () => {
|
|||||||
</StyledActionsContainer>
|
</StyledActionsContainer>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const rootCategories = getCategorizedRootPermissions(
|
||||||
|
overview?.root ?? [],
|
||||||
|
) as IAccessOverviewPermissionCategory[];
|
||||||
|
|
||||||
|
const projectCategories = createProjectPermissionsStructure(
|
||||||
|
overview?.project ?? [],
|
||||||
|
).map(({ label, permissions }) => ({
|
||||||
|
label,
|
||||||
|
permissions: permissions.map(([permission]) => permission),
|
||||||
|
})) as IAccessOverviewPermissionCategory[];
|
||||||
|
|
||||||
|
const environmentCategories = getCategorizedProjectPermissions(
|
||||||
|
overview?.environment ?? [],
|
||||||
|
) as IAccessOverviewPermissionCategory[];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent
|
<PageContent
|
||||||
isLoading={loading}
|
isLoading={loading}
|
||||||
@ -107,19 +128,17 @@ export const AccessOverview = () => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<StyledAccessOverviewContainer>
|
<StyledAccessOverviewContainer>
|
||||||
<AccessOverviewAccordion permissions={overview?.root ?? []}>
|
<AccessOverviewAccordion categories={rootCategories}>
|
||||||
Root permissions for role {rootRole?.name}
|
Root permissions for role {rootRole?.name}
|
||||||
</AccessOverviewAccordion>
|
</AccessOverviewAccordion>
|
||||||
<AccessOverviewAccordion permissions={overview?.project ?? []}>
|
<AccessOverviewAccordion categories={projectCategories}>
|
||||||
Project permissions
|
Project permissions
|
||||||
{project
|
{project
|
||||||
? ` for project ${project}${projectRoles?.length ? ` with project role${projectRoles.length !== 1 ? 's' : ''} ${projectRoles?.map((role: any) => role.name).join(', ')}` : ''}`
|
? ` for project ${project}${projectRoles?.length ? ` with project role${projectRoles.length !== 1 ? 's' : ''} ${projectRoles?.map((role: any) => role.name).join(', ')}` : ''}`
|
||||||
: ''}
|
: ''}
|
||||||
</AccessOverviewAccordion>
|
</AccessOverviewAccordion>
|
||||||
{environment && (
|
{environment && (
|
||||||
<AccessOverviewAccordion
|
<AccessOverviewAccordion categories={environmentCategories}>
|
||||||
permissions={overview?.environment ?? []}
|
|
||||||
>
|
|
||||||
Environment permissions for {environment}
|
Environment permissions for {environment}
|
||||||
</AccessOverviewAccordion>
|
</AccessOverviewAccordion>
|
||||||
)}
|
)}
|
||||||
|
@ -5,8 +5,10 @@ import {
|
|||||||
AccordionSummary,
|
AccordionSummary,
|
||||||
styled,
|
styled,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import type { IAccessOverviewPermission } from 'interfaces/permissions';
|
import {
|
||||||
import { AccessOverviewList } from './AccessOverviewList';
|
AccessOverviewList,
|
||||||
|
type IAccessOverviewPermissionCategory,
|
||||||
|
} from './AccessOverviewList';
|
||||||
|
|
||||||
const StyledAccordion = styled(Accordion)(({ theme }) => ({
|
const StyledAccordion = styled(Accordion)(({ theme }) => ({
|
||||||
border: `1px solid ${theme.palette.divider}`,
|
border: `1px solid ${theme.palette.divider}`,
|
||||||
@ -50,29 +52,33 @@ const StyledAccordionDetails = styled(AccordionDetails)(({ theme }) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
interface IAccessAccordionProps {
|
interface IAccessAccordionProps {
|
||||||
permissions: IAccessOverviewPermission[];
|
categories: IAccessOverviewPermissionCategory[];
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AccessOverviewAccordion = ({
|
export const AccessOverviewAccordion = ({
|
||||||
permissions,
|
categories,
|
||||||
children,
|
children,
|
||||||
}: IAccessAccordionProps) => (
|
}: IAccessAccordionProps) => {
|
||||||
<StyledAccordion>
|
const permissions = categories.flatMap(({ permissions }) => permissions);
|
||||||
<StyledAccordionSummary expandIcon={<ExpandMore />}>
|
|
||||||
<StyledTitleContainer>
|
return (
|
||||||
<StyledTitle>{children}</StyledTitle>
|
<StyledAccordion>
|
||||||
</StyledTitleContainer>
|
<StyledAccordionSummary expandIcon={<ExpandMore />}>
|
||||||
<StyledSecondaryLabel>
|
<StyledTitleContainer>
|
||||||
{
|
<StyledTitle>{children}</StyledTitle>
|
||||||
permissions.filter(({ hasPermission }) => hasPermission)
|
</StyledTitleContainer>
|
||||||
.length
|
<StyledSecondaryLabel>
|
||||||
}
|
{
|
||||||
/{permissions.length} permissions
|
permissions.filter(({ hasPermission }) => hasPermission)
|
||||||
</StyledSecondaryLabel>
|
.length
|
||||||
</StyledAccordionSummary>
|
}
|
||||||
<StyledAccordionDetails>
|
/{permissions.length} permissions
|
||||||
<AccessOverviewList permissions={permissions} />
|
</StyledSecondaryLabel>
|
||||||
</StyledAccordionDetails>
|
</StyledAccordionSummary>
|
||||||
</StyledAccordion>
|
<StyledAccordionDetails>
|
||||||
);
|
<AccessOverviewList categories={categories} />
|
||||||
|
</StyledAccordionDetails>
|
||||||
|
</StyledAccordion>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1,20 +1,34 @@
|
|||||||
import Check from '@mui/icons-material/Check';
|
import Check from '@mui/icons-material/Check';
|
||||||
import Close from '@mui/icons-material/Close';
|
import Close from '@mui/icons-material/Close';
|
||||||
import { Box, styled } from '@mui/material';
|
import { Box, styled } from '@mui/material';
|
||||||
import type { IAccessOverviewPermission } from 'interfaces/permissions';
|
import type {
|
||||||
|
IAccessOverviewPermission,
|
||||||
|
IPermissionCategory,
|
||||||
|
} from 'interfaces/permissions';
|
||||||
|
|
||||||
|
export type IAccessOverviewPermissionCategory = Omit<
|
||||||
|
IPermissionCategory,
|
||||||
|
'permissions'
|
||||||
|
> & {
|
||||||
|
permissions: IAccessOverviewPermission[];
|
||||||
|
};
|
||||||
|
|
||||||
const StyledList = styled('ul')(({ theme }) => ({
|
const StyledList = styled('ul')(({ theme }) => ({
|
||||||
listStyle: 'none',
|
listStyle: 'none',
|
||||||
padding: 0,
|
padding: 0,
|
||||||
margin: 0,
|
margin: 0,
|
||||||
fontSize: theme.fontSizes.smallBody,
|
fontSize: theme.fontSizes.smallBody,
|
||||||
'& li': {
|
'& > li': {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
padding: theme.spacing(2),
|
padding: theme.spacing(2),
|
||||||
'&:not(:last-child)': {
|
borderBottom: `1px solid ${theme.palette.divider}`,
|
||||||
borderBottom: `1px solid ${theme.palette.divider}`,
|
},
|
||||||
},
|
'& ul li': {
|
||||||
|
paddingLeft: theme.spacing(4),
|
||||||
|
},
|
||||||
|
'& ul:last-of-type > li:last-child': {
|
||||||
|
borderBottom: 'none',
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -36,25 +50,32 @@ const StyledPermissionStatus = styled('div', {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
export const AccessOverviewList = ({
|
export const AccessOverviewList = ({
|
||||||
permissions,
|
categories,
|
||||||
}: {
|
}: {
|
||||||
permissions: IAccessOverviewPermission[];
|
categories: IAccessOverviewPermissionCategory[];
|
||||||
}) => {
|
}) => (
|
||||||
return (
|
<Box sx={{ maxHeight: 500, overflow: 'auto' }}>
|
||||||
<Box sx={{ maxHeight: 500, overflow: 'auto' }}>
|
<StyledList>
|
||||||
<StyledList>
|
{categories.map((category) => (
|
||||||
{permissions.map((permission) => (
|
<>
|
||||||
<li key={permission.name}>
|
<li key={category.label}>
|
||||||
<div>{permission.displayName}</div>
|
<strong>{category.label}</strong>
|
||||||
<PermissionStatus
|
|
||||||
hasPermission={permission.hasPermission}
|
|
||||||
/>
|
|
||||||
</li>
|
</li>
|
||||||
))}
|
<StyledList>
|
||||||
</StyledList>
|
{category.permissions.map((permission) => (
|
||||||
</Box>
|
<li key={permission.name}>
|
||||||
);
|
<div>{permission.displayName}</div>
|
||||||
};
|
<PermissionStatus
|
||||||
|
hasPermission={permission.hasPermission}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</StyledList>
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</StyledList>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
const PermissionStatus = ({ hasPermission }: { hasPermission: boolean }) => (
|
const PermissionStatus = ({ hasPermission }: { hasPermission: boolean }) => (
|
||||||
<StyledPermissionStatus hasPermission={hasPermission}>
|
<StyledPermissionStatus hasPermission={hasPermission}>
|
||||||
|
Loading…
Reference in New Issue
Block a user