fix(data-vi): charts flickers (#3836)

This commit is contained in:
YANG QIA 2024-03-27 15:43:11 +08:00 committed by GitHub
parent e95f4ab123
commit 996e89fb14
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 48 additions and 56 deletions

View File

@ -11,38 +11,38 @@ describe('api', () => {
});
test('setGroup', () => {
const charts1 = [new Chart({ name: 'test1', title: 'Test1', component: null })];
const charts1 = [new Chart({ name: 'test1', title: 'Test1', Component: null })];
plugin.charts.setGroup('group', charts1);
expect(plugin.charts.charts.get('group')).toEqual(charts1);
const charts2 = [new Chart({ name: 'test2', title: 'Test2', component: null })];
const charts2 = [new Chart({ name: 'test2', title: 'Test2', Component: null })];
plugin.charts.setGroup('group', charts2);
expect(plugin.charts.charts.get('group')).toEqual(charts2);
});
test('addGroup', () => {
const charts1 = [new Chart({ name: 'test1', title: 'Test1', component: null })];
const charts1 = [new Chart({ name: 'test1', title: 'Test1', Component: null })];
plugin.charts.setGroup('group1', charts1);
const charts2 = [new Chart({ name: 'test2', title: 'Test2', component: null })];
const charts2 = [new Chart({ name: 'test2', title: 'Test2', Component: null })];
plugin.charts.addGroup('group2', charts2);
expect(plugin.charts.charts.get('group1')).toEqual(charts1);
expect(plugin.charts.charts.get('group2')).toEqual(charts2);
});
test('add', () => {
const charts1 = [new Chart({ name: 'test1', title: 'Test1', component: null })];
const charts1 = [new Chart({ name: 'test1', title: 'Test1', Component: null })];
plugin.charts.setGroup('group', charts1);
const chart = new Chart({ name: 'test2', title: 'Test2', component: null });
const chart = new Chart({ name: 'test2', title: 'Test2', Component: null });
plugin.charts.add('group', chart);
expect(plugin.charts.charts.get('group').length).toEqual(2);
expect(plugin.charts.charts.get('group')[1].name).toEqual('test2');
});
test('getChartTypes', () => {
const charts1 = [new Chart({ name: 'test1', title: 'Test1', component: null })];
const charts1 = [new Chart({ name: 'test1', title: 'Test1', Component: null })];
plugin.charts.setGroup('group1', charts1);
const charts2 = [new Chart({ name: 'test2', title: 'Test2', component: null })];
const charts2 = [new Chart({ name: 'test2', title: 'Test2', Component: null })];
plugin.charts.setGroup('group2', charts2);
expect(plugin.charts.getChartTypes()).toEqual([
{
@ -69,9 +69,9 @@ describe('api', () => {
});
test('getCharts', () => {
const charts1 = [new Chart({ name: 'test1', title: 'Test1', component: null })];
const charts1 = [new Chart({ name: 'test1', title: 'Test1', Component: null })];
plugin.charts.setGroup('group1', charts1);
const charts2 = [new Chart({ name: 'test2', title: 'Test2', component: null })];
const charts2 = [new Chart({ name: 'test2', title: 'Test2', Component: null })];
plugin.charts.setGroup('group2', charts2);
expect(plugin.charts.getCharts()).toEqual({
'group1.test1': charts1[0],
@ -80,9 +80,9 @@ describe('api', () => {
});
test('getChart', () => {
const charts1 = [new Chart({ name: 'test1', title: 'Test1', component: null })];
const charts1 = [new Chart({ name: 'test1', title: 'Test1', Component: null })];
plugin.charts.setGroup('group1', charts1);
const charts2 = [new Chart({ name: 'test2', title: 'Test2', component: null })];
const charts2 = [new Chart({ name: 'test2', title: 'Test2', Component: null })];
plugin.charts.setGroup('group2', charts2);
expect(plugin.charts.getChart('group1.test1')).toEqual(charts1[0]);
expect(plugin.charts.getChart('group2.test2')).toEqual(charts2[0]);
@ -90,7 +90,7 @@ describe('api', () => {
});
describe('auto infer', () => {
const chart = new Chart({ name: 'test', title: 'Test', component: null });
const chart = new Chart({ name: 'test', title: 'Test', Component: null });
const fields = [
{
name: 'price',

View File

@ -8,7 +8,7 @@ export class Statistic extends AntdChart {
super({
name: 'statistic',
title: 'Statistic',
component: AntdStatistic,
Component: AntdStatistic,
config: [
{
property: 'field',

View File

@ -4,7 +4,7 @@ import { Table as AntdTable } from 'antd';
export class Table extends AntdChart {
constructor() {
super({ name: 'table', title: 'Table', component: AntdTable });
super({ name: 'table', title: 'Table', Component: AntdTable });
}
getProps({ data, fieldProps, general, advanced }: RenderProps) {

View File

@ -22,7 +22,7 @@ export type RenderProps = {
export interface ChartType {
name: string;
title: string;
component: React.FC<any>;
Component: React.FC<any>;
schema: ISchema;
init?: (
fields: FieldOption[],
@ -34,7 +34,7 @@ export interface ChartType {
general?: any;
advanced?: any;
};
render: (props: RenderProps) => React.FC<any>;
getProps(props: RenderProps): any;
getReference?: () => {
title: string;
link: string;
@ -44,21 +44,21 @@ export interface ChartType {
export type ChartProps = {
name: string;
title: string;
component: React.FC<any>;
Component: React.FC<any>;
config?: Config[];
};
export class Chart implements ChartType {
name: string;
title: string;
component: React.FC<any>;
Component: React.FC<any>;
config: Config[];
configs = new Map<string, Function>();
constructor({ name, title, component, config }: ChartProps) {
constructor({ name, title, Component, config }: ChartProps) {
this.name = name;
this.title = title;
this.component = component;
this.Component = Component;
this.config = config;
this.addConfigs(configs);
}
@ -170,11 +170,4 @@ export class Chart implements ChartType {
getProps(props: RenderProps): any {
return props;
}
render({ data, general, advanced, fieldProps }: RenderProps) {
return () =>
React.createElement(this.component, {
...this.getProps({ data, general, advanced, fieldProps }),
});
}
}

View File

@ -4,7 +4,7 @@ import { ChartType } from '../chart';
export class Bar extends G2PlotChart {
constructor() {
super({ name: 'bar', title: 'Bar Chart', component: G2PlotBar, config: ['isGroup', 'isStack', 'isPercent'] });
super({ name: 'bar', title: 'Bar Chart', Component: G2PlotBar, config: ['isGroup', 'isStack', 'isPercent'] });
}
init: ChartType['init'] = (fields, { measures, dimensions }) => {

View File

@ -6,7 +6,7 @@ import lodash from 'lodash';
export class DualAxes extends G2PlotChart {
constructor() {
super({ name: 'dualAxes', title: 'Dual Axes Chart', component: G2DualAxes });
super({ name: 'dualAxes', title: 'Dual Axes Chart', Component: G2DualAxes });
this.config = [
'xField',
{

View File

@ -2,11 +2,11 @@ import { Chart, ChartProps, ChartType, RenderProps } from '../chart';
import configs from './configs';
export class G2PlotChart extends Chart {
constructor({ name, title, component, config }: ChartProps) {
constructor({ name, title, Component, config }: ChartProps) {
super({
name,
title,
component,
Component,
config: ['xField', 'yField', 'seriesField', ...(config || [])],
});
this.addConfigs(configs);

View File

@ -7,13 +7,13 @@ export default [
new G2PlotChart({
name: 'line',
title: 'Line Chart',
component: Line,
Component: Line,
config: ['smooth', 'isStack'],
}),
new G2PlotChart({
name: 'area',
title: 'Area Chart',
component: Area,
Component: Area,
config: [
'smooth',
{
@ -26,16 +26,16 @@ export default [
new G2PlotChart({
name: 'column',
title: 'Column Chart',
component: Column,
Component: Column,
config: ['isGroup', 'isStack', 'isPercent'],
}),
new G2PlotChart({
name: 'bar',
title: 'Bar Chart',
component: Bar,
Component: Bar,
config: ['isGroup', 'isStack', 'isPercent'],
}),
new Pie(),
new DualAxes(),
new G2PlotChart({ name: 'scatter', title: 'Scatter Chart', component: Scatter }),
new G2PlotChart({ name: 'scatter', title: 'Scatter Chart', Component: Scatter }),
];

View File

@ -4,7 +4,7 @@ import { ChartType, RenderProps } from '../chart';
export class Pie extends G2PlotChart {
constructor() {
super({ name: 'pie', title: 'Pie Chart', component: G2Pie });
super({ name: 'pie', title: 'Pie Chart', Component: G2Pie });
this.config = [
{
property: 'field',

View File

@ -12,7 +12,7 @@ import {
useDesignable,
} from '@nocobase/client';
import { Empty, Result, Spin, Typography } from 'antd';
import React, { useContext } from 'react';
import React, { memo, useContext } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { ChartConfigContext } from '../configure';
import { useData, useFieldTransformer, useFieldsWithAssociation } from '../hooks';
@ -22,6 +22,8 @@ import { ChartRendererContext } from './ChartRendererProvider';
import { useChart } from '../chart/group';
import { ChartDataContext } from '../block/ChartDataProvider';
const { Paragraph, Text } = Typography;
import lodash from 'lodash';
import { Line } from '@ant-design/plots';
export const ChartRenderer: React.FC & {
Designer: React.FC;
@ -38,7 +40,7 @@ export const ChartRenderer: React.FC & {
const chart = useChart(config?.chartType);
const locale = api.auth.getLocale();
const transformers = useFieldTransformer(transform, locale);
const Component = chart?.render({
const chartProps = chart?.getProps({
data,
general,
advanced,
@ -51,30 +53,27 @@ export const ChartRenderer: React.FC & {
return props;
}, {}),
});
const C = chart?.Component;
const C = () =>
chart ? (
if (!chart) {
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={t('Please configure chart')} />;
}
if (!(data && data.length) && !service.loading) {
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={t('No data')} />;
}
return (
<Spin spinning={service.loading}>
<ErrorBoundary
onError={(error) => {
console.error(error);
}}
FallbackComponent={ErrorFallback}
>
<Component />
<C {...chartProps} />
</ErrorBoundary>
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={t('Please configure chart')} />
);
if (service.loading) {
return <Spin />;
}
if (!(data && data.length)) {
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={t('No data')} />;
}
return <C />;
</Spin>
);
};
ChartRenderer.Designer = function Designer() {