Network devices: manage buttons where every other asset keeps them
Machines, PCs, printers and measuring tools all carry Print Label / Edit / Retire / Back to List in a page header. A network device had no header at all: Edit was tucked inside the hero title row, and Print Label and Delete sat in a bar at the very bottom of the page, past every card. Managing one meant looking somewhere different from every other asset type. They move to the standard header. The bottom bar is removed rather than left as a second copy, and the two delete handlers collapse into one - the route is a soft delete, so it is called Retire here as it is everywhere else, and the confirm says what is kept.
This commit is contained in:
@@ -1,5 +1,25 @@
|
||||
<template>
|
||||
<div class="detail-page" v-if="device">
|
||||
<!--
|
||||
The same page-header + header-actions block every other asset detail page
|
||||
uses. This page had no header at all: Edit was tucked inside the hero
|
||||
title row and there was no Print Label, no Retire and no way back to the
|
||||
list, so managing a network device meant looking somewhere different from
|
||||
every other asset type.
|
||||
-->
|
||||
<div class="page-header">
|
||||
<h2>Network Device Details</h2>
|
||||
<div class="header-actions">
|
||||
<router-link :to="`/print/asset-label/network_device/${deviceId}`"
|
||||
class="btn btn-secondary" target="_blank">Print Label</router-link>
|
||||
<router-link v-if="authStore.isAuthenticated" :to="`/network/${deviceId}/edit`"
|
||||
class="btn btn-primary">Edit</router-link>
|
||||
<button v-if="authStore.isAuthenticated" @click="confirmRetire"
|
||||
class="btn btn-danger">Retire</button>
|
||||
<router-link to="/network" class="btn btn-secondary">Back to List</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hero-card">
|
||||
<div class="hero-image">
|
||||
<img v-if="device.networkdevice?.imageurl" :src="withBase(device.networkdevice.imageurl)" alt="Model photo" />
|
||||
@@ -10,13 +30,6 @@
|
||||
<div class="hero-content">
|
||||
<div class="hero-title-row">
|
||||
<h1 class="hero-title">{{ device.networkdevice?.hostname || device.name || device.assetnumber }}</h1>
|
||||
<router-link
|
||||
v-if="authStore.isAuthenticated"
|
||||
:to="`/network/${deviceId}/edit`"
|
||||
class="btn btn-secondary"
|
||||
>
|
||||
Edit
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="hero-meta">
|
||||
<span class="badge" :style="colorStyle(device.statuscolor)">
|
||||
@@ -184,18 +197,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="action-bar" v-if="authStore.isAuthenticated">
|
||||
<router-link :to="`/print/asset-label/network_device/${deviceId}`" class="btn btn-secondary" target="_blank">
|
||||
Print Label
|
||||
</router-link>
|
||||
<router-link :to="`/network/${deviceId}/edit`" class="btn btn-primary">
|
||||
Edit Device
|
||||
</router-link>
|
||||
<button @click="confirmDelete" class="btn btn-danger">
|
||||
Delete Device
|
||||
</button>
|
||||
</div>
|
||||
<!-- The manage actions live in the page header, where every other asset
|
||||
detail page puts them. They used to sit down here instead, which is
|
||||
why finding them on a network device meant looking somewhere else. -->
|
||||
|
||||
<!-- Audit Footer -->
|
||||
<div class="audit-footer">
|
||||
@@ -228,6 +232,7 @@ import PluginAssetPanels from '@/components/PluginAssetPanels.vue'
|
||||
import { useWarrantyBadge } from '@/composables/warrantyBadge'
|
||||
import { useIdentifierFlags } from '@/composables/identifierSettings'
|
||||
import { useToast } from '@/composables/toast'
|
||||
import { apiError } from '@/utils/apiError'
|
||||
import { setRecordTitle } from '@/composables/pageTitle'
|
||||
const toast = useToast()
|
||||
|
||||
@@ -293,17 +298,24 @@ function formatDate(dateStr) {
|
||||
})
|
||||
}
|
||||
|
||||
async function confirmDelete() {
|
||||
if (confirm(`Are you sure you want to delete ${device.value.networkdevice?.hostname || device.value.assetnumber}?`)) {
|
||||
try {
|
||||
await networkApi.delete(deviceId)
|
||||
router.push('/network')
|
||||
} catch (error) {
|
||||
console.error('Error deleting device:', error)
|
||||
toast.error('Failed to delete device')
|
||||
}
|
||||
// Soft delete, like every other asset type: the record leaves the lists while
|
||||
// its history and relationships stay put, and it can be restored by setting
|
||||
// isactive back. Called Retire rather than Delete for exactly that reason.
|
||||
async function confirmRetire () {
|
||||
const label = device.value?.networkdevice?.hostname
|
||||
|| device.value?.name || device.value?.assetnumber || 'this device'
|
||||
if (!confirm(`Retire ${label}?\n\nIt will no longer appear in ShopDB. `
|
||||
+ `History and relationships are kept, and it can be restored.`)) return
|
||||
try {
|
||||
await networkApi.delete(deviceId)
|
||||
toast.success(`Retired ${label}`)
|
||||
router.push('/network')
|
||||
} catch (error) {
|
||||
console.error('Error retiring network device:', error)
|
||||
toast.error(apiError(error, 'Failed to retire network device'))
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user