Skip to content

Commit

Permalink
feat(Yagr plugin): add legendColorKey property to series options
Browse files Browse the repository at this point in the history
  • Loading branch information
korvin89 committed Mar 14, 2024
1 parent b3c90a4 commit 21eb9c2
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 63 deletions.
7 changes: 5 additions & 2 deletions src/plugins/yagr/__stories__/mocks/line10.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {AreaSeriesOptions, RawSerieData, YagrWidgetData} from '../../types';
import type {AreaSeriesOptions, YagrSeriesData, YagrWidgetData} from '../../types';

export const line10: YagrWidgetData = {
data: {
Expand Down Expand Up @@ -118,13 +118,14 @@ function colorHexToRGBA(htmlColor: string, opacity: number) {
return `rgba(${[red, green, blue, opacity].join(',')})`;
}

const graphs: RawSerieData<AreaSeriesOptions>[] = [
const graphs: YagrSeriesData<AreaSeriesOptions>[] = [
{
id: '0',
name: 'Serie 1',
type: 'area',
color: colorHexToRGBA(colors[0], 0.1),
lineColor: colors[0],
legendColorKey: 'lineColor',
data: [45, 52, 89, 72, 39, 49, 82, 59, 36, 5],
},
{
Expand All @@ -133,6 +134,7 @@ const graphs: RawSerieData<AreaSeriesOptions>[] = [
type: 'area',
color: colorHexToRGBA(colors[1], 0.1),
lineColor: colors[1],
legendColorKey: 'lineColor',
data: [37, 6, 51, 10, 65, 35, 72, 0, 94, 54],
},
{
Expand All @@ -141,6 +143,7 @@ const graphs: RawSerieData<AreaSeriesOptions>[] = [
type: 'area',
color: colorHexToRGBA(colors[2], 0.1),
lineColor: colors[2],
legendColorKey: 'lineColor',
data: [26, 54, 15, 40, 43, 18, 65, 46, 51, 33],
},
];
Expand Down
143 changes: 85 additions & 58 deletions src/plugins/yagr/renderer/tooltip/renderTooltip.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {dateTime} from '@gravity-ui/date-utils';

import type {TooltipRenderOptions, TooltipRow, ValueFormatter} from '../../types';
import type {TooltipRenderOptions, TooltipRow, ValueFormatter, YagrWidgetData} from '../../types';

import {formatTooltip} from './tooltip';
import type {TooltipData, TooltipLine} from './types';
Expand All @@ -13,71 +13,98 @@ const calcOption = <T>(d: T | {[key in string]: T} | undefined) => {
: d;
};

const getSeriesColorProperty = (args: {
data: TooltipRenderOptions;
userData: YagrWidgetData['data'];
row: TooltipRow;
rowIndex: number;
}) => {
const {data, userData, row, rowIndex} = args;
const userSeries = userData.graphs[rowIndex];
const lineColor = data.yagr.getSeriesById(row.id)?.lineColor;
let seriesColor = row.color;

switch (userSeries?.legendColorKey) {
case 'lineColor': {
if (lineColor) {
seriesColor = lineColor;
}
break;
}
case 'color':
default: {
seriesColor = row.color;
}
}

return seriesColor;
};

/*
* Default tooltip renderer.
* Adapter between native Yagr tooltip config and ChartKit
* tooltip renderer.
*/
export const getRenderTooltip = (timeZone?: string) => (data: TooltipRenderOptions) => {
const cfg = data.yagr.config;
const timeMultiplier = cfg.chart.timeMultiplier || 1;
const opts = data.options;
const {x, state} = data;
export const getRenderTooltip =
(userData: YagrWidgetData['data']) => (data: TooltipRenderOptions) => {
const {timeZone} = userData;
const cfg = data.yagr.config;
const timeMultiplier = cfg.chart.timeMultiplier || 1;
const opts = data.options;
const {x, state} = data;

let sumTotal = 0;
const rows = Object.values(data.scales).reduce((acc, scale) => {
sumTotal += scale.sum || 0;
return acc.concat(scale.rows);
}, [] as TooltipRow[]);
let sumTotal = 0;
const rows = Object.values(data.scales).reduce((acc, scale) => {
sumTotal += scale.sum || 0;
return acc.concat(scale.rows);
}, [] as TooltipRow[]);
const lines = rows.length;
const sum = calcOption(opts.sum);

const lines = rows.length;
const sum = calcOption(opts.sum);
const maxLines = calcOption<number>(opts.maxLines);
const valueFormatter = calcOption<ValueFormatter>(opts.value);
// eslint-disable-next-line no-nested-ternary
const hiddenRowsNumber = state.pinned
? undefined
: lines > maxLines
? Math.abs(maxLines - lines)
: undefined;

const maxLines = calcOption<number>(opts.maxLines);
const valueFormatter = calcOption<ValueFormatter>(opts.value);
// eslint-disable-next-line no-nested-ternary
const hiddenRowsNumber = state.pinned
? undefined
: lines > maxLines
? Math.abs(maxLines - lines)
: undefined;
const hiddenRowsSum = hiddenRowsNumber
? valueFormatter(
rows
.slice(-hiddenRowsNumber)
.reduce((acc, {originalValue}) => acc + (originalValue || 0), 0),
)
: undefined;
const tooltipFormatOptions: TooltipData = {
activeRowAlwaysFirstInTooltip: rows.length > 1,
tooltipHeader: dateTime({input: x / timeMultiplier, timeZone}).format(
'DD MMMM YYYY HH:mm:ss',
),
shared: true,
lines: rows.map(
(row, i) =>
({
...row,
seriesName: row.name || 'Serie ' + (i + 1),
seriesColor: getSeriesColorProperty({data, userData, row, rowIndex: i}),
selectedSeries: row.active,
seriesIdx: row.seriesIdx,
percentValue:
typeof row.transformed === 'number' ? row.transformed.toFixed(1) : '',
}) as TooltipLine,
),
withPercent: calcOption<boolean>(opts.percent),
hiddenRowsNumber: hiddenRowsNumber as number,
hiddenRowsSum,
};

const hiddenRowsSum = hiddenRowsNumber
? valueFormatter(
rows
.slice(-hiddenRowsNumber)
.reduce((acc, {originalValue}) => acc + (originalValue || 0), 0),
)
: undefined;
if (sum) {
tooltipFormatOptions.sum = valueFormatter(sumTotal);
}

const tooltipFormatOptions: TooltipData = {
activeRowAlwaysFirstInTooltip: rows.length > 1,
tooltipHeader: dateTime({input: x / timeMultiplier, timeZone}).format(
'DD MMMM YYYY HH:mm:ss',
),
shared: true,
lines: rows.map(
(row, i) =>
({
...row,
seriesName: row.name || 'Serie ' + (i + 1),
seriesColor: row.color,
selectedSeries: row.active,
seriesIdx: row.seriesIdx,
percentValue:
typeof row.transformed === 'number' ? row.transformed.toFixed(1) : '',
}) as TooltipLine,
),
withPercent: calcOption<boolean>(opts.percent),
hiddenRowsNumber: hiddenRowsNumber as number,
hiddenRowsSum,
return formatTooltip(tooltipFormatOptions, {
lastVisibleRowIndex: state.pinned ? rows.length - 1 : maxLines - 1,
});
};

if (sum) {
tooltipFormatOptions.sum = valueFormatter(sumTotal);
}

return formatTooltip(tooltipFormatOptions, {
lastVisibleRowIndex: state.pinned ? rows.length - 1 : maxLines - 1,
});
};
2 changes: 1 addition & 1 deletion src/plugins/yagr/renderer/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export const shapeYagrConfig = (args: ShapeYagrConfigArgs): MinimalValidConfig =

if (config.tooltip?.show) {
config.tooltip = config.tooltip || {};
config.tooltip.render = config.tooltip?.render || getRenderTooltip(timeZone);
config.tooltip.render = config.tooltip?.render || getRenderTooltip(data);

if (!config.tooltip.className) {
// "className" property prevent default yagr styles adding
Expand Down
15 changes: 13 additions & 2 deletions src/plugins/yagr/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {MinimalValidConfig, RawSerieData, YagrConfig} from '@gravity-ui/yagr';
import type {MinimalValidConfig, RawSerieData, SeriesOptions, YagrConfig} from '@gravity-ui/yagr';
import type Yagr from '@gravity-ui/yagr';

import {ChartKitProps} from 'src/types';
Expand All @@ -15,9 +15,20 @@ export type YagrWidgetProps = ChartKitProps<'yagr'> & {
id: string;
};

export type YagrSeriesData<T = Omit<SeriesOptions, 'type'>> = RawSerieData<T> & {
/**
* Determines what data value should be used to get a color for tooltip series. Does not work in case of using custom tooltip rendered via `tooltip` property.
* - `lineColor` indicates that lineColor property should be used
* - `color` indicates that color property should be used
*
* @default 'color'
*/
legendColorKey?: 'color' | 'lineColor';
};

export type YagrWidgetData = {
data: {
graphs: RawSerieData[];
graphs: YagrSeriesData[];
timeline: number[];
/**
* Allow to setup timezone for X axis and tooltip's header.
Expand Down

0 comments on commit 21eb9c2

Please sign in to comment.