mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-31 13:47:02 +02:00
feat: new project health widget (#3003)
## About the changes <img width="233" alt="image" src="https://user-images.githubusercontent.com/2625371/214901419-44adc6c3-ba72-4a60-9af9-ca27e9702357.png"> ## Discussion points Am I loading "potentially stale" features right? ## Other Testing Linear integration: Close 1-605 Close ID-1-605 Close ID1-605
This commit is contained in:
parent
200cfd284b
commit
a482ccff63
@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
StyledArrowIcon,
|
StyledArrowIcon,
|
||||||
|
StyledCount,
|
||||||
StyledDivInfoContainer,
|
StyledDivInfoContainer,
|
||||||
StyledDivPercentageContainer,
|
StyledDivPercentageContainer,
|
||||||
StyledLink,
|
StyledLink,
|
||||||
@ -8,12 +9,64 @@ import {
|
|||||||
StyledSpanLinkText,
|
StyledSpanLinkText,
|
||||||
} from './ProjectInfo.styles';
|
} from './ProjectInfo.styles';
|
||||||
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
|
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
|
||||||
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
|
import { Box, styled, Typography } from '@mui/material';
|
||||||
|
|
||||||
interface IHealthWidgetProps {
|
interface IHealthWidgetProps {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
health: number;
|
health: number;
|
||||||
|
total?: number;
|
||||||
|
stale?: number;
|
||||||
}
|
}
|
||||||
export const HealthWidget = ({ projectId, health }: IHealthWidgetProps) => {
|
|
||||||
|
const StyledWarning = styled('span')<{ active?: boolean }>(
|
||||||
|
({ theme, active }) => ({
|
||||||
|
color: active ? theme.palette.warning.dark : 'inherit',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
export const HealthWidget = ({
|
||||||
|
projectId,
|
||||||
|
health,
|
||||||
|
total,
|
||||||
|
stale,
|
||||||
|
}: IHealthWidgetProps) => {
|
||||||
|
const { uiConfig } = useUiConfig();
|
||||||
|
|
||||||
|
if (uiConfig?.flags?.newProjectOverview) {
|
||||||
|
return (
|
||||||
|
<StyledDivInfoContainer>
|
||||||
|
<StyledParagraphSubtitle data-loading>
|
||||||
|
Project health
|
||||||
|
</StyledParagraphSubtitle>
|
||||||
|
<StyledDivPercentageContainer>
|
||||||
|
<PercentageCircle percentage={health} />
|
||||||
|
</StyledDivPercentageContainer>
|
||||||
|
<StyledParagraphEmphasizedText data-loading>
|
||||||
|
{health}%
|
||||||
|
</StyledParagraphEmphasizedText>
|
||||||
|
<Typography data-loading>
|
||||||
|
<StyledCount>{total}</StyledCount> toggles in total
|
||||||
|
</Typography>
|
||||||
|
<Typography data-loading sx={{ marginBottom: 2 }}>
|
||||||
|
<StyledCount>
|
||||||
|
<StyledWarning active={Boolean(stale)}>
|
||||||
|
{stale}
|
||||||
|
</StyledWarning>
|
||||||
|
</StyledCount>{' '}
|
||||||
|
<StyledWarning active={Boolean(stale)}>
|
||||||
|
potentially stale
|
||||||
|
</StyledWarning>
|
||||||
|
</Typography>
|
||||||
|
<StyledLink data-loading to={`/projects/${projectId}/health`}>
|
||||||
|
<StyledSpanLinkText data-loading>
|
||||||
|
View project health
|
||||||
|
</StyledSpanLinkText>
|
||||||
|
</StyledLink>
|
||||||
|
</StyledDivInfoContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledDivInfoContainer>
|
<StyledDivInfoContainer>
|
||||||
<StyledDivPercentageContainer>
|
<StyledDivPercentageContainer>
|
||||||
|
@ -71,10 +71,9 @@ export const StyledParagraphEmphasizedText = styled('p')(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const StyledCount = styled('p')(({ theme }) => ({
|
export const StyledCount = styled('span')(({ theme }) => ({
|
||||||
fontSize: theme.typography.h2.fontSize,
|
fontSize: theme.typography.h2.fontSize,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
textAlign: 'right',
|
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -26,7 +26,12 @@ const ProjectInfo = ({
|
|||||||
return (
|
return (
|
||||||
<aside>
|
<aside>
|
||||||
<StyledDivContainer>
|
<StyledDivContainer>
|
||||||
<HealthWidget projectId={id} health={health} />
|
<HealthWidget
|
||||||
|
projectId={id}
|
||||||
|
health={health}
|
||||||
|
total={features.length}
|
||||||
|
stale={features.filter(feature => feature.stale).length}
|
||||||
|
/>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={id !== DEFAULT_PROJECT_ID}
|
condition={id !== DEFAULT_PROJECT_ID}
|
||||||
show={
|
show={
|
||||||
|
@ -7,11 +7,16 @@ import {
|
|||||||
StyledParagraphSubtitle,
|
StyledParagraphSubtitle,
|
||||||
} from './ProjectInfo.styles';
|
} from './ProjectInfo.styles';
|
||||||
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
|
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
|
||||||
|
import { styled } from '@mui/material';
|
||||||
|
|
||||||
export interface IToggleTypesWidgetProps {
|
export interface IToggleTypesWidgetProps {
|
||||||
features: IFeatureToggleListItem[];
|
features: IFeatureToggleListItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StyledTypeCount = styled(StyledCount)(({ theme }) => ({
|
||||||
|
marginLeft: 'auto',
|
||||||
|
}));
|
||||||
|
|
||||||
export const ToggleTypesWidget = ({ features }: IToggleTypesWidgetProps) => {
|
export const ToggleTypesWidget = ({ features }: IToggleTypesWidgetProps) => {
|
||||||
const { release, experiment, operational, kill, permission } =
|
const { release, experiment, operational, kill, permission } =
|
||||||
useMemo(() => {
|
useMemo(() => {
|
||||||
@ -54,27 +59,27 @@ export const ToggleTypesWidget = ({ features }: IToggleTypesWidgetProps) => {
|
|||||||
<StyledParagraphGridRow data-loading>
|
<StyledParagraphGridRow data-loading>
|
||||||
<ReleaseToggleIcon fontSize="small" data-loading />
|
<ReleaseToggleIcon fontSize="small" data-loading />
|
||||||
<div>Release</div>
|
<div>Release</div>
|
||||||
<StyledCount>{release}</StyledCount>
|
<StyledTypeCount>{release}</StyledTypeCount>
|
||||||
</StyledParagraphGridRow>
|
</StyledParagraphGridRow>
|
||||||
<StyledParagraphGridRow data-loading>
|
<StyledParagraphGridRow data-loading>
|
||||||
<ExperimentToggleIcon fontSize="small" data-loading />
|
<ExperimentToggleIcon fontSize="small" data-loading />
|
||||||
<div>Experiment</div>
|
<div>Experiment</div>
|
||||||
<StyledCount>{experiment}</StyledCount>
|
<StyledTypeCount>{experiment}</StyledTypeCount>
|
||||||
</StyledParagraphGridRow>
|
</StyledParagraphGridRow>
|
||||||
<StyledParagraphGridRow data-loading>
|
<StyledParagraphGridRow data-loading>
|
||||||
<OperationalToggleIcon fontSize="small" data-loading />
|
<OperationalToggleIcon fontSize="small" data-loading />
|
||||||
<div>Operational</div>
|
<div>Operational</div>
|
||||||
<StyledCount>{operational}</StyledCount>
|
<StyledTypeCount>{operational}</StyledTypeCount>
|
||||||
</StyledParagraphGridRow>
|
</StyledParagraphGridRow>
|
||||||
<StyledParagraphGridRow data-loading>
|
<StyledParagraphGridRow data-loading>
|
||||||
<KillToggleIcon fontSize="small" data-loading />
|
<KillToggleIcon fontSize="small" data-loading />
|
||||||
<div>Kill switch</div>
|
<div>Kill switch</div>
|
||||||
<StyledCount>{kill}</StyledCount>
|
<StyledTypeCount>{kill}</StyledTypeCount>
|
||||||
</StyledParagraphGridRow>
|
</StyledParagraphGridRow>
|
||||||
<StyledParagraphGridRow data-loading style={{ margin: 0 }}>
|
<StyledParagraphGridRow data-loading style={{ margin: 0 }}>
|
||||||
<PermissionToggleIcon fontSize="small" data-loading />
|
<PermissionToggleIcon fontSize="small" data-loading />
|
||||||
<div>Permission</div>
|
<div>Permission</div>
|
||||||
<StyledCount>{permission}</StyledCount>
|
<StyledTypeCount>{permission}</StyledTypeCount>
|
||||||
</StyledParagraphGridRow>
|
</StyledParagraphGridRow>
|
||||||
</StyledDivInfoContainer>
|
</StyledDivInfoContainer>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user