diff --git a/frontend-modern/src/components/Dashboard/Dashboard.tsx b/frontend-modern/src/components/Dashboard/Dashboard.tsx index 2c7dd1cf3..02aad88ca 100644 --- a/frontend-modern/src/components/Dashboard/Dashboard.tsx +++ b/frontend-modern/src/components/Dashboard/Dashboard.tsx @@ -1,4 +1,4 @@ -import { createSignal, createMemo, createEffect, For, Show } from 'solid-js'; +import { createSignal, createMemo, createEffect, For, Show, onMount } from 'solid-js'; import type { VM, Container, Node } from '@/types/api'; import { GuestRow } from './GuestRow'; import { useWebSocket } from '@/App'; @@ -11,6 +11,8 @@ import { UnifiedNodeSelector } from '@/components/shared/UnifiedNodeSelector'; import { MetricBar } from './MetricBar'; import { formatBytes, formatUptime } from '@/utils/format'; import { DashboardFilter } from './DashboardFilter'; +import { GuestMetadataAPI } from '@/api/guestMetadata'; +import type { GuestMetadata } from '@/api/guestMetadata'; interface DashboardProps { vms: VM[]; @@ -28,6 +30,7 @@ export function Dashboard(props: DashboardProps) { const [search, setSearch] = createSignal(''); const [isSearchLocked, setIsSearchLocked] = createSignal(false); const [selectedNode, setSelectedNode] = createSignal(null); + const [guestMetadata, setGuestMetadata] = createSignal>({}); // Initialize from localStorage with proper type checking const storedViewMode = localStorage.getItem('dashboardViewMode'); @@ -78,6 +81,17 @@ export function Dashboard(props: DashboardProps) { // Create tooltip system const TooltipComponent = createTooltipSystem(); + // Load all guest metadata on mount (single API call for all guests) + onMount(async () => { + try { + const metadata = await GuestMetadataAPI.getAllMetadata(); + setGuestMetadata(metadata || {}); + } catch (err) { + // Silently fail - metadata is optional for display + console.debug('Failed to load guest metadata:', err); + } + }); + // Create a mapping from node name to host URL @@ -780,10 +794,12 @@ export function Dashboard(props: DashboardProps) { {(() => { const guestId = guest.id || `${guest.instance}-${guest.name}-${guest.vmid}`; + const metadata = guestMetadata()[guestId] || guestMetadata()[`${guest.node}-${guest.vmid}`]; return ( diff --git a/frontend-modern/src/components/Dashboard/GuestRow.tsx b/frontend-modern/src/components/Dashboard/GuestRow.tsx index 289f63b8d..54b81f250 100644 --- a/frontend-modern/src/components/Dashboard/GuestRow.tsx +++ b/frontend-modern/src/components/Dashboard/GuestRow.tsx @@ -1,10 +1,9 @@ -import { Show, createMemo, createSignal, createEffect, onMount } from 'solid-js'; +import { Show, createMemo, createSignal, createEffect } from 'solid-js'; import type { VM, Container } from '@/types/api'; import { formatBytes, formatUptime } from '@/utils/format'; import { MetricBar } from './MetricBar'; import { IOMetric } from './IOMetric'; import { TagBadges } from './TagBadges'; -import { GuestMetadataAPI } from '@/api/guestMetadata'; type Guest = VM | Container; @@ -39,24 +38,7 @@ export function GuestRow(props: GuestRowProps) { // Update custom URL when prop changes createEffect(() => { - if (props.customUrl !== undefined) { - setCustomUrl(props.customUrl); - } - }); - - // Load custom URL from backend if not provided via props - onMount(async () => { - if (!props.customUrl) { - try { - const metadata = await GuestMetadataAPI.getMetadata(guestId()); - if (metadata && metadata.customUrl) { - setCustomUrl(metadata.customUrl); - } - } catch (err) { - // Silently fail - not critical for display - console.debug('Failed to load guest metadata:', err); - } - } + setCustomUrl(props.customUrl); }); const cpuPercent = createMemo(() => (props.guest.cpu || 0) * 100); diff --git a/frontend-modern/vite.config.dev.ts b/frontend-modern/vite.config.dev.ts deleted file mode 100644 index f697aeb4b..000000000 --- a/frontend-modern/vite.config.dev.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { defineConfig } from 'vite'; -import solid from 'vite-plugin-solid'; -import path from 'path'; - -export default defineConfig({ - plugins: [solid()], - resolve: { - alias: { - '@': path.resolve(__dirname, './src'), - }, - }, - server: { - port: 7655, - host: '0.0.0.0', - strictPort: true, // FAIL if port 7655 is not available - proxy: { - '/api': { - target: 'http://127.0.0.1:7656', - changeOrigin: true, - }, - '/ws': { - target: 'ws://127.0.0.1:7656', - ws: true, - changeOrigin: true, - }, - }, - }, - build: { - target: 'esnext', - }, -});