Frontend naming + CSS-variable cleanups (review low)
Some checks failed
CI / backend (push) Has been cancelled
CI / naming (push) Has been cancelled
CI / frontend (push) Has been cancelled

Naming convention (LOCKED): rename the ManifestEditor simulate state sim ->
simulateInputs / simResult -> simulateResult (+ .sim-result CSS class) - 'sim'
was banned standalone shorthand. Rename AssetRelationships props assetId ->
assetid and machineNumber -> machinenumber so a prop holding a DB field value
mirrors it verbatim; updated the five detail-page call sites (:assetid=).

CSS variables: SearchResults per-domain badge palette moved into CSS variables
on the container; the duplicated prefers-color-scheme dark block collapses to a
single set of variable overrides instead of restating all ten selectors.

frontend build green; vitest 49 pass; naming green; search badges + detail
relationships verified rendering with no console errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-07-13 08:48:50 -04:00
parent b99da362b5
commit cd02cd20f4
8 changed files with 64 additions and 125 deletions

View File

@@ -196,12 +196,12 @@ import { apiError } from '../utils/apiError'
const toast = useToast()
const props = defineProps({
assetId: {
assetid: {
type: Number,
default: null
},
// Alternative: lookup by machine/asset number
machineNumber: {
machinenumber: {
type: String,
default: null
}
@@ -315,14 +315,14 @@ onMounted(async () => {
}
})
watch(() => props.assetId, async () => {
watch(() => props.assetid, async () => {
await resolveAssetId()
if (resolvedAssetId.value) {
await loadRelationships()
}
})
watch(() => props.machineNumber, async () => {
watch(() => props.machinenumber, async () => {
await resolveAssetId()
if (resolvedAssetId.value) {
await loadRelationships()
@@ -330,17 +330,17 @@ watch(() => props.machineNumber, async () => {
})
async function resolveAssetId() {
// If assetId is provided directly, use it
if (props.assetId) {
resolvedAssetId.value = props.assetId
// If assetid is provided directly, use it
if (props.assetid) {
resolvedAssetId.value = props.assetid
lookupFailed.value = false
return
}
// Otherwise, try to look up by machine number
if (props.machineNumber) {
if (props.machinenumber) {
try {
const response = await assetsApi.lookup(props.machineNumber)
const response = await assetsApi.lookup(props.machinenumber)
resolvedAssetId.value = response.data.data?.assetid
lookupFailed.value = !resolvedAssetId.value
} catch (error) {

View File

@@ -1,5 +1,5 @@
<template>
<div>
<div class="search-results">
<div class="page-header">
<h2>Search Results</h2>
<span v-if="results.length" class="results-count">
@@ -385,56 +385,33 @@ watch(results, () => {
flex-shrink: 0;
}
.result-type.machine {
background: #e3f2fd;
color: #1565c0;
/* Per-domain badge palette. Values live in CSS variables on the container so
the dark theme overrides them in one place (below) instead of restating
every selector. Each badge rule just references its pair. */
.search-results {
--rt-machine-bg: #e3f2fd; --rt-machine-fg: #1565c0;
--rt-computer-bg: #e8f5e9; --rt-computer-fg: #2e7d32;
--rt-application-bg: #fff3e0; --rt-application-fg: #e65100;
--rt-knowledgebase-bg: #f3e5f5; --rt-knowledgebase-fg: #7b1fa2;
--rt-printer-bg: #fce4ec; --rt-printer-fg: #c2185b;
--rt-network-bg: #fff8e1; --rt-network-fg: #f57f17;
--rt-measuring-bg: #e0f7fa; --rt-measuring-fg: #00838f;
--rt-employee-bg: #e0f2f1; --rt-employee-fg: #00695c;
--rt-notification-bg: #e8eaf6; --rt-notification-fg: #283593;
--rt-subnet-bg: #fbe9e7; --rt-subnet-fg: #bf360c;
}
.result-type.machine { background: var(--rt-machine-bg); color: var(--rt-machine-fg); }
.result-type.pc,
.result-type.computer {
background: #e8f5e9;
color: #2e7d32;
}
.result-type.application {
background: #fff3e0;
color: #e65100;
}
.result-type.knowledgebase {
background: #f3e5f5;
color: #7b1fa2;
}
.result-type.printer {
background: #fce4ec;
color: #c2185b;
}
.result-type.network_device {
background: #fff8e1;
color: #f57f17;
}
.result-type.measuring_tool {
background: #e0f7fa;
color: #00838f;
}
.result-type.employee {
background: #e0f2f1;
color: #00695c;
}
.result-type.notification {
background: #e8eaf6;
color: #283593;
}
.result-type.subnet {
background: #fbe9e7;
color: #bf360c;
}
.result-type.computer { background: var(--rt-computer-bg); color: var(--rt-computer-fg); }
.result-type.application { background: var(--rt-application-bg); color: var(--rt-application-fg); }
.result-type.knowledgebase { background: var(--rt-knowledgebase-bg); color: var(--rt-knowledgebase-fg); }
.result-type.printer { background: var(--rt-printer-bg); color: var(--rt-printer-fg); }
.result-type.network_device { background: var(--rt-network-bg); color: var(--rt-network-fg); }
.result-type.measuring_tool { background: var(--rt-measuring-bg); color: var(--rt-measuring-fg); }
.result-type.employee { background: var(--rt-employee-bg); color: var(--rt-employee-fg); }
.result-type.notification { background: var(--rt-notification-bg); color: var(--rt-notification-fg); }
.result-type.subnet { background: var(--rt-subnet-bg); color: var(--rt-subnet-fg); }
.result-content {
flex: 1;
@@ -486,55 +463,17 @@ watch(results, () => {
}
@media (prefers-color-scheme: dark) {
.result-type.machine {
background: rgba(21, 101, 192, 0.2);
color: #64b5f6;
}
.result-type.pc,
.result-type.computer {
background: rgba(46, 125, 50, 0.2);
color: #81c784;
}
.result-type.application {
background: rgba(230, 81, 0, 0.2);
color: #ffb74d;
}
.result-type.knowledgebase {
background: rgba(123, 31, 162, 0.2);
color: #ce93d8;
}
.result-type.printer {
background: rgba(194, 24, 91, 0.2);
color: #f48fb1;
}
.result-type.network_device {
background: rgba(245, 127, 23, 0.2);
color: #ffd54f;
}
.result-type.measuring_tool {
background: rgba(0, 131, 143, 0.2);
color: #80deea;
}
.result-type.employee {
background: rgba(0, 105, 92, 0.2);
color: #80cbc4;
}
.result-type.notification {
background: rgba(40, 53, 147, 0.2);
color: #9fa8da;
}
.result-type.subnet {
background: rgba(191, 54, 12, 0.2);
color: #ffab91;
.search-results {
--rt-machine-bg: rgba(21, 101, 192, 0.2); --rt-machine-fg: #64b5f6;
--rt-computer-bg: rgba(46, 125, 50, 0.2); --rt-computer-fg: #81c784;
--rt-application-bg: rgba(230, 81, 0, 0.2); --rt-application-fg: #ffb74d;
--rt-knowledgebase-bg: rgba(123, 31, 162, 0.2); --rt-knowledgebase-fg: #ce93d8;
--rt-printer-bg: rgba(194, 24, 91, 0.2); --rt-printer-fg: #f48fb1;
--rt-network-bg: rgba(245, 127, 23, 0.2); --rt-network-fg: #ffd54f;
--rt-measuring-bg: rgba(0, 131, 143, 0.2); --rt-measuring-fg: #80deea;
--rt-employee-bg: rgba(0, 105, 92, 0.2); --rt-employee-fg: #80cbc4;
--rt-notification-bg: rgba(40, 53, 147, 0.2); --rt-notification-fg: #9fa8da;
--rt-subnet-bg: rgba(191, 54, 12, 0.2); --rt-subnet-fg: #ffab91;
}
}
</style>

View File

@@ -192,27 +192,27 @@
<h3 class="section-title">Simulate: what would a PC get?</h3>
<div class="settings-grid">
<div class="setting-row">
<label><span>Subtype</span><input v-model="sim.subtype" placeholder="subtype" /></label>
<label><span>Subtype</span><input v-model="simulateInputs.subtype" placeholder="subtype" /></label>
</div>
<div class="setting-row">
<label><span>Hostname</span><input v-model="sim.hostname" placeholder="hostname" /></label>
<label><span>Hostname</span><input v-model="simulateInputs.hostname" placeholder="hostname" /></label>
</div>
<div class="setting-row">
<label><span>Machine #</span><input v-model="sim.machinenumber" placeholder="machine #" /></label>
<label><span>Machine #</span><input v-model="simulateInputs.machinenumber" placeholder="machine #" /></label>
</div>
<div class="setting-row">
<label><span>CMM version</span><input v-model="sim.cmmversion" placeholder="CMM version" /></label>
<label><span>CMM version</span><input v-model="simulateInputs.cmmversion" placeholder="CMM version" /></label>
</div>
</div>
<button class="btn btn-primary" @click="runSimulate">Run</button>
<div v-if="simResult" class="sim-result">
<div v-if="simulateResult" class="simulate-result">
<div>
<strong>Applies ({{ simResult.applied.length }}):</strong>
{{ simResult.applied.join(', ') || 'none' }}
<strong>Applies ({{ simulateResult.applied.length }}):</strong>
{{ simulateResult.applied.join(', ') || 'none' }}
</div>
<div class="muted">
<strong>Filtered:</strong>
<span v-for="filtered in simResult.filtered" :key="filtered.name">
<span v-for="filtered in simulateResult.filtered" :key="filtered.name">
{{ filtered.name }} ({{ filtered.filteredby.join(',') }});
</span>
</div>
@@ -618,8 +618,8 @@ const versions = ref([])
const showPreview = ref(false)
const previewText = ref('')
const sim = ref({ subtype: '', hostname: '', machinenumber: '', cmmversion: '' })
const simResult = ref(null)
const simulateInputs = ref({ subtype: '', hostname: '', machinenumber: '', cmmversion: '' })
const simulateResult = ref(null)
const compliance = ref(null)
const complianceRows = computed(() => compliance.value?.rows || [])
@@ -655,7 +655,7 @@ async function exportShare() {
async function selectScope(id) {
selectedId.value = id
showVersions.value = false
simResult.value = null
simulateResult.value = null
compliance.value = null
try {
detail.value = payload(await api.get(`/geenforce/scopes/${id}`))
@@ -821,8 +821,8 @@ async function rollback(versionnumber) {
// -- simulate / preview --
async function runSimulate() {
try {
const params = { ...sim.value }
simResult.value = payload(await api.get(
const params = { ...simulateInputs.value }
simulateResult.value = payload(await api.get(
`/geenforce/scopes/${detail.value.scopeid}/simulate`, { params }))
} catch (e) { error.value = 'Simulate failed' }
}
@@ -929,7 +929,7 @@ loadApplications()
.muted { color: var(--text-light); }
/* Simulator result */
.sim-result {
.simulate-result {
margin-top: 1rem;
font-size: 0.9rem;
display: flex;

View File

@@ -208,7 +208,7 @@
<WarrantyPanel :assetid="machine.assetid" :items="warranties" />
<!-- All relationships (dualpath, controls, ...) -->
<AssetRelationships v-if="machine.assetid" :assetId="machine.assetid" />
<AssetRelationships v-if="machine.assetid" :assetid="machine.assetid" />
<!-- Notes -->
<div class="section-card" v-if="machine.notes">

View File

@@ -140,7 +140,7 @@
<WarrantyPanel :assetid="tool.assetid" :items="warranties" />
<!-- All relationships (partof, connectedto, ...) -->
<AssetRelationships v-if="tool.assetid" :assetId="tool.assetid" />
<AssetRelationships v-if="tool.assetid" :assetid="tool.assetid" />
<!-- Notes -->
<div class="section-card" v-if="tool.notes">

View File

@@ -154,7 +154,7 @@
<!-- Relationships -->
<AssetRelationships
v-if="device.assetid"
:assetId="device.assetid"
:assetid="device.assetid"
/>
<!-- Notes -->

View File

@@ -213,7 +213,7 @@
<WarrantyPanel :assetid="computer.assetid" :items="warranties" />
<!-- All relationships (controls, defaultprinter, ...) -->
<AssetRelationships v-if="computer.assetid" :assetId="computer.assetid" />
<AssetRelationships v-if="computer.assetid" :assetid="computer.assetid" />
<!-- Notes -->
<div class="section-card" v-if="computer.notes">

View File

@@ -179,7 +179,7 @@
<WarrantyPanel :assetid="printer.assetid" :items="warranties" />
<!-- All relationships (defaultprinter, connectedto, ...) -->
<AssetRelationships v-if="printer.assetid" :assetId="printer.assetid" />
<AssetRelationships v-if="printer.assetid" :assetid="printer.assetid" />
<!-- Notes -->
<div class="section-card" v-if="printer.notes">