1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-23 00:22:19 +01:00
unleash.unleash/frontend/src/component/personalDashboard/createChartOptions.ts

162 lines
5.1 KiB
TypeScript
Raw Normal View History

import type { Theme } from '@mui/material/styles/createTheme';
import type { ChartOptions } from 'chart.js';
import { formatTickValue } from '../common/Chart/formatTickValue';
import type { ILocationSettings } from '../../hooks/useLocationSettings';
import type { IPoint } from '../feature/FeatureView/FeatureMetrics/FeatureMetricsChart/createChartData';
import {
formatDateHM,
formatDateYMD,
formatDateYMDHM,
} from '../../utils/formatDate';
const formatVariantEntry = (
variant: [string, number],
totalExposure: number,
) => {
if (totalExposure === 0) return '';
const [key, value] = variant;
const percentage = Math.floor((Number(value) / totalExposure) * 100);
return `${value} (${percentage}%) - ${key}`;
};
export const createPlaceholderBarChartOptions = (
theme: Theme,
): ChartOptions<'bar'> => ({
plugins: {
legend: {
position: 'bottom',
labels: {
color: theme.palette.text.primary,
pointStyle: 'circle',
usePointStyle: true,
boxHeight: 6,
padding: 15,
boxPadding: 5,
},
},
tooltip: {
enabled: false,
},
},
responsive: true,
scales: {
x: {
stacked: true,
ticks: {
color: theme.palette.text.secondary,
},
grid: {
display: false,
},
},
y: {
stacked: true,
ticks: {
color: theme.palette.text.secondary,
maxTicksLimit: 5,
callback: formatTickValue,
},
grid: {
drawBorder: false,
},
},
},
elements: {
bar: {
borderRadius: 5,
},
},
interaction: {
mode: 'index',
intersect: false,
},
});
export const createBarChartOptions = (
theme: Theme,
hoursBack: number,
locationSettings: ILocationSettings,
): ChartOptions<'bar'> => {
const { plugins, responsive, elements, interaction, scales } =
createPlaceholderBarChartOptions(theme);
return {
plugins: {
legend: plugins?.legend,
tooltip: {
backgroundColor: theme.palette.background.paper,
titleColor: theme.palette.text.primary,
bodyColor: theme.palette.text.primary,
bodySpacing: 6,
padding: {
top: 20,
bottom: 20,
left: 30,
right: 30,
},
borderColor: 'rgba(0, 0, 0, 0.05)',
borderWidth: 3,
usePointStyle: true,
caretSize: 0,
boxPadding: 10,
callbacks: {
label: (item) => {
return `${item.formattedValue} - ${item.dataset.label}`;
},
afterLabel: (item) => {
const data = item.dataset.data[
item.dataIndex
] as unknown as IPoint;
if (
item.dataset.label !== 'Exposed' ||
data.variants === undefined
) {
return '';
}
const { disabled, ...actualVariants } = data.variants;
return Object.entries(actualVariants)
.map((entry) => formatVariantEntry(entry, data.y))
.join('\n');
},
title: (items) => {
return `Time: ${
hoursBack > 48
? formatDateYMDHM(
items[0].label,
locationSettings.locale,
'UTC',
)
: formatDateHM(
items[0].label,
locationSettings.locale,
)
}`;
},
},
},
},
responsive,
scales: {
x: {
...(scales ? scales.x : {}),
ticks: {
color: theme.palette.text.secondary,
callback(tickValue) {
const label = this.getLabelForValue(Number(tickValue));
return hoursBack > 48
? formatDateYMD(
label,
locationSettings.locale,
'UTC',
)
: formatDateHM(label, locationSettings.locale);
},
},
},
y: scales ? scales.y : {},
},
elements,
interaction,
};
};