widgettdc-api / apps /matrix-frontend /src /hooks /useDashboardPresets.ts
Kraft102's picture
fix: sql.js Docker/Alpine compatibility layer for PatternMemory and FailureMemory
5a81b95
import { useState, useEffect, useCallback } from 'react';
import { DashboardWidget } from '@/pages/Dashboard';
const PRESETS_STORAGE_KEY = 'cyber-dashboard-presets';
const ACTIVE_PRESET_KEY = 'cyber-dashboard-active-preset';
export interface DashboardPreset {
id: string;
name: string;
description?: string;
widgets: DashboardWidget[];
createdAt: number;
updatedAt: number;
isBuiltIn?: boolean;
}
// Built-in presets
const BUILT_IN_PRESETS: DashboardPreset[] = [
{
id: 'default',
name: 'Standard',
description: 'Grundlæggende dashboard layout',
widgets: [
{ id: '1', type: 'news', name: 'News Feed', icon: 'Rss', size: 'medium' },
{ id: '2', type: 'alerts', name: 'Active Alerts', icon: 'AlertTriangle', size: 'medium' },
{ id: '3', type: 'metrics', name: 'Threat Metrics', icon: 'TrendingUp', size: 'small' },
{ id: '4', type: 'radar', name: 'Threat Radar', icon: 'Radar', size: 'small' },
],
createdAt: 0,
updatedAt: 0,
isBuiltIn: true,
},
{
id: 'soc-analyst',
name: 'SOC Analyst',
description: 'Optimeret til sikkerhedsanalytikere',
widgets: [
{ id: '1', type: 'alerts', name: 'Active Alerts', icon: 'AlertTriangle', size: 'large' },
{ id: '2', type: 'events', name: 'Real-Time Events', icon: 'Zap', size: 'medium' },
{ id: '3', type: 'threatmap', name: 'Threat Map', icon: 'Map', size: 'medium' },
{ id: '4', type: 'statistics', name: 'Statistics', icon: 'BarChart3', size: 'small' },
{ id: '5', type: 'radar', name: 'Threat Radar', icon: 'Radar', size: 'small' },
],
createdAt: 0,
updatedAt: 0,
isBuiltIn: true,
},
{
id: 'executive',
name: 'Executive',
description: 'Overblik for ledelsen',
widgets: [
{ id: '1', type: 'metrics', name: 'Threat Metrics', icon: 'TrendingUp', size: 'large' },
{ id: '2', type: 'global', name: 'Global Threats', icon: 'Globe', size: 'medium' },
{ id: '3', type: 'statistics', name: 'Statistics', icon: 'BarChart3', size: 'medium' },
{ id: '4', type: 'trends', name: 'Trend Analysis', icon: 'LineChart', size: 'medium' },
],
createdAt: 0,
updatedAt: 0,
isBuiltIn: true,
},
{
id: 'minimal',
name: 'Minimal',
description: 'Kun det vigtigste',
widgets: [
{ id: '1', type: 'alerts', name: 'Active Alerts', icon: 'AlertTriangle', size: 'large' },
{ id: '2', type: 'metrics', name: 'Threat Metrics', icon: 'TrendingUp', size: 'medium' },
],
createdAt: 0,
updatedAt: 0,
isBuiltIn: true,
},
];
export function useDashboardPresets() {
const [presets, setPresets] = useState<DashboardPreset[]>([]);
const [activePresetId, setActivePresetId] = useState<string | null>(null);
// Load presets from localStorage
useEffect(() => {
const savedPresets = localStorage.getItem(PRESETS_STORAGE_KEY);
const savedActiveId = localStorage.getItem(ACTIVE_PRESET_KEY);
let userPresets: DashboardPreset[] = [];
if (savedPresets) {
try {
userPresets = JSON.parse(savedPresets);
} catch (e) {
console.error('Failed to load presets:', e);
}
}
// Combine built-in and user presets
setPresets([...BUILT_IN_PRESETS, ...userPresets]);
setActivePresetId(savedActiveId || null);
}, []);
// Save user presets to localStorage
const savePresets = useCallback((allPresets: DashboardPreset[]) => {
const userPresets = allPresets.filter(p => !p.isBuiltIn);
localStorage.setItem(PRESETS_STORAGE_KEY, JSON.stringify(userPresets));
setPresets(allPresets);
}, []);
const setActivePreset = useCallback((presetId: string | null) => {
setActivePresetId(presetId);
if (presetId) {
localStorage.setItem(ACTIVE_PRESET_KEY, presetId);
} else {
localStorage.removeItem(ACTIVE_PRESET_KEY);
}
}, []);
const createPreset = useCallback((name: string, widgets: DashboardWidget[], description?: string): DashboardPreset => {
const newPreset: DashboardPreset = {
id: `preset-${Date.now()}`,
name,
description,
widgets: widgets.map((w, i) => ({ ...w, id: `${w.type}-${i}` })),
createdAt: Date.now(),
updatedAt: Date.now(),
isBuiltIn: false,
};
const updatedPresets = [...presets, newPreset];
savePresets(updatedPresets);
return newPreset;
}, [presets, savePresets]);
const updatePreset = useCallback((presetId: string, widgets: DashboardWidget[], name?: string, description?: string) => {
const updatedPresets = presets.map(p => {
if (p.id === presetId && !p.isBuiltIn) {
return {
...p,
name: name ?? p.name,
description: description ?? p.description,
widgets: widgets.map((w, i) => ({ ...w, id: `${w.type}-${i}` })),
updatedAt: Date.now(),
};
}
return p;
});
savePresets(updatedPresets);
}, [presets, savePresets]);
const deletePreset = useCallback((presetId: string) => {
const preset = presets.find(p => p.id === presetId);
if (preset?.isBuiltIn) return false;
const updatedPresets = presets.filter(p => p.id !== presetId);
savePresets(updatedPresets);
if (activePresetId === presetId) {
setActivePreset(null);
}
return true;
}, [presets, activePresetId, savePresets, setActivePreset]);
const getPreset = useCallback((presetId: string): DashboardPreset | undefined => {
return presets.find(p => p.id === presetId);
}, [presets]);
const loadPreset = useCallback((presetId: string): DashboardWidget[] | null => {
const preset = getPreset(presetId);
if (!preset) return null;
setActivePreset(presetId);
// Return new widget instances with fresh IDs
return preset.widgets.map((w, i) => ({ ...w, id: `${w.type}-${Date.now()}-${i}` }));
}, [getPreset, setActivePreset]);
const activePreset = activePresetId ? getPreset(activePresetId) : null;
return {
presets,
activePreset,
activePresetId,
createPreset,
updatePreset,
deletePreset,
loadPreset,
getPreset,
setActivePreset,
};
}