fix: dashboard polish
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { VegaEmbed } from 'react-vega';
|
import { VegaEmbed } from 'react-vega';
|
||||||
import type { ChartSpec } from '@/store/visualizationStore';
|
import type { ChartSpec } from '@/store/visualizationStore';
|
||||||
|
|
||||||
@@ -8,17 +8,38 @@ interface VegaChartProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const VegaChart: React.FC<VegaChartProps> = ({ data, spec }) => {
|
export const VegaChart: React.FC<VegaChartProps> = ({ data, spec }) => {
|
||||||
const vegaSpec: any = {
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [size, setSize] = useState({ width: 0, height: 0 });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const node = containerRef.current;
|
||||||
|
if (!node) return;
|
||||||
|
const observer = new ResizeObserver((entries) => {
|
||||||
|
const entry = entries[0];
|
||||||
|
if (!entry) return;
|
||||||
|
const nextWidth = Math.max(0, Math.floor(entry.contentRect.width));
|
||||||
|
const nextHeight = Math.max(0, Math.floor(entry.contentRect.height));
|
||||||
|
setSize((prev) => (
|
||||||
|
prev.width === nextWidth && prev.height === nextHeight
|
||||||
|
? prev
|
||||||
|
: { width: nextWidth, height: nextHeight }
|
||||||
|
));
|
||||||
|
});
|
||||||
|
observer.observe(node);
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const vegaSpec: any = useMemo(() => ({
|
||||||
$schema: typeof spec.$schema === 'string' ? spec.$schema : 'https://vega.github.io/schema/vega-lite/v5.json',
|
$schema: typeof spec.$schema === 'string' ? spec.$schema : 'https://vega.github.io/schema/vega-lite/v5.json',
|
||||||
...spec,
|
...spec,
|
||||||
width: "container",
|
width: size.width > 0 ? size.width : "container",
|
||||||
height: "container",
|
height: size.height > 0 ? size.height : "container",
|
||||||
data: { values: data },
|
data: { values: data },
|
||||||
autosize: { type: "fit", contains: "padding" },
|
autosize: { type: "fit", contains: "padding", resize: true },
|
||||||
};
|
}), [data, size.height, size.width, spec]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full">
|
<div className="w-full h-full" ref={containerRef}>
|
||||||
<VegaEmbed
|
<VegaEmbed
|
||||||
spec={vegaSpec}
|
spec={vegaSpec}
|
||||||
options={{ actions: false }}
|
options={{ actions: false }}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ function inferChartKeys(data: Record<string, unknown>[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function Dashboard() {
|
export function Dashboard() {
|
||||||
const { charts, removeChart } = useDashboardStore();
|
const { charts, removeChart, updateLayout } = useDashboardStore();
|
||||||
const ResponsiveGridLayout = useMemo(
|
const ResponsiveGridLayout = useMemo(
|
||||||
() => WidthProvider(Responsive as any) as any,
|
() => WidthProvider(Responsive as any) as any,
|
||||||
[]
|
[]
|
||||||
@@ -49,10 +49,16 @@ export function Dashboard() {
|
|||||||
lg: charts.map((c) => c.layout)
|
lg: charts.map((c) => c.layout)
|
||||||
}), [charts]);
|
}), [charts]);
|
||||||
|
|
||||||
const onLayoutChange = (_currentLayout: any, _allLayouts: any) => {
|
const onLayoutChange = (currentLayout: any[]) => {
|
||||||
// updateLayout(currentLayout); // This might cause infinite loops if not handled carefully
|
updateLayout(
|
||||||
// For simplicity, we just log it or update it if needed.
|
currentLayout.map((item) => ({
|
||||||
// In a real app, we would debounce this and save to backend.
|
i: item.i,
|
||||||
|
x: item.x,
|
||||||
|
y: item.y,
|
||||||
|
w: item.w,
|
||||||
|
h: item.h,
|
||||||
|
}))
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (charts.length === 0) {
|
if (charts.length === 0) {
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ export const useDashboardStore = create<DashboardState>((set) => ({
|
|||||||
addChart: (chart) => set((state) => {
|
addChart: (chart) => set((state) => {
|
||||||
const newLayout: GridLayout = {
|
const newLayout: GridLayout = {
|
||||||
i: chart.id,
|
i: chart.id,
|
||||||
x: (state.charts.length * 6) % 12,
|
x: (state.charts.length * 4) % 12,
|
||||||
y: Infinity,
|
y: Infinity,
|
||||||
w: 6,
|
w: 4,
|
||||||
h: 8,
|
h: 4,
|
||||||
};
|
};
|
||||||
return { charts: [...state.charts, { ...chart, layout: newLayout }] };
|
return { charts: [...state.charts, { ...chart, layout: newLayout }] };
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user