Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add stale flags counter #8741

Merged
merged 12 commits into from
Nov 14, 2024
109 changes: 63 additions & 46 deletions frontend/src/component/project/Project/ProjectStatus/ProjectHealth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,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 = () => {
Expand Down Expand Up @@ -53,48 +66,52 @@ export const ProjectHealth = () => {
return (
<HealthContainer>
<ChartRow>
<StyledSVG viewBox='0 0 100 100'>
<circle
cx='50'
cy='50'
r={radius}
fill='none'
stroke={theme.palette.grey[300]}
strokeWidth={strokeWidth}
strokeDasharray={`${filledLength * circumference} ${gapLength * circumference}`}
strokeDashoffset={offset * circumference}
/>
<circle
cx='50'
cy='50'
r={radius}
fill='none'
stroke={healthColor}
strokeWidth={strokeWidth}
strokeDasharray={`${healthLength} ${circumference - healthLength}`}
strokeDashoffset={offset * circumference}
/>
<text
x='50'
y='50'
textAnchor='middle'
dominantBaseline='middle'
fill={theme.palette.text.primary}
fontSize='24px'
>
{averageHealth}%
</text>
</StyledSVG>
<Typography variant='body2'>
On average, your project health has remained at{' '}
{averageHealth}% the last 4 weeks
</Typography>
<SVGWrapper>
<StyledSVG viewBox='0 0 100 100'>
<circle
cx='50'
cy='50'
r={radius}
fill='none'
stroke={theme.palette.grey[300]}
strokeWidth={strokeWidth}
strokeDasharray={`${filledLength * circumference} ${gapLength * circumference}`}
strokeDashoffset={offset * circumference}
/>
<circle
cx='50'
cy='50'
r={radius}
fill='none'
stroke={healthColor}
strokeWidth={strokeWidth}
strokeDasharray={`${healthLength} ${circumference - healthLength}`}
strokeDashoffset={offset * circumference}
/>
<text
x='50'
y='50'
textAnchor='middle'
dominantBaseline='middle'
fill={theme.palette.text.primary}
fontSize='24px'
>
{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>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) => ({
Expand All @@ -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,
},
});

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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>
<ProjectHealth />
<ProjectResources />
</HealthRow>
<HealthContainer>
<HealthGrid>
<ProjectHealth />
<StaleFlags />
<ProjectResources />
</HealthGrid>
</HealthContainer>

<ProjectActivity />

Expand Down
Original file line number Diff line number Diff line change
@@ -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