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:
parent
dfa89d7d58
commit
c69634fda0
@ -11,7 +11,6 @@ import {
|
|||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { PeriodSelector } from './PeriodSelector.tsx';
|
import { PeriodSelector } from './PeriodSelector.tsx';
|
||||||
import { Bar } from 'react-chartjs-2';
|
import { Bar } from 'react-chartjs-2';
|
||||||
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin';
|
|
||||||
import { getChartLabel } from './chart-functions.ts';
|
import { getChartLabel } from './chart-functions.ts';
|
||||||
import { useConsumptionStats } from './hooks/useStats.ts';
|
import { useConsumptionStats } from './hooks/useStats.ts';
|
||||||
import { StyledBox, TopRow } from './SharedComponents.tsx';
|
import { StyledBox, TopRow } from './SharedComponents.tsx';
|
||||||
@ -27,6 +26,7 @@ import {
|
|||||||
import annotationPlugin from 'chartjs-plugin-annotation';
|
import annotationPlugin from 'chartjs-plugin-annotation';
|
||||||
import { useChartDataSelection } from './hooks/useChartDataSelection.ts';
|
import { useChartDataSelection } from './hooks/useChartDataSelection.ts';
|
||||||
import HelpOutline from '@mui/icons-material/HelpOutline';
|
import HelpOutline from '@mui/icons-material/HelpOutline';
|
||||||
|
import { networkTrafficUsageHighlightPlugin } from './networkTrafficUsageHighlightPlugin.ts';
|
||||||
|
|
||||||
const ConnectionExplanationBox = styled(Box)(({ theme }) => ({
|
const ConnectionExplanationBox = styled(Box)(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -73,7 +73,7 @@ export const BackendConnections: FC = () => {
|
|||||||
</TopRow>
|
</TopRow>
|
||||||
<Bar
|
<Bar
|
||||||
data={chartData}
|
data={chartData}
|
||||||
plugins={[customHighlightPlugin()]}
|
plugins={[networkTrafficUsageHighlightPlugin]}
|
||||||
options={options}
|
options={options}
|
||||||
aria-label={getChartLabel(chartDataSelection)}
|
aria-label={getChartLabel(chartDataSelection)}
|
||||||
/>
|
/>
|
||||||
|
@ -15,12 +15,12 @@ import {
|
|||||||
|
|
||||||
import { Bar } from 'react-chartjs-2';
|
import { Bar } from 'react-chartjs-2';
|
||||||
import annotationPlugin from 'chartjs-plugin-annotation';
|
import annotationPlugin from 'chartjs-plugin-annotation';
|
||||||
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin';
|
|
||||||
import { PeriodSelector } from './PeriodSelector.tsx';
|
import { PeriodSelector } from './PeriodSelector.tsx';
|
||||||
import { getChartLabel } from './chart-functions.ts';
|
import { getChartLabel } from './chart-functions.ts';
|
||||||
import { useRequestsStats } from './hooks/useStats.ts';
|
import { useRequestsStats } from './hooks/useStats.ts';
|
||||||
import { StyledBox, TopRow } from './SharedComponents.tsx';
|
import { StyledBox, TopRow } from './SharedComponents.tsx';
|
||||||
import { useChartDataSelection } from './hooks/useChartDataSelection.ts';
|
import { useChartDataSelection } from './hooks/useChartDataSelection.ts';
|
||||||
|
import { networkTrafficUsageHighlightPlugin } from './networkTrafficUsageHighlightPlugin.ts';
|
||||||
|
|
||||||
const FrontendNetworkTrafficUsage: FC = () => {
|
const FrontendNetworkTrafficUsage: FC = () => {
|
||||||
usePageTitle('Network - Frontend Traffic Usage');
|
usePageTitle('Network - Frontend Traffic Usage');
|
||||||
@ -53,7 +53,7 @@ const FrontendNetworkTrafficUsage: FC = () => {
|
|||||||
</TopRow>
|
</TopRow>
|
||||||
<Bar
|
<Bar
|
||||||
data={chartData}
|
data={chartData}
|
||||||
plugins={[customHighlightPlugin()]}
|
plugins={[networkTrafficUsageHighlightPlugin]}
|
||||||
options={options}
|
options={options}
|
||||||
aria-label={getChartLabel(chartDataSelection)}
|
aria-label={getChartLabel(chartDataSelection)}
|
||||||
/>
|
/>
|
||||||
|
@ -17,7 +17,6 @@ import {
|
|||||||
|
|
||||||
import { Bar } from 'react-chartjs-2';
|
import { Bar } from 'react-chartjs-2';
|
||||||
import annotationPlugin from 'chartjs-plugin-annotation';
|
import annotationPlugin from 'chartjs-plugin-annotation';
|
||||||
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin';
|
|
||||||
import { PeriodSelector } from './PeriodSelector.tsx';
|
import { PeriodSelector } from './PeriodSelector.tsx';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
import { OverageInfo, RequestSummary } from './RequestSummary.tsx';
|
import { OverageInfo, RequestSummary } from './RequestSummary.tsx';
|
||||||
@ -27,6 +26,7 @@ import { useTrafficStats } from './hooks/useStats.ts';
|
|||||||
import { BoldText, StyledBox, TopRow } from './SharedComponents.tsx';
|
import { BoldText, StyledBox, TopRow } from './SharedComponents.tsx';
|
||||||
import { useChartDataSelection } from './hooks/useChartDataSelection.ts';
|
import { useChartDataSelection } from './hooks/useChartDataSelection.ts';
|
||||||
import { useTrafficBundles } from '../../../../hooks/api/getters/useTrafficBundles/useTrafficBundles.ts';
|
import { useTrafficBundles } from '../../../../hooks/api/getters/useTrafficBundles/useTrafficBundles.ts';
|
||||||
|
import { networkTrafficUsageHighlightPlugin } from './networkTrafficUsageHighlightPlugin.ts';
|
||||||
|
|
||||||
const TrafficInfoBoxes = styled('div')(({ theme }) => ({
|
const TrafficInfoBoxes = styled('div')(({ theme }) => ({
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -131,7 +131,7 @@ const NetworkTrafficUsage: FC = () => {
|
|||||||
</TopRow>
|
</TopRow>
|
||||||
<Bar
|
<Bar
|
||||||
data={chartData}
|
data={chartData}
|
||||||
plugins={[customHighlightPlugin()]}
|
plugins={[networkTrafficUsageHighlightPlugin]}
|
||||||
options={options}
|
options={options}
|
||||||
aria-label={getChartLabel(chartDataSelection)}
|
aria-label={getChartLabel(chartDataSelection)}
|
||||||
/>
|
/>
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin';
|
||||||
|
|
||||||
|
export const networkTrafficUsageHighlightPlugin = customHighlightPlugin({
|
||||||
|
bottomOverflow: 34,
|
||||||
|
});
|
@ -1,8 +1,34 @@
|
|||||||
import type { Chart } from 'chart.js';
|
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',
|
id: 'customLine',
|
||||||
beforeDraw: (chart: Chart) => {
|
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) {
|
if (chart.tooltip?.opacity && chart.tooltip.x) {
|
||||||
const x = chart.tooltip.caretX;
|
const x = chart.tooltip.caretX;
|
||||||
const yAxis = chart.scales.y;
|
const yAxis = chart.scales.y;
|
||||||
@ -12,23 +38,27 @@ export const customHighlightPlugin = (bottomOverflow = 34) => ({
|
|||||||
x,
|
x,
|
||||||
yAxis.top,
|
yAxis.top,
|
||||||
x,
|
x,
|
||||||
yAxis.bottom + 34,
|
yAxis.bottom + bottomOverflow,
|
||||||
);
|
);
|
||||||
gradient.addColorStop(0, 'rgba(129, 122, 254, 0)');
|
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;
|
ctx.fillStyle = gradient;
|
||||||
|
|
||||||
const barWidth =
|
const args: [number, number, number, number] = [
|
||||||
(chart.width / (chart.data.labels?.length ?? 1)) *
|
x - highlightWidth / 2,
|
||||||
(chart.options.datasets?.bar?.categoryPercentage ?? 1);
|
|
||||||
ctx.roundRect(
|
|
||||||
x - barWidth / 2,
|
|
||||||
yAxis.top,
|
yAxis.top,
|
||||||
barWidth,
|
highlightWidth,
|
||||||
yAxis.bottom - yAxis.top + bottomOverflow,
|
yAxis.bottom - yAxis.top + bottomOverflow,
|
||||||
5,
|
];
|
||||||
);
|
if (bottomOverflow) {
|
||||||
ctx.fill();
|
ctx.roundRect(...args, 5);
|
||||||
|
ctx.fill();
|
||||||
|
} else {
|
||||||
|
ctx.fillRect(...args);
|
||||||
|
}
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -25,6 +25,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
|
|||||||
import { styled } from '@mui/material';
|
import { styled } from '@mui/material';
|
||||||
import { createOptions } from './createChartOptions.ts';
|
import { createOptions } from './createChartOptions.ts';
|
||||||
import merge from 'deepmerge';
|
import merge from 'deepmerge';
|
||||||
|
import { customHighlightPlugin } from 'component/common/Chart/customHighlightPlugin.ts';
|
||||||
|
|
||||||
const StyledContainer = styled('div')(({ theme }) => ({
|
const StyledContainer = styled('div')(({ theme }) => ({
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
@ -52,36 +53,6 @@ const StyledCoverContent = styled('div')(({ theme }) => ({
|
|||||||
textAlign: 'center',
|
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 {
|
function mergeAll<T>(objects: Partial<T>[]): T {
|
||||||
return merge.all<T>(objects.filter((i) => i));
|
return merge.all<T>(objects.filter((i) => i));
|
||||||
}
|
}
|
||||||
@ -126,7 +97,7 @@ const LineChartComponent: FC<{
|
|||||||
key={cover ? 'cover' : 'chart'}
|
key={cover ? 'cover' : 'chart'}
|
||||||
options={options}
|
options={options}
|
||||||
data={data}
|
data={data}
|
||||||
plugins={[customHighlightPlugin]}
|
plugins={[customHighlightPlugin({ width: 26 })]}
|
||||||
height={100}
|
height={100}
|
||||||
width={100 * aspectRatio}
|
width={100 * aspectRatio}
|
||||||
/>
|
/>
|
||||||
|
@ -24,6 +24,7 @@ import { createTooltip } from 'component/insights/components/LineChart/createToo
|
|||||||
import { CreationArchiveRatioTooltip } from './CreationArchiveRatioTooltip.tsx';
|
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';
|
||||||
|
|
||||||
ChartJS.register(
|
ChartJS.register(
|
||||||
CategoryScale,
|
CategoryScale,
|
||||||
@ -108,6 +109,8 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
|
|||||||
data: weeks,
|
data: weeks,
|
||||||
backgroundColor: theme.palette.charts.A2,
|
backgroundColor: theme.palette.charts.A2,
|
||||||
borderColor: theme.palette.charts.A2,
|
borderColor: theme.palette.charts.A2,
|
||||||
|
hoverBackgroundColor: theme.palette.charts.A2,
|
||||||
|
hoverBorderColor: theme.palette.charts.A2,
|
||||||
parsing: { yAxisKey: 'archivedFlags', xAxisKey: 'date' },
|
parsing: { yAxisKey: 'archivedFlags', xAxisKey: 'date' },
|
||||||
order: 1,
|
order: 1,
|
||||||
},
|
},
|
||||||
@ -116,6 +119,8 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
|
|||||||
data: weeks,
|
data: weeks,
|
||||||
backgroundColor: theme.palette.charts.A1,
|
backgroundColor: theme.palette.charts.A1,
|
||||||
borderColor: theme.palette.charts.A1,
|
borderColor: theme.palette.charts.A1,
|
||||||
|
hoverBackgroundColor: theme.palette.charts.A1,
|
||||||
|
hoverBorderColor: theme.palette.charts.A1,
|
||||||
parsing: {
|
parsing: {
|
||||||
yAxisKey: 'totalCreatedFlags',
|
yAxisKey: 'totalCreatedFlags',
|
||||||
xAxisKey: 'date',
|
xAxisKey: 'date',
|
||||||
@ -203,6 +208,11 @@ export const CreationArchiveChart: FC<ICreationArchiveChartProps> = ({
|
|||||||
options={options}
|
options={options}
|
||||||
height={100}
|
height={100}
|
||||||
width={250}
|
width={250}
|
||||||
|
plugins={[
|
||||||
|
customHighlightPlugin({
|
||||||
|
maxHighlightOpacity: 0.24,
|
||||||
|
}),
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
<CreationArchiveRatioTooltip tooltip={tooltip} />
|
<CreationArchiveRatioTooltip tooltip={tooltip} />
|
||||||
</>
|
</>
|
||||||
|
Loading…
Reference in New Issue
Block a user