mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-09 00:18:00 +01:00
feat: Add stale flags counter (#8741)
This PR adds the stale flag component to the health grid. In doing so, it also reworks the layout of the health row (now a grid) and updates the health component. In addition to removing the text from the component, I have adjust the SVG a bit to make it not shrink on smaller screens and have adjusted it's spacing, so that it's not full of dead space at the bottom. This makes it easier to style because it doesn't add 15px of invisible content. This PR also touches up a few other visual issues I found, such as header level and sidebar width. Wide: ![image](https://github.com/user-attachments/assets/acb57b17-eb7f-4b69-9bfa-1113bb748467) Medium: ![image](https://github.com/user-attachments/assets/a57331b0-825f-4b20-9b05-3ecd81804f5d) Narrow: ![image](https://github.com/user-attachments/assets/65c6e8d1-1783-4354-b71b-2867eabcc9ec)
This commit is contained in:
parent
3e424ec20d
commit
9440b52464
@ -1,5 +1,4 @@
|
||||
import { useTheme, Typography } from '@mui/material';
|
||||
import { styled } from '@mui/system';
|
||||
import { styled, useTheme, Typography } from '@mui/material';
|
||||
import { Link } from 'react-router-dom';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { useProjectStatus } from 'hooks/api/getters/useProjectStatus/useProjectStatus';
|
||||
@ -10,21 +9,34 @@ const HealthContainer = styled('div')(({ theme }) => ({
|
||||
padding: theme.spacing(3),
|
||||
borderRadius: theme.shape.borderRadiusExtraLarge,
|
||||
minWidth: '300px',
|
||||
gridArea: 'health',
|
||||
}));
|
||||
|
||||
const TextContainer = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: theme.spacing(1),
|
||||
}));
|
||||
|
||||
const ChartRow = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: theme.spacing(2),
|
||||
}));
|
||||
|
||||
const SVGWrapper = styled('div')(({ theme }) => ({
|
||||
flex: 'none',
|
||||
height: 85,
|
||||
width: 100,
|
||||
position: 'relative',
|
||||
}));
|
||||
|
||||
const StyledSVG = styled('svg')({
|
||||
width: 200,
|
||||
height: 100,
|
||||
position: 'absolute',
|
||||
});
|
||||
|
||||
const DescriptionText = styled(Typography)(({ theme }) => ({
|
||||
color: theme.palette.text.secondary,
|
||||
marginBottom: theme.spacing(2),
|
||||
const StyledLink = styled(Link)(({ theme }) => ({
|
||||
fontSize: theme.typography.body2.fontSize,
|
||||
}));
|
||||
|
||||
export const ProjectHealth = () => {
|
||||
@ -53,6 +65,7 @@ export const ProjectHealth = () => {
|
||||
return (
|
||||
<HealthContainer>
|
||||
<ChartRow>
|
||||
<SVGWrapper>
|
||||
<StyledSVG viewBox='0 0 100 100'>
|
||||
<circle
|
||||
cx='50'
|
||||
@ -85,16 +98,19 @@ export const ProjectHealth = () => {
|
||||
{averageHealth}%
|
||||
</text>
|
||||
</StyledSVG>
|
||||
</SVGWrapper>
|
||||
<TextContainer>
|
||||
<Typography variant='body2'>
|
||||
On average, your project health has remained at{' '}
|
||||
{averageHealth}% the last 4 weeks
|
||||
</Typography>
|
||||
{!isOss() && (
|
||||
<StyledLink to='/insights'>
|
||||
View health over time
|
||||
</StyledLink>
|
||||
)}
|
||||
</TextContainer>
|
||||
</ChartRow>
|
||||
<DescriptionText variant='body2'>
|
||||
Remember to archive your stale feature flags to keep the project
|
||||
health growing
|
||||
</DescriptionText>
|
||||
{!isOss() && <Link to='/insights'>View health over time</Link>}
|
||||
</HealthContainer>
|
||||
);
|
||||
};
|
||||
|
@ -14,6 +14,7 @@ const Wrapper = styled('article')(({ theme }) => ({
|
||||
padding: theme.spacing(3),
|
||||
borderRadius: theme.shape.borderRadiusExtraLarge,
|
||||
minWidth: '300px',
|
||||
gridArea: 'resources',
|
||||
}));
|
||||
|
||||
const ProjectResourcesInner = styled('div')(({ theme }) => ({
|
||||
@ -33,9 +34,9 @@ const ItemContent = styled('span')(({ theme }) => ({
|
||||
}));
|
||||
|
||||
const onNarrowWidget = (css: object) => ({
|
||||
'@container (max-width: 400px)': css,
|
||||
'@container (max-width: 385px)': css,
|
||||
'@supports not (container-type: inline-size)': {
|
||||
'@media (max-width: 400px)': css,
|
||||
'@media (max-width: 385px)': css,
|
||||
},
|
||||
});
|
||||
|
||||
@ -116,8 +117,8 @@ export const ProjectResources = () => {
|
||||
return (
|
||||
<Wrapper ref={loadingRef}>
|
||||
<ProjectResourcesInner>
|
||||
<Typography variant='h3' sx={{ margin: 0 }}>
|
||||
Project Resources
|
||||
<Typography variant='h4' sx={{ margin: 0 }}>
|
||||
Project resources
|
||||
</Typography>
|
||||
<ResourceList>
|
||||
<ListItem
|
||||
|
@ -4,9 +4,12 @@ import { ProjectResources } from './ProjectResources';
|
||||
import { ProjectActivity } from './ProjectActivity';
|
||||
import { ProjectHealth } from './ProjectHealth';
|
||||
import { ProjectLifecycleSummary } from './ProjectLifecycleSummary';
|
||||
import { StaleFlags } from './StaleFlags';
|
||||
|
||||
const ModalContentContainer = styled('div')(({ theme }) => ({
|
||||
const ModalContentContainer = styled('section')(({ theme }) => ({
|
||||
minHeight: '100vh',
|
||||
maxWidth: 1100,
|
||||
width: '95vw',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
padding: theme.spacing(4),
|
||||
display: 'flex',
|
||||
@ -19,27 +22,43 @@ type Props = {
|
||||
close: () => void;
|
||||
};
|
||||
|
||||
const HealthRow = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexFlow: 'row wrap',
|
||||
padding: theme.spacing(2),
|
||||
gap: theme.spacing(2),
|
||||
'&>*': {
|
||||
// todo: reconsider this value when the health widget is
|
||||
// implemented. It may not be right, but it works for the
|
||||
// placeholder
|
||||
flex: '30%',
|
||||
const onNarrowGrid = (css: object) => ({
|
||||
'@container (max-width: 650px)': css,
|
||||
'@supports not (container-type: inline-size)': {
|
||||
'@media (max-width: 712px)': css,
|
||||
},
|
||||
});
|
||||
|
||||
const HealthContainer = styled('div')({
|
||||
containerType: 'inline-size',
|
||||
});
|
||||
|
||||
const HealthGrid = styled('div')(({ theme }) => ({
|
||||
display: 'grid',
|
||||
gridTemplateAreas: `
|
||||
"health resources"
|
||||
"stale resources"
|
||||
`,
|
||||
gridTemplateColumns: '1fr 1fr',
|
||||
gap: theme.spacing(1, 2),
|
||||
...onNarrowGrid({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: theme.spacing(1),
|
||||
}),
|
||||
}));
|
||||
|
||||
export const ProjectStatusModal = ({ open, close }: Props) => {
|
||||
return (
|
||||
<DynamicSidebarModal open={open} onClose={close} label='Project status'>
|
||||
<ModalContentContainer>
|
||||
<HealthRow>
|
||||
<HealthContainer>
|
||||
<HealthGrid>
|
||||
<ProjectHealth />
|
||||
<StaleFlags />
|
||||
<ProjectResources />
|
||||
</HealthRow>
|
||||
</HealthGrid>
|
||||
</HealthContainer>
|
||||
|
||||
<ProjectActivity />
|
||||
|
||||
|
@ -0,0 +1,52 @@
|
||||
import { Typography } from '@mui/material';
|
||||
import { styled } from '@mui/material';
|
||||
import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/PrettifyLargeNumber';
|
||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||
import type { FC } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const Wrapper = styled('article')(({ theme }) => ({
|
||||
backgroundColor: theme.palette.envAccordion.expanded,
|
||||
padding: theme.spacing(3),
|
||||
borderRadius: theme.shape.borderRadiusExtraLarge,
|
||||
minWidth: '300px',
|
||||
gridArea: 'stale',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: theme.spacing(1),
|
||||
}));
|
||||
|
||||
const BigText = styled('span')(({ theme }) => ({
|
||||
fontSize: `calc(2 * ${theme.typography.body1.fontSize})`,
|
||||
lineHeight: 0,
|
||||
}));
|
||||
|
||||
const BigNumber: FC<{ value?: number }> = ({ value }) => {
|
||||
return (
|
||||
<BigText>
|
||||
<PrettifyLargeNumber
|
||||
value={value ?? 0}
|
||||
threshold={1000}
|
||||
precision={1}
|
||||
/>
|
||||
</BigText>
|
||||
);
|
||||
};
|
||||
|
||||
export const StaleFlags = () => {
|
||||
const projectId = useRequiredPathParam('projectId');
|
||||
return (
|
||||
<Wrapper>
|
||||
<Typography component='h4'>
|
||||
<BigNumber value={6} />{' '}
|
||||
<Link to={`/projects/${projectId}?state=IS%3Astale`}>
|
||||
stale flags
|
||||
</Link>
|
||||
</Typography>
|
||||
<Typography variant='body2'>
|
||||
Remember to archive your stale feature flags to keep the project
|
||||
healthy
|
||||
</Typography>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue
Block a user