mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-06 00:07:44 +01:00
a8206f5118
This PR updates the use of references on the project details page to handle the loading state for a single project. Now, if a project is loading, it'll show skeleton loaders for the relevant boxes: ![image](https://github.com/user-attachments/assets/a156cc88-e4bf-421a-8afe-2b46e26d5544) I've also updated the state type we use for this to be more accurate. Shamelessly stolen from Elm. ```ts type RemoteData<T> = | { state: 'error', error: Error } | { state: 'loading' } | { state: 'success', data: T } ``` After refactoring: ![image](https://github.com/user-attachments/assets/03d655de-1ab8-4289-9f0c-d158ede8e116)
121 lines
4.1 KiB
TypeScript
121 lines
4.1 KiB
TypeScript
import { Typography, styled } from '@mui/material';
|
|
import { Badge } from 'component/common/Badge/Badge';
|
|
import { AvatarGroupFromOwners } from 'component/common/AvatarGroupFromOwners/AvatarGroupFromOwners';
|
|
import type { ProjectSchemaOwners } from 'openapi';
|
|
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
|
|
|
|
type Props = {
|
|
roles: string[];
|
|
owners: ProjectSchemaOwners;
|
|
};
|
|
|
|
const Wrapper = styled('div')(({ theme }) => ({
|
|
width: '100%',
|
|
display: 'flex',
|
|
flexFlow: 'row wrap',
|
|
gap: theme.spacing(1),
|
|
justifyContent: 'space-between',
|
|
}));
|
|
|
|
const InfoSection = styled('div')(({ theme }) => ({
|
|
display: 'flex',
|
|
gap: theme.spacing(1),
|
|
alignItems: 'center',
|
|
}));
|
|
|
|
const Roles = styled('ul')(({ theme }) => ({
|
|
display: 'flex',
|
|
gap: theme.spacing(1),
|
|
flexFlow: 'row wrap',
|
|
listStyle: 'none',
|
|
padding: 0,
|
|
}));
|
|
|
|
const TooltipRoles = styled('ul')(({ theme }) => ({
|
|
gap: theme.spacing(1),
|
|
flexFlow: 'column',
|
|
display: 'flex',
|
|
listStyle: 'none',
|
|
padding: 0,
|
|
}));
|
|
|
|
const RoleBadge = styled(Badge)({
|
|
whitespace: 'nowrap',
|
|
});
|
|
|
|
const StyledAvatarGroup = styled(AvatarGroupFromOwners)({
|
|
width: 'max-content',
|
|
});
|
|
|
|
export const RoleAndOwnerInfo = ({ roles, owners }: Props) => {
|
|
const firstRoles = roles.slice(0, 3);
|
|
const extraRoles = roles.slice(3);
|
|
return (
|
|
<Wrapper data-loading>
|
|
<InfoSection>
|
|
{roles.length > 0 ? (
|
|
<>
|
|
<Typography
|
|
sx={{
|
|
whiteSpace: 'nowrap',
|
|
}}
|
|
variant='body1'
|
|
component='h4'
|
|
>
|
|
Your roles in this project:
|
|
</Typography>
|
|
<Roles>
|
|
{firstRoles.map((role) => (
|
|
<li key={role}>
|
|
<RoleBadge color='secondary'>
|
|
{role}
|
|
</RoleBadge>
|
|
</li>
|
|
))}
|
|
{extraRoles.length ? (
|
|
<li>
|
|
<HtmlTooltip
|
|
arrow
|
|
title={
|
|
<TooltipRoles>
|
|
{extraRoles.map((role) => (
|
|
<li key={role}>
|
|
<RoleBadge>
|
|
{role}
|
|
</RoleBadge>
|
|
</li>
|
|
))}
|
|
</TooltipRoles>
|
|
}
|
|
>
|
|
<RoleBadge
|
|
key={'extra-roles'}
|
|
color='secondary'
|
|
>
|
|
{`+ ${extraRoles.length} more`}
|
|
</RoleBadge>
|
|
</HtmlTooltip>
|
|
</li>
|
|
) : null}
|
|
</Roles>
|
|
</>
|
|
) : (
|
|
<span>You have no project roles in this project.</span>
|
|
)}
|
|
</InfoSection>
|
|
<InfoSection>
|
|
<Typography
|
|
variant='body1'
|
|
component='h4'
|
|
sx={{
|
|
whiteSpace: 'nowrap',
|
|
}}
|
|
>
|
|
Project owner{owners.length > 1 ? 's' : ''}
|
|
</Typography>
|
|
<StyledAvatarGroup users={owners} avatarLimit={3} />
|
|
</InfoSection>
|
|
</Wrapper>
|
|
);
|
|
};
|