Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: average time to production chart (#6565)
Adds live data to TimeToProductionChart and AverageTimeToProduction gauge. Create a custom tooltip Changes the interaction mode for tooltips as per @nicolaesocaciu pairing session Improvement: Extract grouping by project to its own hook (3 charts that needed grouped data where handling it independently. <img width="1331" alt="Screenshot 2024-03-14 at 17 19 07" src="https://github.com/Unleash/unleash/assets/104830839/199c556c-8264-46e3-9dd5-9a864588de1f"> Closes # [1-2143](https://linear.app/unleash/issue/1-2143/time-to-production-total-aggregation) --------- Signed-off-by: andreas-unleash <andreas@getunleash.ai>
- Loading branch information
1 parent
4d78c6d
commit 4563468
Showing
14 changed files
with
366 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 17 additions & 5 deletions
22
...ponent/executiveDashboard/componentsChart/TimeToProductionChart/TimeToProductionChart.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
...componentsChart/TimeToProductionChart/TimeToProductionTooltip/TimeToProductionTooltip.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import { type VFC } from 'react'; | ||
import { type ExecutiveSummarySchemaProjectFlagTrendsItem } from 'openapi'; | ||
import { Box, Paper, Typography, styled } from '@mui/material'; | ||
import { Badge } from 'component/common/Badge/Badge'; | ||
import { TooltipState } from '../../../components/LineChart/ChartTooltip/ChartTooltip'; | ||
|
||
const StyledTooltipItemContainer = styled(Paper)(({ theme }) => ({ | ||
padding: theme.spacing(2), | ||
})); | ||
|
||
const StyledItemHeader = styled(Box)(({ theme }) => ({ | ||
display: 'flex', | ||
justifyContent: 'space-between', | ||
gap: theme.spacing(2), | ||
alignItems: 'center', | ||
})); | ||
|
||
const getInterval = (days?: number) => { | ||
if (!days) { | ||
return 'N/A'; | ||
} | ||
|
||
if (days > 11) { | ||
const weeks = days / 7; | ||
if (weeks > 6) { | ||
const months = weeks / 4.34524; | ||
return `${months.toFixed(2)} months`; | ||
} else { | ||
return `${weeks.toFixed(1)} weeks`; | ||
} | ||
} else { | ||
return `${days} days`; | ||
} | ||
}; | ||
|
||
const resolveBadge = (input?: number) => { | ||
const ONE_MONTH = 30; | ||
const ONE_WEEK = 7; | ||
|
||
if (!input) { | ||
return null; | ||
} | ||
|
||
if (input >= ONE_MONTH) { | ||
return <Badge color='error'>Low</Badge>; | ||
} | ||
|
||
if (input <= ONE_MONTH && input >= ONE_WEEK + 1) { | ||
return <Badge>Medium</Badge>; | ||
} | ||
|
||
if (input <= ONE_WEEK) { | ||
return <Badge color='success'>High</Badge>; | ||
} | ||
}; | ||
|
||
export const TimeToProductionTooltip: VFC<{ tooltip: TooltipState | null }> = ({ | ||
tooltip, | ||
}) => { | ||
const data = tooltip?.dataPoints.map((point) => { | ||
return { | ||
label: point.label, | ||
title: point.dataset.label, | ||
color: point.dataset.borderColor, | ||
value: point.raw as ExecutiveSummarySchemaProjectFlagTrendsItem, | ||
}; | ||
}); | ||
|
||
const limitedData = data?.slice(0, 5); | ||
|
||
return ( | ||
<Box | ||
sx={(theme) => ({ | ||
display: 'flex', | ||
flexDirection: 'column', | ||
gap: theme.spacing(2), | ||
width: '300px', | ||
})} | ||
> | ||
{limitedData?.map((point, index) => ( | ||
<StyledTooltipItemContainer | ||
elevation={3} | ||
key={`${point.title}-${index}`} | ||
> | ||
<StyledItemHeader> | ||
<Typography | ||
variant='body2' | ||
color='textSecondary' | ||
component='span' | ||
> | ||
{point.label} | ||
</Typography> | ||
</StyledItemHeader> | ||
<StyledItemHeader> | ||
<Typography variant='body2' component='span'> | ||
<Typography | ||
sx={{ color: point.color }} | ||
component='span' | ||
> | ||
{'● '} | ||
</Typography> | ||
<strong>{point.title}</strong> | ||
</Typography> | ||
<Typography | ||
variant='body2' | ||
component='span' | ||
sx={{ mr: (theme) => theme.spacing(1), pt: 0.25 }} | ||
> | ||
{getInterval(point.value.timeToProduction)} | ||
</Typography> | ||
{resolveBadge(point.value.timeToProduction)} | ||
</StyledItemHeader> | ||
</StyledTooltipItemContainer> | ||
)) || null} | ||
</Box> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
frontend/src/component/executiveDashboard/hooks/useAvgTimeToProduction.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { useAvgTimeToProduction } from './useAvgTimeToProduction'; | ||
import { renderHook } from '@testing-library/react-hooks'; | ||
|
||
describe('useAvgTimeToProduction', () => { | ||
test('returns 0 when projectsData is empty', () => { | ||
const projectsData = {}; | ||
const { result } = renderHook(() => | ||
useAvgTimeToProduction(projectsData), | ||
); | ||
expect(result.current).toBe(0); | ||
}); | ||
|
||
test('calculates result.current time to production correctly', () => { | ||
const projectsData = { | ||
project1: [{ timeToProduction: 10 }, { timeToProduction: 20 }], | ||
project2: [{ timeToProduction: 15 }, { timeToProduction: 25 }], | ||
} as any; | ||
const { result } = renderHook(() => | ||
useAvgTimeToProduction(projectsData), | ||
); | ||
expect(result.current).toBe(17.5); | ||
}); | ||
|
||
test('ignores projects without time to production data', () => { | ||
const projectsData = { | ||
project1: [{ timeToProduction: 10 }, { timeToProduction: 20 }], | ||
project2: [], | ||
} as any; | ||
const { result } = renderHook(() => | ||
useAvgTimeToProduction(projectsData), | ||
); | ||
expect(result.current).toBe(7.5); | ||
}); | ||
}); |
Oops, something went wrong.