feat(dashboard): add revision-safe interactive widget grid

This commit is contained in:
cesnimda
2026-10-28 15:32:47 +01:00
parent aea7c29e70
commit 0bd290e788
21 changed files with 696 additions and 108 deletions
@@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef, useState, type Dispatch, type SetStateA
import { api } from '../api';
import { AUTH_USER_CHANGED_EVENT, getAuthUserKey } from '../auth';
import { getUserKeyFromToken } from '../themePrefs';
import { defaultDashboardLayout, normalizeDashboardLayout, type DashboardLayout } from '../dashboardLayout';
import { arrangeDashboardWidgets, defaultDashboardLayout, normalizeDashboardLayout, type DashboardLayout } from '../dashboardLayout';
type LayoutError = 'request' | 'unsupportedVersion' | null;
type LayoutState = {
@@ -16,8 +16,8 @@ function initialState(owner: string, loading: boolean): LayoutState {
}
function readLayout(input: unknown): DashboardLayout {
const value = input as Partial<DashboardLayout> | null;
if (value && value.version !== 1) throw new Error('unsupportedVersion');
const value = input as { version?: unknown; revision?: unknown; widgets?: unknown } | null;
if (value && value.version !== 1 && value.version !== 2) throw new Error('unsupportedVersion');
if (!value || !Number.isSafeInteger(value.revision) || (value.revision as number) < 0 || !Array.isArray(value.widgets)) throw new Error('request');
const layout = normalizeDashboardLayout(input);
if (layout.revision === 0 && layout.widgets.length && value.widgets.length === 0 && getUserKeyFromToken() !== 'anon') {
@@ -26,6 +26,7 @@ function readLayout(input: unknown): DashboardLayout {
for (const widget of layout.widgets) {
if (['cards', 'activity', 'funnel', 'companies', 'skills'].includes(widget.id) && typeof legacy?.[widget.id] === 'boolean') widget.visible = legacy[widget.id];
}
layout.widgets = arrangeDashboardWidgets(layout.widgets);
} catch { /* Corrupt or unavailable local preferences leave defaults intact. */ }
}
return layout;