Files
shopdb-flask/plugins/machines/frontend/views/MachinesList.vue
cproudlock e22322dcc9
Some checks failed
CI / backend (push) Failing after 8s
CI / naming (push) Successful in 2s
CI / frontend (push) Successful in 9s
CI / migrations-mysql (push) Failing after 7s
Show model type in the machines list
The machine's own type is blank for the 134 machines that came from the classic
ASP database on machinetypeid=1, a LocationOnly placeholder the import refuses
to carry across as a real subtype. The catalog model knows what those machines
are, and its type is populated, so the column reads modeltypename under a
heading that says so.

Where both values exist they are identical - all 262 machines in the development
database match exactly - so nothing is lost by showing the one that is reliably
filled in.

This does not fix the underlying gap. A null machinetypeid also excludes a
machine from the map's subtype filter and drops its marker to the default
colour, and no column heading affects that. Only populating machinetypeid does,
which is what the backfill script is for.
2026-08-05 10:45:35 -04:00

155 lines
4.5 KiB
Vue

<template>
<div>
<div class="page-header">
<h2>Machines</h2>
<router-link to="/print/asset-label-batch/machine" class="btn btn-secondary" target="_blank">Print Labels</router-link>
<router-link to="/machines/new" class="btn btn-primary">Add Machine</router-link>
</div>
<!-- Filters -->
<div class="filters">
<input
v-model="search"
type="text"
class="form-control"
placeholder="Search machines..."
@input="debouncedSearch"
/>
</div>
<div class="card">
<div v-if="loading" class="loading">Loading...</div>
<template v-else>
<div class="table-container">
<table>
<thead>
<tr>
<th>Machine #</th>
<th>Name</th>
<th>Serial Number</th>
<th>Model Type</th>
<th>Vendor</th>
<th>Status</th>
<th>Location</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="item in machines" :key="item.assetid" class="clickable-row" @click="$router.push(`/machines/${item.machine?.machineid || item.assetid}`)">
<td>
{{ item.assetnumber }}<template v-if="item.dualpathpartner"> / {{ item.dualpathpartner.assetnumber }}</template>
</td>
<td>{{ item.name || '-' }}</td>
<td class="mono">{{ item.serialnumber || '-' }}</td>
<!--
The catalog model's type, not the machine's own. 134 machines
arrived from the classic ASP database on machinetypeid=1 - a
LocationOnly placeholder the import refuses to carry across as
a real subtype - so Machine Type is blank for them while the
model knows exactly what they are.
-->
<td>{{ item.machine?.modeltypename || '-' }}</td>
<td>{{ item.machine?.vendorname || '-' }}</td>
<td>
<span class="badge" :style="colorStyle(item.statuscolor)">
{{ item.statusname || 'Unknown' }}
</span>
</td>
<td>{{ item.locationname || '-' }}</td>
<td class="actions" @click.stop>
<router-link
:to="`/machines/${item.machine?.machineid || item.assetid}`"
class="btn btn-secondary btn-sm"
>
View
</router-link>
</td>
</tr>
<tr v-if="machines.length === 0">
<td colspan="8" style="text-align: center; color: var(--text-light);">
No machines found
</td>
</tr>
</tbody>
</table>
</div>
<!-- Pagination -->
<PaginationBar
:page="page"
:totalPages="totalPages"
:perPage="perPage"
@update:page="goToPage"
@update:perPage="changePerPage"
/>
</template>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { colorStyle } from "@/utils/colorStyle"
import { machinesApi } from '@/api'
import PaginationBar from '@/components/PaginationBar.vue'
import { useListQuery } from '@/composables/listQuery'
const machines = ref([])
const loading = ref(true)
const { page, search, setPage, setSearch } = useListQuery({ onChange: loadMachines })
const totalPages = ref(1)
const perPage = ref(20)
let searchTimeout = null
onMounted(() => {
loadMachines()
})
async function loadMachines() {
loading.value = true
try {
const params = {
page: page.value,
perpage: perPage.value
}
if (search.value) params.search = search.value
const response = await machinesApi.list(params)
machines.value = response.data.data || []
totalPages.value = response.data.meta?.pagination?.totalpages || response.data.meta?.pagination?.total_pages || 1
} catch (error) {
console.error('Error loading machines:', error)
} finally {
loading.value = false
}
}
function debouncedSearch() {
clearTimeout(searchTimeout)
searchTimeout = setTimeout(() => {
setSearch(search.value)
loadMachines()
}, 300)
}
function goToPage(p) {
setPage(p)
loadMachines()
}
function changePerPage(newPerPage) {
perPage.value = newPerPage
setPage(1)
loadMachines()
}
</script>
<style scoped>
.mono {
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
}
</style>