1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-06 00:07:44 +01:00
unleash.unleash/frontend/src/component/personalDashboard/RoleAndOwnerInfo.tsx
Thomas Heartman a8206f5118
fix: handle loading states for project details for a single project (#8492)
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)
2024-10-21 14:27:43 +02:00

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