[#912,@portaljs/components][m]: refactor LineChart and add more params
This commit is contained in:
@@ -90,5 +90,5 @@ const TableInner: React.FC<FlatUiTableProps> = ({
|
|||||||
<Grid data={parsedData.data} />
|
<Grid data={parsedData.data} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return <Spinning />;
|
return <LoadingSpinner />;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import LoadingSpinner from './LoadingSpinner';
|
||||||
import { VegaLite } from './VegaLite';
|
import { VegaLite } from './VegaLite';
|
||||||
|
import loadData from '../lib/loadData';
|
||||||
|
|
||||||
|
type AxisType = 'quantitative' | 'temporal';
|
||||||
|
type TimeUnit = 'year' | undefined; // or ...
|
||||||
|
|
||||||
export type LineChartProps = {
|
export type LineChartProps = {
|
||||||
data: Array<Array<string | number>> | string | { x: string; y: number }[];
|
data: Array<Array<string | number>> | string | { x: string; y: number }[];
|
||||||
title?: string;
|
title?: string;
|
||||||
xAxis?: string;
|
xAxis?: string;
|
||||||
|
xAxisType?: AxisType;
|
||||||
|
xAxisTimeUnit: TimeUnit;
|
||||||
yAxis?: string;
|
yAxis?: string;
|
||||||
|
yAxisType?: AxisType;
|
||||||
fullWidth?: boolean;
|
fullWidth?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -13,15 +22,16 @@ export function LineChart({
|
|||||||
fullWidth = false,
|
fullWidth = false,
|
||||||
title = '',
|
title = '',
|
||||||
xAxis = 'x',
|
xAxis = 'x',
|
||||||
|
xAxisType = 'temporal',
|
||||||
|
xAxisTimeUnit = 'year', // TODO: defaults to undefined would probably work better... keeping it as it's for compatibility purposes
|
||||||
yAxis = 'y',
|
yAxis = 'y',
|
||||||
|
yAxisType = 'quantitative',
|
||||||
}: LineChartProps) {
|
}: LineChartProps) {
|
||||||
var tmp = data;
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
if (Array.isArray(data)) {
|
|
||||||
tmp = data.map((r) => {
|
// By default, assumes data is an Array...
|
||||||
return { x: r[0], y: r[1] };
|
const [specData, setSpecData] = useState<any>({ name: 'table' });
|
||||||
});
|
|
||||||
}
|
|
||||||
const vegaData = { table: tmp };
|
|
||||||
const spec = {
|
const spec = {
|
||||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
||||||
title,
|
title,
|
||||||
@@ -33,9 +43,7 @@ export function LineChart({
|
|||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
tooltip: true,
|
tooltip: true,
|
||||||
},
|
},
|
||||||
data: {
|
data: specData,
|
||||||
name: 'table',
|
|
||||||
},
|
|
||||||
selection: {
|
selection: {
|
||||||
grid: {
|
grid: {
|
||||||
type: 'interval',
|
type: 'interval',
|
||||||
@@ -45,19 +53,44 @@ export function LineChart({
|
|||||||
encoding: {
|
encoding: {
|
||||||
x: {
|
x: {
|
||||||
field: xAxis,
|
field: xAxis,
|
||||||
timeUnit: 'year',
|
timeUnit: xAxisTimeUnit,
|
||||||
type: 'temporal',
|
type: xAxisType,
|
||||||
},
|
},
|
||||||
y: {
|
y: {
|
||||||
field: yAxis,
|
field: yAxis,
|
||||||
type: 'quantitative',
|
type: yAxisType,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
} as any;
|
||||||
if (typeof data === 'string') {
|
|
||||||
spec.data = { url: data } as any;
|
useEffect(() => {
|
||||||
return <VegaLite fullWidth={fullWidth} spec={spec} />;
|
// If data is string, assume it's a URL
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
// Manualy loading the data allows us to do other kinds
|
||||||
|
// of stuff later e.g. load a file partially
|
||||||
|
loadData(data).then((res: any) => {
|
||||||
|
setSpecData({ values: res, format: { type: 'csv' } });
|
||||||
|
setIsLoading(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
var vegaData = {};
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
var dataObj;
|
||||||
|
dataObj = data.map((r) => {
|
||||||
|
return { x: r[0], y: r[1] };
|
||||||
|
});
|
||||||
|
vegaData = { table: dataObj };
|
||||||
}
|
}
|
||||||
|
|
||||||
return <VegaLite fullWidth={fullWidth} data={vegaData} spec={spec} />;
|
return isLoading ? (
|
||||||
|
<div className="w-full flex items-center justify-center w-[600px] h-[300px]">
|
||||||
|
<LoadingSpinner />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<VegaLite fullWidth={fullWidth} data={vegaData} spec={spec} />
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,19 @@ const meta: Meta = {
|
|||||||
description:
|
description:
|
||||||
'Name of the X axis on the data. Required when the "data" parameter is an URL.',
|
'Name of the X axis on the data. Required when the "data" parameter is an URL.',
|
||||||
},
|
},
|
||||||
|
xAxisType: {
|
||||||
|
description: 'Type of the X axis',
|
||||||
|
},
|
||||||
|
xAxisTimeUnit: {
|
||||||
|
description: 'Time unit of the X axis (optional)',
|
||||||
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
description:
|
description:
|
||||||
'Name of the Y axis on the data. Required when the "data" parameter is an URL.',
|
'Name of the Y axis on the data. Required when the "data" parameter is an URL.',
|
||||||
},
|
},
|
||||||
|
yAxisType: {
|
||||||
|
description: 'Type of the Y axis',
|
||||||
|
},
|
||||||
fullWidth: {
|
fullWidth: {
|
||||||
description:
|
description:
|
||||||
'Whether the component should be rendered as full bleed or not',
|
'Whether the component should be rendered as full bleed or not',
|
||||||
|
|||||||
Reference in New Issue
Block a user