mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-09 00:18:00 +01:00
feat: style project resources component (#8636)
This PR adds full styling for the project resources UI widget, adding icons, links, and sorting out the layout. Light mode: <img width="663" alt="image" src="https://github.com/user-attachments/assets/51231c67-1a0f-4018-9603-c476dac3b03a"> Dark mode: <img width="663" alt="image" src="https://github.com/user-attachments/assets/8943e479-2ecb-4917-9fad-fb6e1f1649a5"> On narrower screens: <img width="474" alt="image" src="https://github.com/user-attachments/assets/e0133f79-c389-444c-8d82-226cffd1015c">
This commit is contained in:
parent
2e99452645
commit
9a5d965636
@ -1,22 +1,99 @@
|
|||||||
import { styled } from '@mui/material';
|
import { Typography, styled } from '@mui/material';
|
||||||
import { useProjectApiTokens } from 'hooks/api/getters/useProjectApiTokens/useProjectApiTokens';
|
import { useProjectApiTokens } from 'hooks/api/getters/useProjectApiTokens/useProjectApiTokens';
|
||||||
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
|
||||||
import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
|
import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import { useMemo } from 'react';
|
import {
|
||||||
|
type ReactNode,
|
||||||
|
useMemo,
|
||||||
|
type FC,
|
||||||
|
type PropsWithChildren,
|
||||||
|
} from 'react';
|
||||||
|
import UsersIcon from '@mui/icons-material/Group';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import ApiKeyIcon from '@mui/icons-material/Key';
|
||||||
|
import SegmentsIcon from '@mui/icons-material/DonutLarge';
|
||||||
|
import ConnectedIcon from '@mui/icons-material/Cable';
|
||||||
|
|
||||||
const Wrapper = styled('article')(({ theme }) => ({
|
const Wrapper = styled('article')(({ theme }) => ({
|
||||||
backgroundColor: theme.palette.envAccordion.expanded,
|
backgroundColor: theme.palette.envAccordion.expanded,
|
||||||
padding: theme.spacing(2),
|
padding: theme.spacing(3),
|
||||||
borderRadius: theme.shape.borderRadiusExtraLarge,
|
borderRadius: theme.shape.borderRadiusExtraLarge,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const ProjectResourcesInner = styled('div')(({ theme }) => ({
|
const ProjectResourcesInner = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
gap: '1rem',
|
gap: theme.spacing(2),
|
||||||
|
containerType: 'inline-size',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const ItemContent = styled('span')(({ theme }) => ({
|
||||||
|
display: 'inline-flex',
|
||||||
|
flexFlow: 'row nowrap',
|
||||||
|
gap: theme.spacing(1),
|
||||||
|
svg: {
|
||||||
|
fill: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const onNarrowWidget = (css: object) => ({
|
||||||
|
'@container (max-width: 400px)': css,
|
||||||
|
'@supports not (container-type: inline-size)': {
|
||||||
|
'@media (max-width: 400px)': css,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const ListItemRow = styled('li')(({ theme }) => {
|
||||||
|
return {
|
||||||
|
display: 'flex',
|
||||||
|
flexFlow: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: theme.spacing(1),
|
||||||
|
|
||||||
|
...onNarrowWidget({
|
||||||
|
flexFlow: 'column',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
justifyContent: 'unset',
|
||||||
|
'& + li': {
|
||||||
|
marginTop: theme.spacing(5),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const ResourceList = styled('ul')(({ theme }) => ({
|
||||||
|
margin: 0,
|
||||||
|
listStyle: 'none',
|
||||||
|
padding: 0,
|
||||||
|
'li + li': {
|
||||||
|
marginTop: theme.spacing(2),
|
||||||
|
},
|
||||||
|
|
||||||
|
...onNarrowWidget({
|
||||||
|
'li + li': {
|
||||||
|
marginTop: theme.spacing(4),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const ListItem: FC<
|
||||||
|
PropsWithChildren<{
|
||||||
|
linkUrl: string;
|
||||||
|
linkText: string;
|
||||||
|
icon: ReactNode;
|
||||||
|
}>
|
||||||
|
> = ({ children, linkUrl, linkText, icon }) => (
|
||||||
|
<ListItemRow>
|
||||||
|
<ItemContent>
|
||||||
|
{icon}
|
||||||
|
<span>{children}</span>
|
||||||
|
</ItemContent>
|
||||||
|
<Link to={linkUrl}>{linkText}</Link>
|
||||||
|
</ListItemRow>
|
||||||
|
);
|
||||||
|
|
||||||
export const ProjectResources = () => {
|
export const ProjectResources = () => {
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const { project, loading: loadingProject } = useProjectOverview(projectId);
|
const { project, loading: loadingProject } = useProjectOverview(projectId);
|
||||||
@ -34,11 +111,42 @@ export const ProjectResources = () => {
|
|||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<ProjectResourcesInner>
|
<ProjectResourcesInner>
|
||||||
<h3>Project Resources</h3>
|
<Typography variant='h3' sx={{ margin: 0 }}>
|
||||||
<span>{project.members} project member(s)</span>
|
Project Resources
|
||||||
<span>{tokens.length} API key(s)</span>
|
</Typography>
|
||||||
<span>1 SDK connection(s)</span>
|
<ResourceList>
|
||||||
<span>{segmentCount} project segment(s)</span>
|
<ListItem
|
||||||
|
linkUrl={`/projects/${projectId}/settings/access`}
|
||||||
|
linkText='Add members'
|
||||||
|
icon={<UsersIcon />}
|
||||||
|
>
|
||||||
|
{project.members} project member(s)
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem
|
||||||
|
linkUrl={`/projects/${projectId}/settings/api-access`}
|
||||||
|
linkText='Add new key'
|
||||||
|
icon={<ApiKeyIcon />}
|
||||||
|
>
|
||||||
|
{tokens.length} API key(s)
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem
|
||||||
|
linkUrl={`/projects/${projectId}/settings/placeholder`}
|
||||||
|
linkText='View connections'
|
||||||
|
icon={<ConnectedIcon />}
|
||||||
|
>
|
||||||
|
1 connected environment(s)
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem
|
||||||
|
linkUrl={`/projects/${projectId}/settings/segments`}
|
||||||
|
linkText='Add segments'
|
||||||
|
icon={<SegmentsIcon />}
|
||||||
|
>
|
||||||
|
{segmentCount} project segment(s)
|
||||||
|
</ListItem>
|
||||||
|
</ResourceList>
|
||||||
</ProjectResourcesInner>
|
</ProjectResourcesInner>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user