mirror of
https://github.com/Unleash/unleash.git
synced 2025-03-14 00:15:52 +01:00
feat: time to production chart (#6100)
This commit is contained in:
parent
99b8fa2943
commit
4e3ab7186c
@ -15,6 +15,7 @@ import { FlagStats } from './FlagStats/FlagStats';
|
|||||||
import { Widget } from './Widget/Widget';
|
import { Widget } from './Widget/Widget';
|
||||||
import { FlagsProjectChart } from './FlagsProjectChart/FlagsProjectChart';
|
import { FlagsProjectChart } from './FlagsProjectChart/FlagsProjectChart';
|
||||||
import { ProjectHealthChart } from './ProjectHealthChart/ProjectHealthChart';
|
import { ProjectHealthChart } from './ProjectHealthChart/ProjectHealthChart';
|
||||||
|
import { TimeToProductionChart } from './TimeToProductionChart/TimeToProductionChart';
|
||||||
|
|
||||||
const StyledGrid = styled(Box)(({ theme }) => ({
|
const StyledGrid = styled(Box)(({ theme }) => ({
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -138,6 +139,17 @@ export const ExecutiveDashboard: VFC = () => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
<Widget
|
||||||
|
title='Time to production'
|
||||||
|
order={7}
|
||||||
|
span={largeChartSpan}
|
||||||
|
>
|
||||||
|
<TimeToProductionChart
|
||||||
|
projectFlagTrends={
|
||||||
|
executiveDashboardData.projectFlagTrends
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Widget>
|
||||||
</StyledGrid>
|
</StyledGrid>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
} from 'openapi';
|
} from 'openapi';
|
||||||
import { LineChart } from '../LineChart/LineChart';
|
import { LineChart } from '../LineChart/LineChart';
|
||||||
import { getRandomColor } from '../executive-dashboard-utils';
|
import { getRandomColor } from '../executive-dashboard-utils';
|
||||||
|
import { useProjectChartData } from '../useProjectChartData';
|
||||||
|
|
||||||
interface IFlagsProjectChartProps {
|
interface IFlagsProjectChartProps {
|
||||||
projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends'];
|
projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends'];
|
||||||
@ -15,38 +16,7 @@ interface IFlagsProjectChartProps {
|
|||||||
export const FlagsProjectChart: VFC<IFlagsProjectChartProps> = ({
|
export const FlagsProjectChart: VFC<IFlagsProjectChartProps> = ({
|
||||||
projectFlagTrends,
|
projectFlagTrends,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const data = useProjectChartData(projectFlagTrends, 'total');
|
||||||
const data = useMemo(() => {
|
|
||||||
const groupedFlagTrends = projectFlagTrends.reduce<
|
|
||||||
Record<string, ExecutiveSummarySchemaProjectFlagTrendsItem[]>
|
|
||||||
>((groups, item) => {
|
|
||||||
if (!groups[item.project]) {
|
|
||||||
groups[item.project] = [];
|
|
||||||
}
|
|
||||||
groups[item.project].push(item);
|
|
||||||
return groups;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
const datasets = Object.entries(groupedFlagTrends).map(
|
|
||||||
([project, trends]) => {
|
|
||||||
const color = getRandomColor();
|
|
||||||
return {
|
|
||||||
label: project,
|
|
||||||
data: trends.map((item) => item.total),
|
|
||||||
borderColor: color,
|
|
||||||
backgroundColor: color,
|
|
||||||
fill: true,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const objectKeys = Object.keys(groupedFlagTrends);
|
|
||||||
|
|
||||||
return {
|
|
||||||
labels: groupedFlagTrends[objectKeys[0]].map((item) => item.date),
|
|
||||||
datasets,
|
|
||||||
};
|
|
||||||
}, [theme, projectFlagTrends]);
|
|
||||||
|
|
||||||
return <LineChart data={data} />;
|
return <LineChart data={data} />;
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
} from 'openapi';
|
} from 'openapi';
|
||||||
import { LineChart } from '../LineChart/LineChart';
|
import { LineChart } from '../LineChart/LineChart';
|
||||||
import { getRandomColor } from '../executive-dashboard-utils';
|
import { getRandomColor } from '../executive-dashboard-utils';
|
||||||
|
import { useProjectChartData } from '../useProjectChartData';
|
||||||
|
|
||||||
interface IFlagsProjectChartProps {
|
interface IFlagsProjectChartProps {
|
||||||
projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends'];
|
projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends'];
|
||||||
@ -15,39 +16,7 @@ interface IFlagsProjectChartProps {
|
|||||||
export const ProjectHealthChart: VFC<IFlagsProjectChartProps> = ({
|
export const ProjectHealthChart: VFC<IFlagsProjectChartProps> = ({
|
||||||
projectFlagTrends,
|
projectFlagTrends,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const data = useProjectChartData(projectFlagTrends, 'health');
|
||||||
|
|
||||||
const data = useMemo(() => {
|
|
||||||
const groupedFlagTrends = projectFlagTrends.reduce<
|
|
||||||
Record<string, ExecutiveSummarySchemaProjectFlagTrendsItem[]>
|
|
||||||
>((groups, item) => {
|
|
||||||
if (!groups[item.project]) {
|
|
||||||
groups[item.project] = [];
|
|
||||||
}
|
|
||||||
groups[item.project].push(item);
|
|
||||||
return groups;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
const datasets = Object.entries(groupedFlagTrends).map(
|
|
||||||
([project, trends]) => {
|
|
||||||
const color = getRandomColor();
|
|
||||||
return {
|
|
||||||
label: project,
|
|
||||||
data: trends.map((item) => item.health || 0),
|
|
||||||
borderColor: color,
|
|
||||||
backgroundColor: color,
|
|
||||||
fill: true,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const objectKeys = Object.keys(groupedFlagTrends);
|
|
||||||
|
|
||||||
return {
|
|
||||||
labels: groupedFlagTrends[objectKeys[0]].map((item) => item.date),
|
|
||||||
datasets,
|
|
||||||
};
|
|
||||||
}, [theme, projectFlagTrends]);
|
|
||||||
|
|
||||||
return <LineChart data={data} />;
|
return <LineChart data={data} />;
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
import { useMemo, type VFC } from 'react';
|
||||||
|
import 'chartjs-adapter-date-fns';
|
||||||
|
import { useTheme } from '@mui/material';
|
||||||
|
import {
|
||||||
|
ExecutiveSummarySchema,
|
||||||
|
ExecutiveSummarySchemaProjectFlagTrendsItem,
|
||||||
|
} from 'openapi';
|
||||||
|
import { LineChart } from '../LineChart/LineChart';
|
||||||
|
import { getRandomColor } from '../executive-dashboard-utils';
|
||||||
|
import { useProjectChartData } from '../useProjectChartData';
|
||||||
|
|
||||||
|
interface IFlagsProjectChartProps {
|
||||||
|
projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TimeToProductionChart: VFC<IFlagsProjectChartProps> = ({
|
||||||
|
projectFlagTrends,
|
||||||
|
}) => {
|
||||||
|
const data = useProjectChartData(projectFlagTrends, 'timeToProduction');
|
||||||
|
|
||||||
|
return <LineChart data={data} />;
|
||||||
|
};
|
@ -0,0 +1,55 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import {
|
||||||
|
ExecutiveSummarySchema,
|
||||||
|
ExecutiveSummarySchemaProjectFlagTrendsItem,
|
||||||
|
} from '../../openapi';
|
||||||
|
import { getRandomColor } from './executive-dashboard-utils';
|
||||||
|
import { useTheme } from '@mui/material';
|
||||||
|
|
||||||
|
type ProjectFlagTrends = ExecutiveSummarySchema['projectFlagTrends'];
|
||||||
|
|
||||||
|
export const useProjectChartData = (
|
||||||
|
projectFlagTrends: ProjectFlagTrends,
|
||||||
|
field: 'timeToProduction' | 'total' | 'health',
|
||||||
|
) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const data = useMemo(() => {
|
||||||
|
const groupedFlagTrends = projectFlagTrends.reduce<
|
||||||
|
Record<string, ExecutiveSummarySchemaProjectFlagTrendsItem[]>
|
||||||
|
>((groups, item) => {
|
||||||
|
if (!groups[item.project]) {
|
||||||
|
groups[item.project] = [];
|
||||||
|
}
|
||||||
|
groups[item.project].push(item);
|
||||||
|
return groups;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const datasets = Object.entries(groupedFlagTrends).map(
|
||||||
|
([project, trends]) => {
|
||||||
|
const color = getRandomColor();
|
||||||
|
return {
|
||||||
|
label: project,
|
||||||
|
data: trends.map((item) => {
|
||||||
|
return item[field] || 0;
|
||||||
|
}),
|
||||||
|
borderColor: color,
|
||||||
|
backgroundColor: color,
|
||||||
|
fill: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const objectKeys = Object.keys(groupedFlagTrends);
|
||||||
|
|
||||||
|
const firstElementTrends = groupedFlagTrends[objectKeys[0]] || [];
|
||||||
|
const firstElementsDates = firstElementTrends.map((item) => item.date);
|
||||||
|
|
||||||
|
return {
|
||||||
|
labels: firstElementsDates,
|
||||||
|
datasets,
|
||||||
|
};
|
||||||
|
}, [theme, projectFlagTrends]);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user