feat: Winkeyer

This commit is contained in:
2026-06-02 01:17:26 +02:00
parent 2eb77370e4
commit 2b4326b553
26 changed files with 3125 additions and 645 deletions
+15 -11
View File
@@ -4,13 +4,14 @@ import {
type ColDef, type ColumnState, type GridReadyEvent, type RowClickedEvent,
} from 'ag-grid-community';
import { AgGridReact } from 'ag-grid-react';
import { Columns3 } from 'lucide-react';
import { Columns3, FilterX } from 'lucide-react';
import {
Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { cleanSpotter, inferSpotMode, spotStatusKey } from '@/lib/spot';
import { loadLocal, loadRemote, saveState, seedLocal } from '@/lib/gridPrefs';
ModuleRegistry.registerModules([AllCommunityModule]);
@@ -304,19 +305,18 @@ export function ClusterGrid({ rows, spotStatus, onSpotClick }: Props) {
const context = useMemo(() => ({ spotStatus }), [spotStatus]);
function onGridReady(e: GridReadyEvent) {
try {
const raw = localStorage.getItem(COL_STATE_KEY);
if (raw) {
const state = JSON.parse(raw) as ColumnState[];
if (Array.isArray(state)) e.api.applyColumnState({ state, applyOrder: true });
const local = loadLocal(COL_STATE_KEY);
if (local) e.api.applyColumnState({ state: local as ColumnState[], applyOrder: true });
loadRemote(COL_STATE_KEY).then((remote) => {
if (remote && !local) {
e.api.applyColumnState({ state: remote as ColumnState[], applyOrder: true });
seedLocal(COL_STATE_KEY, remote);
}
} catch {}
});
}
const saveColumnState = useCallback(() => {
try {
const state = gridRef.current?.api?.getColumnState();
if (state) localStorage.setItem(COL_STATE_KEY, JSON.stringify(state));
} catch {}
const state = gridRef.current?.api?.getColumnState();
if (state) saveState(COL_STATE_KEY, state);
}, []);
function handleRowClicked(e: RowClickedEvent<ClusterSpot>) {
@@ -360,6 +360,10 @@ export function ClusterGrid({ rows, spotStatus, onSpotClick }: Props) {
return (
<>
<div className="flex items-center justify-end gap-2 px-2.5 py-1 border-b border-border/60 bg-muted/20">
<Button variant="ghost" size="sm" className="h-7 text-[11px]" onClick={() => gridRef.current?.api?.setFilterModel(null)}
title="Clear all column filters">
<FilterX className="size-3.5" /> Clear filters
</Button>
<Button variant="ghost" size="sm" className="h-7 text-[11px]" onClick={() => setPickerOpen(true)}>
<Columns3 className="size-3.5" /> Columns
</Button>