Replaces the two flat "Network Devices" + "View Networks" nav entries with a single "Network" entry opening a tabbed hub: Devices | Networks | VLANs (NetworkHub renders the existing device list, the subnet browse, and the VLAN list; VLANs is now reachable outside Settings). /network -> hub; /networks redirects to the Networks tab; subnet detail stays at /networks/:id. Subnet "Devices on this network" now matches ANY asset whose primary IP falls in the CIDR (PCs, printers, machines, measuring tools - not just network devices), computed on the core Communication + Asset tables; each row links to its typed detail (extension id resolved lazily/guarded per plugin). Fixes the empty list - printers and PCs carry IPs and now appear (e.g. 35 devices on 10.80.92.0/24). Also: subnet-browse search uses the standard form-control styling; dropped the redundant per-tab page header. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
89 lines
3.3 KiB
Vue
89 lines
3.3 KiB
Vue
<template>
|
|
<div class="detail-page">
|
|
<div v-if="loading" class="loading">Loading...</div>
|
|
<div v-else-if="!subnet" class="empty-state"><p>Network not found.</p></div>
|
|
<template v-else>
|
|
<div class="page-header">
|
|
<h1>{{ subnet.name || subnet.cidr }}</h1>
|
|
<router-link to="/networks" class="btn btn-secondary">Back to Networks</router-link>
|
|
</div>
|
|
|
|
<div class="content-grid">
|
|
<div class="content-column">
|
|
<div class="section-card">
|
|
<h3 class="section-title">Network</h3>
|
|
<div class="info-list">
|
|
<div class="info-row"><span class="info-label">CIDR</span><span class="info-value mono">{{ subnet.cidr }}</span></div>
|
|
<div class="info-row"><span class="info-label">Network Address</span><span class="info-value mono">{{ subnet.networkaddress || '-' }}</span></div>
|
|
<div class="info-row"><span class="info-label">Type</span><span class="info-value">{{ subnet.subnettype || '-' }}</span></div>
|
|
<div class="info-row"><span class="info-label">VLAN</span><span class="info-value">{{ subnet.vlannumber || subnet.vlanid || '-' }}</span></div>
|
|
<div class="info-row" v-if="subnet.gatewayip"><span class="info-label">Gateway</span><span class="info-value mono">{{ subnet.gatewayip }}</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section-card" v-if="subnet.description">
|
|
<h3 class="section-title">Notes</h3>
|
|
<div class="notes-content">{{ subnet.description }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="content-column">
|
|
<div class="section-card">
|
|
<h3 class="section-title">Devices on this network ({{ devices.length }})</h3>
|
|
<div v-if="devices.length === 0" class="empty-state"><p>No devices found in this range.</p></div>
|
|
<div v-else class="table-container">
|
|
<table>
|
|
<thead>
|
|
<tr><th>Device</th><th>IP</th><th>Type</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="dev in devices" :key="dev.assetid">
|
|
<td>
|
|
<router-link v-if="dev.url" :to="dev.url">{{ dev.name || dev.assetnumber }}</router-link>
|
|
<span v-else>{{ dev.name || dev.assetnumber }}</span>
|
|
</td>
|
|
<td class="mono">{{ dev.ipaddress }}</td>
|
|
<td>{{ typeLabel(dev.assettype) }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed, onMounted } from 'vue'
|
|
import { useRoute } from 'vue-router'
|
|
import { networkApi } from '@/api'
|
|
|
|
const route = useRoute()
|
|
const subnet = ref(null)
|
|
const loading = ref(true)
|
|
|
|
const devices = computed(() => subnet.value?.devices || [])
|
|
|
|
const TYPE_LABELS = {
|
|
computer: 'PC', network_device: 'Network Device', printer: 'Printer',
|
|
machine: 'Machine', measuring_tool: 'Measuring Tool',
|
|
}
|
|
function typeLabel(type) {
|
|
return TYPE_LABELS[type] || type || '-'
|
|
}
|
|
|
|
async function load() {
|
|
loading.value = true
|
|
try {
|
|
const response = await networkApi.subnets.get(route.params.id)
|
|
subnet.value = response.data?.data || response.data
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
onMounted(load)
|
|
</script>
|