ui: use unique id for window values
This commit is contained in:
parent
db88d039ff
commit
1f3bb2b33c
4 changed files with 70 additions and 56 deletions
|
|
@ -5,7 +5,7 @@ import {
|
|||
customTooltipFormatter
|
||||
} from './utils';
|
||||
import { buildBarDatasetsAndSeries } from './barUtils';
|
||||
import { defaultOptions, echarts } from './init';
|
||||
import { defaultOptions, echarts, initWindowStorages } from "./init";
|
||||
import { BarChart } from 'echarts/charts';
|
||||
|
||||
echarts.use([BarChart]);
|
||||
|
|
@ -16,6 +16,7 @@ interface BarChartProps extends DataProps {
|
|||
}
|
||||
|
||||
function ORBarChart(props: BarChartProps) {
|
||||
const chartUuid = React.useRef<string>(Math.random().toString(36).substring(7));
|
||||
const chartRef = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
@ -24,23 +25,19 @@ function ORBarChart(props: BarChartProps) {
|
|||
const categories = buildCategories(props.data);
|
||||
const { datasets, series } = buildBarDatasetsAndSeries(props, props.horizontal ?? false);
|
||||
|
||||
(window as any).__seriesValueMap = {};
|
||||
(window as any).__seriesColorMap = {};
|
||||
(window as any).__timestampMap = props.data.chart.map((item) => item.timestamp);
|
||||
(window as any).__categoryMap = categories;
|
||||
|
||||
initWindowStorages(chartUuid.current, categories, props.data.chart);
|
||||
series.forEach((s: any) => {
|
||||
(window as any).__seriesColorMap[s.name] = s.itemStyle?.color ?? '#999';
|
||||
(window as any).__seriesColorMap[chartUuid.current][s.name] = s.itemStyle?.color ?? '#999';
|
||||
const ds = datasets.find((d) => d.id === s.datasetId);
|
||||
if (!ds) return;
|
||||
const yDim = props.horizontal ? s.encode.x : s.encode.y;
|
||||
const yDimIndex = ds.dimensions.indexOf(yDim);
|
||||
if (yDimIndex < 0) return;
|
||||
|
||||
(window as any).__seriesValueMap[s.name] = {};
|
||||
(window as any).__seriesValueMap[chartUuid.current][s.name] = {};
|
||||
ds.source.forEach((row: any[]) => {
|
||||
const rowIdx = row[0]; // 'idx'
|
||||
(window as any).__seriesValueMap[s.name][rowIdx] = row[yDimIndex];
|
||||
(window as any).__seriesValueMap[chartUuid.current][s.name][rowIdx] = row[yDimIndex];
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -65,7 +62,7 @@ function ORBarChart(props: BarChartProps) {
|
|||
},
|
||||
tooltip: {
|
||||
...defaultOptions.tooltip,
|
||||
formatter: customTooltipFormatter,
|
||||
formatter: customTooltipFormatter(chartUuid.current),
|
||||
},
|
||||
xAxis,
|
||||
yAxis,
|
||||
|
|
@ -75,10 +72,10 @@ function ORBarChart(props: BarChartProps) {
|
|||
|
||||
return () => {
|
||||
chart.dispose();
|
||||
delete (window as any).__seriesValueMap;
|
||||
delete (window as any).__seriesColorMap;
|
||||
delete (window as any).__categoryMap;
|
||||
delete (window as any).__timestampMap;
|
||||
delete (window as any).__seriesValueMap[chartUuid.current];
|
||||
delete (window as any).__seriesColorMap[chartUuid.current];
|
||||
delete (window as any).__categoryMap[chartUuid.current];
|
||||
delete (window as any).__timestampMap[chartUuid.current];
|
||||
};
|
||||
}, [props.data, props.compData, props.horizontal]);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { echarts, defaultOptions } from './init';
|
||||
import { echarts, defaultOptions, initWindowStorages } from './init';
|
||||
import { customTooltipFormatter, buildCategories, buildDatasetsAndSeries } from './utils'
|
||||
import type { DataProps } from './utils'
|
||||
import { LineChart } from 'echarts/charts';
|
||||
|
|
@ -15,6 +15,7 @@ interface Props extends DataProps {
|
|||
}
|
||||
|
||||
function ORLineChart(props: Props) {
|
||||
const chartUuid = React.useRef<string>(Math.random().toString(36).substring(7));
|
||||
const chartRef = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
@ -24,22 +25,16 @@ function ORLineChart(props: Props) {
|
|||
const categories = buildCategories(props.data);
|
||||
const { datasets, series } = buildDatasetsAndSeries(props);
|
||||
|
||||
// Create a quick map of name => dataIndex => value, for partner lookups
|
||||
// and a map for colors. We'll store them on window in this example for brevity.
|
||||
(window as any).__seriesValueMap = {};
|
||||
(window as any).__seriesColorMap = {};
|
||||
(window as any).__timestampMap = props.data.chart.map(item => item.timestamp);
|
||||
(window as any).__categoryMap = categories;
|
||||
initWindowStorages(chartUuid.current, categories, props.data.chart);
|
||||
|
||||
series.forEach((s: any) => {
|
||||
if (props.isArea) {
|
||||
s.areaStyle = {};
|
||||
s.stack = 'Total'
|
||||
// s.emphasis = { focus: 'series' };
|
||||
s.stack = 'Total';
|
||||
} else {
|
||||
s.areaStyle = null;
|
||||
}
|
||||
(window as any).__seriesColorMap[s.name] = s.itemStyle?.color ?? '#999';
|
||||
(window as any).__seriesColorMap[chartUuid.current][s.name] = s.itemStyle?.color ?? '#999';
|
||||
const datasetId = s.datasetId || 'current';
|
||||
const ds = datasets.find((d) => d.id === datasetId);
|
||||
if (!ds) return;
|
||||
|
|
@ -47,10 +42,10 @@ function ORLineChart(props: Props) {
|
|||
const yDimIndex = ds.dimensions.indexOf(yDim);
|
||||
if (yDimIndex < 0) return;
|
||||
|
||||
(window as any).__seriesValueMap[s.name] = {};
|
||||
(window as any).__seriesValueMap[chartUuid.current][s.name] = {};
|
||||
ds.source.forEach((row: any[]) => {
|
||||
const rowIdx = row[0];
|
||||
(window as any).__seriesValueMap[s.name][rowIdx] = row[yDimIndex];
|
||||
(window as any).__seriesValueMap[chartUuid.current][s.name][rowIdx] = row[yDimIndex];
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -77,23 +72,23 @@ function ORLineChart(props: Props) {
|
|||
},
|
||||
tooltip: {
|
||||
...defaultOptions.tooltip,
|
||||
formatter: customTooltipFormatter,
|
||||
formatter: customTooltipFormatter(chartUuid.current),
|
||||
},
|
||||
dataset: datasets,
|
||||
series,
|
||||
});
|
||||
chart.on('click', (event) => {
|
||||
const index = event.dataIndex;
|
||||
const timestamp = (window as any).__timestampMap?.[index];
|
||||
const timestamp = (window as any).__timestampMap?.[chartUuid.current]?.[index];
|
||||
props.onClick?.({ activePayload: [{ payload: { timestamp }}]})
|
||||
})
|
||||
|
||||
return () => {
|
||||
chart.dispose();
|
||||
delete (window as any).__seriesValueMap;
|
||||
delete (window as any).__seriesColorMap;
|
||||
delete (window as any).__categoryMap;
|
||||
delete (window as any).__timestampMap;
|
||||
delete (window as any).__seriesValueMap[chartUuid.current];
|
||||
delete (window as any).__seriesColorMap[chartUuid.current];
|
||||
delete (window as any).__categoryMap[chartUuid.current];
|
||||
delete (window as any).__timestampMap[chartUuid.current];
|
||||
};
|
||||
}, [props.data, props.compData]);
|
||||
|
||||
|
|
|
|||
|
|
@ -66,4 +66,24 @@ const defaultOptions = {
|
|||
},
|
||||
}
|
||||
|
||||
export function initWindowStorages(chartUuid: string, categories: string[] = [], chartArr: any[] = []) {
|
||||
(window as any).__seriesValueMap = (window as any).__seriesValueMap ?? {};
|
||||
(window as any).__seriesColorMap = (window as any).__seriesColorMap ?? {};
|
||||
(window as any).__timestampMap = (window as any).__timestampMap ?? {};
|
||||
(window as any).__categoryMap = (window as any).__categoryMap ?? {};
|
||||
|
||||
if (!(window as any).__seriesColorMap[chartUuid]) {
|
||||
(window as any).__seriesColorMap[chartUuid] = {};
|
||||
}
|
||||
if (!(window as any).__seriesValueMap[chartUuid]) {
|
||||
(window as any).__seriesValueMap[chartUuid] = {};
|
||||
}
|
||||
if (!(window as any).__categoryMap[chartUuid]) {
|
||||
(window as any).__categoryMap[chartUuid] = categories;
|
||||
}
|
||||
if (!(window as any).__timestampMap[chartUuid]) {
|
||||
(window as any).__timestampMap[chartUuid] = chartArr.map((item) => item.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
export { echarts, defaultOptions };
|
||||
|
|
@ -42,28 +42,29 @@ export function assignColorsByBaseName(series: any[]) {
|
|||
/**
|
||||
* Show the hovered “current” or “previous” line + the matching partner (if it exists).
|
||||
*/
|
||||
export function customTooltipFormatter(params: any): string {
|
||||
// With trigger='item', params is a single object describing the hovered point
|
||||
// { seriesName, dataIndex, data, marker, color, encode, ... }
|
||||
if (!params) return '';
|
||||
const { seriesName, dataIndex } = params;
|
||||
export function customTooltipFormatter(uuid: string) {
|
||||
return (params: any): string => {
|
||||
// With trigger='item', params is a single object describing the hovered point
|
||||
// { seriesName, dataIndex, data, marker, color, encode, ... }
|
||||
if (!params) return '';
|
||||
const { seriesName, dataIndex } = params;
|
||||
|
||||
// 'value' of the hovered point
|
||||
const yKey = params.encode.y[0]; // "Series 1"
|
||||
const value = params.data?.[yKey];
|
||||
// 'value' of the hovered point
|
||||
const yKey = params.encode.y[0]; // "Series 1"
|
||||
const value = params.data?.[yKey];
|
||||
|
||||
const isPrevious = /^Previous\s+/.test(seriesName);
|
||||
const baseName = seriesName.replace(/^Previous\s+/, '');
|
||||
const partnerName = isPrevious ? baseName : `Previous ${baseName}`;
|
||||
const isPrevious = /^Previous\s+/.test(seriesName);
|
||||
const baseName = seriesName.replace(/^Previous\s+/, '');
|
||||
const partnerName = isPrevious ? baseName : `Previous ${baseName}`;
|
||||
|
||||
// Get partner’s value from some global map
|
||||
const partnerVal = (window as any).__seriesValueMap?.[partnerName]?.[dataIndex];
|
||||
const timestamp = (window as any).__timestampMap?.[dataIndex];
|
||||
const categoryLabel = (window as any).__categoryMap
|
||||
? (window as any).__categoryMap[dataIndex]
|
||||
: dataIndex;
|
||||
// Get partner’s value from some global map
|
||||
const partnerVal = (window as any).__seriesValueMap?.[uuid]?.[partnerName]?.[dataIndex];
|
||||
const timestamp = (window as any).__timestampMap?.[uuid]?.[dataIndex];
|
||||
const categoryLabel = (window as any).__categoryMap[uuid]
|
||||
? (window as any).__categoryMap[uuid][dataIndex]
|
||||
: dataIndex;
|
||||
|
||||
let tooltipContent = `
|
||||
let tooltipContent = `
|
||||
<div class="flex flex-col gap-1 bg-white shadow border rounded p-2 z-50">
|
||||
<div class="flex gap-2 items-center">
|
||||
<div style="
|
||||
|
|
@ -86,9 +87,9 @@ export function customTooltipFormatter(params: any): string {
|
|||
</div>
|
||||
`;
|
||||
|
||||
if (partnerVal !== undefined) {
|
||||
const partnerColor = (window as any).__seriesColorMap?.[partnerName] || '#999';
|
||||
tooltipContent += `
|
||||
if (partnerVal !== undefined) {
|
||||
const partnerColor = (window as any).__seriesColorMap?.[uuid]?.[partnerName] || '#999';
|
||||
tooltipContent += `
|
||||
<div class="flex gap-2 items-center mt-2">
|
||||
<div style="
|
||||
border-radius: 99px;
|
||||
|
|
@ -108,10 +109,11 @@ export function customTooltipFormatter(params: any): string {
|
|||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
tooltipContent += '</div>';
|
||||
return tooltipContent;
|
||||
tooltipContent += '</div>';
|
||||
return tooltipContent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue