Files
shopdb-flask/frontend/src/views/network/SubnetsBrowse.vue
cproudlock 8528617037
Some checks failed
CI / backend (push) Successful in 1m39s
CI / naming (push) Successful in 1s
CI / frontend (push) Successful in 8s
CI / migrations-mysql (push) Failing after 8s
Network: consolidate into one tabbed hub; subnet devices span all asset types
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>
2026-07-13 14:15:51 -04:00

76 lines
2.3 KiB
Vue

<template>
<div>
<div class="filters">
<input v-model="search" type="text" placeholder="Search networks..." class="form-control" />
</div>
<div class="card">
<div v-if="loading" class="loading">Loading...</div>
<div v-else-if="filtered.length === 0" class="empty-state"><p>No networks found.</p></div>
<div v-else class="table-container">
<table>
<thead>
<tr>
<th>Name</th>
<th>CIDR</th>
<th>Type</th>
<th>VLAN</th>
<th>Notes</th>
<th class="actions"></th>
</tr>
</thead>
<tbody>
<tr v-for="subnet in filtered" :key="subnet.subnetid" class="clickable-row"
@click="$router.push(`/networks/${subnet.subnetid}`)">
<td>{{ subnet.name || '-' }}</td>
<td class="mono">{{ subnet.cidr }}</td>
<td>{{ subnet.subnettype || '-' }}</td>
<td>{{ subnet.vlannumber || subnet.vlanid || '-' }}</td>
<td class="cell-truncate" :title="subnet.description">{{ subnet.description || '-' }}</td>
<td class="actions">
<router-link :to="`/networks/${subnet.subnetid}`" class="btn btn-sm btn-secondary" @click.stop>View</router-link>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { networkApi } from '@/api'
const subnets = ref([])
const loading = ref(true)
const search = ref('')
const filtered = computed(() => {
const term = search.value.trim().toLowerCase()
if (!term) return subnets.value
return subnets.value.filter(s =>
(s.name || '').toLowerCase().includes(term) ||
(s.cidr || '').toLowerCase().includes(term) ||
(s.subnettype || '').toLowerCase().includes(term) ||
(s.description || '').toLowerCase().includes(term))
})
async function load() {
loading.value = true
try {
const response = await networkApi.subnets.list({ per_page: 1000 })
subnets.value = response.data?.data || response.data || []
} finally {
loading.value = false
}
}
onMounted(load)
</script>
<style scoped>
.clickable-row { cursor: pointer; }
.clickable-row:hover { background: var(--bg); }
</style>