mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-22 01:16:07 +02:00
feat: project health card (#6595)
This commit is contained in:
parent
5db0e9ac6e
commit
52363f176a
@ -0,0 +1,101 @@
|
|||||||
|
import { ProjectHealthChart } from './ProjectHealthChart';
|
||||||
|
import { Alert, Box, styled, Typography, useTheme } from '@mui/material';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
|
|
||||||
|
const Dot = styled('span', {
|
||||||
|
shouldForwardProp: (prop) => prop !== 'color',
|
||||||
|
})<{ color?: string }>(({ theme, color }) => ({
|
||||||
|
height: '15px',
|
||||||
|
width: '15px',
|
||||||
|
borderRadius: '50%',
|
||||||
|
display: 'inline-block',
|
||||||
|
backgroundColor: color,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const FlagsCount = styled('p')(({ theme }) => ({
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
marginLeft: theme.spacing(3),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const FlagCounts = styled(Box)(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: theme.spacing(2),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const Container = styled(Box)(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: theme.spacing(2),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StatusWithDot = styled(Box)(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: theme.spacing(1),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const ProjectHealth = () => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const projectId = useRequiredPathParam('projectId');
|
||||||
|
const active = 15;
|
||||||
|
const stale = 10;
|
||||||
|
const potentiallyStale = 3;
|
||||||
|
const health = 93;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Typography variant='h3'>Project Health</Typography>
|
||||||
|
<Alert severity='warning'>
|
||||||
|
<b>Health alert!</b> Review your flags and delete the stale
|
||||||
|
flags
|
||||||
|
</Alert>
|
||||||
|
<Box
|
||||||
|
sx={(theme) => ({
|
||||||
|
display: 'flex',
|
||||||
|
gap: theme.spacing(4),
|
||||||
|
marginTop: theme.spacing(3),
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<ProjectHealthChart
|
||||||
|
active={active}
|
||||||
|
stale={stale}
|
||||||
|
potentiallyStale={potentiallyStale}
|
||||||
|
health={health}
|
||||||
|
/>
|
||||||
|
<FlagCounts>
|
||||||
|
<Box>
|
||||||
|
<StatusWithDot>
|
||||||
|
<Dot color={theme.palette.success.border} />
|
||||||
|
<Box sx={{ fontWeight: 'bold' }}>Active</Box>
|
||||||
|
</StatusWithDot>
|
||||||
|
<FlagsCount>{active} feature flags</FlagsCount>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<StatusWithDot>
|
||||||
|
<Dot color={theme.palette.warning.border} />
|
||||||
|
<Box sx={{ fontWeight: 'bold' }}>
|
||||||
|
Potentially stale
|
||||||
|
</Box>
|
||||||
|
<Link to='/feature-toggle-type'>(configure)</Link>
|
||||||
|
</StatusWithDot>
|
||||||
|
<FlagsCount>
|
||||||
|
{potentiallyStale} feature flags
|
||||||
|
</FlagsCount>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<StatusWithDot>
|
||||||
|
<Dot color={theme.palette.error.border} />
|
||||||
|
<Box sx={{ fontWeight: 'bold' }}>Stale</Box>
|
||||||
|
<Link to={`/projects/${projectId}`}>
|
||||||
|
(view flags)
|
||||||
|
</Link>
|
||||||
|
</StatusWithDot>
|
||||||
|
<FlagsCount>{stale} feature flags</FlagsCount>
|
||||||
|
</Box>
|
||||||
|
</FlagCounts>
|
||||||
|
</Box>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
@ -1,7 +1,6 @@
|
|||||||
import React from 'react';
|
|
||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
import { ProjectHealthChart } from './ProjectHealthChart';
|
import { ProjectHealthChart } from './ProjectHealthChart';
|
||||||
import { render } from 'utils/testRenderer';
|
import { render } from '../../../../../utils/testRenderer';
|
||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
|
|
||||||
describe('ProjectHealthChart', () => {
|
describe('ProjectHealthChart', () => {
|
@ -1,5 +1,12 @@
|
|||||||
import { Box, styled } from '@mui/material';
|
import { Box, styled } from '@mui/material';
|
||||||
import { LeadTimeForChanges } from './LeadTimeForChanges/LeadTimeForChanges';
|
import { LeadTimeForChanges } from './LeadTimeForChanges/LeadTimeForChanges';
|
||||||
|
import { ProjectHealth } from './ProjectHealth/ProjectHealth';
|
||||||
|
|
||||||
|
const Container = styled(Box)(({ theme }) => ({
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
|
padding: theme.spacing(3),
|
||||||
|
borderRadius: theme.shape.borderRadiusLarge,
|
||||||
|
}));
|
||||||
|
|
||||||
const Grid = styled(Box)(({ theme }) => ({
|
const Grid = styled(Box)(({ theme }) => ({
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -11,7 +18,7 @@ const Overview = styled(Box)(({ theme }) => ({
|
|||||||
gridColumn: '1 / -1',
|
gridColumn: '1 / -1',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const Health = styled(Box)(({ theme }) => ({
|
const Health = styled(Container)(({ theme }) => ({
|
||||||
gridColumn: 'span 5',
|
gridColumn: 'span 5',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -34,7 +41,9 @@ export const ProjectInsights = () => {
|
|||||||
Total changes / avg time to production / feature flags /stale
|
Total changes / avg time to production / feature flags /stale
|
||||||
flags
|
flags
|
||||||
</Overview>
|
</Overview>
|
||||||
<Health>Project Health</Health>
|
<Health>
|
||||||
|
<ProjectHealth />
|
||||||
|
</Health>
|
||||||
<LeadTimeForChanges />
|
<LeadTimeForChanges />
|
||||||
<ToggleTypesUsed>Toggle types used</ToggleTypesUsed>
|
<ToggleTypesUsed>Toggle types used</ToggleTypesUsed>
|
||||||
<ProjectMembers>Project members</ProjectMembers>
|
<ProjectMembers>Project members</ProjectMembers>
|
||||||
|
Loading…
Reference in New Issue
Block a user