1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-10 01:16:39 +02:00
Nuno Góis 2025-03-17 08:24:48 +00:00 committed by GitHub
parent e38a58d635
commit 76b3e06fe5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 96 additions and 50 deletions

View File

@ -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>
)} )}

View File

@ -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>
);
};

View File

@ -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}>