warranty: show the machine a covered PC drives, with a map on hover

A shopfloor PC is bought, warranted and replaced as a PC, but it is FOUND by
the machine it drives - nobody walks the floor looking for an asset number. The
warranty tables listed the covered asset and left the reader to work out where
that is.

Both tables gain a Machine # column. The payload resolves it by walking the
asset relationship graph in BOTH directions: the canonical edge is
PC --controls--> machine, but a dual-bay pair carries controls on both bays and
hand-made links are not reliably oriented.

Hovering the chip shows the floor map with the machine marked, so the row
answers "where do I go" without opening anything. The blueprint follows the
viewer's theme and the marker is placed from mapx/mapy as a percentage of the
configured map dimensions, since the preview is a few hundred pixels wide
rather than the full plan. It renders only while hovered, so a long table does
not build a blueprint per row.

A machine with no map position still gets its chip and says so, rather than
being dropped: against real data 142 PCs resolve to a machine and 125 of those
are placed, so 17 rows would otherwise have silently lost their number.

The chip is deliberately not a link. /machines/:id is keyed by machineid, not
assetid, and resolving one to the other here would make the warranty plugin
import the machines plugin (ADR-014). Worth noting separately: the existing
assetLink() in these tables already sends machine-type assets to
/machines/<assetid>, which is that same mismatch and predates this change.
This commit is contained in:
cproudlock
2026-08-10 09:41:48 -04:00
parent c0a7655aab
commit 9e271b4c03
4 changed files with 186 additions and 1 deletions

View File

@@ -33,6 +33,7 @@
<th>Service Level</th>
<th>Ends</th>
<th>Covers</th>
<th>Machine #</th>
</tr>
</thead>
<tbody>
@@ -44,6 +45,12 @@
<router-link v-for="a in w.assets" :key="a.assetid" :to="assetLink(a)" class="asset-chip">{{ a.assetnumber }}</router-link>
<span v-if="!w.assets.length" class="muted">-</span>
</td>
<td>
<template v-for="a in w.assets" :key="`m-${a.assetid}`">
<MachineMapChip v-if="a.machine" :machine="a.machine" />
</template>
<span v-if="!w.assets.some(a => a.machine)" class="muted">-</span>
</td>
</tr>
</tbody>
</table>
@@ -58,6 +65,7 @@
import { ref, computed, onMounted } from 'vue'
import { warrantyApi } from '@/api'
import EmailReportButton from '@/components/EmailReportButton.vue'
import MachineMapChip from '../components/MachineMapChip.vue'
const loading = ref(true)
const counts = ref({})