Pulse/frontend-modern/src/utils/localStorage.ts
rcourtman a15dc6b899 feat: Toggleable table columns with rich tooltips for Proxmox dashboard
Replace drawer-based info display with inline columns that can be toggled:
- Add IP, Uptime, Node, Backup, OS, Tags columns (user-toggleable)
- Add ColumnPicker dropdown to show/hide columns with localStorage persistence
- Columns auto-show based on screen width using priority system
- Remove GuestDrawer - all info now visible inline or via tooltips

Rich hover tooltips:
- Disk bar: Shows all mount points with usage %, color-coded by severity
- Memory bar: Shows used/free/balloon/swap breakdown
- IP column: Shows network icon + count, hover for interfaces, MACs, IPs, traffic

Also:
- Create useColumnVisibility hook for responsive column management
- Create ColumnPicker component for column toggle UI
- Update drawer layouts in Hosts/Docker tabs for consistency
2025-12-05 12:12:56 +00:00

116 lines
3.2 KiB
TypeScript

import { createSignal, createEffect, Signal } from 'solid-js';
/**
* Creates a signal that syncs with localStorage
* @param key - The localStorage key
* @param defaultValue - Default value if nothing in localStorage
* @param parse - Optional parser function for complex types
* @param stringify - Optional stringify function for complex types
*/
function createLocalStorageSignal<T>(
key: string,
defaultValue: T,
parse?: (value: string) => T,
stringify?: (value: T) => string,
): Signal<T> {
// Get initial value from localStorage
const stored = localStorage.getItem(key);
const initialValue =
stored !== null ? (parse ? parse(stored) : (stored as unknown as T)) : defaultValue;
const [value, setValue] = createSignal<T>(initialValue);
// Sync to localStorage on changes
createEffect(() => {
const val = value();
if (val === null || val === undefined) {
localStorage.removeItem(key);
} else {
localStorage.setItem(key, stringify ? stringify(val) : String(val));
}
});
return [value, setValue];
}
/**
* Creates a boolean signal that syncs with localStorage
* @param key - The localStorage key
* @param defaultValue - Default value if nothing in localStorage
*/
export function createLocalStorageBooleanSignal(
key: string,
defaultValue: boolean = false,
): Signal<boolean> {
return createLocalStorageSignal(
key,
defaultValue,
(val) => val === 'true',
(val) => String(val),
);
}
/**
* Creates a number signal that syncs with localStorage
* @param key - The localStorage key
* @param defaultValue - Default value if nothing in localStorage
*/
// Storage keys used throughout the application
export const STORAGE_KEYS = {
// Authentication
AUTH: 'pulse_auth',
LEGACY_TOKEN: 'pulse_api_token',
// UI preferences
DARK_MODE: 'darkMode',
SIDEBAR_COLLAPSED: 'sidebarCollapsed',
// Metadata
GUEST_METADATA: 'pulseGuestMetadata',
DOCKER_METADATA: 'pulseDockerMetadata',
// Platform tracking
PLATFORMS_SEEN: 'pulse-platforms-seen',
// Updates
UPDATES: 'pulse-updates',
// Alert settings
ALERT_HISTORY_TIME_FILTER: 'alertHistoryTimeFilter',
ALERT_HISTORY_SEVERITY_FILTER: 'alertHistorySeverityFilter',
// Storage settings
STORAGE_SHOW_FILTERS: 'storageShowFilters',
STORAGE_VIEW_MODE: 'storageViewMode',
// Backup settings
BACKUPS_SHOW_FILTERS: 'backupsShowFilters',
BACKUPS_USE_RELATIVE_TIME: 'backupsUseRelativeTime',
BACKUPS_SEARCH_HISTORY: 'backupsSearchHistory',
// Dashboard settings
DASHBOARD_SHOW_FILTERS: 'dashboardShowFilters',
DASHBOARD_CARD_VIEW: 'dashboardCardView',
DASHBOARD_AUTO_REFRESH: 'dashboardAutoRefresh',
DASHBOARD_SEARCH_HISTORY: 'dashboardSearchHistory',
// Storage search
STORAGE_SEARCH_HISTORY: 'storageSearchHistory',
// Docker search
DOCKER_SEARCH_HISTORY: 'dockerSearchHistory',
// Hosts search
HOSTS_SEARCH_HISTORY: 'hostsSearchHistory',
// Alerts search
ALERTS_SEARCH_HISTORY: 'alertsSearchHistory',
// Metrics display
METRICS_VIEW_MODE: 'metricsViewMode', // 'bars' | 'sparklines'
// Column visibility
DASHBOARD_HIDDEN_COLUMNS: 'dashboardHiddenColumns',
HOSTS_HIDDEN_COLUMNS: 'hostsHiddenColumns',
DOCKER_HIDDEN_COLUMNS: 'dockerHiddenColumns',
} as const;