chore: add prettier with config and format all files

This commit is contained in:
Sebastian Seedorf
2026-06-04 11:44:20 +02:00
parent d212ae3f30
commit cf9bb33ecb
50 changed files with 1290 additions and 714 deletions

View File

@@ -6,12 +6,20 @@ import type { Layout, LayoutItem } from 'react-grid-layout';
import 'react-grid-layout/css/styles.css';
import 'react-resizable/css/styles.css';
import { useApp } from '@/lib/context';
import { fetchCharts, createChart, updateChart, deleteChart, fetchSignals, fetchSessions, fetchUps } from '@/lib/api';
import {
fetchCharts,
createChart,
updateChart,
deleteChart,
fetchSignals,
fetchSessions,
fetchUps,
} from '@/lib/api';
import type { ChartConfig, SignalRow, UpsRow, SessionBoundary, AlertConfig } from '@/lib/types';
import ChartCard from './ChartCard';
import ChartEditor from './ChartEditor';
const COLS = 6;
const COLS = 6;
const ROW_HEIGHT = 80;
interface Props {
@@ -20,21 +28,25 @@ interface Props {
export default function Dashboard({ alerts }: Props) {
const { timeRange, timeMode, getFromTo } = useApp();
const [charts, setCharts] = useState<ChartConfig[]>([]);
const [signalData, setSignalData] = useState<Map<string, SignalRow[]>>(new Map());
const [upsData, setUpsData] = useState<Map<string, UpsRow[]>>(new Map());
const [sessions, setSessions] = useState<SessionBoundary[]>([]);
const [editingChart, setEditingChart] = useState<ChartConfig | null>(null);
const [creatingChart, setCreatingChart] = useState(false);
const [charts, setCharts] = useState<ChartConfig[]>([]);
const [signalData, setSignalData] = useState<Map<string, SignalRow[]>>(new Map());
const [upsData, setUpsData] = useState<Map<string, UpsRow[]>>(new Map());
const [sessions, setSessions] = useState<SessionBoundary[]>([]);
const [editingChart, setEditingChart] = useState<ChartConfig | null>(null);
const [creatingChart, setCreatingChart] = useState(false);
const [containerWidth, setContainerWidth] = useState(1200);
const containerRef = useRef<HTMLDivElement>(null);
const chartsRef = useRef<ChartConfig[]>([]);
const refreshingRef = useRef(false);
const containerRef = useRef<HTMLDivElement>(null);
const chartsRef = useRef<ChartConfig[]>([]);
const refreshingRef = useRef(false);
const layoutSaveTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => { chartsRef.current = charts; }, [charts]);
useEffect(() => { fetchCharts().then(setCharts); }, []);
useEffect(() => {
chartsRef.current = charts;
}, [charts]);
useEffect(() => {
fetchCharts().then(setCharts);
}, []);
const refreshData = useCallback(async () => {
if (refreshingRef.current) return;
@@ -44,24 +56,27 @@ export default function Dashboard({ alerts }: Props) {
refreshingRef.current = true;
try {
const { from, to } = getFromTo();
const signalCharts = current.filter(c => c.chart_type === 'signals');
const upsCharts = current.filter(c => c.chart_type === 'ups');
const signalCharts = current.filter((c) => c.chart_type === 'signals');
const upsCharts = current.filter((c) => c.chart_type === 'ups');
if (signalCharts.length === 0 && upsCharts.length === 0) return;
const [newSessions, ...results] = await Promise.all([
fetchSessions(from, to),
...signalCharts.map(c => fetchSignals({
combinator: c.filter_combinators ?? undefined,
item: c.filter_items ?? undefined,
exclude: c.filter_items_exclude ?? undefined,
signal: c.signal_type,
time_mode: timeMode,
from, to,
regex: c.filter_items_regex || undefined,
...(c.order_by !== 'time' ? { order_by: c.order_by, limit: c.series_limit } : {}),
})),
...upsCharts.map(c => fetchUps({ combinator: c.filter_combinators?.[0], from, to })),
...signalCharts.map((c) =>
fetchSignals({
combinator: c.filter_combinators ?? undefined,
item: c.filter_items ?? undefined,
exclude: c.filter_items_exclude ?? undefined,
signal: c.signal_type,
time_mode: timeMode,
from,
to,
regex: c.filter_items_regex || undefined,
...(c.order_by !== 'time' ? { order_by: c.order_by, limit: c.series_limit } : {}),
}),
),
...upsCharts.map((c) => fetchUps({ combinator: c.filter_combinators?.[0], from, to })),
]);
setSessions(newSessions as SessionBoundary[]);
@@ -98,47 +113,56 @@ export default function Dashboard({ alerts }: Props) {
async function handleCreate(draft: Omit<ChartConfig, 'id'>) {
const created = await createChart(draft);
setCharts(cs => [...cs, created]);
setCharts((cs) => [...cs, created]);
setCreatingChart(false);
}
async function handleUpdate(id: string, draft: Omit<ChartConfig, 'id'>) {
const updated = await updateChart(id, draft);
setCharts(cs => cs.map(c => c.id === id ? updated : c));
setCharts((cs) => cs.map((c) => (c.id === id ? updated : c)));
setEditingChart(null);
}
async function handleDelete(id: string) {
await deleteChart(id);
setCharts(cs => cs.filter(c => c.id !== id));
setCharts((cs) => cs.filter((c) => c.id !== id));
}
function handleLayoutChange(layout: Layout) {
const items = layout as readonly LayoutItem[];
const changed = items.filter(item => {
const chart = chartsRef.current.find(c => c.id === item.i);
return chart && (
chart.pos_x !== item.x || chart.pos_y !== item.y ||
chart.width !== item.w || chart.height !== item.h
const changed = items.filter((item) => {
const chart = chartsRef.current.find((c) => c.id === item.i);
return (
chart &&
(chart.pos_x !== item.x ||
chart.pos_y !== item.y ||
chart.width !== item.w ||
chart.height !== item.h)
);
});
if (changed.length === 0) return;
setCharts(cs => cs.map(c => {
const l = changed.find(item => item.i === c.id);
return l ? { ...c, pos_x: l.x, pos_y: l.y, width: l.w, height: l.h } : c;
}));
setCharts((cs) =>
cs.map((c) => {
const l = changed.find((item) => item.i === c.id);
return l ? { ...c, pos_x: l.x, pos_y: l.y, width: l.w, height: l.h } : c;
}),
);
if (layoutSaveTimer.current) clearTimeout(layoutSaveTimer.current);
layoutSaveTimer.current = setTimeout(() => {
changed.forEach(item =>
changed.forEach((item) =>
updateChart(item.i, { pos_x: item.x, pos_y: item.y, width: item.w, height: item.h }),
);
}, 500);
}
const layout: Layout = charts.map(c => ({
i: c.id, x: c.pos_x, y: c.pos_y, w: c.width, h: c.height,
const layout: Layout = charts.map((c) => ({
i: c.id,
x: c.pos_x,
y: c.pos_y,
w: c.width,
h: c.height,
minW: 1,
minH: c.chart_type === 'divider' ? 1 : 2,
}));
@@ -153,7 +177,8 @@ export default function Dashboard({ alerts }: Props) {
dragConfig={{ handle: '.drag-handle' }}
resizeConfig={{
handleComponent: (axis, ref) => (
<span ref={ref}
<span
ref={ref}
className="react-resizable-handle react-resizable-handle-se"
style={{
borderRight: '3px solid #4b5563',
@@ -164,16 +189,18 @@ export default function Dashboard({ alerts }: Props) {
),
}}
>
{charts.map(c => (
{charts.map((c) => (
<div key={c.id} className="drag-handle cursor-grab active:cursor-grabbing">
<ChartCard
config={c}
rows={signalData.get(c.id) ?? []}
upsRows={upsData.get(c.id) ?? []}
sessions={sessions}
alerts={alerts.filter(a =>
!c.filter_combinators || !a.combinator ||
c.filter_combinators.includes(a.combinator),
alerts={alerts.filter(
(a) =>
!c.filter_combinators ||
!a.combinator ||
c.filter_combinators.includes(a.combinator),
)}
timeMode={timeMode}
onEdit={() => setEditingChart(c)}
@@ -196,10 +223,10 @@ export default function Dashboard({ alerts }: Props) {
{editingChart && (
<ChartEditor
initial={editingChart}
onSave={draft => handleUpdate(editingChart.id, draft)}
onSave={(draft) => handleUpdate(editingChart.id, draft)}
onClose={() => setEditingChart(null)}
/>
)}
</div>
);
}
}