Migrate frontend to plugin-based asset architecture

- Add equipmentApi and computersApi to replace legacy machinesApi
- Add controller vendor/model fields to Equipment model and forms
- Fix map marker navigation to use plugin-specific IDs (equipmentid,
  computerid, printerid, networkdeviceid) instead of assetid
- Fix search to use unified Asset table with correct plugin IDs
- Remove legacy printer search that used non-existent field names
- Enable optional JWT auth for detail endpoints (public read access)
- Clean up USB plugin models (remove unused checkout model)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-01-29 16:07:41 -05:00
parent c8b325d2e7
commit 180e6a0915
28 changed files with 4123 additions and 3454 deletions

View File

@@ -24,9 +24,9 @@
<table>
<thead>
<tr>
<th>Machine #</th>
<th>Alias</th>
<th>Hostname</th>
<th>Asset #</th>
<th>Name</th>
<th>Serial Number</th>
<th>Type</th>
<th>Status</th>
<th>Location</th>
@@ -34,27 +34,27 @@
</tr>
</thead>
<tbody>
<tr v-for="machine in machines" :key="machine.machineid">
<td>{{ machine.machinenumber }}</td>
<td>{{ machine.alias || '-' }}</td>
<td>{{ machine.hostname || '-' }}</td>
<td>{{ machine.machinetype }}</td>
<tr v-for="item in equipment" :key="item.assetid">
<td>{{ item.assetnumber }}</td>
<td>{{ item.name || '-' }}</td>
<td class="mono">{{ item.serialnumber || '-' }}</td>
<td>{{ item.equipment?.equipmenttype_name || '-' }}</td>
<td>
<span class="badge" :class="getStatusClass(machine.status)">
{{ machine.status || 'Unknown' }}
<span class="badge" :class="getStatusClass(item.status_name)">
{{ item.status_name || 'Unknown' }}
</span>
</td>
<td>{{ machine.location || '-' }}</td>
<td>{{ item.location_name || '-' }}</td>
<td class="actions">
<router-link
:to="`/machines/${machine.machineid}`"
:to="`/machines/${item.equipment?.equipmentid || item.assetid}`"
class="btn btn-secondary btn-sm"
>
View
</router-link>
</td>
</tr>
<tr v-if="machines.length === 0">
<tr v-if="equipment.length === 0">
<td colspan="7" style="text-align: center; color: var(--text-light);">
No equipment found
</td>
@@ -82,9 +82,9 @@
<script setup>
import { ref, onMounted } from 'vue'
import { machinesApi } from '../../api'
import { equipmentApi } from '../../api'
const machines = ref([])
const equipment = ref([])
const loading = ref(true)
const search = ref('')
const page = ref(1)
@@ -93,21 +93,20 @@ const totalPages = ref(1)
let searchTimeout = null
onMounted(() => {
loadMachines()
loadEquipment()
})
async function loadMachines() {
async function loadEquipment() {
loading.value = true
try {
const params = {
page: page.value,
perpage: 20,
category: 'Equipment'
per_page: 20
}
if (search.value) params.search = search.value
const response = await machinesApi.list(params)
machines.value = response.data.data || []
const response = await equipmentApi.list(params)
equipment.value = response.data.data || []
totalPages.value = response.data.meta?.pagination?.total_pages || 1
} catch (error) {
console.error('Error loading equipment:', error)
@@ -120,13 +119,13 @@ function debouncedSearch() {
clearTimeout(searchTimeout)
searchTimeout = setTimeout(() => {
page.value = 1
loadMachines()
loadEquipment()
}, 300)
}
function goToPage(p) {
page.value = p
loadMachines()
loadEquipment()
}
function getStatusClass(status) {
@@ -138,3 +137,9 @@ function getStatusClass(status) {
return 'badge-info'
}
</script>
<style scoped>
.mono {
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
}
</style>