mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-17 13:46:47 +02:00
This change swaps out the color of the health chart "unfilled" section for `theme.palette.background.application`. This is the same color that's used in the sketches, so it should apply better for dark mode. Why? I noticed that the graph looks choppy in dark mode, so figured I'd go and investigate. This update makes it look a lot smoother. Light mode looks the same as before. Before (notice the leaking light grey):  After: 
176 lines
6.1 KiB
TypeScript
176 lines
6.1 KiB
TypeScript
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';
|
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
|
import { HealthGridTile } from './ProjectHealthGrid.styles';
|
|
import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/PrettifyLargeNumber';
|
|
|
|
const ChartRadius = 40;
|
|
const ChartStrokeWidth = 13;
|
|
const ChartTotalWidth = ChartRadius * 2 + ChartStrokeWidth;
|
|
const ChartContainerWidth = 100;
|
|
|
|
const TextContainer = styled('div')(({ theme }) => ({
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: theme.spacing(1),
|
|
}));
|
|
|
|
const ChartRow = styled('div')(({ theme }) => ({
|
|
display: 'flex',
|
|
alignItems: 'flex-start',
|
|
gap: theme.spacing(2),
|
|
}));
|
|
|
|
const SVGWrapper = styled('div')(({ theme }) => ({
|
|
flex: 'none',
|
|
height: 85,
|
|
width: ChartContainerWidth,
|
|
position: 'relative',
|
|
}));
|
|
|
|
const StyledSVG = styled('svg')({
|
|
position: 'absolute',
|
|
});
|
|
|
|
const BigText = styled('span')(({ theme }) => ({
|
|
fontSize: theme.typography.h1.fontSize,
|
|
}));
|
|
|
|
const UnhealthyStatContainer = styled('div')(({ theme }) => ({
|
|
flex: 'none',
|
|
display: 'grid',
|
|
placeItems: 'center',
|
|
width: ChartContainerWidth,
|
|
}));
|
|
|
|
const UnhealthyStatText = styled('p')(({ theme }) => ({
|
|
fontSize: theme.typography.body2.fontSize,
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
borderRadius: '50%',
|
|
backgroundColor:
|
|
theme.mode === 'light'
|
|
? theme.palette.background.elevation2
|
|
: '#302E42', // in dark mode, elevation2 and elevation1 are the same color. This is an alternative
|
|
width: ChartTotalWidth,
|
|
height: ChartTotalWidth,
|
|
overflow: 'hidden',
|
|
}));
|
|
|
|
const UnhealthyFlagBox = ({ flagCount }: { flagCount: number }) => {
|
|
const flagWord = flagCount === 1 ? 'flag' : 'flags';
|
|
return (
|
|
<UnhealthyStatContainer>
|
|
<UnhealthyStatText>
|
|
<BigText>
|
|
<PrettifyLargeNumber
|
|
value={flagCount}
|
|
threshold={1000}
|
|
precision={1}
|
|
/>
|
|
</BigText>
|
|
<span>unhealthy</span>
|
|
<span>{flagWord}</span>
|
|
</UnhealthyStatText>
|
|
</UnhealthyStatContainer>
|
|
);
|
|
};
|
|
|
|
const Wrapper = styled(HealthGridTile)(({ theme }) => ({
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
justifyContent: 'space-around',
|
|
gap: theme.spacing(2),
|
|
}));
|
|
|
|
export const ProjectHealth = () => {
|
|
const projectId = useRequiredPathParam('projectId');
|
|
const {
|
|
data: { averageHealth, staleFlags },
|
|
} = useProjectStatus(projectId);
|
|
const { isOss } = useUiConfig();
|
|
const theme = useTheme();
|
|
const circumference = 2 * Math.PI * ChartRadius; //
|
|
|
|
const gapLength = 0.3;
|
|
const filledLength = 1 - gapLength;
|
|
const offset = 0.75 - gapLength / 2;
|
|
const healthLength = (averageHealth / 100) * circumference * 0.7;
|
|
|
|
const healthColor =
|
|
averageHealth >= 0 && averageHealth <= 24
|
|
? theme.palette.error.main
|
|
: averageHealth >= 25 && averageHealth <= 74
|
|
? theme.palette.warning.border
|
|
: theme.palette.success.border;
|
|
|
|
return (
|
|
<Wrapper>
|
|
<ChartRow>
|
|
<SVGWrapper>
|
|
<StyledSVG viewBox='0 0 100 100'>
|
|
<circle
|
|
cx='50'
|
|
cy='50'
|
|
r={ChartRadius}
|
|
fill='none'
|
|
stroke={theme.palette.background.application}
|
|
strokeWidth={ChartStrokeWidth}
|
|
strokeDasharray={`${filledLength * circumference} ${gapLength * circumference}`}
|
|
strokeDashoffset={offset * circumference}
|
|
/>
|
|
<circle
|
|
cx='50'
|
|
cy='50'
|
|
r={ChartRadius}
|
|
fill='none'
|
|
stroke={healthColor}
|
|
strokeWidth={ChartStrokeWidth}
|
|
strokeDasharray={`${healthLength} ${circumference - healthLength}`}
|
|
strokeDashoffset={offset * circumference}
|
|
/>
|
|
<text
|
|
x='50'
|
|
y='50'
|
|
textAnchor='middle'
|
|
dominantBaseline='middle'
|
|
fill={theme.palette.text.primary}
|
|
fontSize={theme.typography.h1.fontSize}
|
|
>
|
|
{averageHealth}%
|
|
</text>
|
|
</StyledSVG>
|
|
</SVGWrapper>
|
|
<TextContainer>
|
|
<Typography>
|
|
On average, your project health has remained at{' '}
|
|
{averageHealth}% the last 4 weeks
|
|
</Typography>
|
|
{!isOss() && (
|
|
<Link to={`/insights?project=IS%3A${projectId}`}>
|
|
View health over time
|
|
</Link>
|
|
)}
|
|
</TextContainer>
|
|
</ChartRow>
|
|
<ChartRow>
|
|
<UnhealthyFlagBox flagCount={staleFlags.total} />
|
|
<TextContainer>
|
|
<Typography variant='body2'>
|
|
To keep your project healthy, archive stale feature
|
|
flags and remove code from your code base to reduce
|
|
technical debt.
|
|
</Typography>
|
|
<Link to={`/projects/${projectId}?state=IS%3Astale`}>
|
|
View unhealthy flags
|
|
</Link>
|
|
</TextContainer>
|
|
</ChartRow>
|
|
</Wrapper>
|
|
);
|
|
};
|