From bce25bf0f14069928cf886b066293ed3f9e30937 Mon Sep 17 00:00:00 2001 From: andreas-unleash Date: Thu, 21 Mar 2024 13:29:48 +0200 Subject: [PATCH] fix: do not show flagsPerUser when calculation results to NaN (#6639) What it says on the tin Closes # [1-2209](https://linear.app/unleash/issue/1-2209/total-flag-widget-says-nan-when-no-data) --------- Signed-off-by: andreas-unleash Co-authored-by: Thomas Heartman --- .../component/executiveDashboard/Charts.tsx | 5 +- .../hooks/useDashboardData.ts | 5 +- .../hooks/useFilteredFlagsSummary.test.ts | 193 ++++++++++-------- .../hooks/useFilteredFlagsSummary.ts | 12 +- 4 files changed, 122 insertions(+), 93 deletions(-) diff --git a/frontend/src/component/executiveDashboard/Charts.tsx b/frontend/src/component/executiveDashboard/Charts.tsx index 06eaea9ba9..85343f89b7 100644 --- a/frontend/src/component/executiveDashboard/Charts.tsx +++ b/frontend/src/component/executiveDashboard/Charts.tsx @@ -39,6 +39,7 @@ interface IChartsProps { potentiallyStale: number; averageUsers: number; averageHealth?: string; + flagsPerUser?: string; }; avgDaysToProduction: number; loading: boolean; @@ -124,9 +125,7 @@ export const Charts: VFC = ({ diff --git a/frontend/src/component/executiveDashboard/hooks/useDashboardData.ts b/frontend/src/component/executiveDashboard/hooks/useDashboardData.ts index 09059e1e93..50cf54fb64 100644 --- a/frontend/src/component/executiveDashboard/hooks/useDashboardData.ts +++ b/frontend/src/component/executiveDashboard/hooks/useDashboardData.ts @@ -22,7 +22,10 @@ export const useDashboardData = ( ); const groupedMetricsData = useGroupedProjectTrends(metricsData); - const summary = useFilteredFlagsSummary(projectsData); + const summary = useFilteredFlagsSummary( + projectsData, + executiveDashboardData.users, + ); const avgDaysToProduction = useAvgTimeToProduction(groupedProjectsData); diff --git a/frontend/src/component/executiveDashboard/hooks/useFilteredFlagsSummary.test.ts b/frontend/src/component/executiveDashboard/hooks/useFilteredFlagsSummary.test.ts index e65f9c0e9a..b4a19b73ef 100644 --- a/frontend/src/component/executiveDashboard/hooks/useFilteredFlagsSummary.test.ts +++ b/frontend/src/component/executiveDashboard/hooks/useFilteredFlagsSummary.test.ts @@ -1,51 +1,55 @@ import { renderHook } from '@testing-library/react-hooks'; import { useFilteredFlagsSummary } from './useFilteredFlagsSummary'; +import type { ExecutiveSummarySchemaUsers } from '../../../openapi'; describe('useFilteredFlagTrends', () => { it('should summarize only last week of project flag trends', () => { const { result } = renderHook(() => - useFilteredFlagsSummary([ - { - week: '2024-01', - project: 'project1', - total: 1, - active: 1, - stale: 0, - potentiallyStale: 0, - users: 1, - date: '', - }, - { - week: '2024-01', - project: 'project2', - total: 2, - active: 2, - stale: 0, - potentiallyStale: 0, - users: 2, - date: '', - }, - { - week: '2024-02', - project: 'project1', - total: 4, - active: 3, - stale: 0, - potentiallyStale: 1, - users: 1, - date: '', - }, - { - week: '2024-02', - project: 'project3', - total: 10, - active: 8, - stale: 2, - potentiallyStale: 0, - users: 3, - date: '', - }, - ]), + useFilteredFlagsSummary( + [ + { + week: '2024-01', + project: 'project1', + total: 1, + active: 1, + stale: 0, + potentiallyStale: 0, + users: 1, + date: '', + }, + { + week: '2024-01', + project: 'project2', + total: 2, + active: 2, + stale: 0, + potentiallyStale: 0, + users: 2, + date: '', + }, + { + week: '2024-02', + project: 'project1', + total: 4, + active: 3, + stale: 0, + potentiallyStale: 1, + users: 1, + date: '', + }, + { + week: '2024-02', + project: 'project3', + total: 10, + active: 8, + stale: 2, + potentiallyStale: 0, + users: 3, + date: '', + }, + ], + { total: 1 } as unknown as ExecutiveSummarySchemaUsers, + ), ); expect(result.current).toEqual({ @@ -55,23 +59,27 @@ describe('useFilteredFlagTrends', () => { potentiallyStale: 1, averageUsers: 2, averageHealth: '79', + flagsPerUser: '14.00', }); }); it('should work with project with zero users', () => { const { result, rerender } = renderHook(() => - useFilteredFlagsSummary([ - { - week: '2024-01', - project: 'project1', - total: 5, - active: 5, - stale: 0, - potentiallyStale: 0, - users: 0, - date: '', - }, - ]), + useFilteredFlagsSummary( + [ + { + week: '2024-01', + project: 'project1', + total: 5, + active: 5, + stale: 0, + potentiallyStale: 0, + users: 0, + date: '', + }, + ], + { total: 1 } as unknown as ExecutiveSummarySchemaUsers, + ), ); expect(result.current).toEqual({ @@ -81,33 +89,37 @@ describe('useFilteredFlagTrends', () => { potentiallyStale: 0, averageUsers: 0, averageHealth: '100', + flagsPerUser: '5.00', }); }); it('should work with projects where some have with zero users', () => { const { result } = renderHook(() => - useFilteredFlagsSummary([ - { - week: '2024-01', - project: 'project1', - total: 5, - active: 5, - stale: 0, - potentiallyStale: 0, - users: 0, - date: '', - }, - { - week: '2024-01', - project: 'project2', - total: 5, - active: 5, - stale: 0, - potentiallyStale: 0, - users: 3, - date: '', - }, - ]), + useFilteredFlagsSummary( + [ + { + week: '2024-01', + project: 'project1', + total: 5, + active: 5, + stale: 0, + potentiallyStale: 0, + users: 0, + date: '', + }, + { + week: '2024-01', + project: 'project2', + total: 5, + active: 5, + stale: 0, + potentiallyStale: 0, + users: 3, + date: '', + }, + ], + { total: 1 } as unknown as ExecutiveSummarySchemaUsers, + ), ); expect(result.current).toEqual({ @@ -117,23 +129,27 @@ describe('useFilteredFlagTrends', () => { potentiallyStale: 0, averageUsers: 1.5, averageHealth: '100', + flagsPerUser: '10.00', }); }); it('should set health of a project without feature toggles to undefined', () => { const { result } = renderHook(() => - useFilteredFlagsSummary([ - { - week: '2024-01', - project: 'project1', - total: 0, - active: 0, - stale: 0, - potentiallyStale: 0, - users: 0, - date: '', - }, - ]), + useFilteredFlagsSummary( + [ + { + week: '2024-01', + project: 'project1', + total: 0, + active: 0, + stale: 0, + potentiallyStale: 0, + users: 0, + date: '', + }, + ], + { total: 1 } as unknown as ExecutiveSummarySchemaUsers, + ), ); expect(result.current).toEqual({ @@ -143,6 +159,7 @@ describe('useFilteredFlagTrends', () => { potentiallyStale: 0, averageUsers: 0, averageHealth: undefined, + flagsPerUser: '0.00', }); }); }); diff --git a/frontend/src/component/executiveDashboard/hooks/useFilteredFlagsSummary.ts b/frontend/src/component/executiveDashboard/hooks/useFilteredFlagsSummary.ts index 026ed357d7..5c3ac1608e 100644 --- a/frontend/src/component/executiveDashboard/hooks/useFilteredFlagsSummary.ts +++ b/frontend/src/component/executiveDashboard/hooks/useFilteredFlagsSummary.ts @@ -1,9 +1,13 @@ import { useMemo } from 'react'; -import type { ExecutiveSummarySchemaProjectFlagTrendsItem } from 'openapi'; +import type { + ExecutiveSummarySchemaProjectFlagTrendsItem, + ExecutiveSummarySchemaUsers, +} from 'openapi'; // NOTE: should we move project filtering to the backend? export const useFilteredFlagsSummary = ( filteredProjectFlagTrends: ExecutiveSummarySchemaProjectFlagTrendsItem[], + users: ExecutiveSummarySchemaUsers, ) => useMemo(() => { const lastWeekId = filteredProjectFlagTrends.reduce((prev, current) => { @@ -38,8 +42,14 @@ export const useFilteredFlagsSummary = ( }, ); + const flagsPerUserCalculation = sum.total / users.total; + const flagsPerUser = Number.isNaN(flagsPerUserCalculation) + ? 'N/A' + : flagsPerUserCalculation.toFixed(2); + return { ...sum, + flagsPerUser, averageUsers, averageHealth: sum.total ? ((sum.active / (sum.total || 1)) * 100).toFixed(0)