1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-05 17:53:12 +02:00

chore: Use custom highlighter for archive:creation chart (#10589)

Uses the same custom highlighter that we've used for the other analytics
charts, but customizes it for the archive : creation ratio chart. Also
removes the color change on hover from the bars.

Because this plugin (or a version of it) is also used in the network
traffic graphs, I've consolidated all the uses into a more configurable
one (because I was mistakenly working in the wrong file).

Before:
<img width="596" height="392" alt="image"
src="https://github.com/user-attachments/assets/d4270a6d-b1c6-47ff-8e98-424d0e7fe089"
/>


After:

<img width="1141" height="476" alt="image"
src="https://github.com/user-attachments/assets/aa10aa87-e111-4a75-8dce-4a2fec7af8ad"
/>
This commit is contained in:
Thomas Heartman 2025-09-02 15:20:12 +02:00 committed by GitHub
parent dfa89d7d58
commit c69634fda0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 65 additions and 49 deletions

View File

@ -11,7 +11,6 @@ import {
} from '@mui/material';
import { PeriodSelector } from './PeriodSelector.tsx';
import { Bar } from 'react-chartjs-2';
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin';
import { getChartLabel } from './chart-functions.ts';
import { useConsumptionStats } from './hooks/useStats.ts';
import { StyledBox, TopRow } from './SharedComponents.tsx';
@ -27,6 +26,7 @@ import {
import annotationPlugin from 'chartjs-plugin-annotation';
import { useChartDataSelection } from './hooks/useChartDataSelection.ts';
import HelpOutline from '@mui/icons-material/HelpOutline';
import { networkTrafficUsageHighlightPlugin } from './networkTrafficUsageHighlightPlugin.ts';
const ConnectionExplanationBox = styled(Box)(({ theme }) => ({
display: 'flex',
@ -73,7 +73,7 @@ export const BackendConnections: FC = () => {
</TopRow>
<Bar
data={chartData}
plugins={[customHighlightPlugin()]}
plugins={[networkTrafficUsageHighlightPlugin]}
options={options}
aria-label={getChartLabel(chartDataSelection)}
/>

View File

@ -15,12 +15,12 @@ import {
import { Bar } from 'react-chartjs-2';
import annotationPlugin from 'chartjs-plugin-annotation';
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin';
import { PeriodSelector } from './PeriodSelector.tsx';
import { getChartLabel } from './chart-functions.ts';
import { useRequestsStats } from './hooks/useStats.ts';
import { StyledBox, TopRow } from './SharedComponents.tsx';
import { useChartDataSelection } from './hooks/useChartDataSelection.ts';
import { networkTrafficUsageHighlightPlugin } from './networkTrafficUsageHighlightPlugin.ts';
const FrontendNetworkTrafficUsage: FC = () => {
usePageTitle('Network - Frontend Traffic Usage');
@ -53,7 +53,7 @@ const FrontendNetworkTrafficUsage: FC = () => {
</TopRow>
<Bar
data={chartData}
plugins={[customHighlightPlugin()]}
plugins={[networkTrafficUsageHighlightPlugin]}
options={options}
aria-label={getChartLabel(chartDataSelection)}
/>

View File

@ -17,7 +17,6 @@ import {
import { Bar } from 'react-chartjs-2';
import annotationPlugin from 'chartjs-plugin-annotation';
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin';
import { PeriodSelector } from './PeriodSelector.tsx';
import { useUiFlag } from 'hooks/useUiFlag';
import { OverageInfo, RequestSummary } from './RequestSummary.tsx';
@ -27,6 +26,7 @@ import { useTrafficStats } from './hooks/useStats.ts';
import { BoldText, StyledBox, TopRow } from './SharedComponents.tsx';
import { useChartDataSelection } from './hooks/useChartDataSelection.ts';
import { useTrafficBundles } from '../../../../hooks/api/getters/useTrafficBundles/useTrafficBundles.ts';
import { networkTrafficUsageHighlightPlugin } from './networkTrafficUsageHighlightPlugin.ts';
const TrafficInfoBoxes = styled('div')(({ theme }) => ({
display: 'grid',
@ -131,7 +131,7 @@ const NetworkTrafficUsage: FC = () => {
</TopRow>
<Bar
data={chartData}
plugins={[customHighlightPlugin()]}
plugins={[networkTrafficUsageHighlightPlugin]}
options={options}
aria-label={getChartLabel(chartDataSelection)}
/>

View File

@ -0,0 +1,5 @@
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin';
export const networkTrafficUsageHighlightPlugin = customHighlightPlugin({
bottomOverflow: 34,
});

View File

@ -1,8 +1,34 @@
import type { Chart } from 'chart.js';
export const customHighlightPlugin = (bottomOverflow = 34) => ({
type CustomHighlightPluginOptions = {
width?: number | ((chart: Chart) => number);
maxHighlightOpacity?: number;
bottomOverflow?: number;
};
const defaultCategoryPercentage = 0.8;
export const categoryWidth = (chart: Chart) => {
return (
(chart.width / chart.scales.x.ticks.length) *
(chart.options.datasets?.bar?.categoryPercentage ??
defaultCategoryPercentage)
);
};
// Vertical line on the hovered chart, filled with gradient. Highlights a section of a chart when you hover over datapoints
export const customHighlightPlugin = (
options?: CustomHighlightPluginOptions,
) => ({
id: 'customLine',
beforeDraw: (chart: Chart) => {
const {
width = categoryWidth,
maxHighlightOpacity = 0.12,
bottomOverflow = 0,
} = options ?? {};
const highlightWidth =
typeof width === 'function' ? width(chart) : width;
if (chart.tooltip?.opacity && chart.tooltip.x) {
const x = chart.tooltip.caretX;
const yAxis = chart.scales.y;
@ -12,23 +38,27 @@ export const customHighlightPlugin = (bottomOverflow = 34) => ({
x,
yAxis.top,
x,
yAxis.bottom + 34,
yAxis.bottom + bottomOverflow,
);
gradient.addColorStop(0, 'rgba(129, 122, 254, 0)');
gradient.addColorStop(1, 'rgba(129, 122, 254, 0.12)');
gradient.addColorStop(
1,
`rgba(129, 122, 254, ${maxHighlightOpacity})`,
);
ctx.fillStyle = gradient;
const barWidth =
(chart.width / (chart.data.labels?.length ?? 1)) *
(chart.options.datasets?.bar?.categoryPercentage ?? 1);
ctx.roundRect(
x - barWidth / 2,
const args: [number, number, number, number] = [
x - highlightWidth / 2,
yAxis.top,
barWidth,
highlightWidth,
yAxis.bottom - yAxis.top + bottomOverflow,
5,
);
ctx.fill();
];
if (bottomOverflow) {
ctx.roundRect(...args, 5);
ctx.fill();
} else {
ctx.fillRect(...args);
}
ctx.restore();
}
},

View File

@ -25,6 +25,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
import { styled } from '@mui/material';
import { createOptions } from './createChartOptions.ts';
import merge from 'deepmerge';
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin.ts';
const StyledContainer = styled('div')(({ theme }) => ({
position: 'relative',
@ -52,36 +53,6 @@ const StyledCoverContent = styled('div')(({ theme }) => ({
textAlign: 'center',
}));
// Vertical line on the hovered chart, filled with gradient. Highlights a section of a chart when you hover over datapoints
const customHighlightPlugin = {
id: 'customLine',
afterDraw: (chart: Chart) => {
const width = 26;
if (chart.tooltip?.opacity && chart.tooltip.x) {
const x = chart.tooltip.caretX;
const yAxis = chart.scales.y;
const ctx = chart.ctx;
ctx.save();
const gradient = ctx.createLinearGradient(
x,
yAxis.top,
x,
yAxis.bottom,
);
gradient.addColorStop(0, 'rgba(129, 122, 254, 0)');
gradient.addColorStop(1, 'rgba(129, 122, 254, 0.12)');
ctx.fillStyle = gradient;
ctx.fillRect(
x - width / 2,
yAxis.top,
width,
yAxis.bottom - yAxis.top,
);
ctx.restore();
}
},
};
function mergeAll<T>(objects: Partial<T>[]): T {
return merge.all<T>(objects.filter((i) => i));
}
@ -126,7 +97,7 @@ const LineChartComponent: FC<{
key={cover ? 'cover' : 'chart'}
options={options}
data={data}
plugins={[customHighlightPlugin]}
plugins={[customHighlightPlugin({ width: 26 })]}
height={100}
width={100 * aspectRatio}
/>

View File

@ -24,6 +24,7 @@ import { createTooltip } from 'component/insights/components/LineChart/createToo
import { CreationArchiveRatioTooltip } from './CreationArchiveRatioTooltip.tsx';
import { Chart } from 'react-chartjs-2';
import { getDateFnsLocale } from '../../getDateFnsLocale.ts';
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin.ts';
ChartJS.register(
CategoryScale,
@ -108,6 +109,8 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
data: weeks,
backgroundColor: theme.palette.charts.A2,
borderColor: theme.palette.charts.A2,
hoverBackgroundColor: theme.palette.charts.A2,
hoverBorderColor: theme.palette.charts.A2,
parsing: { yAxisKey: 'archivedFlags', xAxisKey: 'date' },
order: 1,
},
@ -116,6 +119,8 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
data: weeks,
backgroundColor: theme.palette.charts.A1,
borderColor: theme.palette.charts.A1,
hoverBackgroundColor: theme.palette.charts.A1,
hoverBorderColor: theme.palette.charts.A1,
parsing: {
yAxisKey: 'totalCreatedFlags',
xAxisKey: 'date',
@ -203,6 +208,11 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
options={options}
height={100}
width={250}
plugins={[
customHighlightPlugin({
maxHighlightOpacity: 0.24,
}),
]}
/>
<CreationArchiveRatioTooltip tooltip={tooltip} />
</>