diff --git a/km-console/packages/layout-clusters-fe/src/components/DashboardDragChart/ChartDetail.tsx b/km-console/packages/layout-clusters-fe/src/components/DashboardDragChart/ChartDetail.tsx
index d89c37ff..84527a9c 100644
--- a/km-console/packages/layout-clusters-fe/src/components/DashboardDragChart/ChartDetail.tsx
+++ b/km-console/packages/layout-clusters-fe/src/components/DashboardDragChart/ChartDetail.tsx
@@ -1,18 +1,20 @@
-import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
-import { AppContainer, Button, Drawer, IconFont, message, Spin, Table, SingleChart, Utils, Tooltip } from 'knowdesign';
+import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
+import { AppContainer, Drawer, Spin, Table, SingleChart, Utils, Tooltip } from 'knowdesign';
import moment from 'moment';
import api, { MetricType } from '@src/api';
import { useParams } from 'react-router-dom';
import { debounce } from 'lodash';
import { MetricDefaultChartDataType, MetricChartDataType, formatChartData, getDetailChartConfig } from './config';
import { UNIT_MAP } from '@src/constants/chartConfig';
-import { CloseOutlined } from '@ant-design/icons';
+import RenderEmpty from '../RenderEmpty';
interface ChartDetailProps {
metricType: MetricType;
metricName: string;
queryLines: string[];
- onClose: () => void;
+ setSliderRange: (range: string) => void;
+ // eslint-disable-next-line @typescript-eslint/ban-types
+ setDisposeChartInstance: Function;
}
interface MetricTableInfo {
@@ -24,6 +26,18 @@ interface MetricTableInfo {
color: string;
}
+interface ChartInfo {
+ chartInstance?: echarts.ECharts;
+ isLoadingAdditionData?: boolean;
+ isLoadedFullData?: boolean;
+ fullTimeRange?: readonly [number, number];
+ curTimeRange?: readonly [number, number];
+ sliderPos?: readonly [number, number];
+ transformUnit?: [string, number];
+ fullMetricData?: MetricChartDataType;
+ oldDataZoomOption?: any;
+}
+
interface DataZoomEventProps {
type: 'datazoom';
// 缩放的开始位置的百分比,0 - 100
@@ -34,8 +48,6 @@ interface DataZoomEventProps {
// 缩放区默认选中范围比例(0.01~1)
const DATA_ZOOM_DEFAULT_SCALE = 0.25;
-// 选中范围最少展示的时间长度(默认 10 分钟),单位: ms
-const LEAST_SELECTED_TIME_RANGE = 1 * 60 * 1000;
// 单次向服务器请求数据的范围(默认 6 小时,超过后采集频率间隔会变长),单位: ms
const DEFAULT_REQUEST_TIME_RANGE = 6 * 60 * 60 * 1000;
// 采样间隔,影响前端补点逻辑,单位: ms
@@ -47,70 +59,15 @@ const DEFAULT_ENTER_TIME_RANGE = 2 * 60 * 60 * 1000;
// 预缓存数据阈值,图表展示数据的开始时间处于前端缓存数据的时间范围的前 40% 时,向服务器请求数据
const PRECACHE_THRESHOLD = 0.4;
-// 表格列
-const colunms = [
- {
- title: 'Host',
- dataIndex: 'name',
- width: 200,
- render(name: string, record: any) {
- return (
-
- );
- },
- },
- {
- title: 'Avg',
- dataIndex: 'avg',
- width: 120,
- render(num: number) {
- return num.toFixed(2);
- },
- },
- {
- title: 'Max',
- dataIndex: 'max',
- width: 120,
- render(num: number, record: any) {
- return (
-
- {num.toFixed(2)}
-
- );
- },
- },
- {
- title: 'Min',
- dataIndex: 'min',
- width: 120,
- render(num: number, record: any) {
- return (
-
- {num.toFixed(2)}
-
- );
- },
- },
- {
- title: 'Latest',
- dataIndex: 'latest',
- width: 120,
- render(latest: number[]) {
- return `${latest[1].toFixed(2)}`;
- },
- },
-];
-
const ChartDetail = (props: ChartDetailProps) => {
const [global] = AppContainer.useGlobalValue();
const { clusterId } = useParams<{
clusterId: string;
}>();
- const { metricType, metricName, queryLines, onClose } = props;
+ const { metricType, metricName, queryLines, setSliderRange, setDisposeChartInstance } = props;
+ // 初始化拖拽防抖函数
+ const debouncedZoomDrag = useRef(null);
// 存储图表相关的不需要触发渲染的数据,用于计算图表展示状态并进行操作
const chartInfo = useRef(
(() => {
@@ -119,16 +76,16 @@ const ChartDetail = (props: ChartDetailProps) => {
const curTimeRange = [curTime - DEFAULT_ENTER_TIME_RANGE, curTime] as const;
return {
- chartInstance: undefined as echarts.ECharts,
+ chartInstance: undefined,
+ isLoadingAdditionData: false,
isLoadedFullData: false,
fullTimeRange: curTimeRange,
fullMetricData: {} as MetricChartDataType,
curTimeRange,
- oldDataZoomOption: {} as any,
- sliderPos: [0, 0] as readonly [number, number],
- sliderRange: '',
- transformUnit: undefined as [string, number],
- };
+ oldDataZoomOption: {},
+ sliderPos: [0, 0],
+ transformUnit: undefined,
+ } as ChartInfo;
})()
);
@@ -137,8 +94,76 @@ const ChartDetail = (props: ChartDetailProps) => {
const [curMetricData, setCurMetricData] = useState();
// 图表数据的各项计算指标
const [tableInfo, setTableInfo] = useState([]);
- // 选中展示的图表
- const [selectedLines, setSelectedLines] = useState([]);
+ const [linesStatus, setLinesStatus] = useState<{
+ [lineName: string]: boolean;
+ }>({});
+
+ // 表格列
+ const colunms = useMemo(
+ () => [
+ {
+ title: metricType === MetricType.Broker ? 'Host' : 'Topic',
+ dataIndex: 'name',
+ width: 200,
+ render(name: string, record: any) {
+ return (
+
+ );
+ },
+ },
+ {
+ title: 'Avg',
+ dataIndex: 'avg',
+ width: 120,
+ render(num: number) {
+ return num.toFixed(2);
+ },
+ },
+ {
+ title: 'Max',
+ dataIndex: 'max',
+ width: 120,
+ render(num: number, record: any) {
+ return (
+
+ {num.toFixed(2)}
+
+ );
+ },
+ },
+ {
+ title: 'Min',
+ dataIndex: 'min',
+ width: 120,
+ render(num: number, record: any) {
+ return (
+
+ {num.toFixed(2)}
+
+ );
+ },
+ },
+ {
+ title: 'Latest',
+ dataIndex: 'latest',
+ width: 120,
+ render(latest: number[]) {
+ return `${latest[1].toFixed(2)}`;
+ },
+ },
+ ],
+ [metricType]
+ );
+
+ const updateChartInfo = (changedInfo: ChartInfo) => {
+ chartInfo.current = {
+ ...chartInfo.current,
+ ...changedInfo,
+ };
+ };
// 请求图表数据
const getMetricChartData = ([startTime, endTime]: readonly [number, number]) => {
@@ -175,11 +200,10 @@ const ChartDetail = (props: ChartDetailProps) => {
// 如果滑块整体拖动,则只更新拖动后滑块的位(保留小数点后三位是防止低位值的干扰)
if (oldScale.toFixed(3) === newScale.toFixed(3)) {
- chartInfo.current = {
- ...chartInfo.current,
+ updateChartInfo({
sliderPos: [newStartSliderPos, newEndSliderPos],
oldDataZoomOption: newDataZoomOption,
- };
+ });
renderTableInfo();
return false;
@@ -217,23 +241,14 @@ const ChartDetail = (props: ChartDetailProps) => {
}
} else {
// 3. 滑块拖动后缩放比例变小
- // 判断拖动后选择的时间范围并提示
- if (newEndSliderPos - newStartSliderPos < LEAST_SELECTED_TIME_RANGE) {
- // TODO: 补充逻辑
- updateChartData([oldStartTimestamp, oldEndTimestamp], [oldStartSliderPos, oldEndSliderPos]);
- message.warning(`当前选择范围小于 ${LEAST_SELECTED_TIME_RANGE / 60 / 1000} 分钟,图表可能无数据`);
- return true;
- }
-
const isOldLarger = oldScale - DATA_ZOOM_DEFAULT_SCALE > 0.01;
const isNewLarger = newScale - DATA_ZOOM_DEFAULT_SCALE > 0.01;
if (isOldLarger && isNewLarger) {
// 如果拖拽前后比例均高于默认比例,则不对图表展示范围进行操作
- chartInfo.current = {
- ...chartInfo.current,
+ updateChartInfo({
sliderPos: [newStartSliderPos, newEndSliderPos],
oldDataZoomOption: newDataZoomOption,
- };
+ });
renderTableInfo();
return true;
} else {
@@ -259,79 +274,98 @@ const ChartDetail = (props: ChartDetailProps) => {
const updateChartData = (timeRange: [number, number], sliderPos: [number, number]) => {
const {
fullTimeRange: [fullStartTimestamp, fullEndTimestamp],
- fullMetricData,
isLoadedFullData,
} = chartInfo.current;
- let leftBoundaryTimestamp = Math.floor(timeRange[0]);
+ const leftBoundaryTimestamp = Math.floor(timeRange[0]);
const isNeedCacheExtraData = leftBoundaryTimestamp < fullStartTimestamp + (fullEndTimestamp - fullStartTimestamp) * PRECACHE_THRESHOLD;
let isRendered = false;
// 如果本地存储的数据足够展示或者已经获取到所有数据,则展示数据
if (leftBoundaryTimestamp > fullStartTimestamp || isLoadedFullData) {
- chartInfo.current = {
- ...chartInfo.current,
+ updateChartInfo({
curTimeRange: [leftBoundaryTimestamp > fullStartTimestamp ? leftBoundaryTimestamp : fullStartTimestamp, timeRange[1]],
sliderPos,
- };
+ });
renderNewMetricData();
isRendered = true;
}
if (!isLoadedFullData && isNeedCacheExtraData) {
- // 向服务器请求新的数据缓存
- let reqEndTime = fullStartTimestamp;
- const requestArr: any[] = [];
- const requestTimeRanges: [number, number][] = [];
- for (let i = 0; i < DEFAULT_REQUEST_COUNT; i++) {
- setTimeout(() => {
- const nextReqEndTime = reqEndTime - DEFAULT_REQUEST_TIME_RANGE;
- requestArr.unshift(getMetricChartData([nextReqEndTime, reqEndTime]));
- requestTimeRanges.unshift([nextReqEndTime, reqEndTime]);
- reqEndTime = nextReqEndTime;
+ getAdditionChartData(!isRendered, leftBoundaryTimestamp, timeRange[1], sliderPos);
+ }
+ };
- // 当最后一次请求发送后,处理返回
- if (i === DEFAULT_REQUEST_COUNT - 1) {
- Promise.all(requestArr).then((resList) => {
- let isSettle = -1;
- // 填充增量的图表数据
- resList.forEach((res: MetricDefaultChartDataType[], i) => {
- // 图表没有返回数据的情况
- if (!res?.length) {
- if (isSettle === -1) {
- chartInfo.current = {
- ...chartInfo.current,
- // 标记数据已经全部加载完毕
- isLoadedFullData: true,
- };
- isSettle = i;
- }
- } else {
- resolveAdditionChartData(res, requestTimeRanges[i]);
- }
- });
- // 更新左侧边界为当前已获取到数据的最小边界
- const curLocalStartTimestamp = Number(fullMetricData.metricLines.map((line) => line.data[0][0]).sort()[0]);
- if (leftBoundaryTimestamp < curLocalStartTimestamp) {
- leftBoundaryTimestamp = curLocalStartTimestamp;
- }
+ // 缓存增量的图表数据
+ const getAdditionChartData = (
+ needRender: boolean,
+ leftBoundaryTimestamp: number,
+ rightBoundaryTimestamp: number,
+ sliderPos?: [number, number]
+ ) => {
+ const {
+ fullTimeRange: [fullStartTimestamp, fullEndTimestamp],
+ fullMetricData,
+ isLoadingAdditionData,
+ } = chartInfo.current;
- chartInfo.current = {
- ...chartInfo.current,
- fullTimeRange: [reqEndTime - DEFAULT_REQUEST_TIME_RANGE, fullEndTimestamp],
- sliderPos,
- };
- if (!isRendered) {
- chartInfo.current = {
- ...chartInfo.current,
- curTimeRange: [leftBoundaryTimestamp, timeRange[1]],
- };
- renderNewMetricData();
+ // 当前有缓存数据的任务时,直接退出
+ if (isLoadingAdditionData) {
+ return false;
+ }
+ updateChartInfo({
+ isLoadingAdditionData: true,
+ });
+
+ let reqEndTime = fullStartTimestamp;
+ const requestArr: any[] = [];
+ const requestTimeRanges: [number, number][] = [];
+ for (let i = 0; i < DEFAULT_REQUEST_COUNT; i++) {
+ setTimeout(() => {
+ const nextReqEndTime = reqEndTime - DEFAULT_REQUEST_TIME_RANGE;
+ requestArr.push(getMetricChartData([nextReqEndTime, reqEndTime]));
+ requestTimeRanges.push([nextReqEndTime, reqEndTime]);
+ reqEndTime = nextReqEndTime;
+
+ // 当最后一次请求发送后,处理返回
+ if (i === DEFAULT_REQUEST_COUNT - 1) {
+ Promise.all(requestArr).then((resList) => {
+ // 填充增量的图表数据
+ resList.forEach((res: MetricDefaultChartDataType[], i) => {
+ // 最后一个请求返回数据为空时,认为已获取到全部图表数据
+ if (!res?.length) {
+ // 标记数据已经全部加载完毕
+ i === resList.length - 1 &&
+ updateChartInfo({
+ isLoadedFullData: true,
+ });
+ } else {
+ // TODO: res 可能为 [],需要处理兼容
+ resolveAdditionChartData(res, requestTimeRanges[i]);
}
});
- }
- }, i * 10);
- }
+
+ // 更新左侧边界为当前已获取到数据的最小边界
+ const curLocalStartTimestamp = Number(fullMetricData.metricLines.map((line) => line?.data?.[0]?.[0]).sort()[0]);
+ if (leftBoundaryTimestamp < curLocalStartTimestamp) {
+ leftBoundaryTimestamp = curLocalStartTimestamp;
+ }
+
+ updateChartInfo({
+ fullTimeRange: [reqEndTime - DEFAULT_REQUEST_TIME_RANGE, fullEndTimestamp],
+ ...(sliderPos ? { sliderPos } : {}),
+ isLoadingAdditionData: false,
+ });
+ if (needRender) {
+ updateChartInfo({
+ curTimeRange: [leftBoundaryTimestamp, rightBoundaryTimestamp],
+ });
+ renderNewMetricData();
+ }
+ });
+ }
+ }, i * 10);
}
+ return true;
};
// 处理增量图表数据
@@ -362,7 +396,7 @@ const ChartDetail = (props: ChartDetailProps) => {
});
};
- // 根据需要展示的时间范围过滤出对应的数据展示
+ // 根据需要展示的时间范围过滤出对应的数据
const renderNewMetricData = () => {
const { fullMetricData, curTimeRange } = chartInfo.current;
const newMetricData = { ...fullMetricData };
@@ -378,12 +412,25 @@ const ChartDetail = (props: ChartDetailProps) => {
});
newMetricData.metricLines[i] = line;
});
+
// 只过滤出当前时间段有数据点的线条,确保 Table 统一展示
newMetricData.metricLines = newMetricData.metricLines.filter((line) => line.data.length);
setCurMetricData(newMetricData);
+
+ setLinesStatus((curStatus) => {
+ // 过滤维持线条选中状态
+ const newLinesStatus = { ...curStatus };
+ const newLineNames = newMetricData.metricLines.map((line) => line.name);
+ newLineNames.forEach((name) => {
+ if (newLinesStatus[name] === undefined) {
+ newLinesStatus[name] = false;
+ }
+ });
+ return newLinesStatus;
+ });
};
- // 计算当前选中范围
+ // 计算展示当前拖拽轴选中的时间范围
const calculateSliderRange = () => {
const { sliderPos } = chartInfo.current;
let minutes = Number(((sliderPos[1] - sliderPos[0]) / 60 / 1000).toFixed(2));
@@ -398,13 +445,11 @@ const ChartDetail = (props: ChartDetailProps) => {
hours = Number((hours % 24).toFixed(2));
}
- chartInfo.current = {
- ...chartInfo.current,
- sliderRange: ` 当前选中范围: ${days > 0 ? `${days} 天 ` : ''}${hours > 0 ? `${hours} 小时 ` : ''}${minutes} 分钟`,
- };
+ const sliderRange = ` 当前选中范围: ${days > 0 ? `${days} 天 ` : ''}${hours > 0 ? `${hours} 小时 ` : ''}${minutes} 分钟`;
+ setSliderRange(sliderRange);
};
- // 遍历图表,获取需要的指标数据,展示到 Table
+ // 遍历图表,计算得到指标聚合数据展示到表格
const renderTableInfo = () => {
const tableData: MetricTableInfo[] = [];
const { sliderPos, chartInstance } = chartInfo.current;
@@ -447,140 +492,131 @@ const ChartDetail = (props: ChartDetailProps) => {
calculateSliderRange();
setTableInfo(tableData);
- setSelectedLines(tableData.map((line) => line.name));
};
const tableLineChange = (keys: string[]) => {
- const updatedLines: { [name: string]: boolean } = {};
- selectedLines.forEach((name) => !keys.includes(name) && (updatedLines[name] = false));
- keys.forEach((name) => !selectedLines.includes(name) && (updatedLines[name] = true));
+ const newLinesStatus = { ...linesStatus };
- // 更新
- Object.keys(updatedLines).forEach((name) => {
- chartInfo.current.chartInstance.dispatchAction({
- type: 'legendToggleSelect',
- // 图例名称
- name: name,
- });
+ Object.entries(newLinesStatus).forEach(([name, status]) => {
+ if (keys.includes(name)) {
+ !status && (newLinesStatus[name] = true);
+ } else {
+ status && (newLinesStatus[name] = false);
+ }
});
- setSelectedLines(keys);
+ setLinesStatus(newLinesStatus);
};
+ // 图表数据更新渲染后,更新图表拖拽轴信息并重新计算列表值
useEffect(() => {
if (curMetricData) {
setTimeout(() => {
- // 新的图表数据渲染后,更新图表拖拽轴信息
chartInfo.current.oldDataZoomOption = (chartInfo.current.chartInstance.getOption() as any).dataZoom[0];
});
renderTableInfo();
}
}, [curMetricData]);
+ // 更新图例选中状态
+ useEffect(() => {
+ Object.entries(linesStatus).map(([name, status]) => {
+ const type = status ? 'legendSelect' : 'legendUnSelect';
+ chartInfo.current.chartInstance.dispatchAction({
+ type,
+ name,
+ });
+ });
+ }, [linesStatus]);
+
// 进入详情时,首次获取数据
useEffect(() => {
if (metricType && metricName) {
setLoading(true);
const { curTimeRange } = chartInfo.current;
- getMetricChartData(curTimeRange).then((res: any[] | null) => {
- // 如果图表返回数据
- if (res?.length) {
- // 格式化图表需要的数据
- const formattedMetricData = (
- formatChartData(
- res,
- global.getMetricDefine || {},
- metricType,
- curTimeRange,
- DEFAULT_POINT_INTERVAL,
- false
- ) as MetricChartDataType[]
- )[0];
- // 填充图表数据
- let initFullTimeRange = curTimeRange;
- const pointsOfFirstLine = formattedMetricData.metricLines.find((line) => line.data.length).data;
- if (pointsOfFirstLine) {
- initFullTimeRange = [pointsOfFirstLine[0][0] as number, pointsOfFirstLine[pointsOfFirstLine.length - 1][0] as number] as const;
- }
-
- // 获取单位保存起来
- let transformUnit = undefined;
- Object.entries(UNIT_MAP).forEach((unit) => {
- if (formattedMetricData.metricUnit.includes(unit[0])) {
- transformUnit = unit;
+ getMetricChartData(curTimeRange).then(
+ (res: any[] | null) => {
+ // 如果图表返回数据
+ if (res?.length) {
+ // 格式化图表需要的数据
+ const formattedMetricData = (
+ formatChartData(
+ res,
+ global.getMetricDefine || {},
+ metricType,
+ curTimeRange,
+ DEFAULT_POINT_INTERVAL,
+ false
+ ) as MetricChartDataType[]
+ )[0];
+ // 填充图表数据
+ let initFullTimeRange = curTimeRange;
+ const pointsOfFirstLine = formattedMetricData.metricLines.find((line) => line.data.length).data;
+ if (pointsOfFirstLine) {
+ initFullTimeRange = [
+ pointsOfFirstLine[0][0] as number,
+ pointsOfFirstLine[pointsOfFirstLine.length - 1][0] as number,
+ ] as const;
}
- });
- chartInfo.current = {
- ...chartInfo.current,
- fullMetricData: formattedMetricData,
- fullTimeRange: [...initFullTimeRange],
- curTimeRange: [...initFullTimeRange],
- sliderPos: [
- initFullTimeRange[1] - (initFullTimeRange[1] - initFullTimeRange[0]) * DATA_ZOOM_DEFAULT_SCALE,
- initFullTimeRange[1],
- ],
- transformUnit,
- };
- setCurMetricData(formattedMetricData);
- setLoading(false);
- }
- });
+ // 获取单位保存起来
+ let transformUnit = undefined;
+ Object.entries(UNIT_MAP).forEach((unit) => {
+ if (formattedMetricData.metricUnit.includes(unit[0])) {
+ transformUnit = unit;
+ }
+ });
+
+ updateChartInfo({
+ fullMetricData: formattedMetricData,
+ fullTimeRange: [...initFullTimeRange],
+ curTimeRange: [...initFullTimeRange],
+ sliderPos: [
+ initFullTimeRange[1] - (initFullTimeRange[1] - initFullTimeRange[0]) * DATA_ZOOM_DEFAULT_SCALE,
+ initFullTimeRange[1],
+ ],
+ transformUnit,
+ });
+ setCurMetricData(formattedMetricData);
+ const newLinesStatus: { [lineName: string]: boolean } = {};
+ formattedMetricData.metricLines.forEach((line) => {
+ newLinesStatus[line.name] = true;
+ });
+ setLinesStatus(newLinesStatus);
+ setLoading(false);
+ getAdditionChartData(false, initFullTimeRange[0], initFullTimeRange[1]);
+ }
+ },
+ () => setLoading(false)
+ );
}
}, []);
- const debounced = debounce(onDataZoomDrag, 300);
+ debouncedZoomDrag.current = debounce(onDataZoomDrag, 300);
return (
- {curMetricData && (
+ {curMetricData ? (
<>
-
-
-
- {
- let content = '';
- const metricDefine = global.getMetricDefine(metricType, curMetricData.metricName);
- if (metricDefine) {
- content = metricDefine.desc;
- }
- return content;
- }}
- >
-
- {curMetricData.metricName} ({curMetricData.metricUnit})
-
-
-
-
{chartInfo.current.sliderRange}
-
-
-
-
-
{
- debounced(record);
- },
+ dataZoom: (record: any) => debouncedZoomDrag?.current(record),
}}
+ showHeader={false}
propChartData={curMetricData.metricLines}
optionMergeProps={{ notMerge: true }}
getChartInstance={(chartInstance) => {
- chartInfo.current = {
- ...chartInfo.current,
+ setDisposeChartInstance(() => () => chartInstance.dispose());
+ updateChartInfo({
chartInstance,
- };
+ });
}}
{...getDetailChartConfig(`${curMetricData.metricName}{unit|(${curMetricData.metricUnit})}`, chartInfo.current.sliderPos)}
/>
@@ -588,16 +624,10 @@ const ChartDetail = (props: ChartDetailProps) => {
className="detail-table"
rowKey="name"
rowSelection={{
- // hideSelectAll: true,
preserveSelectedRowKeys: true,
- selectedRowKeys: selectedLines,
- // getCheckboxProps: (record) => {
- // return selectedLines.length <= 1 && selectedLines.includes(record.name)
- // ? {
- // disabled: true,
- // }
- // : {};
- // },
+ selectedRowKeys: Object.entries(linesStatus)
+ .filter(([, status]) => status)
+ .map(([name]) => name),
selections: [Table.SELECTION_INVERT, Table.SELECTION_NONE],
onChange: (keys: string[]) => tableLineChange(keys),
}}
@@ -610,6 +640,8 @@ const ChartDetail = (props: ChartDetailProps) => {
pagination={false}
/>
>
+ ) : (
+ !loading &&
)}
@@ -618,22 +650,46 @@ const ChartDetail = (props: ChartDetailProps) => {
// eslint-disable-next-line react/display-name
const ChartDrawer = forwardRef((_, ref) => {
+ const [global] = AppContainer.useGlobalValue();
const [visible, setVisible] = useState(false);
- const [dashboardType, setDashboardType] = useState();
- const [metricName, setMetricName] = useState();
const [queryLines, setQueryLines] = useState([]);
+ const [sliderRange, setSliderRange] = useState('');
+ const [disposeChartInstance, setDisposeChartInstance] = useState<() => void>(() => 0);
+ const [metricInfo, setMetricInfo] = useState<{
+ type: MetricType | undefined;
+ name: string;
+ unit: string;
+ desc: string;
+ }>({
+ type: undefined,
+ name: '',
+ unit: '',
+ desc: '',
+ });
const onOpen = (dashboardType: MetricType, metricName: string, queryLines: string[]) => {
- setDashboardType(dashboardType);
- setMetricName(metricName);
+ const metricDefine = global.getMetricDefine(dashboardType, metricName);
+ setMetricInfo({
+ type: dashboardType,
+ name: metricName,
+ unit: metricDefine?.unit || '',
+ desc: metricDefine?.desc || '',
+ });
setQueryLines(queryLines);
setVisible(true);
};
const onClose = () => {
setVisible(false);
- setDashboardType(undefined);
- setMetricName(undefined);
+ setSliderRange('');
+ disposeChartInstance();
+ setDisposeChartInstance(() => () => 0);
+ setMetricInfo({
+ type: undefined,
+ name: '',
+ unit: '',
+ desc: '',
+ });
};
useImperativeHandle(ref, () => ({
@@ -641,9 +697,36 @@ const ChartDrawer = forwardRef((_, ref) => {
}));
return (
-
- {dashboardType && metricName && (
-
+
+
+
+
+ {metricInfo.name} ({metricInfo.unit})
+
+
+
+ {sliderRange}
+
+ }
+ footer={null}
+ closable={true}
+ maskClosable={false}
+ destroyOnClose={true}
+ onClose={onClose}
+ >
+ {metricInfo.type && metricInfo.name && (
+
)}
);