-
-
Notifications
You must be signed in to change notification settings - Fork 731
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add project flags component #6070
Changes from all commits
d7dbeca
27d4e7b
76d02c0
457b724
477ee69
5d755f8
87fea8e
7639d13
04ca10d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { lazy } from 'react'; | ||
|
||
export const FlagsProjectChart = lazy( | ||
() => import('./FlagsProjectChartComponent'), | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
import { useMemo, type VFC } from 'react'; | ||
import { | ||
Chart as ChartJS, | ||
CategoryScale, | ||
LinearScale, | ||
PointElement, | ||
LineElement, | ||
Title, | ||
Tooltip, | ||
Legend, | ||
TimeScale, | ||
} from 'chart.js'; | ||
import { Line } from 'react-chartjs-2'; | ||
import 'chartjs-adapter-date-fns'; | ||
import { Paper, Theme, Typography, useTheme } from '@mui/material'; | ||
import { | ||
useLocationSettings, | ||
type ILocationSettings, | ||
} from 'hooks/useLocationSettings'; | ||
import { formatDateYMD } from 'utils/formatDate'; | ||
import { | ||
ExecutiveSummarySchema, | ||
ExecutiveSummarySchemaProjectFlagTrendsItem, | ||
} from 'openapi'; | ||
|
||
const getRandomColor = () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you add a sample screenshot so we can take a look at the colors that got generated? In other words I'd like to see if the color choice is smart enough to avoid very similar colors There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
const letters = '0123456789ABCDEF'; | ||
let color = '#'; | ||
for (let i = 0; i < 6; i++) { | ||
color += letters[Math.floor(Math.random() * 16)]; | ||
} | ||
return color; | ||
}; | ||
|
||
const createData = ( | ||
theme: Theme, | ||
flagTrends: ExecutiveSummarySchema['projectFlagTrends'] = [], | ||
) => { | ||
const groupedFlagTrends = flagTrends.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, | ||
}; | ||
}, | ||
); | ||
|
||
return { | ||
labels: flagTrends.map((item) => item.date), | ||
datasets, | ||
}; | ||
}; | ||
|
||
const createOptions = (theme: Theme, locationSettings: ILocationSettings) => | ||
({ | ||
responsive: true, | ||
plugins: { | ||
legend: { | ||
position: 'bottom', | ||
}, | ||
tooltip: { | ||
callbacks: { | ||
title: (tooltipItems: any) => { | ||
const item = tooltipItems?.[0]; | ||
const date = | ||
item?.chart?.data?.labels?.[item.dataIndex]; | ||
return date | ||
? formatDateYMD( | ||
date, | ||
locationSettings.locale, | ||
'UTC', | ||
) | ||
: ''; | ||
}, | ||
}, | ||
}, | ||
}, | ||
locale: locationSettings.locale, | ||
interaction: { | ||
intersect: false, | ||
axis: 'x', | ||
}, | ||
color: theme.palette.text.secondary, | ||
scales: { | ||
y: { | ||
type: 'linear', | ||
grid: { | ||
color: theme.palette.divider, | ||
borderColor: theme.palette.divider, | ||
}, | ||
ticks: { color: theme.palette.text.secondary }, | ||
}, | ||
x: { | ||
type: 'time', | ||
time: { | ||
unit: 'month', | ||
}, | ||
grid: { | ||
color: theme.palette.divider, | ||
borderColor: theme.palette.divider, | ||
}, | ||
ticks: { | ||
color: theme.palette.text.secondary, | ||
}, | ||
}, | ||
}, | ||
}) as const; | ||
|
||
interface IFlagsChartComponentProps { | ||
projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends']; | ||
} | ||
|
||
const FlagsProjectChart: VFC<IFlagsChartComponentProps> = ({ | ||
projectFlagTrends, | ||
}) => { | ||
const theme = useTheme(); | ||
const { locationSettings } = useLocationSettings(); | ||
const data = useMemo( | ||
() => createData(theme, projectFlagTrends), | ||
[theme, projectFlagTrends], | ||
); | ||
const options = createOptions(theme, locationSettings); | ||
|
||
return ( | ||
<Paper sx={(theme) => ({ padding: theme.spacing(4) })}> | ||
<Typography | ||
variant='h3' | ||
sx={(theme) => ({ marginBottom: theme.spacing(3) })} | ||
> | ||
Number of flags per project | ||
</Typography> | ||
<Line options={options} data={data} /> | ||
</Paper> | ||
); | ||
}; | ||
|
||
ChartJS.register( | ||
CategoryScale, | ||
LinearScale, | ||
PointElement, | ||
LineElement, | ||
TimeScale, | ||
Title, | ||
Tooltip, | ||
Legend, | ||
); | ||
|
||
export default FlagsProjectChart; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/** | ||
* Generated by Orval | ||
* Do not edit manually. | ||
* See `gen:api` script in package.json | ||
*/ | ||
|
||
export type ExecutiveSummarySchemaProjectFlagTrendsItem = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I recommend running it again one more time to get health and time to production that got added a second ago :) We'll avoid another orval run in future |
||
/** The number of active flags on a particular day */ | ||
active: number; | ||
/** A UTC date when the stats were captured. Time is the very end of a given day. */ | ||
date: string; | ||
/** An indicator of the [project's health](https://docs.getunleash.io/reference/technical-debt#health-rating) on a scale from 0 to 100 */ | ||
health?: number; | ||
/** The number of time calculated potentially stale flags on a particular day */ | ||
potentiallyStale: number; | ||
/** Project id of the project the flag trends belong to */ | ||
project: string; | ||
/** The number of user marked stale flags on a particular day */ | ||
stale: number; | ||
/** The average time from when a feature was created to when it was enabled in the "production" environment during the current window */ | ||
timeToProduction?: number; | ||
/** The number of all flags on a particular day */ | ||
total: number; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we do this for each chart? maybe we can lazy load all charts that show up together