163 lines
4.6 KiB
JavaScript

import { Utils } from 'arm-common';
import p from 'prop-types';
import React, { useLayoutEffect, useMemo, useState } from 'react';
import { ChartContainer, getRoot, useAm5, useAm5Colors } from '../Am5.jsx';
const classNamePrefix = 'armu_ai_chatbot-time-chart';
export default function TimeChart(props) {
const { id, xAxis, yAxis, series, data } = props;
const [chartId] = useState(id || Utils.uuid(classNamePrefix));
const am5 = useAm5();
const am5Colors = useAm5Colors();
const allValues = useMemo(() => {
if (data?.length) {
if (series?.length) {
const values = [];
for (let item of data) {
for (let serie of series) {
if (!isNaN(item[serie.yAxis])) {
values.push(item[serie.yAxis]);
}
}
}
return values;
} else {
return data.map(d => d[yAxis]);
}
}
return [];
}, [data, series, yAxis]);
const minValue = Math.min(...allValues);
const maxValue = Math.max(...allValues);
const largerValue = Math.max(maxValue, Math.abs(minValue));
useLayoutEffect(() => {
if (am5 && data) {
const root = getRoot(chartId);
const chart = root.container.children.push(
am5xy.XYChart.new(root, {
panX: true,
panY: true,
wheelX: "panX",
wheelY: "zoomX",
pinchZoomX: true,
layout: root.verticalLayout
})
);
const cursor = chart.set("cursor", am5xy.XYCursor.new(root, {
behavior: "none"
}));
cursor.lineY.set("visible", false);
const xAxisAm5 = chart.xAxes.push(
am5xy.DateAxis.new(root, {
maxDeviation: 0.2,
baseInterval: {
timeUnit: "day",
count: 1
},
renderer: am5xy.AxisRendererX.new(root, {}),
tooltip: am5.Tooltip.new(root, {})
})
);
const yAxisAm5 = chart.yAxes.push(
am5xy.ValueAxis.new(root, {
renderer: am5xy.AxisRendererY.new(root, {
pan: "zoom"
}),
min: minValue - (largerValue * 0.1),
max: maxValue + (largerValue * 0.1),
strictMinMax: true
})
);
chart.set("colors", am5.ColorSet.new(root, {
colors: am5Colors
}));
if (series?.length) {
const legend = chart.children.push(am5.Legend.new(root, {
centerX: am5.p50,
x: am5.p50,
}));
series.forEach(addSeries.bind({ root, chart, xAxisAm5, yAxisAm5, xAxis, data }));
legend.data.setAll(chart.series.values);
} else if (yAxis) {
addSeries.call({ root, chart, xAxisAm5, yAxisAm5, xAxis, data }, { yAxis });
}
chart.set("scrollbarX", am5.Scrollbar.new(root, {
orientation: "horizontal"
}));
}
}, [am5, allValues]);
return (
<ChartContainer id={chartId} className={classNamePrefix} />
);
}
TimeChart.defaultProps = {
id: '',
xAxis: '',
yAxis: '',
series: [],
data: null
}
TimeChart.propTypes = {
id: p.string,
xAxis: p.string.isRequired,
yAxis: p.string,
series: p.arrayOf(p.shape({
name: p.string,
yAxis: p.string
})),
data: p.arrayOf(p.object).isRequired
}
function addSeries(seriesConfig) {
const { root, chart, xAxisAm5, yAxisAm5, xAxis, data } = this;
const { name, yAxis } = seriesConfig;
const tooltip = am5.Tooltip.new(root, {
labelText: "{valueY}",
});
const series = chart.series.push(
am5xy.LineSeries.new(root, {
name,
minBulletDistance: 10,
xAxis: xAxisAm5,
yAxis: yAxisAm5,
valueXField: xAxis,
valueYField: yAxis,
tooltip
})
);
series.bullets.push(function () {
return am5.Bullet.new(root, {
sprite: am5.Circle.new(root, {
radius: 6,
fill: series.get("fill"),
stroke: root.interfaceColors.get("background"),
strokeWidth: 2,
})
});
});
series.data.setAll(data);
}