1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01:00

refactor: fix stats layout and unify components (#6671)

This commit is contained in:
Jaanus Sellin 2024-03-22 10:07:44 +02:00 committed by GitHub
parent e6150def36
commit f5a7cc9125
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 135 additions and 137 deletions

View File

@ -57,7 +57,7 @@ export const ProjectInsights = () => {
<NarrowContainer>
<FlagTypesUsed featureTypeCounts={data.featureTypeCounts} />
</NarrowContainer>
<NarrowContainer>
<NarrowContainer sx={{ padding: 0 }}>
<ProjectMembers projectId={projectId} members={data.members} />
</NarrowContainer>
<WideContainer>

View File

@ -34,13 +34,7 @@ export const HelpPopper: FC<IHelpPopperProps> = ({ children, id }) => {
const open = Boolean(anchor);
return (
<Box
sx={{
position: 'absolute',
top: (theme) => theme.spacing(0.5),
right: (theme) => theme.spacing(0.5),
}}
>
<Box>
<IconButton onClick={onOpen} aria-describedby={id} size='small'>
<HelpOutline
sx={{

View File

@ -2,6 +2,9 @@ import { Box, styled, Typography } from '@mui/material';
import type { ProjectStatsSchema } from 'openapi/models';
import { HelpPopper } from './HelpPopper';
import { StatusBox } from './StatusBox';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
import { Link } from 'react-router-dom';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
const StyledBox = styled(Box)(({ theme }) => ({
display: 'grid',
@ -16,27 +19,20 @@ const StyledBox = styled(Box)(({ theme }) => ({
},
}));
const StyledWidget = styled(Box)(({ theme }) => ({
position: 'relative',
padding: theme.spacing(3),
backgroundColor: theme.palette.background.paper,
flex: 1,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: `${theme.shape.borderRadiusLarge}px`,
[theme.breakpoints.down('lg')]: {
padding: theme.spacing(2),
},
}));
const StyledTimeToProductionDescription = styled(Typography)(({ theme }) => ({
color: theme.palette.text.secondary,
fontSize: theme.typography.body2.fontSize,
lineHeight: theme.typography.body2.lineHeight,
}));
const NavigationBar = styled(Link)(({ theme }) => ({
marginLeft: 'auto',
display: 'flex',
justifyContent: 'space-between',
textDecoration: 'none',
color: theme.palette.text.primary,
}));
interface IProjectStatsProps {
stats: ProjectStatsSchema;
}
@ -45,6 +41,7 @@ export const ProjectInsightsStats = ({ stats }: IProjectStatsProps) => {
if (Object.keys(stats).length === 0) {
return null;
}
const projectId = useRequiredPathParam('projectId');
const {
avgTimeToProdCurrentWindow,
@ -58,79 +55,77 @@ export const ProjectInsightsStats = ({ stats }: IProjectStatsProps) => {
return (
<StyledBox>
<StyledWidget>
<StatusBox
title='Total changes'
boxText={String(projectActivityCurrentWindow)}
change={
projectActivityCurrentWindow - projectActivityPastWindow
}
>
<HelpPopper id='total-changes'>
Sum of all configuration and state modifications in the
project.
</HelpPopper>
</StatusBox>
</StyledWidget>
<StyledWidget>
<StatusBox
title='Avg. time to production'
boxText={
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: (theme) => theme.spacing(1),
}}
>
{avgTimeToProdCurrentWindow}{' '}
<Typography component='span'>days</Typography>
</Box>
}
customChangeElement={
<StyledTimeToProductionDescription>
In project life
</StyledTimeToProductionDescription>
}
percentage
>
<HelpPopper id='avg-time-to-prod'>
How long did it take on average from a feature toggle
was created until it was enabled in an environment of
type production. This is calculated only from feature
toggles with the type of "release".
</HelpPopper>
</StatusBox>
</StyledWidget>
<StyledWidget>
<StatusBox
title='Features created'
boxText={String(createdCurrentWindow)}
change={createdCurrentWindow - createdPastWindow}
/>
</StyledWidget>
<StatusBox
title='Total changes'
boxText={String(projectActivityCurrentWindow)}
change={
projectActivityCurrentWindow - projectActivityPastWindow
}
>
<HelpPopper id='total-changes'>
Sum of all configuration and state modifications in the
project.
</HelpPopper>
</StatusBox>
<StatusBox
title='Avg. time to production'
boxText={
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: (theme) => theme.spacing(1),
}}
>
{avgTimeToProdCurrentWindow}{' '}
<Typography component='span'>days</Typography>
</Box>
}
customChangeElement={
<StyledTimeToProductionDescription>
In project life
</StyledTimeToProductionDescription>
}
percentage
>
<HelpPopper id='avg-time-to-prod'>
How long did it take on average from a feature toggle was
created until it was enabled in an environment of type
production. This is calculated only from feature toggles
with the type of "release".
</HelpPopper>
</StatusBox>
<StatusBox
title='Features created'
boxText={String(createdCurrentWindow)}
change={createdCurrentWindow - createdPastWindow}
>
<NavigationBar to={`/projects/${projectId}`}>
<KeyboardArrowRight />
</NavigationBar>
</StatusBox>
<StyledWidget>
<StatusBox
title='Stale toggles'
boxText={String(projectActivityCurrentWindow)}
change={
projectActivityCurrentWindow - projectActivityPastWindow
}
>
<HelpPopper id='stale-toggles'>
Sum of all stale toggles in the project
</HelpPopper>
</StatusBox>
</StyledWidget>
<StatusBox
title='Stale flags'
boxText={String(projectActivityCurrentWindow)}
change={
projectActivityCurrentWindow - projectActivityPastWindow
}
>
<NavigationBar to={`/projects/${projectId}/health`}>
<KeyboardArrowRight />
</NavigationBar>
</StatusBox>
<StyledWidget>
<StatusBox
title='Features archived'
boxText={String(archivedCurrentWindow)}
change={archivedCurrentWindow - archivedPastWindow}
/>
</StyledWidget>
<StatusBox
title='Features archived'
boxText={String(archivedCurrentWindow)}
change={archivedCurrentWindow - archivedPastWindow}
>
<NavigationBar to={`/projects/${projectId}/archive`}>
<KeyboardArrowRight />
</NavigationBar>
</StatusBox>
</StyledBox>
);
};

View File

@ -5,10 +5,6 @@ import { Box, Typography, styled } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { flexRow } from 'themes/themeStyles';
const StyledTypographyHeader = styled(Typography)(({ theme }) => ({
marginBottom: theme.spacing(2.5),
}));
const StyledTypographyCount = styled(Box)(({ theme }) => ({
fontSize: theme.fontSizes.largeHeader,
}));
@ -31,8 +27,25 @@ const StyledTypographyChange = styled(Typography)(({ theme }) => ({
fontWeight: theme.typography.fontWeightBold,
}));
const RowContainer = styled(Box)(({ theme }) => ({
...flexRow,
}));
const StyledWidget = styled(Box)(({ theme }) => ({
padding: theme.spacing(3),
backgroundColor: theme.palette.background.paper,
flex: 1,
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(2.5),
borderRadius: `${theme.shape.borderRadiusLarge}px`,
[theme.breakpoints.down('lg')]: {
padding: theme.spacing(2),
},
}));
interface IStatusBoxProps {
title?: string;
title: string;
boxText: ReactNode;
change?: number;
percentage?: boolean;
@ -42,10 +55,24 @@ interface IStatusBoxProps {
const resolveIcon = (change: number) => {
if (change > 0) {
return (
<CallMade sx={{ color: 'success.dark', height: 20, width: 20 }} />
<CallMade
sx={{
color: 'success.dark',
height: 20,
width: 20,
}}
/>
);
}
return <SouthEast sx={{ color: 'warning.dark', height: 20, width: 20 }} />;
return (
<SouthEast
sx={{
color: 'warning.dark',
height: 20,
width: 20,
}}
/>
);
};
const resolveColor = (change: number) => {
@ -63,23 +90,14 @@ export const StatusBox: FC<IStatusBoxProps> = ({
children,
customChangeElement,
}) => (
<>
<ConditionallyRender
condition={Boolean(title)}
show={
<StyledTypographyHeader data-loading>
{title}
</StyledTypographyHeader>
}
/>
{children}
<Box
sx={{
...flexRow,
justifyContent: 'center',
width: 'auto',
}}
>
<StyledWidget>
<RowContainer>
<Typography variant='h3' data-loading>
{title}
</Typography>
{children}
</RowContainer>
<RowContainer>
<StyledTypographyCount data-loading>
{boxText}
</StyledTypographyCount>
@ -124,6 +142,6 @@ export const StatusBox: FC<IStatusBoxProps> = ({
/>
}
/>
</Box>
</>
</RowContainer>
</StyledWidget>
);

View File

@ -1,5 +1,5 @@
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { Box, styled, Typography } from '@mui/material';
import { styled } from '@mui/material';
import { StatusBox } from '../ProjectInsightsStats/StatusBox';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
import { Link } from 'react-router-dom';
@ -11,18 +11,13 @@ interface IProjectMembersProps {
}
const NavigationBar = styled(Link)(({ theme }) => ({
marginLeft: 'auto',
display: 'flex',
justifyContent: 'space-between',
textDecoration: 'none',
color: theme.palette.text.primary,
}));
export const StyledProjectInfoWidgetContainer = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(2.5),
}));
export const ProjectMembers = ({
members,
projectId,
@ -35,18 +30,14 @@ export const ProjectMembers = ({
const { currentMembers, change } = members;
return (
<StyledProjectInfoWidgetContainer>
<StatusBox
title={'Project members'}
boxText={`${currentMembers}`}
change={change}
>
<NavigationBar to={link}>
<Typography variant='h3'>Project members</Typography>
<KeyboardArrowRight />
</NavigationBar>
<Box
sx={{
display: 'flex',
}}
>
<StatusBox boxText={`${currentMembers}`} change={change} />
</Box>
</StyledProjectInfoWidgetContainer>
</StatusBox>
);
};