Remediate the 2026-09-03 feature-test findings

This commit is contained in:
2026-09-03 17:15:03 -04:00
parent cf95daf3bb
commit fd513c08eb
112 changed files with 5182 additions and 857 deletions

View File

@@ -9,11 +9,21 @@
<router-link :to="`/measuringtools/${tool?.measuringtool?.measuringtoolid}/edit`" class="btn btn-primary" v-if="tool">
Edit
</router-link>
<button @click="confirmRetire" class="btn btn-danger" v-if="tool">Retire</button>
<button v-if="tool && !isRetired" @click="confirmRetire" class="btn btn-danger">Retire</button>
<!-- A retired record offered Edit and Retire exactly like a live
one, and nothing said it was retired. Restoring it was possible
through the API and nowhere in the product. -->
<button v-if="tool && isRetired" @click="restore" class="btn btn-primary">Restore</button>
<router-link to="/measuringtools" class="btn btn-secondary">Back to List</router-link>
</div>
</div>
<div v-if="tool && tool.isactive === false" class="retired-banner card">
<strong>This measuring tool is retired.</strong>
It stays out of every list and report, and its history and relationships
are intact. Restore puts it back.
</div>
<div v-if="loading" class="loading">Loading...</div>
<template v-else-if="tool">
@@ -181,7 +191,7 @@
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { ref, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { colorStyle } from '@/utils/colorStyle'
import { measuringtoolsApi } from '@/api'
@@ -227,6 +237,21 @@ onMounted(async () => {
// Retire, not delete: the server deactivates the asset, so the measuring tool
// leaves every list and report while its history and relationships stay put.
// Reversible by an admin setting isactive back to true.
const isRetired = computed(() => tool.value?.isactive === false)
async function restore() {
const label = tool.value?.assetnumber || tool.value?.name || 'this tool'
try {
await measuringtoolsApi.update(route.params.id, { isactive: true })
toast.success(`Restored ${label}`)
const response = await measuringtoolsApi.get(route.params.id)
tool.value = response.data.data
} catch (error) {
console.error('Error restoring:', error)
toast.error(apiError(error, 'Failed to restore'))
}
}
async function confirmRetire() {
const label = tool.value?.assetnumber || tool.value?.name || 'this measuring tool'
if (!confirm(`Retire ${label}?\n\nIt will no longer appear in ShopDB. `
@@ -243,6 +268,10 @@ async function confirmRetire() {
</script>
<style scoped>
.retired-banner {
border-left: 3px solid var(--warning);
margin-bottom: 1rem;
}
.mono {
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
}

View File

@@ -179,10 +179,10 @@ const businessunits = ref([])
onMounted(async () => {
try {
const [typesResponse, statusResponse, locResponse, buResponse, assetTypesResponse] = await Promise.all([
measuringtoolsApi.types.list({ perpage: 200 }),
measuringtoolsApi.types.list({ perpage: 100 }),
assetsApi.statuses.list(),
locationsApi.listAll(), // backend caps perpage at 100; page through all
businessunitsApi.list({ perpage: 500 }),
businessunitsApi.listAll(),
assetsApi.types.list(),
])
types.value = typesResponse.data.data || []

View File

@@ -107,7 +107,7 @@ onMounted(() => loadData())
async function loadData() {
loading.value = true
try {
const response = await measuringtoolsApi.types.list({ perpage: 200, active: false })
const response = await measuringtoolsApi.types.list({ perpage: 100, active: false })
types.value = response.data.data || []
} catch (err) {
console.error('Error loading measuring tool types:', err)

View File

@@ -28,7 +28,14 @@
<option value="current">Current</option>
<option value="unknown">Unknown</option>
</select>
</div>
<!-- Retire is a soft delete and the confirm dialog promises the record
"can be restored". The API kept that promise (?active=false lists
them, PUT isactive restores); nothing in the UI could reach it. -->
<label class="checkbox-label">
<input type="checkbox" v-model="showRetired" @change="loadTools" />
Show retired
</label>
</div>
<div class="card">
<div v-if="loading" class="loading">Loading...</div>
@@ -115,6 +122,7 @@ function applySuggestion(word) {
}
const typeid = ref('')
const calibrationstatus = ref('')
const showRetired = ref(false)
const totalPages = ref(1)
const perPage = ref(20)
@@ -126,7 +134,7 @@ function formatDate(d) { return new Date(d + 'T00:00:00').toLocaleDateString() }
onMounted(async () => {
try {
const typesResponse = await measuringtoolsApi.types.list({ perpage: 200 })
const typesResponse = await measuringtoolsApi.types.list({ perpage: 100 })
types.value = typesResponse.data.data || []
} catch (err) {
console.error('Error loading types:', err)
@@ -139,6 +147,8 @@ async function loadTools() {
try {
const params = { page: page.value, perpage: perPage.value }
if (search.value) params.search = search.value
// active=false means "include retired", matching the API.
if (showRetired.value) params.active = 'false'
if (typeid.value) params.typeid = typeid.value
if (calibrationstatus.value) params.calibrationstatus = calibrationstatus.value