1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-24 17:51:14 +02:00

chore: add a cover to graph when there's not enough data

This commit is contained in:
Thomas Heartman 2025-09-02 15:32:17 +02:00
parent c69634fda0
commit 26c2a2bf4f
No known key found for this signature in database
GPG Key ID: BD1F880DAED1EE78

View File

@ -2,9 +2,8 @@ import 'chartjs-adapter-date-fns';
import { type FC, useMemo, useState } from 'react'; import { type FC, useMemo, useState } from 'react';
import type { InstanceInsightsSchema } from 'openapi'; import type { InstanceInsightsSchema } from 'openapi';
import { useProjectChartData } from 'component/insights/hooks/useProjectChartData'; import { useProjectChartData } from 'component/insights/hooks/useProjectChartData';
import { useTheme } from '@mui/material'; import { styled, useTheme } from '@mui/material';
import type { GroupedDataByProject } from 'component/insights/hooks/useGroupedProjectTrends'; import type { GroupedDataByProject } from 'component/insights/hooks/useGroupedProjectTrends';
import { usePlaceholderData } from 'component/insights/hooks/usePlaceholderData';
import { import {
CategoryScale, CategoryScale,
LinearScale, LinearScale,
@ -25,6 +24,8 @@ import { CreationArchiveRatioTooltip } from './CreationArchiveRatioTooltip.tsx';
import { Chart } from 'react-chartjs-2'; import { Chart } from 'react-chartjs-2';
import { getDateFnsLocale } from '../../getDateFnsLocale.ts'; import { getDateFnsLocale } from '../../getDateFnsLocale.ts';
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin.ts'; import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin.ts';
import { NotEnoughData } from 'component/insights/components/LineChart/LineChart.tsx';
import { usePlaceholderData } from 'component/insights/hooks/usePlaceholderData.ts';
ChartJS.register( ChartJS.register(
CategoryScale, CategoryScale,
@ -45,6 +46,28 @@ interface ICreationArchiveChartProps {
isLoading?: boolean; isLoading?: boolean;
} }
const StyledCover = styled('div')(({ theme }) => ({
position: 'absolute',
inset: 0,
display: 'flex',
zIndex: theme.zIndex.appBar,
'&::before': {
zIndex: theme.zIndex.fab,
content: '""',
position: 'absolute',
inset: 0,
backgroundColor: theme.palette.background.paper,
opacity: 0.8,
},
}));
const StyledCoverContent = styled('div')(({ theme }) => ({
zIndex: theme.zIndex.modal,
margin: 'auto',
color: theme.palette.text.secondary,
textAlign: 'center',
}));
export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
creationArchiveTrends, creationArchiveTrends,
isLoading, isLoading,
@ -55,7 +78,7 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
const { locationSettings } = useLocationSettings(); const { locationSettings } = useLocationSettings();
const [tooltip, setTooltip] = useState<null | TooltipState>(null); const [tooltip, setTooltip] = useState<null | TooltipState>(null);
const aggregateOrProjectData = useMemo(() => { const { notEnoughData, aggregateOrProjectData } = useMemo(() => {
const labels: string[] = Array.from( const labels: string[] = Array.from(
new Set( new Set(
creationVsArchivedChart.datasets.flatMap((d) => creationVsArchivedChart.datasets.flatMap((d) =>
@ -103,6 +126,8 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
.sort((a, b) => (a.week > b.week ? 1 : -1)); .sort((a, b) => (a.week > b.week ? 1 : -1));
return { return {
notEnoughData: weeks.length < 2,
aggregateOrProjectData: {
datasets: [ datasets: [
{ {
label: 'Flags archived', label: 'Flags archived',
@ -111,7 +136,10 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
borderColor: theme.palette.charts.A2, borderColor: theme.palette.charts.A2,
hoverBackgroundColor: theme.palette.charts.A2, hoverBackgroundColor: theme.palette.charts.A2,
hoverBorderColor: theme.palette.charts.A2, hoverBorderColor: theme.palette.charts.A2,
parsing: { yAxisKey: 'archivedFlags', xAxisKey: 'date' }, parsing: {
yAxisKey: 'archivedFlags',
xAxisKey: 'date',
},
order: 1, order: 1,
}, },
{ {
@ -128,21 +156,23 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
order: 2, order: 2,
}, },
], ],
},
}; };
}, [creationVsArchivedChart, theme]); }, [creationVsArchivedChart, theme]);
const notEnoughData = useMemo( const useGraphCover = notEnoughData || isLoading;
() => const data = useGraphCover ? placeholderData : aggregateOrProjectData;
!isLoading &&
!creationVsArchivedChart.datasets.some((d) => d.data.length > 1),
[creationVsArchivedChart, isLoading],
);
const data =
notEnoughData || isLoading ? placeholderData : aggregateOrProjectData;
const options = useMemo( const options = useMemo(
() => ({ () => ({
responsive: true, responsive: true,
...(useGraphCover
? {
animation: {
duration: 0,
},
}
: {}),
interaction: { interaction: {
mode: 'index' as const, mode: 'index' as const,
intersect: false, intersect: false,
@ -157,6 +187,7 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
padding: 21, padding: 21,
boxHeight: 8, boxHeight: 8,
}, },
display: !useGraphCover,
}, },
tooltip: { tooltip: {
enabled: false, enabled: false,
@ -181,7 +212,10 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
grid: { grid: {
display: false, display: false,
}, },
ticks: { source: 'data' }, ticks: {
source: 'data',
display: !useGraphCover,
},
}, },
y: { y: {
type: 'linear' as const, type: 'linear' as const,
@ -193,6 +227,7 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
}, },
ticks: { ticks: {
stepSize: 1, stepSize: 1,
display: !useGraphCover,
}, },
}, },
}, },
@ -215,6 +250,13 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
]} ]}
/> />
<CreationArchiveRatioTooltip tooltip={tooltip} /> <CreationArchiveRatioTooltip tooltip={tooltip} />
{useGraphCover ? (
<StyledCover>
<StyledCoverContent>
{notEnoughData ? <NotEnoughData /> : isLoading}
</StyledCoverContent>
</StyledCover>
) : null}
</> </>
); );
}; };