Files
supersonic/webapp/packages/supersonic-fe/src/pages/SemanticModel/Metric/components/MetricTrend.tsx
tristanliu 9f813ca1c0 [improvement][semantic-fe] Adding batch operations for indicators/dimensions/models (#313)
* [improvement][semantic-fe] Add model alias setting & Add view permission restrictions to the model permission management tab.
[improvement][semantic-fe] Add permission control to the action buttons for the main domain; apply high sensitivity filtering to the authorization of metrics/dimensions.
[improvement][semantic-fe] Optimize the editing mode in the dimension/metric/datasource components to use the modelId stored in the database for data, instead of relying on the data from the state manager.

* [improvement][semantic-fe] Add time granularity setting in the data source configuration.

* [improvement][semantic-fe] Dictionary import for dimension values supported in Q&A visibility

* [improvement][semantic-fe] Modification of data source creation prompt wording"

* [improvement][semantic-fe] metric market experience optimization

* [improvement][semantic-fe] enhance the analysis of metric trends

* [improvement][semantic-fe] optimize the presentation of metric trend permissions

* [improvement][semantic-fe] add metric trend download functionality

* [improvement][semantic-fe] fix the dimension initialization issue in metric correlation

* [improvement][semantic-fe] Fix the issue of database changes not taking effect when creating based on an SQL data source.

* [improvement][semantic-fe] Optimizing pagination logic and some CSS styles

* [improvement][semantic-fe] Fixing the API for the indicator list by changing "current" to "pageNum"

* [improvement][semantic-fe] Fixing the default value setting for the indicator list

* [improvement][semantic-fe] Adding batch operations for indicators/dimensions/models
2023-11-02 06:11:12 -05:00

218 lines
5.6 KiB
TypeScript

import { CHART_SECONDARY_COLOR } from '@/common/constants';
import {
formatByDecimalPlaces,
formatByPercentageData,
getFormattedValueData,
} from '@/utils/utils';
import { Skeleton, Button, Tooltip } from 'antd';
import { DownloadOutlined } from '@ant-design/icons';
import type { ECharts } from 'echarts';
import * as echarts from 'echarts';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import styles from '../style.less';
import moment from 'moment';
type Props = {
title?: string;
tip?: string;
data: any[];
fields: any[];
// columnFieldName: string;
// valueFieldName: string;
loading: boolean;
isPer?: boolean;
isPercent?: boolean;
dateFieldName?: string;
dateFormat?: string;
height?: number;
renderType?: string;
decimalPlaces?: number;
onDownload?: () => void;
};
const TrendChart: React.FC<Props> = ({
title,
tip,
data,
fields,
loading,
isPer,
isPercent,
dateFieldName,
// columnFieldName,
// valueFieldName,
dateFormat,
height,
renderType,
decimalPlaces,
onDownload,
}) => {
const chartRef = useRef<any>();
const [instance, setInstance] = useState<ECharts>();
const renderChart = useCallback(() => {
let instanceObj: ECharts;
if (!instance) {
instanceObj = echarts.init(chartRef.current);
setInstance(instanceObj);
} else {
instanceObj = instance;
if (renderType === 'clear') {
instanceObj.clear();
}
}
const xData = Array.from(
new Set(
data
.map((item) =>
moment(`${(dateFieldName && item[dateFieldName]) || item.sys_imp_date}`).format(
dateFormat ?? 'YYYY-MM-DD',
),
)
.sort((a, b) => {
return moment(a).valueOf() - moment(b).valueOf();
}),
),
);
const seriesData = fields.map((field) => {
const fieldData = {
type: 'line',
name: field.name,
symbol: 'circle',
showSymbol: data.length === 1,
smooth: true,
data: data.reduce((itemData, item) => {
const target = item[field.column];
if (target) {
itemData.push(target);
}
return itemData;
}, []),
};
return fieldData;
});
instanceObj.setOption({
legend: {
left: 0,
top: 0,
icon: 'rect',
itemWidth: 15,
itemHeight: 5,
selected: fields.reduce((result, item) => {
if (item.selected === false) {
result[item.name] = false;
}
return result;
}, {}),
},
xAxis: {
type: 'category',
axisTick: {
alignWithLabel: true,
lineStyle: {
color: CHART_SECONDARY_COLOR,
},
},
axisLine: {
lineStyle: {
color: CHART_SECONDARY_COLOR,
},
},
axisLabel: {
showMaxLabel: true,
color: '#999',
},
data: xData,
},
yAxis: {
type: 'value',
splitLine: {
lineStyle: {
opacity: 0.3,
},
},
axisLabel: {
formatter: function (value: any) {
return value === 0
? 0
: isPer
? `${formatByDecimalPlaces(value, decimalPlaces ?? 0)}%`
: isPercent
? formatByPercentageData(value, decimalPlaces ?? 0)
: getFormattedValueData(value);
},
},
},
tooltip: {
trigger: 'axis',
formatter: function (params: any) {
const param = params[0];
const valueLabels = params
.map(
(item: any) =>
`<div style="margin-top: 3px;">${
item.marker
} <span style="display: inline-block; width: 70px; margin-right: 5px;">${
item.seriesName
}</span><span style="display: inline-block; width: 90px; text-align: right; font-weight: 500;">${
item.value === ''
? '-'
: isPer
? `${formatByDecimalPlaces(item.value, decimalPlaces ?? 2)}%`
: isPercent
? formatByPercentageData(item.value, decimalPlaces ?? 2)
: getFormattedValueData(item.value)
}</span></div>`,
)
.join('');
return `${param.name}<br />${valueLabels}`;
},
},
grid: {
left: '1%',
right: '4%',
bottom: '3%',
top: height && height < 300 ? 45 : 60,
containLabel: true,
},
series: seriesData,
});
instanceObj.resize();
}, [data, fields, instance, isPer, isPercent, dateFieldName, decimalPlaces, renderType]);
useEffect(() => {
if (!loading) {
renderChart();
}
}, [renderChart, loading, data]);
return (
<div className={styles.trendChart}>
{title && (
<div className={styles.top}>
<div className={styles.title}>{title}</div>
{onDownload && (
<Tooltip title="下载">
<Button shape="circle" className={styles.downloadBtn} onClick={onDownload}>
<DownloadOutlined />
</Button>
</Tooltip>
)}
</div>
)}
<Skeleton
className={styles.chart}
style={{ height, display: loading ? 'table' : 'none' }}
paragraph={{ rows: height && height > 300 ? 9 : 6 }}
/>
<div
className={styles.chart}
style={{ height, display: !loading ? 'block' : 'none' }}
ref={chartRef}
/>
</div>
);
};
export default TrendChart;