mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-09 01:17:06 +02:00
feat: show the metrics summary chart (#6297)
Creates the impressions summary chart <img width="1358" alt="Screenshot 2024-02-21 at 13 25 05" src="https://github.com/Unleash/unleash/assets/104830839/ddf15637-34de-4883-9ef7-517e37eab331"> Closes # [1-2060](https://linear.app/unleash/issue/1-2060/impressions-summary-widget-frontend) --------- Signed-off-by: andreas-unleash <andreas@getunleash.ai> Co-authored-by: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
This commit is contained in:
parent
153c60d335
commit
bae195add9
@ -18,6 +18,11 @@ import { ProjectHealthChart } from './ProjectHealthChart/ProjectHealthChart';
|
|||||||
import { TimeToProductionChart } from './TimeToProductionChart/TimeToProductionChart';
|
import { TimeToProductionChart } from './TimeToProductionChart/TimeToProductionChart';
|
||||||
import { TimeToProduction } from './TimeToProduction/TimeToProduction';
|
import { TimeToProduction } from './TimeToProduction/TimeToProduction';
|
||||||
import { ProjectSelect, allOption } from './ProjectSelect/ProjectSelect';
|
import { ProjectSelect, allOption } from './ProjectSelect/ProjectSelect';
|
||||||
|
import { MetricsSummaryChart } from './MetricsSummaryChart/MetricsSummaryChart';
|
||||||
|
import {
|
||||||
|
ExecutiveSummarySchemaMetricsSummaryTrendsItem,
|
||||||
|
ExecutiveSummarySchemaProjectFlagTrendsItem,
|
||||||
|
} from '../../openapi';
|
||||||
import { HealthStats } from './HealthStats/HealthStats';
|
import { HealthStats } from './HealthStats/HealthStats';
|
||||||
|
|
||||||
const StyledGrid = styled(Box)(({ theme }) => ({
|
const StyledGrid = styled(Box)(({ theme }) => ({
|
||||||
@ -61,6 +66,11 @@ const useDashboardGrid = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface FilteredProjectData {
|
||||||
|
filteredProjectFlagTrends: ExecutiveSummarySchemaProjectFlagTrendsItem[];
|
||||||
|
filteredMetricsSummaryTrends: ExecutiveSummarySchemaMetricsSummaryTrendsItem[];
|
||||||
|
}
|
||||||
|
|
||||||
export const ExecutiveDashboard: VFC = () => {
|
export const ExecutiveDashboard: VFC = () => {
|
||||||
const { executiveDashboardData, loading, error } = useExecutiveDashboard();
|
const { executiveDashboardData, loading, error } = useExecutiveDashboard();
|
||||||
const [projects, setProjects] = useState([allOption.id]);
|
const [projects, setProjects] = useState([allOption.id]);
|
||||||
@ -78,15 +88,32 @@ export const ExecutiveDashboard: VFC = () => {
|
|||||||
).toFixed(1);
|
).toFixed(1);
|
||||||
}, [executiveDashboardData]);
|
}, [executiveDashboardData]);
|
||||||
|
|
||||||
const filteredProjectFlagTrends = useMemo(() => {
|
const { filteredProjectFlagTrends, filteredMetricsSummaryTrends } =
|
||||||
if (projects[0] === allOption.id) {
|
useMemo<FilteredProjectData>(() => {
|
||||||
return executiveDashboardData.projectFlagTrends;
|
if (projects[0] === allOption.id) {
|
||||||
}
|
return {
|
||||||
|
filteredProjectFlagTrends:
|
||||||
|
executiveDashboardData.projectFlagTrends,
|
||||||
|
filteredMetricsSummaryTrends:
|
||||||
|
executiveDashboardData.metricsSummaryTrends,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return executiveDashboardData.projectFlagTrends.filter((trend) =>
|
const filteredProjectFlagTrends =
|
||||||
projects.includes(trend.project),
|
executiveDashboardData.projectFlagTrends.filter((trend) =>
|
||||||
);
|
projects.includes(trend.project),
|
||||||
}, [executiveDashboardData, projects]);
|
) as ExecutiveSummarySchemaProjectFlagTrendsItem[];
|
||||||
|
|
||||||
|
const filteredImpressionsSummary =
|
||||||
|
executiveDashboardData.metricsSummaryTrends.filter((summary) =>
|
||||||
|
projects.includes(summary.project),
|
||||||
|
) as ExecutiveSummarySchemaMetricsSummaryTrendsItem[];
|
||||||
|
|
||||||
|
return {
|
||||||
|
filteredProjectFlagTrends,
|
||||||
|
filteredMetricsSummaryTrends: filteredImpressionsSummary,
|
||||||
|
};
|
||||||
|
}, [executiveDashboardData, projects]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
gridTemplateColumns,
|
gridTemplateColumns,
|
||||||
@ -159,13 +186,23 @@ export const ExecutiveDashboard: VFC = () => {
|
|||||||
projectFlagTrends={filteredProjectFlagTrends}
|
projectFlagTrends={filteredProjectFlagTrends}
|
||||||
/>
|
/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget title='Average time to production' order={8}>
|
<Widget
|
||||||
|
title='Metrics over time per project'
|
||||||
|
order={8}
|
||||||
|
span={largeChartSpan}
|
||||||
|
>
|
||||||
|
<MetricsSummaryChart
|
||||||
|
metricsSummaryTrends={filteredMetricsSummaryTrends}
|
||||||
|
/>
|
||||||
|
</Widget>
|
||||||
|
|
||||||
|
<Widget title='Average time to production' order={9}>
|
||||||
<TimeToProduction
|
<TimeToProduction
|
||||||
//FIXME: data from API
|
//FIXME: data from API
|
||||||
daysToProduction={12}
|
daysToProduction={12}
|
||||||
/>
|
/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget title='Time to production' order={9} span={chartSpan}>
|
<Widget title='Time to production' order={10} span={chartSpan}>
|
||||||
<TimeToProductionChart
|
<TimeToProductionChart
|
||||||
projectFlagTrends={filteredProjectFlagTrends}
|
projectFlagTrends={filteredProjectFlagTrends}
|
||||||
/>
|
/>
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
import { type VFC } from 'react';
|
||||||
|
import 'chartjs-adapter-date-fns';
|
||||||
|
import { ExecutiveSummarySchema } from 'openapi';
|
||||||
|
import { LineChart } from '../LineChart/LineChart';
|
||||||
|
import { useMetricsSummary } from '../useMetricsSummary';
|
||||||
|
|
||||||
|
interface IMetricsSummaryChartProps {
|
||||||
|
metricsSummaryTrends: ExecutiveSummarySchema['metricsSummaryTrends'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MetricsSummaryChart: VFC<IMetricsSummaryChartProps> = ({
|
||||||
|
metricsSummaryTrends,
|
||||||
|
}) => {
|
||||||
|
const data = useMetricsSummary(metricsSummaryTrends, 'total');
|
||||||
|
|
||||||
|
return <LineChart data={data} />;
|
||||||
|
};
|
@ -0,0 +1,58 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { getProjectColor } from './executive-dashboard-utils';
|
||||||
|
import { useTheme } from '@mui/material';
|
||||||
|
import {
|
||||||
|
ExecutiveSummarySchema,
|
||||||
|
ExecutiveSummarySchemaMetricsSummaryTrendsItem,
|
||||||
|
} from '../../openapi';
|
||||||
|
|
||||||
|
type MetricsSummaryTrends = ExecutiveSummarySchema['metricsSummaryTrends'];
|
||||||
|
|
||||||
|
export const useMetricsSummary = (
|
||||||
|
metricsSummaryTrends: MetricsSummaryTrends,
|
||||||
|
field: 'total' | 'totalYes' | 'totalNo' | 'totalApps',
|
||||||
|
) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const data = useMemo(() => {
|
||||||
|
const groupedFlagTrends = metricsSummaryTrends.reduce<
|
||||||
|
Record<string, ExecutiveSummarySchemaMetricsSummaryTrendsItem[]>
|
||||||
|
>((groups, item) => {
|
||||||
|
if (!groups[item.project]) {
|
||||||
|
groups[item.project] = [];
|
||||||
|
}
|
||||||
|
groups[item.project].push(item);
|
||||||
|
return groups;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const datasets = Object.entries(groupedFlagTrends).map(
|
||||||
|
([project, metricsSummaryTrends]) => {
|
||||||
|
const color = getProjectColor(project);
|
||||||
|
return {
|
||||||
|
label: project,
|
||||||
|
data: metricsSummaryTrends.map((item) => {
|
||||||
|
if (field !== 'total') {
|
||||||
|
return item[field] || 0;
|
||||||
|
}
|
||||||
|
return item.totalYes + item.totalNo || 0;
|
||||||
|
}),
|
||||||
|
borderColor: color,
|
||||||
|
backgroundColor: color,
|
||||||
|
fill: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const objectKeys = Object.keys(groupedFlagTrends);
|
||||||
|
|
||||||
|
const firstElementSummary = groupedFlagTrends[objectKeys[0]] || [];
|
||||||
|
const firstElementsDates = firstElementSummary.map((item) => item.date);
|
||||||
|
|
||||||
|
return {
|
||||||
|
labels: firstElementsDates,
|
||||||
|
datasets,
|
||||||
|
};
|
||||||
|
}, [theme, metricsSummaryTrends]);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
@ -33,7 +33,7 @@ export const useExecutiveDashboard = (
|
|||||||
userTrends: [],
|
userTrends: [],
|
||||||
flagTrends: [],
|
flagTrends: [],
|
||||||
projectFlagTrends: [],
|
projectFlagTrends: [],
|
||||||
impressionsSummary: [],
|
metricsSummaryTrends: [],
|
||||||
},
|
},
|
||||||
refetchExecutiveDashboard,
|
refetchExecutiveDashboard,
|
||||||
loading: !error && !data,
|
loading: !error && !data,
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
import type { ExecutiveSummarySchemaFlags } from './executiveSummarySchemaFlags';
|
import type { ExecutiveSummarySchemaFlags } from './executiveSummarySchemaFlags';
|
||||||
import type { ExecutiveSummarySchemaFlagTrendsItem } from './executiveSummarySchemaFlagTrendsItem';
|
import type { ExecutiveSummarySchemaFlagTrendsItem } from './executiveSummarySchemaFlagTrendsItem';
|
||||||
import type { ExecutiveSummarySchemaImpressionsSummaryItem } from './executiveSummarySchemaImpressionsSummaryItem';
|
import type { ExecutiveSummarySchemaMetricsSummaryTrendsItem } from './executiveSummarySchemaMetricsSummaryTrendsItem';
|
||||||
import type { ExecutiveSummarySchemaProjectFlagTrendsItem } from './executiveSummarySchemaProjectFlagTrendsItem';
|
import type { ExecutiveSummarySchemaProjectFlagTrendsItem } from './executiveSummarySchemaProjectFlagTrendsItem';
|
||||||
import type { ExecutiveSummarySchemaUsers } from './executiveSummarySchemaUsers';
|
import type { ExecutiveSummarySchemaUsers } from './executiveSummarySchemaUsers';
|
||||||
import type { ExecutiveSummarySchemaUserTrendsItem } from './executiveSummarySchemaUserTrendsItem';
|
import type { ExecutiveSummarySchemaUserTrendsItem } from './executiveSummarySchemaUserTrendsItem';
|
||||||
@ -18,8 +18,8 @@ export interface ExecutiveSummarySchema {
|
|||||||
flags: ExecutiveSummarySchemaFlags;
|
flags: ExecutiveSummarySchemaFlags;
|
||||||
/** How number of flags changed over time */
|
/** How number of flags changed over time */
|
||||||
flagTrends: ExecutiveSummarySchemaFlagTrendsItem[];
|
flagTrends: ExecutiveSummarySchemaFlagTrendsItem[];
|
||||||
/** How impression data per project changed over time */
|
/** How metrics data per project changed over time */
|
||||||
impressionsSummary: ExecutiveSummarySchemaImpressionsSummaryItem[];
|
metricsSummaryTrends: ExecutiveSummarySchemaMetricsSummaryTrendsItem[];
|
||||||
/** How number of flags per project changed over time */
|
/** How number of flags per project changed over time */
|
||||||
projectFlagTrends: ExecutiveSummarySchemaProjectFlagTrendsItem[];
|
projectFlagTrends: ExecutiveSummarySchemaProjectFlagTrendsItem[];
|
||||||
/** High level user count statistics */
|
/** High level user count statistics */
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* See `gen:api` script in package.json
|
* See `gen:api` script in package.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export type ExecutiveSummarySchemaImpressionsSummaryItem = {
|
export type ExecutiveSummarySchemaMetricsSummaryTrendsItem = {
|
||||||
/** Date the impressions summary were calculated */
|
/** Date the impressions summary were calculated */
|
||||||
date: string;
|
date: string;
|
||||||
/** Project id of the project the impressions summary belong to */
|
/** Project id of the project the impressions summary belong to */
|
@ -512,7 +512,7 @@ export * from './eventsSchemaVersion';
|
|||||||
export * from './executiveSummarySchema';
|
export * from './executiveSummarySchema';
|
||||||
export * from './executiveSummarySchemaFlagTrendsItem';
|
export * from './executiveSummarySchemaFlagTrendsItem';
|
||||||
export * from './executiveSummarySchemaFlags';
|
export * from './executiveSummarySchemaFlags';
|
||||||
export * from './executiveSummarySchemaImpressionsSummaryItem';
|
export * from './executiveSummarySchemaMetricsSummaryTrendsItem';
|
||||||
export * from './executiveSummarySchemaProjectFlagTrendsItem';
|
export * from './executiveSummarySchemaProjectFlagTrendsItem';
|
||||||
export * from './executiveSummarySchemaUserTrendsItem';
|
export * from './executiveSummarySchemaUserTrendsItem';
|
||||||
export * from './executiveSummarySchemaUsers';
|
export * from './executiveSummarySchemaUsers';
|
||||||
|
Loading…
Reference in New Issue
Block a user