1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-23 00:22:19 +01:00

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 <andreas@getunleash.ai>
Co-authored-by: Thomas Heartman <thomas@getunleash.io>
This commit is contained in:
andreas-unleash 2024-03-21 13:29:48 +02:00 committed by GitHub
parent 3241d14a05
commit bce25bf0f1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 122 additions and 93 deletions

View File

@ -39,6 +39,7 @@ interface IChartsProps {
potentiallyStale: number; potentiallyStale: number;
averageUsers: number; averageUsers: number;
averageHealth?: string; averageHealth?: string;
flagsPerUser?: string;
}; };
avgDaysToProduction: number; avgDaysToProduction: number;
loading: boolean; loading: boolean;
@ -124,9 +125,7 @@ export const Charts: VFC<IChartsProps> = ({
<FlagStats <FlagStats
count={summary.total} count={summary.total}
flagsPerUser={ flagsPerUser={
showAllProjects showAllProjects ? summary.flagsPerUser : ''
? (summary.total / users.total).toFixed(2)
: ''
} }
/> />
</Widget> </Widget>

View File

@ -22,7 +22,10 @@ export const useDashboardData = (
); );
const groupedMetricsData = useGroupedProjectTrends(metricsData); const groupedMetricsData = useGroupedProjectTrends(metricsData);
const summary = useFilteredFlagsSummary(projectsData); const summary = useFilteredFlagsSummary(
projectsData,
executiveDashboardData.users,
);
const avgDaysToProduction = useAvgTimeToProduction(groupedProjectsData); const avgDaysToProduction = useAvgTimeToProduction(groupedProjectsData);

View File

@ -1,51 +1,55 @@
import { renderHook } from '@testing-library/react-hooks'; import { renderHook } from '@testing-library/react-hooks';
import { useFilteredFlagsSummary } from './useFilteredFlagsSummary'; import { useFilteredFlagsSummary } from './useFilteredFlagsSummary';
import type { ExecutiveSummarySchemaUsers } from '../../../openapi';
describe('useFilteredFlagTrends', () => { describe('useFilteredFlagTrends', () => {
it('should summarize only last week of project flag trends', () => { it('should summarize only last week of project flag trends', () => {
const { result } = renderHook(() => const { result } = renderHook(() =>
useFilteredFlagsSummary([ useFilteredFlagsSummary(
{ [
week: '2024-01', {
project: 'project1', week: '2024-01',
total: 1, project: 'project1',
active: 1, total: 1,
stale: 0, active: 1,
potentiallyStale: 0, stale: 0,
users: 1, potentiallyStale: 0,
date: '', users: 1,
}, date: '',
{ },
week: '2024-01', {
project: 'project2', week: '2024-01',
total: 2, project: 'project2',
active: 2, total: 2,
stale: 0, active: 2,
potentiallyStale: 0, stale: 0,
users: 2, potentiallyStale: 0,
date: '', users: 2,
}, date: '',
{ },
week: '2024-02', {
project: 'project1', week: '2024-02',
total: 4, project: 'project1',
active: 3, total: 4,
stale: 0, active: 3,
potentiallyStale: 1, stale: 0,
users: 1, potentiallyStale: 1,
date: '', users: 1,
}, date: '',
{ },
week: '2024-02', {
project: 'project3', week: '2024-02',
total: 10, project: 'project3',
active: 8, total: 10,
stale: 2, active: 8,
potentiallyStale: 0, stale: 2,
users: 3, potentiallyStale: 0,
date: '', users: 3,
}, date: '',
]), },
],
{ total: 1 } as unknown as ExecutiveSummarySchemaUsers,
),
); );
expect(result.current).toEqual({ expect(result.current).toEqual({
@ -55,23 +59,27 @@ describe('useFilteredFlagTrends', () => {
potentiallyStale: 1, potentiallyStale: 1,
averageUsers: 2, averageUsers: 2,
averageHealth: '79', averageHealth: '79',
flagsPerUser: '14.00',
}); });
}); });
it('should work with project with zero users', () => { it('should work with project with zero users', () => {
const { result, rerender } = renderHook(() => const { result, rerender } = renderHook(() =>
useFilteredFlagsSummary([ useFilteredFlagsSummary(
{ [
week: '2024-01', {
project: 'project1', week: '2024-01',
total: 5, project: 'project1',
active: 5, total: 5,
stale: 0, active: 5,
potentiallyStale: 0, stale: 0,
users: 0, potentiallyStale: 0,
date: '', users: 0,
}, date: '',
]), },
],
{ total: 1 } as unknown as ExecutiveSummarySchemaUsers,
),
); );
expect(result.current).toEqual({ expect(result.current).toEqual({
@ -81,33 +89,37 @@ describe('useFilteredFlagTrends', () => {
potentiallyStale: 0, potentiallyStale: 0,
averageUsers: 0, averageUsers: 0,
averageHealth: '100', averageHealth: '100',
flagsPerUser: '5.00',
}); });
}); });
it('should work with projects where some have with zero users', () => { it('should work with projects where some have with zero users', () => {
const { result } = renderHook(() => const { result } = renderHook(() =>
useFilteredFlagsSummary([ useFilteredFlagsSummary(
{ [
week: '2024-01', {
project: 'project1', week: '2024-01',
total: 5, project: 'project1',
active: 5, total: 5,
stale: 0, active: 5,
potentiallyStale: 0, stale: 0,
users: 0, potentiallyStale: 0,
date: '', users: 0,
}, date: '',
{ },
week: '2024-01', {
project: 'project2', week: '2024-01',
total: 5, project: 'project2',
active: 5, total: 5,
stale: 0, active: 5,
potentiallyStale: 0, stale: 0,
users: 3, potentiallyStale: 0,
date: '', users: 3,
}, date: '',
]), },
],
{ total: 1 } as unknown as ExecutiveSummarySchemaUsers,
),
); );
expect(result.current).toEqual({ expect(result.current).toEqual({
@ -117,23 +129,27 @@ describe('useFilteredFlagTrends', () => {
potentiallyStale: 0, potentiallyStale: 0,
averageUsers: 1.5, averageUsers: 1.5,
averageHealth: '100', averageHealth: '100',
flagsPerUser: '10.00',
}); });
}); });
it('should set health of a project without feature toggles to undefined', () => { it('should set health of a project without feature toggles to undefined', () => {
const { result } = renderHook(() => const { result } = renderHook(() =>
useFilteredFlagsSummary([ useFilteredFlagsSummary(
{ [
week: '2024-01', {
project: 'project1', week: '2024-01',
total: 0, project: 'project1',
active: 0, total: 0,
stale: 0, active: 0,
potentiallyStale: 0, stale: 0,
users: 0, potentiallyStale: 0,
date: '', users: 0,
}, date: '',
]), },
],
{ total: 1 } as unknown as ExecutiveSummarySchemaUsers,
),
); );
expect(result.current).toEqual({ expect(result.current).toEqual({
@ -143,6 +159,7 @@ describe('useFilteredFlagTrends', () => {
potentiallyStale: 0, potentiallyStale: 0,
averageUsers: 0, averageUsers: 0,
averageHealth: undefined, averageHealth: undefined,
flagsPerUser: '0.00',
}); });
}); });
}); });

View File

@ -1,9 +1,13 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import type { ExecutiveSummarySchemaProjectFlagTrendsItem } from 'openapi'; import type {
ExecutiveSummarySchemaProjectFlagTrendsItem,
ExecutiveSummarySchemaUsers,
} from 'openapi';
// NOTE: should we move project filtering to the backend? // NOTE: should we move project filtering to the backend?
export const useFilteredFlagsSummary = ( export const useFilteredFlagsSummary = (
filteredProjectFlagTrends: ExecutiveSummarySchemaProjectFlagTrendsItem[], filteredProjectFlagTrends: ExecutiveSummarySchemaProjectFlagTrendsItem[],
users: ExecutiveSummarySchemaUsers,
) => ) =>
useMemo(() => { useMemo(() => {
const lastWeekId = filteredProjectFlagTrends.reduce((prev, current) => { 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 { return {
...sum, ...sum,
flagsPerUser,
averageUsers, averageUsers,
averageHealth: sum.total averageHealth: sum.total
? ((sum.active / (sum.total || 1)) * 100).toFixed(0) ? ((sum.active / (sum.total || 1)) * 100).toFixed(0)