1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-21 13:47:39 +02:00

Fix(1-3564)/hide project owner if system (#9686)

Hides owner avatars in cases where the owner type is "system". Touches
dashboard and project card owners.

Back when all projects required owners, we introduced the new project
cards that have the owner listed in the footer. Because, theoretically,
you weren’t allowed to create projects without owners, the only project
that should ever be without an owner was the default project. So we
thought it made sense to say that it was owned by the system.

But now that owners are optional, that doesn't necessarily make sense
anymore. As such, we'll just hide their avatars to begin with.

<img width="726" alt="image"
src="https://github.com/user-attachments/assets/950cd909-c891-48f1-9ef7-fd74922a5990"
/>

<img width="1497" alt="image"
src="https://github.com/user-attachments/assets/f4d213f5-febb-46f8-89f0-899e77652e07"
/>

Because the components expected the avatars to be there, we now need to
set an explicit min-height on them, so that they don't collapse.
Luckily, we can use the default avatar height (and also force that so
that they change in tandem) and use that in both places.
This commit is contained in:
Thomas Heartman 2025-04-03 10:43:58 +02:00 committed by GitHub
parent 4344c94a90
commit 3447b03e1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 14 deletions

View File

@ -9,6 +9,8 @@ type Props = {
owners: ProjectSchemaOwners; owners: ProjectSchemaOwners;
}; };
const avatarHeight = 3.5;
const Wrapper = styled('div')(({ theme }) => ({ const Wrapper = styled('div')(({ theme }) => ({
width: '100%', width: '100%',
display: 'flex', display: 'flex',
@ -21,6 +23,7 @@ const InfoSection = styled('div')(({ theme }) => ({
display: 'flex', display: 'flex',
gap: theme.spacing(1), gap: theme.spacing(1),
alignItems: 'center', alignItems: 'center',
minHeight: theme.spacing(avatarHeight),
})); }));
const Roles = styled('ul')(({ theme }) => ({ const Roles = styled('ul')(({ theme }) => ({
@ -43,13 +46,17 @@ const RoleBadge = styled(Badge)({
whitespace: 'nowrap', whitespace: 'nowrap',
}); });
const StyledAvatarGroup = styled(AvatarGroupFromOwners)({ const StyledAvatarGroup = styled(AvatarGroupFromOwners)(({ theme }) => ({
width: 'max-content', width: 'max-content',
}); height: theme.spacing(avatarHeight),
}));
export const RoleAndOwnerInfo = ({ roles, owners }: Props) => { export const RoleAndOwnerInfo = ({ roles, owners }: Props) => {
const firstRoles = roles.slice(0, 3); const firstRoles = roles.slice(0, 3);
const extraRoles = roles.slice(3); const extraRoles = roles.slice(3);
const ownersWithoutSystem = owners.filter(
(owner) => owner.ownerType !== 'system',
);
return ( return (
<Wrapper data-loading> <Wrapper data-loading>
<InfoSection> <InfoSection>
@ -104,6 +111,8 @@ export const RoleAndOwnerInfo = ({ roles, owners }: Props) => {
)} )}
</InfoSection> </InfoSection>
<InfoSection> <InfoSection>
{ownersWithoutSystem.length > 0 ? (
<>
<Typography <Typography
variant='body1' variant='body1'
component='h4' component='h4'
@ -111,9 +120,15 @@ export const RoleAndOwnerInfo = ({ roles, owners }: Props) => {
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
}} }}
> >
Project owner{owners.length > 1 ? 's' : ''} Project owner
{ownersWithoutSystem.length > 1 ? 's' : ''}
</Typography> </Typography>
<StyledAvatarGroup users={owners} avatarLimit={3} /> <StyledAvatarGroup
users={ownersWithoutSystem as ProjectSchemaOwners}
avatarLimit={3}
/>
</>
) : null}
</InfoSection> </InfoSection>
</Wrapper> </Wrapper>
); );

View File

@ -5,6 +5,7 @@ import {
ProjectOwners, ProjectOwners,
type IProjectOwnersProps, type IProjectOwnersProps,
} from './ProjectOwners/ProjectOwners'; } from './ProjectOwners/ProjectOwners';
import type { ProjectSchemaOwners } from 'openapi';
interface IProjectCardFooterProps { interface IProjectCardFooterProps {
id?: string; id?: string;
@ -24,6 +25,8 @@ const StyledFooter = styled(Box)<{ disabled: boolean }>(
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between', justifyContent: 'space-between',
borderTop: `1px solid ${theme.palette.divider}`, borderTop: `1px solid ${theme.palette.divider}`,
paddingInline: theme.spacing(2),
paddingBlock: theme.spacing(1.5),
}), }),
); );
@ -32,9 +35,16 @@ export const ProjectCardFooter: FC<IProjectCardFooterProps> = ({
owners, owners,
disabled = false, disabled = false,
}) => { }) => {
const ownersWithoutSystem = owners?.filter(
(owner) => owner.ownerType !== 'system',
);
return ( return (
<StyledFooter disabled={disabled}> <StyledFooter disabled={disabled}>
{owners ? <ProjectOwners owners={owners} /> : null} {ownersWithoutSystem ? (
<ProjectOwners
owners={ownersWithoutSystem as ProjectSchemaOwners}
/>
) : null}
{children} {children}
</StyledFooter> </StyledFooter>
); );

View File

@ -45,14 +45,16 @@ const StyledHeader = styled('span')(({ theme }) => ({
marginRight: 'auto', marginRight: 'auto',
})); }));
const AvatarHeight = 3.5;
const StyledWrapper = styled('div')(({ theme }) => ({ const StyledWrapper = styled('div')(({ theme }) => ({
padding: theme.spacing(1.5, 0, 1.5, 2),
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
minHeight: theme.spacing(AvatarHeight),
})); }));
const StyledAvatarComponent = styled(AvatarComponent)(({ theme }) => ({ const StyledAvatarComponent = styled(AvatarComponent)(({ theme }) => ({
cursor: 'default', cursor: 'default',
height: theme.spacing(AvatarHeight),
})); }));
const getOwnerName = (owner?: ProjectSchemaOwners[number]) => { const getOwnerName = (owner?: ProjectSchemaOwners[number]) => {