Fix 21 bugs: build failures, broken pages, IPC mismatches, and missing error handling

Critical fixes:
- Add esbuild dependency and fix Vite build target (safari13 → es2022)
- Fix StorageDetail always failing (null node parameter)
- Fix VNC/Terminal console stuck on 'Connecting...' (add onConnected callback)
- Fix Ctrl+Alt+Del not working (add data-vnc attribute and event listener)
- Add serde(rename_all='camelCase') to all 27 Rust structs crossing IPC
- Fix login methods returning empty connection_id (generate from URL hash)
- Fix add_connection not storing connections in HashMap
- Fix keyring_entry panicking on failure (replace expect with map_err)

High-severity fixes:
- Fix refresh_ticket reading wrong keyring entry for username
- Add onError handlers to all 23 mutations (toast notifications)
- Fix stale closure on activeConnectionId (use getState() instead)
- Fix WebSocket listener teardown race condition
- Add WebSocket reconnection retry limit (max 10 attempts)

Medium-severity fixes:
- Add Settings navigation to CommandPalette (Cmd+K)
- Disable dead Nodes/Containers sidebar items
- Wire up HardwareTab save button with warning toast
- Wire up QuickActions navigation buttons
- Add Dashboard error state (was stuck on 'Loading...')
- Add default case to App.tsx view switch
- Extract formatBytes/formatUptime/formatNetworkRate to shared utility
- Fix formatBytes negative input bug

32 files changed, 1073 insertions(+), 356 deletions(-)
This commit is contained in:
Matt
2026-07-29 19:35:37 +00:00
parent 535ba5e189
commit 9ad7fc85bd
32 changed files with 1080 additions and 363 deletions
+7 -1
View File
@@ -5,9 +5,10 @@ import { RefreshCw, Server, Box, HardDrive, ListTodo, Shield } from 'lucide-reac
interface QuickActionsProps {
onRefresh: () => void
isRefreshing: boolean
onNavigate?: (view: string) => void
}
export function QuickActions({ onRefresh, isRefreshing }: QuickActionsProps) {
export function QuickActions({ onRefresh, isRefreshing, onNavigate }: QuickActionsProps) {
return (
<Card>
<CardHeader>
@@ -27,6 +28,7 @@ export function QuickActions({ onRefresh, isRefreshing }: QuickActionsProps) {
<Button
variant="outline"
className="flex flex-col items-center gap-1.5 h-auto py-3"
onClick={() => onNavigate?.('dashboard')}
>
<Server className="h-4 w-4" />
<span className="text-xs">Nodes</span>
@@ -34,6 +36,7 @@ export function QuickActions({ onRefresh, isRefreshing }: QuickActionsProps) {
<Button
variant="outline"
className="flex flex-col items-center gap-1.5 h-auto py-3"
onClick={() => onNavigate?.('vms')}
>
<Box className="h-4 w-4" />
<span className="text-xs">VMs</span>
@@ -41,6 +44,7 @@ export function QuickActions({ onRefresh, isRefreshing }: QuickActionsProps) {
<Button
variant="outline"
className="flex flex-col items-center gap-1.5 h-auto py-3"
onClick={() => onNavigate?.('storage')}
>
<HardDrive className="h-4 w-4" />
<span className="text-xs">Storage</span>
@@ -48,6 +52,7 @@ export function QuickActions({ onRefresh, isRefreshing }: QuickActionsProps) {
<Button
variant="outline"
className="flex flex-col items-center gap-1.5 h-auto py-3"
onClick={() => onNavigate?.('tasks')}
>
<ListTodo className="h-4 w-4" />
<span className="text-xs">Tasks</span>
@@ -55,6 +60,7 @@ export function QuickActions({ onRefresh, isRefreshing }: QuickActionsProps) {
<Button
variant="outline"
className="flex flex-col items-center gap-1.5 h-auto py-3"
onClick={() => onNavigate?.('backups')}
>
<Shield className="h-4 w-4" />
<span className="text-xs">Backups</span>