Rename the equipment domain to machines; retype the models catalog (ADR-011)
The equipment plugin is now the machines plugin, ending the UI-vs-code vocabulary split while the contract is pre-1.0 and nothing external depends on the old names. - plugins/equipment -> plugins/machines: manifest, class, /api/machines, machines.* permissions, registry key (with an auto-migrating load shim for existing installs). - Tables: equipment -> machines (equipmentid -> machineid) and equipmenttypes -> machinetypes, renamed in the plugin's own migration chain (machines0002rename), idempotent for both upgrading and fresh installs. - The legacy core machinetypes lookup actually types the vendor MODELS catalog, so it is renamed losslessly to modeltypes (models.modeltypeid, /api/modeltypes, Model Types settings page) rather than collapsed, freeing the machinetypes name. Core migration 7d17_machines_rename also flips data in place: assettypes row equipment -> machine, auditlog entitytype, identifier_/search_ settings keys, permission rows, and renames alembic_version_equipment. - Frontend: machinesApi/modeltypesApi, item.machine response shape, assettype value compares 'equipment' -> 'machine' (map, search, custom fields, relationships), routes machines.js with plugin gating retagged, /print/machine-badge, Machine Types (subtypes) and Model Types (catalog) settings pages, machines-by-type report id. - Docs swept; ADRs left as history per the authoring rule. Upgrade: flask db upgrade then flask plugin upgrade-all. Verified: dev DB flipped live (262 machines, 35 modeltypes, 95 models retyped, zero equipment tables remain); fresh scratch-MySQL install produces the new names; 341 tests green; naming/style green; frontend builds; live E2E on machines list/detail, PC relationships, map, reports, and both settings pages. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,348 +1,352 @@
|
||||
<template>
|
||||
<div class="detail-page">
|
||||
<div class="page-header">
|
||||
<h2>Machine Details</h2>
|
||||
<div class="header-actions">
|
||||
<router-link :to="`/print/equipment-badge/${equipment?.equipment?.equipmentid}`" class="btn btn-secondary" v-if="equipment" target="_blank">
|
||||
Print Badge
|
||||
</router-link>
|
||||
<router-link :to="`/machines/${equipment?.equipment?.equipmentid}/edit`" class="btn btn-primary" v-if="equipment">
|
||||
Edit
|
||||
</router-link>
|
||||
<router-link to="/machines" class="btn btn-secondary">Back to List</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="loading" class="loading">Loading...</div>
|
||||
|
||||
<template v-else-if="equipment">
|
||||
<!-- Hero Section -->
|
||||
<div class="hero-card">
|
||||
<div class="hero-content">
|
||||
<div class="hero-title">
|
||||
<h1>{{ equipment.assetnumber }}</h1>
|
||||
<span v-if="equipment.name" class="hero-alias">{{ equipment.name }}</span>
|
||||
</div>
|
||||
<div class="hero-meta">
|
||||
<span class="badge badge-lg badge-primary">
|
||||
{{ equipment.assettypename || 'Machine' }}
|
||||
</span>
|
||||
<span class="badge badge-lg" :class="getStatusClass(equipment.statusname)">
|
||||
{{ equipment.statusname || 'Unknown' }}
|
||||
</span>
|
||||
<span v-if="heroWarranty" class="badge badge-lg" :style="{ background: heroWarranty.statuscolor, color: '#fff' }"
|
||||
:title="heroWarranty.enddate ? `Warranty ends ${warrantyDate(heroWarranty.enddate)}` : 'Warranty'">
|
||||
{{ heroWarranty.label }}<template v-if="heroWarranty.enddate"> - {{ warrantyDate(heroWarranty.enddate) }}</template>
|
||||
</span>
|
||||
</div>
|
||||
<div class="hero-details">
|
||||
<div class="hero-detail" v-if="equipment.equipment?.equipmenttypename">
|
||||
<span class="hero-detail-label">Type</span>
|
||||
<span class="hero-detail-value">{{ equipment.equipment.equipmenttypename }}</span>
|
||||
</div>
|
||||
<div class="hero-detail" v-if="equipment.equipment?.vendorname">
|
||||
<span class="hero-detail-label">Vendor</span>
|
||||
<span class="hero-detail-value">{{ equipment.equipment.vendorname }}</span>
|
||||
</div>
|
||||
<div class="hero-detail" v-if="equipment.equipment?.modelname">
|
||||
<span class="hero-detail-label">Model</span>
|
||||
<span class="hero-detail-value">{{ equipment.equipment.modelname }}</span>
|
||||
</div>
|
||||
<div class="hero-detail" v-if="equipment.locationname">
|
||||
<span class="hero-detail-label">Location</span>
|
||||
<span class="hero-detail-value">{{ equipment.locationname }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Grid -->
|
||||
<div class="content-grid">
|
||||
<!-- Left Column -->
|
||||
<div class="content-column">
|
||||
<!-- Identity Section -->
|
||||
<div class="section-card">
|
||||
<h3 class="section-title">Identity</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row">
|
||||
<span class="info-label">Asset Number</span>
|
||||
<span class="info-value">{{ equipment.assetnumber }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="equipment.name">
|
||||
<span class="info-label">Name</span>
|
||||
<span class="info-value">{{ equipment.name }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="isEnabled('gaugelabreference', 'equipment') && equipment.gaugelabreference">
|
||||
<span class="info-label">Gauge Lab Reference</span>
|
||||
<span class="info-value mono">{{ equipment.gaugelabreference }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="isEnabled('maintenancereference', 'equipment') && equipment.maintenancereference">
|
||||
<span class="info-label">Maintenance Reference</span>
|
||||
<span class="info-value mono">{{ equipment.maintenancereference }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="equipment.serialnumber">
|
||||
<span class="info-label">Serial Number</span>
|
||||
<span class="info-value mono">{{ equipment.serialnumber }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hardware Section -->
|
||||
<div class="section-card">
|
||||
<h3 class="section-title">Hardware</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row">
|
||||
<span class="info-label">Type</span>
|
||||
<span class="info-value">{{ equipment.equipment?.equipmenttypename || '-' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Vendor</span>
|
||||
<span class="info-value">{{ equipment.equipment?.vendorname || '-' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Model</span>
|
||||
<span class="info-value">{{ equipment.equipment?.modelname || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Controller Section (for CNC machines) -->
|
||||
<div class="section-card" v-if="equipment.equipment?.controllervendorname || equipment.equipment?.controllermodelname">
|
||||
<h3 class="section-title">Controller</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row">
|
||||
<span class="info-label">Vendor</span>
|
||||
<span class="info-value">{{ equipment.equipment?.controllervendorname || '-' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Model</span>
|
||||
<span class="info-value">{{ equipment.equipment?.controllermodelname || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Equipment Configuration -->
|
||||
<div class="section-card">
|
||||
<h3 class="section-title">Configuration</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row">
|
||||
<span class="info-label">Requires Manual Config</span>
|
||||
<span class="info-value">
|
||||
<span class="feature-tag" :class="{ active: equipment.equipment?.requiresmanualconfig }">
|
||||
{{ equipment.equipment?.requiresmanualconfig ? 'Yes' : 'No' }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Maintenance Section -->
|
||||
<div class="section-card" v-if="equipment.equipment?.lastmaintenancedate || equipment.equipment?.nextmaintenancedate">
|
||||
<h3 class="section-title">Maintenance</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row" v-if="equipment.equipment?.lastmaintenancedate">
|
||||
<span class="info-label">Last Maintenance</span>
|
||||
<span class="info-value">{{ formatDate(equipment.equipment.lastmaintenancedate) }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="equipment.equipment?.nextmaintenancedate">
|
||||
<span class="info-label">Next Maintenance</span>
|
||||
<span class="info-value">{{ formatDate(equipment.equipment.nextmaintenancedate) }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="equipment.equipment?.maintenanceintervaldays">
|
||||
<span class="info-label">Interval</span>
|
||||
<span class="info-value">{{ equipment.equipment.maintenanceintervaldays }} days</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column -->
|
||||
<div class="content-column">
|
||||
<!-- Location & Organization -->
|
||||
<div class="section-card">
|
||||
<h3 class="section-title">Location & Organization</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row">
|
||||
<span class="info-label">Location</span>
|
||||
<span class="info-value">
|
||||
<LocationMapTooltip
|
||||
v-if="equipment.mapx != null && equipment.mapy != null"
|
||||
:left="equipment.mapx"
|
||||
:top="equipment.mapy"
|
||||
:machineName="equipment.assetnumber"
|
||||
>
|
||||
<span class="location-link">{{ equipment.locationname || 'On Map' }}</span>
|
||||
</LocationMapTooltip>
|
||||
<span v-else>{{ equipment.locationname || '-' }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Business Unit</span>
|
||||
<span class="info-value">{{ equipment.businessunitname || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Connected PC -->
|
||||
<div class="section-card">
|
||||
<h3 class="section-title">Connected PC</h3>
|
||||
<div v-if="!controllingPc" class="empty-message">
|
||||
No controlling PC assigned
|
||||
</div>
|
||||
<div v-else class="connected-device">
|
||||
<router-link :to="`/pcs/${controllingPc.pluginid || controllingPc.assetid}`" class="device-link">
|
||||
<div class="device-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
|
||||
<line x1="8" y1="21" x2="16" y2="21"></line>
|
||||
<line x1="12" y1="17" x2="12" y2="21"></line>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="device-info">
|
||||
<span class="device-name">{{ controllingPc.assetnumber }}</span>
|
||||
<span class="device-alias" v-if="controllingPc.name">{{ controllingPc.name }}</span>
|
||||
</div>
|
||||
</router-link>
|
||||
<span class="connection-type">{{ controllingPc.relationshipType }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Custom Fields -->
|
||||
<CustomFieldsSection :assetid="equipment.assetid" />
|
||||
|
||||
<!-- Warranty -->
|
||||
<WarrantyPanel :assetid="equipment.assetid" :items="warranties" />
|
||||
|
||||
<!-- Notes -->
|
||||
<div class="section-card" v-if="equipment.notes">
|
||||
<h3 class="section-title">Notes</h3>
|
||||
<p class="notes-text">{{ equipment.notes }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Audit Footer -->
|
||||
<div class="audit-footer">
|
||||
<span>Created {{ formatDate(equipment.createddate) }}<template v-if="equipment.createdby"> by {{ equipment.createdby }}</template></span>
|
||||
<span>Modified {{ formatDate(equipment.modifieddate) }}<template v-if="equipment.modifiedby"> by {{ equipment.modifiedby }}</template></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-else class="card">
|
||||
<p style="text-align: center; color: var(--text-light);">Machine not found</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { equipmentApi, assetsApi } from '../../api'
|
||||
import LocationMapTooltip from '../../components/LocationMapTooltip.vue'
|
||||
import CustomFieldsSection from '../../components/CustomFieldsSection.vue'
|
||||
import WarrantyPanel from '../../components/WarrantyPanel.vue'
|
||||
import { useWarrantyBadge } from '../../composables/warrantyBadge'
|
||||
import { useIdentifierFlags } from '../../composables/identifierSettings'
|
||||
|
||||
const route = useRoute()
|
||||
const { isEnabled } = useIdentifierFlags()
|
||||
|
||||
const loading = ref(true)
|
||||
const equipment = ref(null)
|
||||
const { warranties, heroWarranty, warrantyDate } = useWarrantyBadge(() => equipment.value?.assetid)
|
||||
const relationships = ref({ incoming: [], outgoing: [] })
|
||||
|
||||
// type name is data, sites may seed 'controls' or 'Controls' - compare folded
|
||||
function isControls(rel) {
|
||||
return (rel.relationshiptypename || '').toLowerCase() === 'controls'
|
||||
}
|
||||
|
||||
const controllingPc = computed(() => {
|
||||
// For equipment, find a related computer in any "Controls" relationship
|
||||
// Check both incoming (computer controls this) and outgoing (legacy data may have equipment -> computer)
|
||||
|
||||
// First check incoming - computer as source controlling this equipment
|
||||
for (const rel of relationships.value.incoming || []) {
|
||||
if (rel.sourceasset?.assettypename === 'computer' && isControls(rel)) {
|
||||
return {
|
||||
...rel.sourceasset,
|
||||
relationshipType: rel.relationshiptypename
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also check outgoing - legacy data may have equipment -> computer Controls relationships
|
||||
for (const rel of relationships.value.outgoing || []) {
|
||||
if (rel.targetasset?.assettypename === 'computer' && isControls(rel)) {
|
||||
return {
|
||||
...rel.targetasset,
|
||||
relationshipType: rel.relationshiptypename
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const response = await equipmentApi.get(route.params.id)
|
||||
equipment.value = response.data.data
|
||||
|
||||
// Load relationships using asset ID
|
||||
if (equipment.value?.assetid) {
|
||||
try {
|
||||
const relResponse = await assetsApi.getRelationships(equipment.value.assetid)
|
||||
relationships.value = relResponse.data.data || { incoming: [], outgoing: [] }
|
||||
} catch (e) {
|
||||
console.log('Relationships not available')
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading equipment:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
function getStatusClass(status) {
|
||||
if (!status) return 'badge-info'
|
||||
const s = status.toLowerCase()
|
||||
if (s === 'in use' || s === 'active') return 'badge-success'
|
||||
if (s === 'in repair' || s === 'spare') return 'badge-warning'
|
||||
if (s === 'retired' || s === 'disposed') return 'badge-danger'
|
||||
return 'badge-info'
|
||||
}
|
||||
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr) return '-'
|
||||
return new Date(dateStr).toLocaleString()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mono {
|
||||
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
|
||||
}
|
||||
|
||||
.feature-tag {
|
||||
display: inline-block;
|
||||
padding: 0.3rem 0.625rem;
|
||||
font-size: 0.875rem;
|
||||
border-radius: 5px;
|
||||
background: var(--bg);
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
.feature-tag.active {
|
||||
background: #e3f2fd;
|
||||
color: #1976d2;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.feature-tag.active {
|
||||
background: #1e3a5f;
|
||||
color: #60a5fa;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="detail-page">
|
||||
<div class="page-header">
|
||||
<h2>Machine Details</h2>
|
||||
<div class="header-actions">
|
||||
<router-link :to="`/print/machine-badge/${machine?.machine?.machineid}`" class="btn btn-secondary" v-if="machine" target="_blank">
|
||||
Print Badge
|
||||
</router-link>
|
||||
<router-link :to="`/machines/${machine?.machine?.machineid}/edit`" class="btn btn-primary" v-if="machine">
|
||||
Edit
|
||||
</router-link>
|
||||
<router-link to="/machines" class="btn btn-secondary">Back to List</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="loading" class="loading">Loading...</div>
|
||||
|
||||
<template v-else-if="machine">
|
||||
<!-- Hero Section -->
|
||||
<div class="hero-card">
|
||||
<div class="hero-content">
|
||||
<div class="hero-title">
|
||||
<h1>{{ machine.assetnumber }}</h1>
|
||||
<span v-if="machine.name" class="hero-alias">{{ machine.name }}</span>
|
||||
</div>
|
||||
<div class="hero-meta">
|
||||
<span class="badge badge-lg badge-primary">
|
||||
{{ machine.assettypename || 'Machine' }}
|
||||
</span>
|
||||
<span class="badge badge-lg" :class="getStatusClass(machine.statusname)">
|
||||
{{ machine.statusname || 'Unknown' }}
|
||||
</span>
|
||||
<span v-if="heroWarranty" class="badge badge-lg" :style="{ background: heroWarranty.statuscolor, color: '#fff' }"
|
||||
:title="heroWarranty.enddate ? `Warranty ends ${warrantyDate(heroWarranty.enddate)}` : 'Warranty'">
|
||||
{{ heroWarranty.label }}<template v-if="heroWarranty.enddate"> - {{ warrantyDate(heroWarranty.enddate) }}</template>
|
||||
</span>
|
||||
</div>
|
||||
<div class="hero-details">
|
||||
<div class="hero-detail" v-if="machine.machine?.machinetypename">
|
||||
<span class="hero-detail-label">Type</span>
|
||||
<span class="hero-detail-value">{{ machine.machine.machinetypename }}</span>
|
||||
</div>
|
||||
<div class="hero-detail" v-if="machine.machine?.vendorname">
|
||||
<span class="hero-detail-label">Vendor</span>
|
||||
<span class="hero-detail-value">{{ machine.machine.vendorname }}</span>
|
||||
</div>
|
||||
<div class="hero-detail" v-if="machine.machine?.modelname">
|
||||
<span class="hero-detail-label">Model</span>
|
||||
<span class="hero-detail-value">{{ machine.machine.modelname }}</span>
|
||||
</div>
|
||||
<div class="hero-detail" v-if="machine.locationname">
|
||||
<span class="hero-detail-label">Location</span>
|
||||
<span class="hero-detail-value">{{ machine.locationname }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Grid -->
|
||||
<div class="content-grid">
|
||||
<!-- Left Column -->
|
||||
<div class="content-column">
|
||||
<!-- Identity Section -->
|
||||
<div class="section-card">
|
||||
<h3 class="section-title">Identity</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row">
|
||||
<span class="info-label">Asset Number</span>
|
||||
<span class="info-value">{{ machine.assetnumber }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="machine.name">
|
||||
<span class="info-label">Name</span>
|
||||
<span class="info-value">{{ machine.name }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="isEnabled('gaugelabreference', 'machine') && machine.gaugelabreference">
|
||||
<span class="info-label">Gauge Lab Reference</span>
|
||||
<span class="info-value mono">{{ machine.gaugelabreference }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="isEnabled('maintenancereference', 'machine') && machine.maintenancereference">
|
||||
<span class="info-label">Maintenance Reference</span>
|
||||
<span class="info-value mono">{{ machine.maintenancereference }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="machine.serialnumber">
|
||||
<span class="info-label">Serial Number</span>
|
||||
<span class="info-value mono">{{ machine.serialnumber }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hardware Section -->
|
||||
<div class="section-card">
|
||||
<h3 class="section-title">Hardware</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row">
|
||||
<span class="info-label">Type</span>
|
||||
<span class="info-value">{{ machine.machine?.machinetypename || '-' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Vendor</span>
|
||||
<span class="info-value">{{ machine.machine?.vendorname || '-' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Model</span>
|
||||
<span class="info-value">{{ machine.machine?.modelname || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Controller Section (for CNC machines) -->
|
||||
<div class="section-card" v-if="machine.machine?.controllervendorname || machine.machine?.controllermodelname">
|
||||
<h3 class="section-title">Controller</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row">
|
||||
<span class="info-label">Vendor</span>
|
||||
<span class="info-value">{{ machine.machine?.controllervendorname || '-' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Model</span>
|
||||
<span class="info-value">{{ machine.machine?.controllermodelname || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Machine Configuration -->
|
||||
<div class="section-card">
|
||||
<h3 class="section-title">Configuration</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row">
|
||||
<span class="info-label">Requires Manual Config</span>
|
||||
<span class="info-value">
|
||||
<span class="feature-tag" :class="{ active: machine.machine?.requiresmanualconfig }">
|
||||
{{ machine.machine?.requiresmanualconfig ? 'Yes' : 'No' }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Maintenance Section -->
|
||||
<div class="section-card" v-if="machine.machine?.lastmaintenancedate || machine.machine?.nextmaintenancedate">
|
||||
<h3 class="section-title">Maintenance</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row" v-if="machine.machine?.lastmaintenancedate">
|
||||
<span class="info-label">Last Maintenance</span>
|
||||
<span class="info-value">{{ formatDate(machine.machine.lastmaintenancedate) }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="machine.machine?.nextmaintenancedate">
|
||||
<span class="info-label">Next Maintenance</span>
|
||||
<span class="info-value">{{ formatDate(machine.machine.nextmaintenancedate) }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="machine.machine?.maintenanceintervaldays">
|
||||
<span class="info-label">Interval</span>
|
||||
<span class="info-value">{{ machine.machine.maintenanceintervaldays }} days</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column -->
|
||||
<div class="content-column">
|
||||
<!-- Location & Organization -->
|
||||
<div class="section-card">
|
||||
<h3 class="section-title">Location & Organization</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row">
|
||||
<span class="info-label">Location</span>
|
||||
<span class="info-value">
|
||||
<LocationMapTooltip
|
||||
v-if="machine.mapx != null && machine.mapy != null"
|
||||
:left="machine.mapx"
|
||||
:top="machine.mapy"
|
||||
:machineName="machine.assetnumber"
|
||||
>
|
||||
<span class="location-link">{{ machine.locationname || 'On Map' }}</span>
|
||||
</LocationMapTooltip>
|
||||
<span v-else>{{ machine.locationname || '-' }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Business Unit</span>
|
||||
<span class="info-value">{{ machine.businessunitname || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Connected PC -->
|
||||
<div class="section-card">
|
||||
<h3 class="section-title">Connected PC</h3>
|
||||
<div v-if="!controllingPc" class="empty-message">
|
||||
No controlling PC assigned
|
||||
</div>
|
||||
<div v-else class="connected-device">
|
||||
<router-link :to="`/pcs/${controllingPc.pluginid || controllingPc.assetid}`" class="device-link">
|
||||
<div class="device-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
|
||||
<line x1="8" y1="21" x2="16" y2="21"></line>
|
||||
<line x1="12" y1="17" x2="12" y2="21"></line>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="device-info">
|
||||
<span class="device-name">{{ controllingPc.assetnumber }}</span>
|
||||
<span class="device-alias" v-if="controllingPc.name">{{ controllingPc.name }}</span>
|
||||
</div>
|
||||
</router-link>
|
||||
<span class="connection-type">{{ controllingPc.relationshipType }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Custom Fields -->
|
||||
<CustomFieldsSection :assetid="machine.assetid" />
|
||||
|
||||
<!-- Warranty -->
|
||||
<WarrantyPanel :assetid="machine.assetid" :items="warranties" />
|
||||
|
||||
<!-- All relationships (dualpath, controls, ...) -->
|
||||
<AssetRelationships v-if="machine.assetid" :assetId="machine.assetid" />
|
||||
|
||||
<!-- Notes -->
|
||||
<div class="section-card" v-if="machine.notes">
|
||||
<h3 class="section-title">Notes</h3>
|
||||
<p class="notes-text">{{ machine.notes }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Audit Footer -->
|
||||
<div class="audit-footer">
|
||||
<span>Created {{ formatDate(machine.createddate) }}<template v-if="machine.createdby"> by {{ machine.createdby }}</template></span>
|
||||
<span>Modified {{ formatDate(machine.modifieddate) }}<template v-if="machine.modifiedby"> by {{ machine.modifiedby }}</template></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-else class="card">
|
||||
<p style="text-align: center; color: var(--text-light);">Machine not found</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { machinesApi, assetsApi } from '../../api'
|
||||
import LocationMapTooltip from '../../components/LocationMapTooltip.vue'
|
||||
import CustomFieldsSection from '../../components/CustomFieldsSection.vue'
|
||||
import WarrantyPanel from '../../components/WarrantyPanel.vue'
|
||||
import AssetRelationships from '../../components/AssetRelationships.vue'
|
||||
import { useWarrantyBadge } from '../../composables/warrantyBadge'
|
||||
import { useIdentifierFlags } from '../../composables/identifierSettings'
|
||||
|
||||
const route = useRoute()
|
||||
const { isEnabled } = useIdentifierFlags()
|
||||
|
||||
const loading = ref(true)
|
||||
const machine = ref(null)
|
||||
const { warranties, heroWarranty, warrantyDate } = useWarrantyBadge(() => machine.value?.assetid)
|
||||
const relationships = ref({ incoming: [], outgoing: [] })
|
||||
|
||||
// type name is data, sites may seed 'controls' or 'Controls' - compare folded
|
||||
function isControls(rel) {
|
||||
return (rel.relationshiptypename || '').toLowerCase() === 'controls'
|
||||
}
|
||||
|
||||
const controllingPc = computed(() => {
|
||||
// For a machine, find a related computer in any "Controls" relationship
|
||||
// Check both incoming (computer controls this) and outgoing (legacy data may have machine -> computer)
|
||||
|
||||
// First check incoming - computer as source controlling this machine
|
||||
for (const rel of relationships.value.incoming || []) {
|
||||
if (rel.sourceasset?.assettypename === 'computer' && isControls(rel)) {
|
||||
return {
|
||||
...rel.sourceasset,
|
||||
relationshipType: rel.relationshiptypename
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also check outgoing - legacy data may have machine -> computer Controls relationships
|
||||
for (const rel of relationships.value.outgoing || []) {
|
||||
if (rel.targetasset?.assettypename === 'computer' && isControls(rel)) {
|
||||
return {
|
||||
...rel.targetasset,
|
||||
relationshipType: rel.relationshiptypename
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const response = await machinesApi.get(route.params.id)
|
||||
machine.value = response.data.data
|
||||
|
||||
// Load relationships using asset ID
|
||||
if (machine.value?.assetid) {
|
||||
try {
|
||||
const relResponse = await assetsApi.getRelationships(machine.value.assetid)
|
||||
relationships.value = relResponse.data.data || { incoming: [], outgoing: [] }
|
||||
} catch (e) {
|
||||
console.log('Relationships not available')
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading machine:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
function getStatusClass(status) {
|
||||
if (!status) return 'badge-info'
|
||||
const s = status.toLowerCase()
|
||||
if (s === 'in use' || s === 'active') return 'badge-success'
|
||||
if (s === 'in repair' || s === 'spare') return 'badge-warning'
|
||||
if (s === 'retired' || s === 'disposed') return 'badge-danger'
|
||||
return 'badge-info'
|
||||
}
|
||||
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr) return '-'
|
||||
return new Date(dateStr).toLocaleString()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mono {
|
||||
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
|
||||
}
|
||||
|
||||
.feature-tag {
|
||||
display: inline-block;
|
||||
padding: 0.3rem 0.625rem;
|
||||
font-size: 0.875rem;
|
||||
border-radius: 5px;
|
||||
background: var(--bg);
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
.feature-tag.active {
|
||||
background: #e3f2fd;
|
||||
color: #1976d2;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.feature-tag.active {
|
||||
background: #1e3a5f;
|
||||
color: #60a5fa;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="card">
|
||||
<div v-if="loading" class="loading">Loading...</div>
|
||||
|
||||
<form v-else @submit.prevent="saveEquipment">
|
||||
<form v-else @submit.prevent="saveMachine">
|
||||
<!-- Identity Section -->
|
||||
<h3 class="form-section-title">Identity</h3>
|
||||
<div class="form-row">
|
||||
@@ -34,8 +34,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row" v-if="isEnabled('gaugelabreference', 'equipment') || isEnabled('maintenancereference', 'equipment')">
|
||||
<div class="form-group" v-if="isEnabled('gaugelabreference', 'equipment')">
|
||||
<div class="form-row" v-if="isEnabled('gaugelabreference', 'machine') || isEnabled('maintenancereference', 'machine')">
|
||||
<div class="form-group" v-if="isEnabled('gaugelabreference', 'machine')">
|
||||
<label for="gaugelabreference">Gauge Lab Reference</label>
|
||||
<input
|
||||
id="gaugelabreference"
|
||||
@@ -46,7 +46,7 @@
|
||||
<small class="form-help">Authoritative gauge lab asset reference (if tracked)</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group" v-if="isEnabled('maintenancereference', 'equipment')">
|
||||
<div class="form-group" v-if="isEnabled('maintenancereference', 'machine')">
|
||||
<label for="maintenancereference">Maintenance Reference</label>
|
||||
<input
|
||||
id="maintenancereference"
|
||||
@@ -88,23 +88,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Equipment Hardware Section -->
|
||||
<!-- Machine Hardware Section -->
|
||||
<h3 class="form-section-title">Machine Hardware</h3>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="equipmenttypeid">Equipment Type</label>
|
||||
<label for="machinetypeid">Machine Type</label>
|
||||
<select
|
||||
id="equipmenttypeid"
|
||||
v-model="form.equipmenttypeid"
|
||||
id="machinetypeid"
|
||||
v-model="form.machinetypeid"
|
||||
class="form-control"
|
||||
>
|
||||
<option value="">Select type...</option>
|
||||
<option
|
||||
v-for="et in equipmentTypes"
|
||||
:key="et.equipmenttypeid"
|
||||
:value="et.equipmenttypeid"
|
||||
v-for="mt in machineTypes"
|
||||
:key="mt.machinetypeid"
|
||||
:value="mt.machinetypeid"
|
||||
>
|
||||
{{ et.equipmenttype }}
|
||||
{{ mt.machinetype }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -294,7 +294,7 @@
|
||||
{{ pc.assetnumber }}{{ pc.name ? ` (${pc.name})` : '' }}
|
||||
</option>
|
||||
</select>
|
||||
<small class="form-help">Select the PC that controls this equipment</small>
|
||||
<small class="form-help">Select the PC that controls this machine</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group" v-if="controllingPcId">
|
||||
@@ -312,7 +312,7 @@
|
||||
{{ rt.relationshiptype }}
|
||||
</option>
|
||||
</select>
|
||||
<small class="form-help">How the PC connects to this equipment</small>
|
||||
<small class="form-help">How the PC connects to this machine</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -328,8 +328,8 @@
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Site-defined custom fields for equipment -->
|
||||
<CustomFieldsInputs ref="customFieldsRef" :assettypeid="EQUIPMENT_ASSETTYPEID" :assetid="currentAssetId" />
|
||||
<!-- Site-defined custom fields for machines -->
|
||||
<CustomFieldsInputs ref="customFieldsRef" :assettypeid="MACHINE_ASSETTYPEID" :assetid="currentAssetId" />
|
||||
|
||||
<div v-if="error" class="error-message">{{ error }}</div>
|
||||
|
||||
@@ -347,7 +347,7 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, computed, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { equipmentApi, vendorsApi, locationsApi, modelsApi, businessunitsApi, computersApi, assetsApi } from '../../api'
|
||||
import { machinesApi, vendorsApi, locationsApi, modelsApi, businessunitsApi, computersApi, assetsApi } from '../../api'
|
||||
import ShopFloorMap from '../../components/ShopFloorMap.vue'
|
||||
import Modal from '../../components/Modal.vue'
|
||||
import CustomFieldsInputs from '../../components/CustomFieldsInputs.vue'
|
||||
@@ -362,8 +362,8 @@ const router = useRouter()
|
||||
|
||||
const isEdit = computed(() => !!route.params.id)
|
||||
|
||||
// Seeded asset-type id for equipment (see /api/assets/types).
|
||||
const EQUIPMENT_ASSETTYPEID = 1
|
||||
// Seeded asset-type id for machines (see /api/assets/types).
|
||||
const MACHINE_ASSETTYPEID = 1
|
||||
const customFieldsRef = ref(null)
|
||||
const currentAssetId = ref(null)
|
||||
|
||||
@@ -380,7 +380,7 @@ const form = ref({
|
||||
maintenancereference: '',
|
||||
serialnumber: '',
|
||||
statusid: 1,
|
||||
equipmenttypeid: '',
|
||||
machinetypeid: '',
|
||||
vendorid: '',
|
||||
modelnumberid: '',
|
||||
controllervendorid: '',
|
||||
@@ -394,7 +394,7 @@ const form = ref({
|
||||
mapy: null
|
||||
})
|
||||
|
||||
const equipmentTypes = ref([])
|
||||
const machineTypes = ref([])
|
||||
const statuses = ref([])
|
||||
const vendors = ref([])
|
||||
const locations = ref([])
|
||||
@@ -405,9 +405,9 @@ const relationshipTypes = ref([])
|
||||
const controllingPcId = ref(null)
|
||||
const relationshipTypeId = ref(null)
|
||||
const existingRelationshipId = ref(null)
|
||||
const currentEquipment = ref(null)
|
||||
const currentMachine = ref(null)
|
||||
|
||||
// Filter models by selected equipment vendor
|
||||
// Filter models by selected machine vendor
|
||||
const filteredModels = computed(() => {
|
||||
if (!form.value.vendorid) return models.value
|
||||
return models.value.filter(m => m.vendorid === form.value.vendorid)
|
||||
@@ -443,7 +443,7 @@ onMounted(async () => {
|
||||
try {
|
||||
// Load reference data in parallel
|
||||
const [typesRes, statusRes, vendorRes, locRes, allModels, buRes, pcsRes, relTypesRes] = await Promise.all([
|
||||
equipmentApi.types.list(),
|
||||
machinesApi.types.list(),
|
||||
assetsApi.statuses.list(),
|
||||
vendorsApi.list({ perpage: 500 }),
|
||||
locationsApi.list({ perpage: 500 }),
|
||||
@@ -453,7 +453,7 @@ onMounted(async () => {
|
||||
assetsApi.types.list() // Used for relationship types, will fix below
|
||||
])
|
||||
|
||||
equipmentTypes.value = typesRes.data.data || []
|
||||
machineTypes.value = typesRes.data.data || []
|
||||
statuses.value = statusRes.data.data || []
|
||||
vendors.value = vendorRes.data.data || []
|
||||
locations.value = locRes.data.data || []
|
||||
@@ -479,12 +479,12 @@ onMounted(async () => {
|
||||
relationshipTypeId.value = controlsType.relationshiptypeid
|
||||
}
|
||||
|
||||
// Load equipment if editing
|
||||
// Load machine if editing
|
||||
if (isEdit.value) {
|
||||
const response = await equipmentApi.get(route.params.id)
|
||||
const response = await machinesApi.get(route.params.id)
|
||||
const data = response.data.data
|
||||
currentAssetId.value = data.assetid || null
|
||||
currentEquipment.value = data
|
||||
currentMachine.value = data
|
||||
|
||||
form.value = {
|
||||
assetnumber: data.assetnumber || '',
|
||||
@@ -493,15 +493,15 @@ onMounted(async () => {
|
||||
maintenancereference: data.maintenancereference || '',
|
||||
serialnumber: data.serialnumber || '',
|
||||
statusid: data.statusid || 1,
|
||||
equipmenttypeid: data.equipment?.equipmenttypeid || '',
|
||||
vendorid: data.equipment?.vendorid || '',
|
||||
modelnumberid: data.equipment?.modelnumberid || '',
|
||||
controllervendorid: data.equipment?.controllervendorid || '',
|
||||
controllermodelid: data.equipment?.controllermodelid || '',
|
||||
machinetypeid: data.machine?.machinetypeid || '',
|
||||
vendorid: data.machine?.vendorid || '',
|
||||
modelnumberid: data.machine?.modelnumberid || '',
|
||||
controllervendorid: data.machine?.controllervendorid || '',
|
||||
controllermodelid: data.machine?.controllermodelid || '',
|
||||
locationid: data.locationid || '',
|
||||
businessunitid: data.businessunitid || '',
|
||||
requiresmanualconfig: data.equipment?.requiresmanualconfig || false,
|
||||
islocationonly: data.equipment?.islocationonly || false,
|
||||
requiresmanualconfig: data.machine?.requiresmanualconfig || false,
|
||||
islocationonly: data.machine?.islocationonly || false,
|
||||
notes: data.notes || '',
|
||||
mapx: data.mapx ?? null,
|
||||
mapy: data.mapy ?? null
|
||||
@@ -553,7 +553,7 @@ function clearMapPosition() {
|
||||
tempMapPosition.value = null
|
||||
}
|
||||
|
||||
async function saveEquipment() {
|
||||
async function saveMachine() {
|
||||
error.value = ''
|
||||
saving.value = true
|
||||
|
||||
@@ -565,7 +565,7 @@ async function saveEquipment() {
|
||||
maintenancereference: form.value.maintenancereference || null,
|
||||
serialnumber: form.value.serialnumber || null,
|
||||
statusid: form.value.statusid || 1,
|
||||
equipmenttypeid: form.value.equipmenttypeid || null,
|
||||
machinetypeid: form.value.machinetypeid || null,
|
||||
vendorid: form.value.vendorid || null,
|
||||
modelnumberid: form.value.modelnumberid || null,
|
||||
controllervendorid: form.value.controllervendorid || null,
|
||||
@@ -579,17 +579,17 @@ async function saveEquipment() {
|
||||
mapy: form.value.mapy
|
||||
}
|
||||
|
||||
let savedEquipment
|
||||
let savedMachine
|
||||
let assetId
|
||||
|
||||
if (isEdit.value) {
|
||||
const response = await equipmentApi.update(route.params.id, data)
|
||||
savedEquipment = response.data.data
|
||||
assetId = savedEquipment.assetid
|
||||
const response = await machinesApi.update(route.params.id, data)
|
||||
savedMachine = response.data.data
|
||||
assetId = savedMachine.assetid
|
||||
} else {
|
||||
const response = await equipmentApi.create(data)
|
||||
savedEquipment = response.data.data
|
||||
assetId = savedEquipment.assetid
|
||||
const response = await machinesApi.create(data)
|
||||
savedMachine = response.data.data
|
||||
assetId = savedMachine.assetid
|
||||
}
|
||||
|
||||
// Handle relationship (controlling PC)
|
||||
@@ -604,10 +604,10 @@ async function saveEquipment() {
|
||||
}
|
||||
}
|
||||
|
||||
router.push(`/machines/${savedEquipment.equipment?.equipmentid || route.params.id}`)
|
||||
router.push(`/machines/${savedMachine.machine?.machineid || route.params.id}`)
|
||||
} catch (err) {
|
||||
console.error('Error saving equipment:', err)
|
||||
error.value = apiError(err, 'Failed to save equipment')
|
||||
console.error('Error saving machine:', err)
|
||||
error.value = apiError(err, 'Failed to save machine')
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
@@ -632,7 +632,7 @@ async function saveRelationship(assetId) {
|
||||
await assetsApi.deleteRelationship(existingRelationshipId.value)
|
||||
}
|
||||
|
||||
// Create new relationship (PC controls Equipment, so PC is source, Equipment is target)
|
||||
// Create new relationship (PC controls Machine, so PC is source, Machine is target)
|
||||
await assetsApi.createRelationship({
|
||||
sourceassetid: controllingPcId.value,
|
||||
targetassetid: assetId,
|
||||
|
||||
@@ -35,12 +35,12 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in equipment" :key="item.assetid">
|
||||
<tr v-for="item in machines" :key="item.assetid">
|
||||
<td>{{ item.assetnumber }}</td>
|
||||
<td>{{ item.name || '-' }}</td>
|
||||
<td class="mono">{{ item.serialnumber || '-' }}</td>
|
||||
<td>{{ item.equipment?.equipmenttypename || '-' }}</td>
|
||||
<td>{{ item.equipment?.vendorname || '-' }}</td>
|
||||
<td>{{ item.machine?.machinetypename || '-' }}</td>
|
||||
<td>{{ item.machine?.vendorname || '-' }}</td>
|
||||
<td>
|
||||
<span class="badge" :style="colorStyle(item.statuscolor)">
|
||||
{{ item.statusname || 'Unknown' }}
|
||||
@@ -49,16 +49,16 @@
|
||||
<td>{{ item.locationname || '-' }}</td>
|
||||
<td class="actions">
|
||||
<router-link
|
||||
:to="`/machines/${item.equipment?.equipmentid || item.assetid}`"
|
||||
:to="`/machines/${item.machine?.machineid || item.assetid}`"
|
||||
class="btn btn-secondary btn-sm"
|
||||
>
|
||||
View
|
||||
</router-link>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="equipment.length === 0">
|
||||
<tr v-if="machines.length === 0">
|
||||
<td colspan="8" style="text-align: center; color: var(--text-light);">
|
||||
No equipment found
|
||||
No machines found
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -82,10 +82,10 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { colorStyle } from "@/utils/colorStyle"
|
||||
import { equipmentApi } from '../../api'
|
||||
import { machinesApi } from '../../api'
|
||||
import PaginationBar from '../../components/PaginationBar.vue'
|
||||
|
||||
const equipment = ref([])
|
||||
const machines = ref([])
|
||||
const loading = ref(true)
|
||||
const search = ref('')
|
||||
const page = ref(1)
|
||||
@@ -95,10 +95,10 @@ const perPage = ref(20)
|
||||
let searchTimeout = null
|
||||
|
||||
onMounted(() => {
|
||||
loadEquipment()
|
||||
loadMachines()
|
||||
})
|
||||
|
||||
async function loadEquipment() {
|
||||
async function loadMachines() {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = {
|
||||
@@ -107,11 +107,11 @@ async function loadEquipment() {
|
||||
}
|
||||
if (search.value) params.search = search.value
|
||||
|
||||
const response = await equipmentApi.list(params)
|
||||
equipment.value = response.data.data || []
|
||||
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 equipment:', error)
|
||||
console.error('Error loading machines:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
@@ -121,19 +121,19 @@ function debouncedSearch() {
|
||||
clearTimeout(searchTimeout)
|
||||
searchTimeout = setTimeout(() => {
|
||||
page.value = 1
|
||||
loadEquipment()
|
||||
loadMachines()
|
||||
}, 300)
|
||||
}
|
||||
|
||||
function goToPage(p) {
|
||||
page.value = p
|
||||
loadEquipment()
|
||||
loadMachines()
|
||||
}
|
||||
|
||||
function changePerPage(newPerPage) {
|
||||
perPage.value = newPerPage
|
||||
page.value = 1
|
||||
loadEquipment()
|
||||
loadMachines()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user