mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-05 17:53:12 +02:00
refactor: Clean up healthToTechDebt feature flag, enable technical debt view
This commit is contained in:
parent
64f7004721
commit
09870f3497
@ -18,7 +18,6 @@ import { allOption } from 'component/common/ProjectSelect/ProjectSelect';
|
|||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import { WidgetTitle } from './components/WidgetTitle/WidgetTitle.tsx';
|
import { WidgetTitle } from './components/WidgetTitle/WidgetTitle.tsx';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag.ts';
|
|
||||||
|
|
||||||
export interface IChartsProps {
|
export interface IChartsProps {
|
||||||
flagTrends: InstanceInsightsSchema['flagTrends'];
|
flagTrends: InstanceInsightsSchema['flagTrends'];
|
||||||
@ -39,6 +38,7 @@ export interface IChartsProps {
|
|||||||
potentiallyStale: number;
|
potentiallyStale: number;
|
||||||
averageUsers: number;
|
averageUsers: number;
|
||||||
averageHealth?: string;
|
averageHealth?: string;
|
||||||
|
technicalDebt?: string;
|
||||||
flagsPerUser?: string;
|
flagsPerUser?: string;
|
||||||
medianTimeToProduction?: number;
|
medianTimeToProduction?: number;
|
||||||
};
|
};
|
||||||
@ -105,7 +105,6 @@ export const InsightsCharts: FC<IChartsProps> = ({
|
|||||||
const showAllProjects = projects[0] === allOption.id;
|
const showAllProjects = projects[0] === allOption.id;
|
||||||
const isOneProjectSelected = projects.length === 1;
|
const isOneProjectSelected = projects.length === 1;
|
||||||
const { isEnterprise } = useUiConfig();
|
const { isEnterprise } = useUiConfig();
|
||||||
const healthToDebtEnabled = useUiFlag('healthToTechDebt');
|
|
||||||
|
|
||||||
const lastUserTrend = userTrends[userTrends.length - 1];
|
const lastUserTrend = userTrends[userTrends.length - 1];
|
||||||
const lastFlagTrend = flagTrends[flagTrends.length - 1];
|
const lastFlagTrend = flagTrends[flagTrends.length - 1];
|
||||||
@ -186,20 +185,15 @@ export const InsightsCharts: FC<IChartsProps> = ({
|
|||||||
<StyledWidgetStats width={350} padding={0}>
|
<StyledWidgetStats width={350} padding={0}>
|
||||||
<HealthStats
|
<HealthStats
|
||||||
value={summary.averageHealth}
|
value={summary.averageHealth}
|
||||||
|
technicalDebt={summary.technicalDebt}
|
||||||
healthy={summary.active}
|
healthy={summary.active}
|
||||||
stale={summary.stale}
|
stale={summary.stale}
|
||||||
potentiallyStale={summary.potentiallyStale}
|
potentiallyStale={summary.potentiallyStale}
|
||||||
title={
|
title={
|
||||||
<WidgetTitle
|
<WidgetTitle
|
||||||
title={
|
title={'Technical debt'}
|
||||||
healthToDebtEnabled
|
|
||||||
? 'Technical debt'
|
|
||||||
: 'Health'
|
|
||||||
}
|
|
||||||
tooltip={
|
tooltip={
|
||||||
healthToDebtEnabled
|
'Percentage of stale and potentially stale flags.'
|
||||||
? 'Percentage of stale and potentially stale flags.'
|
|
||||||
: 'Percentage of flags that are not stale or potentially stale.'
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import type { TooltipState } from 'component/insights/components/LineChart/Chart
|
|||||||
import { HorizontalDistributionChart } from 'component/insights/components/HorizontalDistributionChart/HorizontalDistributionChart';
|
import { HorizontalDistributionChart } from 'component/insights/components/HorizontalDistributionChart/HorizontalDistributionChart';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { getTechnicalDebtColor } from 'utils/getTechnicalDebtColor.ts';
|
import { getTechnicalDebtColor } from 'utils/getTechnicalDebtColor.ts';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
const StyledTooltipItemContainer = styled(Paper)(({ theme }) => ({
|
const StyledTooltipItemContainer = styled(Paper)(({ theme }) => ({
|
||||||
padding: theme.spacing(2),
|
padding: theme.spacing(2),
|
||||||
@ -19,22 +18,6 @@ const StyledItemHeader = styled(Box)(({ theme }) => ({
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const getHealthBadgeColor = (health?: number | null) => {
|
|
||||||
if (health === undefined || health === null) {
|
|
||||||
return 'info';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (health >= 75) {
|
|
||||||
return 'success';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (health >= 50) {
|
|
||||||
return 'warning';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'error';
|
|
||||||
};
|
|
||||||
|
|
||||||
const getTechnicalDebtBadgeColor = (technicalDebt?: number | null) => {
|
const getTechnicalDebtBadgeColor = (technicalDebt?: number | null) => {
|
||||||
if (technicalDebt === undefined || technicalDebt === null) {
|
if (technicalDebt === undefined || technicalDebt === null) {
|
||||||
return 'info';
|
return 'info';
|
||||||
@ -108,8 +91,6 @@ const Distribution = ({ stale = 0, potentiallyStale = 0, total = 0 }) => {
|
|||||||
export const HealthTooltip: FC<{ tooltip: TooltipState | null }> = ({
|
export const HealthTooltip: FC<{ tooltip: TooltipState | null }> = ({
|
||||||
tooltip,
|
tooltip,
|
||||||
}) => {
|
}) => {
|
||||||
const healthToTechDebtEnabled = useUiFlag('healthToTechDebt');
|
|
||||||
|
|
||||||
const data = tooltip?.dataPoints.map((point) => {
|
const data = tooltip?.dataPoints.map((point) => {
|
||||||
return {
|
return {
|
||||||
label: point.label,
|
label: point.label,
|
||||||
@ -148,9 +129,7 @@ export const HealthTooltip: FC<{ tooltip: TooltipState | null }> = ({
|
|||||||
color='textSecondary'
|
color='textSecondary'
|
||||||
component='span'
|
component='span'
|
||||||
>
|
>
|
||||||
{healthToTechDebtEnabled
|
Technical debt
|
||||||
? 'Technical debt'
|
|
||||||
: 'Project health'}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
</StyledItemHeader>
|
</StyledItemHeader>
|
||||||
<StyledItemHeader>
|
<StyledItemHeader>
|
||||||
@ -163,21 +142,13 @@ export const HealthTooltip: FC<{ tooltip: TooltipState | null }> = ({
|
|||||||
</Typography>
|
</Typography>
|
||||||
<strong>{point.title}</strong>
|
<strong>{point.title}</strong>
|
||||||
</Typography>
|
</Typography>
|
||||||
{healthToTechDebtEnabled ? (
|
<Badge
|
||||||
<Badge
|
color={getTechnicalDebtBadgeColor(
|
||||||
color={getTechnicalDebtBadgeColor(
|
point.value.technicalDebt,
|
||||||
point.value.technicalDebt,
|
)}
|
||||||
)}
|
>
|
||||||
>
|
{point.value.technicalDebt}%
|
||||||
{point.value.technicalDebt}%
|
</Badge>
|
||||||
</Badge>
|
|
||||||
) : (
|
|
||||||
<Badge
|
|
||||||
color={getHealthBadgeColor(point.value.health)}
|
|
||||||
>
|
|
||||||
{point.value.health}%
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</StyledItemHeader>{' '}
|
</StyledItemHeader>{' '}
|
||||||
<Divider
|
<Divider
|
||||||
sx={(theme) => ({ margin: theme.spacing(1.5, 0) })}
|
sx={(theme) => ({ margin: theme.spacing(1.5, 0) })}
|
||||||
|
@ -14,7 +14,6 @@ import {
|
|||||||
import { useTheme } from '@mui/material';
|
import { useTheme } from '@mui/material';
|
||||||
import type { GroupedDataByProject } from 'component/insights/hooks/useGroupedProjectTrends';
|
import type { GroupedDataByProject } from 'component/insights/hooks/useGroupedProjectTrends';
|
||||||
import { usePlaceholderData } from 'component/insights/hooks/usePlaceholderData';
|
import { usePlaceholderData } from 'component/insights/hooks/usePlaceholderData';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag.ts';
|
|
||||||
|
|
||||||
interface IProjectHealthChartProps {
|
interface IProjectHealthChartProps {
|
||||||
projectFlagTrends: GroupedDataByProject<
|
projectFlagTrends: GroupedDataByProject<
|
||||||
@ -46,7 +45,6 @@ export const ProjectHealthChart: FC<IProjectHealthChartProps> = ({
|
|||||||
const projectsData = useProjectChartData(projectFlagTrends);
|
const projectsData = useProjectChartData(projectFlagTrends);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const placeholderData = usePlaceholderData();
|
const placeholderData = usePlaceholderData();
|
||||||
const healthToTechDebtEnabled = useUiFlag('healthToTechDebt');
|
|
||||||
|
|
||||||
const aggregateHealthData = useMemo(() => {
|
const aggregateHealthData = useMemo(() => {
|
||||||
const labels = Array.from(
|
const labels = Array.from(
|
||||||
@ -85,18 +83,12 @@ export const ProjectHealthChart: FC<IProjectHealthChartProps> = ({
|
|||||||
return {
|
return {
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: healthToTechDebtEnabled
|
label: 'Technical debt',
|
||||||
? 'Technical debt'
|
|
||||||
: 'Health',
|
|
||||||
data: weeks.map((item) => ({
|
data: weeks.map((item) => ({
|
||||||
health: item.total ? calculateHealth(item) : undefined,
|
health: item.total ? calculateHealth(item) : undefined,
|
||||||
...(healthToTechDebtEnabled
|
technicalDebt: item.total
|
||||||
? {
|
? calculateTechDebt(item)
|
||||||
technicalDebt: item.total
|
: undefined,
|
||||||
? calculateTechDebt(item)
|
|
||||||
: undefined,
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
date: item.date,
|
date: item.date,
|
||||||
total: item.total,
|
total: item.total,
|
||||||
stale: item.stale,
|
stale: item.stale,
|
||||||
@ -132,9 +124,7 @@ export const ProjectHealthChart: FC<IProjectHealthChartProps> = ({
|
|||||||
? {}
|
? {}
|
||||||
: {
|
: {
|
||||||
parsing: {
|
parsing: {
|
||||||
yAxisKey: healthToTechDebtEnabled
|
yAxisKey: 'technicalDebt',
|
||||||
? 'technicalDebt'
|
|
||||||
: 'health',
|
|
||||||
xAxisKey: 'date',
|
xAxisKey: 'date',
|
||||||
},
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import type { FC, ReactNode } from 'react';
|
import type { FC, ReactNode } from 'react';
|
||||||
import { Box, Divider, Link, styled } from '@mui/material';
|
import { Box, Divider, Link, styled } from '@mui/material';
|
||||||
import { ReactComponent as InstanceHealthIcon } from 'assets/icons/instance-health.svg';
|
import { ReactComponent as InstanceHealthIcon } from 'assets/icons/instance-health.svg';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
interface IHealthStatsProps {
|
interface IHealthStatsProps {
|
||||||
value?: string | number;
|
value?: string | number;
|
||||||
@ -73,8 +72,6 @@ export const HealthStats: FC<IHealthStatsProps> = ({
|
|||||||
potentiallyStale,
|
potentiallyStale,
|
||||||
title,
|
title,
|
||||||
}) => {
|
}) => {
|
||||||
const healthToDebtEnabled = useUiFlag('healthToTechDebt');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<StyledHeader>
|
<StyledHeader>
|
||||||
@ -84,12 +81,8 @@ export const HealthStats: FC<IHealthStatsProps> = ({
|
|||||||
<StyledSection>
|
<StyledSection>
|
||||||
<StyledStatsRow>
|
<StyledStatsRow>
|
||||||
<StyledIcon />
|
<StyledIcon />
|
||||||
{healthToDebtEnabled ? 'Technical debt' : 'Instance health'}
|
Technical debt
|
||||||
{healthToDebtEnabled ? (
|
<StyledMainValue>{`${technicalDebt}%`}</StyledMainValue>
|
||||||
<StyledMainValue>{`${technicalDebt}%`}</StyledMainValue>
|
|
||||||
) : (
|
|
||||||
<StyledMainValue>{`${value || 0}%`}</StyledMainValue>
|
|
||||||
)}
|
|
||||||
</StyledStatsRow>
|
</StyledStatsRow>
|
||||||
</StyledSection>
|
</StyledSection>
|
||||||
<Divider />
|
<Divider />
|
||||||
@ -112,9 +105,7 @@ export const HealthStats: FC<IHealthStatsProps> = ({
|
|||||||
target='_blank'
|
target='_blank'
|
||||||
rel='noreferrer'
|
rel='noreferrer'
|
||||||
>
|
>
|
||||||
{healthToDebtEnabled
|
What affects technical debt?
|
||||||
? 'What affects technical debt?'
|
|
||||||
: 'What affects instance health?'}
|
|
||||||
</Link>
|
</Link>
|
||||||
</ExplanationRow>
|
</ExplanationRow>
|
||||||
</FlagsSection>
|
</FlagsSection>
|
||||||
|
@ -23,7 +23,6 @@ import {
|
|||||||
StyledWidgetContent,
|
StyledWidgetContent,
|
||||||
StyledWidgetStats,
|
StyledWidgetStats,
|
||||||
} from '../InsightsCharts.styles';
|
} from '../InsightsCharts.styles';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
export const PerformanceInsights: FC = () => {
|
export const PerformanceInsights: FC = () => {
|
||||||
const statePrefix = 'performance-';
|
const statePrefix = 'performance-';
|
||||||
@ -48,8 +47,6 @@ export const PerformanceInsights: FC = () => {
|
|||||||
state[`${statePrefix}to`]?.values[0],
|
state[`${statePrefix}to`]?.values[0],
|
||||||
);
|
);
|
||||||
|
|
||||||
const healthToTechDebtEnabled = useUiFlag('healthToTechDebt');
|
|
||||||
|
|
||||||
const projects = state[`${statePrefix}project`]?.values ?? [allOption.id];
|
const projects = state[`${statePrefix}project`]?.values ?? [allOption.id];
|
||||||
|
|
||||||
const showAllProjects = projects[0] === allOption.id;
|
const showAllProjects = projects[0] === allOption.id;
|
||||||
@ -135,21 +132,12 @@ export const PerformanceInsights: FC = () => {
|
|||||||
stale={summary.stale}
|
stale={summary.stale}
|
||||||
potentiallyStale={summary.potentiallyStale}
|
potentiallyStale={summary.potentiallyStale}
|
||||||
title={
|
title={
|
||||||
healthToTechDebtEnabled ? (
|
<WidgetTitle
|
||||||
<WidgetTitle
|
title='Technical debt'
|
||||||
title='Technical debt'
|
tooltip={
|
||||||
tooltip={
|
'Percentage of flags that are stale or potentially stale.'
|
||||||
'Percentage of flags that are stale or potentially stale.'
|
}
|
||||||
}
|
/>
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<WidgetTitle
|
|
||||||
title='Health'
|
|
||||||
tooltip={
|
|
||||||
'Percentage of flags that are not stale or potentially stale.'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</StyledWidgetStats>
|
</StyledWidgetStats>
|
||||||
|
@ -39,13 +39,10 @@ import { ActionBox } from './ActionBox.tsx';
|
|||||||
import useLoading from 'hooks/useLoading';
|
import useLoading from 'hooks/useLoading';
|
||||||
import { NoProjectsContactAdmin } from './NoProjectsContactAdmin.tsx';
|
import { NoProjectsContactAdmin } from './NoProjectsContactAdmin.tsx';
|
||||||
import { AskOwnerToAddYouToTheirProject } from './AskOwnerToAddYouToTheirProject.tsx';
|
import { AskOwnerToAddYouToTheirProject } from './AskOwnerToAddYouToTheirProject.tsx';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag.ts';
|
|
||||||
|
|
||||||
const ActiveProjectDetails: FC<{
|
const ActiveProjectDetails: FC<{
|
||||||
project: PersonalDashboardSchemaProjectsItem;
|
project: PersonalDashboardSchemaProjectsItem;
|
||||||
}> = ({ project }) => {
|
}> = ({ project }) => {
|
||||||
const healthToTechDebtEnabled = useUiFlag('healthToTechDebt');
|
|
||||||
|
|
||||||
const techicalDebt = project.technicalDebt;
|
const techicalDebt = project.technicalDebt;
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: 'flex', gap: 2 }}>
|
<Box sx={{ display: 'flex', gap: 2 }}>
|
||||||
@ -67,10 +64,10 @@ const ActiveProjectDetails: FC<{
|
|||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
|
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
<Typography variant='subtitle2' color='primary'>
|
<Typography variant='subtitle2' color='primary'>
|
||||||
{healthToTechDebtEnabled ? techicalDebt : project.health}%
|
{techicalDebt}%
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant='caption' color='text.secondary'>
|
<Typography variant='caption' color='text.secondary'>
|
||||||
{healthToTechDebtEnabled ? 'technical debt' : 'health'}
|
technical debt
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -4,7 +4,6 @@ import { Link } from 'react-router-dom';
|
|||||||
import Lightbulb from '@mui/icons-material/LightbulbOutlined';
|
import Lightbulb from '@mui/icons-material/LightbulbOutlined';
|
||||||
import type { PersonalDashboardProjectDetailsSchemaInsights } from 'openapi';
|
import type { PersonalDashboardProjectDetailsSchemaInsights } from 'openapi';
|
||||||
import { ActionBox } from './ActionBox.tsx';
|
import { ActionBox } from './ActionBox.tsx';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag.ts';
|
|
||||||
|
|
||||||
const PercentageScore = styled('span')(({ theme }) => ({
|
const PercentageScore = styled('span')(({ theme }) => ({
|
||||||
fontWeight: theme.typography.fontWeightBold,
|
fontWeight: theme.typography.fontWeightBold,
|
||||||
@ -58,42 +57,24 @@ const ProjectHealthMessage: FC<{
|
|||||||
insights: PersonalDashboardProjectDetailsSchemaInsights;
|
insights: PersonalDashboardProjectDetailsSchemaInsights;
|
||||||
project: string;
|
project: string;
|
||||||
}> = ({ trend, insights, project }) => {
|
}> = ({ trend, insights, project }) => {
|
||||||
const healthToTechDebtEnabled = useUiFlag('healthToTechDebt');
|
const { avgHealthCurrentWindow, avgHealthPastWindow } = insights;
|
||||||
const { avgHealthCurrentWindow, avgHealthPastWindow, health } = insights;
|
const improveMessage =
|
||||||
const improveMessage = healthToTechDebtEnabled
|
'Remember to archive your stale feature flags to keep the technical debt low.';
|
||||||
? 'Remember to archive your stale feature flags to keep the technical debt low.'
|
|
||||||
: 'Remember to archive your stale feature flags to keep the project health growing.';
|
|
||||||
const keepDoingMessage =
|
const keepDoingMessage =
|
||||||
'This indicates that you are doing a good job of archiving your feature flags.';
|
'This indicates that you are doing a good job of archiving your feature flags.';
|
||||||
const avgCurrentTechnicalDebt = 100 - (avgHealthCurrentWindow ?? 0);
|
const avgCurrentTechnicalDebt = 100 - (avgHealthCurrentWindow ?? 0);
|
||||||
const avgPastTechnicalDebt = 100 - (avgHealthPastWindow ?? 0);
|
const avgPastTechnicalDebt = 100 - (avgHealthPastWindow ?? 0);
|
||||||
|
|
||||||
if (trend === 'improved') {
|
if (trend === 'improved') {
|
||||||
if (healthToTechDebtEnabled) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Typography>
|
|
||||||
On average, your project technical debt went down from{' '}
|
|
||||||
<PercentageScore>
|
|
||||||
{avgPastTechnicalDebt}%
|
|
||||||
</PercentageScore>{' '}
|
|
||||||
to{' '}
|
|
||||||
<PercentageScore>
|
|
||||||
{avgCurrentTechnicalDebt}%
|
|
||||||
</PercentageScore>{' '}
|
|
||||||
during the last 4 weeks.
|
|
||||||
</Typography>
|
|
||||||
<Typography>{keepDoingMessage}</Typography>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Typography>
|
<Typography>
|
||||||
On average, your project health went up from{' '}
|
On average, your project technical debt went down from{' '}
|
||||||
<PercentageScore>{avgHealthPastWindow}%</PercentageScore> to{' '}
|
<PercentageScore>{avgPastTechnicalDebt}%</PercentageScore>{' '}
|
||||||
<PercentageScore>{avgHealthCurrentWindow}%</PercentageScore>{' '}
|
to{' '}
|
||||||
|
<PercentageScore>
|
||||||
|
{avgCurrentTechnicalDebt}%
|
||||||
|
</PercentageScore>{' '}
|
||||||
during the last 4 weeks.
|
during the last 4 weeks.
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>{keepDoingMessage}</Typography>
|
<Typography>{keepDoingMessage}</Typography>
|
||||||
@ -102,31 +83,15 @@ const ProjectHealthMessage: FC<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (trend === 'declined') {
|
if (trend === 'declined') {
|
||||||
if (healthToTechDebtEnabled) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Typography>
|
|
||||||
On average, your project technical debt went up from{' '}
|
|
||||||
<PercentageScore>
|
|
||||||
{avgPastTechnicalDebt}%
|
|
||||||
</PercentageScore>{' '}
|
|
||||||
to{' '}
|
|
||||||
<PercentageScore>
|
|
||||||
{avgCurrentTechnicalDebt}%
|
|
||||||
</PercentageScore>{' '}
|
|
||||||
during the last 4 weeks.
|
|
||||||
</Typography>
|
|
||||||
<Typography>{improveMessage}</Typography>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Typography>
|
<Typography>
|
||||||
On average, your project health went down from{' '}
|
On average, your project technical debt went up from{' '}
|
||||||
<PercentageScore>{avgHealthPastWindow}%</PercentageScore> to{' '}
|
<PercentageScore>{avgPastTechnicalDebt}%</PercentageScore>{' '}
|
||||||
<PercentageScore>{avgHealthCurrentWindow}%</PercentageScore>{' '}
|
to{' '}
|
||||||
|
<PercentageScore>
|
||||||
|
{avgCurrentTechnicalDebt}%
|
||||||
|
</PercentageScore>{' '}
|
||||||
during the last 4 weeks.
|
during the last 4 weeks.
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>{improveMessage}</Typography>
|
<Typography>{improveMessage}</Typography>
|
||||||
@ -135,62 +100,29 @@ const ProjectHealthMessage: FC<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (trend === 'consistent') {
|
if (trend === 'consistent') {
|
||||||
if (healthToTechDebtEnabled) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Typography>
|
|
||||||
On average, your project technical debt has remained at{' '}
|
|
||||||
<PercentageScore>
|
|
||||||
{avgCurrentTechnicalDebt}%
|
|
||||||
</PercentageScore>{' '}
|
|
||||||
during the last 4 weeks.
|
|
||||||
</Typography>
|
|
||||||
<Typography>{keepDoingMessage}</Typography>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Typography>
|
<Typography>
|
||||||
On average, your project health has remained at{' '}
|
On average, your project technical debt has remained at{' '}
|
||||||
<PercentageScore>{avgHealthCurrentWindow}%</PercentageScore>{' '}
|
<PercentageScore>
|
||||||
|
{avgCurrentTechnicalDebt}%
|
||||||
|
</PercentageScore>{' '}
|
||||||
during the last 4 weeks.
|
during the last 4 weeks.
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>
|
<Typography>{keepDoingMessage}</Typography>
|
||||||
{avgHealthCurrentWindow && avgHealthCurrentWindow >= 75
|
|
||||||
? keepDoingMessage
|
|
||||||
: improveMessage}
|
|
||||||
</Typography>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trend === 'unknown') {
|
if (trend === 'unknown') {
|
||||||
if (healthToTechDebtEnabled) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Typography>
|
|
||||||
Your current project technical debt is{' '}
|
|
||||||
<PercentageScore>
|
|
||||||
{avgCurrentTechnicalDebt}%
|
|
||||||
</PercentageScore>
|
|
||||||
.
|
|
||||||
</Typography>
|
|
||||||
<Typography>{improveMessage}</Typography>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Typography>
|
<Typography>
|
||||||
Your current health score is{' '}
|
Your current project technical debt is{' '}
|
||||||
<PercentageScore>{health}%</PercentageScore>.
|
<PercentageScore>{avgCurrentTechnicalDebt}%</PercentageScore>
|
||||||
</Typography>
|
.
|
||||||
<Typography>
|
|
||||||
{health >= 75 ? keepDoingMessage : improveMessage}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Typography>{improveMessage}</Typography>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -202,7 +134,6 @@ export const ProjectSetupComplete: FC<{
|
|||||||
project: string;
|
project: string;
|
||||||
insights: PersonalDashboardProjectDetailsSchemaInsights;
|
insights: PersonalDashboardProjectDetailsSchemaInsights;
|
||||||
}> = ({ project, insights }) => {
|
}> = ({ project, insights }) => {
|
||||||
const healthToTechDebtEnabled = useUiFlag('healthToTechDebt');
|
|
||||||
const projectHealthTrend = determineProjectHealthTrend(insights);
|
const projectHealthTrend = determineProjectHealthTrend(insights);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -211,9 +142,7 @@ export const ProjectSetupComplete: FC<{
|
|||||||
<>
|
<>
|
||||||
<Lightbulb color='primary' />
|
<Lightbulb color='primary' />
|
||||||
<Typography sx={{ fontWeight: 'bold' }} component='h4'>
|
<Typography sx={{ fontWeight: 'bold' }} component='h4'>
|
||||||
{healthToTechDebtEnabled
|
Technical debt
|
||||||
? 'Technical debt'
|
|
||||||
: 'Project health'}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
|||||||
import { HealthGridTile } from './ProjectHealthGrid.styles';
|
import { HealthGridTile } from './ProjectHealthGrid.styles';
|
||||||
import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/PrettifyLargeNumber';
|
import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/PrettifyLargeNumber';
|
||||||
import { getTechnicalDebtColor } from 'utils/getTechnicalDebtColor.ts';
|
import { getTechnicalDebtColor } from 'utils/getTechnicalDebtColor.ts';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
const ChartRadius = 40;
|
const ChartRadius = 40;
|
||||||
const ChartStrokeWidth = 13;
|
const ChartStrokeWidth = 13;
|
||||||
@ -82,17 +81,6 @@ const UnhealthyFlagBox = ({ flagCount }: { flagCount: number }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const useHealthColor = (healthRating: number) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
if (healthRating <= 24) {
|
|
||||||
return theme.palette.error.main;
|
|
||||||
}
|
|
||||||
if (healthRating <= 74) {
|
|
||||||
return theme.palette.warning.border;
|
|
||||||
}
|
|
||||||
return theme.palette.success.border;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useTechnicalDebtColor = (techicalDebt: number) => {
|
const useTechnicalDebtColor = (techicalDebt: number) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
switch (getTechnicalDebtColor(techicalDebt)) {
|
switch (getTechnicalDebtColor(techicalDebt)) {
|
||||||
@ -115,22 +103,18 @@ const Wrapper = styled(HealthGridTile)(({ theme }) => ({
|
|||||||
export const ProjectHealth = () => {
|
export const ProjectHealth = () => {
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const {
|
const {
|
||||||
data: { health, technicalDebt, staleFlags },
|
data: { technicalDebt, staleFlags },
|
||||||
} = useProjectStatus(projectId);
|
} = useProjectStatus(projectId);
|
||||||
const { isOss } = useUiConfig();
|
const { isOss } = useUiConfig();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const healthToDebtEnabled = useUiFlag('healthToTechDebt');
|
|
||||||
const circumference = 2 * Math.PI * ChartRadius;
|
const circumference = 2 * Math.PI * ChartRadius;
|
||||||
const healthRating = health.current;
|
|
||||||
|
|
||||||
const gapLength = 0.3;
|
const gapLength = 0.3;
|
||||||
const filledLength = 1 - gapLength;
|
const filledLength = 1 - gapLength;
|
||||||
const offset = 0.75 - gapLength / 2;
|
const offset = 0.75 - gapLength / 2;
|
||||||
const healthLength = (healthRating / 100) * circumference * 0.7;
|
|
||||||
const technicalDebtLength =
|
const technicalDebtLength =
|
||||||
((technicalDebt.current || 0) / 100) * circumference * 0.7;
|
((technicalDebt.current || 0) / 100) * circumference * 0.7;
|
||||||
|
|
||||||
const healthColor = useHealthColor(healthRating);
|
|
||||||
const technicalDebtColor = useTechnicalDebtColor(
|
const technicalDebtColor = useTechnicalDebtColor(
|
||||||
technicalDebt.current || 0,
|
technicalDebt.current || 0,
|
||||||
);
|
);
|
||||||
@ -155,17 +139,9 @@ export const ProjectHealth = () => {
|
|||||||
cy='50'
|
cy='50'
|
||||||
r={ChartRadius}
|
r={ChartRadius}
|
||||||
fill='none'
|
fill='none'
|
||||||
stroke={
|
stroke={technicalDebtColor}
|
||||||
healthToDebtEnabled
|
|
||||||
? technicalDebtColor
|
|
||||||
: healthColor
|
|
||||||
}
|
|
||||||
strokeWidth={ChartStrokeWidth}
|
strokeWidth={ChartStrokeWidth}
|
||||||
strokeDasharray={
|
strokeDasharray={`${technicalDebtLength} ${circumference - technicalDebtLength}`}
|
||||||
healthToDebtEnabled
|
|
||||||
? `${technicalDebtLength} ${circumference - technicalDebtLength}`
|
|
||||||
: `${healthLength} ${circumference - healthLength}`
|
|
||||||
}
|
|
||||||
strokeDashoffset={offset * circumference}
|
strokeDashoffset={offset * circumference}
|
||||||
/>
|
/>
|
||||||
<text
|
<text
|
||||||
@ -176,32 +152,18 @@ export const ProjectHealth = () => {
|
|||||||
fill={theme.palette.text.primary}
|
fill={theme.palette.text.primary}
|
||||||
fontSize={theme.typography.h1.fontSize}
|
fontSize={theme.typography.h1.fontSize}
|
||||||
>
|
>
|
||||||
{healthToDebtEnabled
|
{technicalDebt.current || 0}%
|
||||||
? technicalDebt.current || 0
|
|
||||||
: healthRating}
|
|
||||||
%
|
|
||||||
</text>
|
</text>
|
||||||
</StyledSVG>
|
</StyledSVG>
|
||||||
</SVGWrapper>
|
</SVGWrapper>
|
||||||
<TextContainer>
|
<TextContainer>
|
||||||
<Typography>
|
<Typography>
|
||||||
{healthToDebtEnabled ? (
|
Your current technical debt rating is{' '}
|
||||||
<>
|
{technicalDebt.current}%.
|
||||||
Your current technical debt rating is{' '}
|
|
||||||
{technicalDebt.current}%.
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
Your current project health rating is{' '}
|
|
||||||
{healthRating}%.
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
{!isOss() && (
|
{!isOss() && (
|
||||||
<Link to={`/insights?project=IS%3A${projectId}`}>
|
<Link to={`/insights?project=IS%3A${projectId}`}>
|
||||||
{healthToDebtEnabled
|
View technical debt over time
|
||||||
? 'View technical debt over time'
|
|
||||||
: 'View health over time'}
|
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</TextContainer>
|
</TextContainer>
|
||||||
|
@ -87,7 +87,6 @@ export type UiFlags = {
|
|||||||
customMetrics?: boolean;
|
customMetrics?: boolean;
|
||||||
lifecycleMetrics?: boolean;
|
lifecycleMetrics?: boolean;
|
||||||
createFlagDialogCache?: boolean;
|
createFlagDialogCache?: boolean;
|
||||||
healthToTechDebt?: boolean;
|
|
||||||
improvedJsonDiff?: boolean;
|
improvedJsonDiff?: boolean;
|
||||||
impactMetrics?: boolean;
|
impactMetrics?: boolean;
|
||||||
crDiffView?: boolean;
|
crDiffView?: boolean;
|
||||||
|
@ -56,7 +56,6 @@ export type IFlagKey =
|
|||||||
| 'edgeObservability'
|
| 'edgeObservability'
|
||||||
| 'reportUnknownFlags'
|
| 'reportUnknownFlags'
|
||||||
| 'lifecycleMetrics'
|
| 'lifecycleMetrics'
|
||||||
| 'healthToTechDebt'
|
|
||||||
| 'customMetrics'
|
| 'customMetrics'
|
||||||
| 'impactMetrics'
|
| 'impactMetrics'
|
||||||
| 'createFlagDialogCache'
|
| 'createFlagDialogCache'
|
||||||
@ -269,10 +268,6 @@ const flags: IFlags = {
|
|||||||
process.env.UNLEASH_EXPERIMENTAL_LIFECYCLE_METRICS,
|
process.env.UNLEASH_EXPERIMENTAL_LIFECYCLE_METRICS,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
healthToTechDebt: parseEnvVarBoolean(
|
|
||||||
process.env.UNLEASH_EXPERIMENTAL_HEALTH_TO_TECH_DEBT,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
createFlagDialogCache: parseEnvVarBoolean(
|
createFlagDialogCache: parseEnvVarBoolean(
|
||||||
process.env.UNLEASH_EXPERIMENTAL_CREATE_FLAG_DIALOG_CACHE,
|
process.env.UNLEASH_EXPERIMENTAL_CREATE_FLAG_DIALOG_CACHE,
|
||||||
false,
|
false,
|
||||||
|
Loading…
Reference in New Issue
Block a user