avocet/web/src/views/NodeManagementView.vue

93 lines
2.2 KiB
Vue

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import NodeCard from '../components/nodes/NodeCard.vue'
interface GpuEntry {
gpu_id: number
card: string
vram_total_mb: number
vram_used_mb: number
vram_free_mb: number
temp_c: number | null
utilization_pct: number | null
compute_cap: number | null
services_assigned: string[]
services_running: string[]
}
interface ServiceInfo {
min_compute_cap: number
max_mb: number
catalog_size: number
}
interface NodeSummary {
node_id: string
online: boolean
agent_url: string
gpus: GpuEntry[]
profile_loaded: boolean
services_catalog: Record<string, ServiceInfo>
}
const nodes = ref<NodeSummary[]>([])
const loading = ref(true)
const error = ref('')
async function fetchNodes() {
loading.value = true
error.value = ''
try {
const r = await fetch('/api/nodes-mgmt/nodes')
if (!r.ok) throw new Error(`HTTP ${r.status}`)
nodes.value = await r.json()
} catch (e) {
error.value = e instanceof Error ? e.message : 'Failed to load nodes'
} finally {
loading.value = false
}
}
onMounted(fetchNodes)
</script>
<template>
<main class="nodes-page">
<header class="nodes-header">
<h1>Nodes</h1>
<button class="btn-secondary" @click="fetchNodes" :disabled="loading">Refresh</button>
</header>
<div v-if="loading" class="nodes-status" aria-live="polite">Loading nodes...</div>
<div v-else-if="error" class="nodes-status nodes-error" role="alert">{{ error }}</div>
<div v-else-if="nodes.length === 0" class="nodes-status">
No nodes found. Check <code>coordinator_url</code> in config.
</div>
<div v-else class="nodes-grid">
<NodeCard
v-for="node in nodes"
:key="node.node_id"
:node="node"
@updated="fetchNodes"
/>
</div>
</main>
</template>
<style scoped>
.nodes-page { padding: 1.5rem; }
.nodes-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1.5rem;
}
.nodes-header h1 { margin: 0; font-size: 1.5rem; }
.nodes-grid { display: flex; flex-direction: column; gap: 1.5rem; }
.nodes-status {
color: var(--text-secondary, #888);
padding: 2rem;
text-align: center;
}
.nodes-error { color: var(--color-error, #fc8181); }
</style>