This commit includes comprehensive codebase cleanup and refactoring: ## Code Cleanup - Remove dead TypeScript code (types/monitoring.ts - 194 lines duplicate) - Remove unused Go functions (GetClusterNodes, MigratePassword, GetClusterHealthInfo) - Clean up commented-out code blocks across multiple files - Remove unused TypeScript exports (helpTextClass, private tag color helpers) - Delete obsolete test files and components ## localStorage Consolidation - Centralize all storage keys into STORAGE_KEYS constant - Update 5 files to use centralized keys: * utils/apiClient.ts (AUTH, LEGACY_TOKEN) * components/Dashboard/Dashboard.tsx (GUEST_METADATA) * components/Docker/DockerHosts.tsx (DOCKER_METADATA) * App.tsx (PLATFORMS_SEEN) * stores/updates.ts (UPDATES) - Benefits: Single source of truth, prevents typos, better maintainability ## Previous Work Committed - Docker monitoring improvements and disk metrics - Security enhancements and setup fixes - API refactoring and cleanup - Documentation updates - Build system improvements ## Testing - All frontend tests pass (29 tests) - All Go tests pass (15 packages) - Production build successful - Zero breaking changes Total: 186 files changed, 5825 insertions(+), 11602 deletions(-)
67 lines
2 KiB
TypeScript
67 lines
2 KiB
TypeScript
import type { Component } from 'solid-js';
|
|
import { For } from 'solid-js';
|
|
import Server from 'lucide-solid/icons/server';
|
|
import HardDrive from 'lucide-solid/icons/hard-drive';
|
|
import Mail from 'lucide-solid/icons/mail';
|
|
|
|
type SettingsSection = 'pve' | 'pbs' | 'pmg';
|
|
|
|
interface SettingsSectionNavProps {
|
|
current: SettingsSection;
|
|
onSelect: (section: SettingsSection) => void;
|
|
class?: string;
|
|
}
|
|
|
|
const allSections: Array<{
|
|
id: SettingsSection;
|
|
label: string;
|
|
icon: typeof Server;
|
|
}> = [
|
|
{
|
|
id: 'pve',
|
|
label: 'Virtual Environment',
|
|
icon: Server,
|
|
},
|
|
{
|
|
id: 'pbs',
|
|
label: 'Backup Server',
|
|
icon: HardDrive,
|
|
},
|
|
{
|
|
id: 'pmg',
|
|
label: 'Mail Gateway',
|
|
icon: Mail,
|
|
},
|
|
];
|
|
|
|
export const SettingsSectionNav: Component<SettingsSectionNavProps> = (props) => {
|
|
const baseClasses =
|
|
'inline-flex items-center gap-2 px-2 sm:px-3 py-1 text-xs sm:text-sm font-medium border-b-2 border-transparent text-gray-600 dark:text-gray-400 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400/60 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-gray-900';
|
|
|
|
return (
|
|
<div class={`flex flex-wrap items-center gap-3 sm:gap-4 ${props.class ?? ''}`} aria-label="Settings sections">
|
|
<For each={allSections}>
|
|
{(section) => {
|
|
const isActive = section.id === props.current;
|
|
const classes = isActive
|
|
? `${baseClasses} text-blue-600 dark:text-blue-300 border-blue-500 dark:border-blue-400`
|
|
: `${baseClasses} hover:text-blue-500 dark:hover:text-blue-300 hover:border-blue-300/70 dark:hover:border-blue-500/50`;
|
|
|
|
const Icon = section.icon;
|
|
|
|
return (
|
|
<button
|
|
type="button"
|
|
class={classes}
|
|
onClick={() => props.onSelect(section.id)}
|
|
aria-pressed={isActive}
|
|
>
|
|
<Icon size={16} stroke-width={2} />
|
|
<span>{section.label}</span>
|
|
</button>
|
|
);
|
|
}}
|
|
</For>
|
|
</div>
|
|
);
|
|
};
|