map: drop the marker popup that was never meant to be reached
Some checks failed
CI / backend (push) Failing after 1m55s
CI / naming (push) Successful in 1s
CI / frontend (push) Successful in 9s
CI / migrations-mysql (push) Failing after 7s

Each marker bound both a hover tooltip and a click popup. On the map page the
click handler routes to the detail page, so the popup opened and the
navigation discarded it in the same tick - it was never visible. Where it did
render (the map editor and the picker forms) its 'View Details' link only
served to pull the user off an unsaved form.

Keep hover as a glance and leave the click to the consumer. Removes the popup
markup, its styles, and the two now-unused detail-route helpers.
This commit is contained in:
cproudlock
2026-07-31 10:17:17 -04:00
parent 2528b7e556
commit 6639afd1f0

View File

@@ -96,7 +96,7 @@ import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
import L from 'leaflet' import L from 'leaflet'
import 'leaflet/dist/leaflet.css' import 'leaflet/dist/leaflet.css'
import { loadMapConfig, blueprintUrlFor, state as mapConfig } from '../composables/mapConfig' import { loadMapConfig, blueprintUrlFor, state as mapConfig } from '../composables/mapConfig'
import { assetTypeLabel, assetDetailRoute } from '../utils/assetTypes' import { assetTypeLabel } from '../utils/assetTypes'
import { getSubtypeId, markerRingColor, UNSPECIFIED_COLOR } from '../utils/mapColors' import { getSubtypeId, markerRingColor, UNSPECIFIED_COLOR } from '../utils/mapColors'
import api from '../api' import api from '../api'
@@ -356,22 +356,6 @@ function clearPosition() {
emit('positionPicked', null) emit('positionPicked', null)
} }
// Get the detail page route based on machine category
// Extensible for future addon types (network, cameras, etc.)
function getDetailRoute(machine) {
const category = machine.category?.toLowerCase() || ''
const routeMap = {
'machine': '/machines',
'pc': '/pcs',
'printer': '/printers',
// Future addon routes can be added here:
// 'network': '/network',
// 'camera': '/cameras',
}
const basePath = routeMap[category] || '/machines'
return `${basePath}/${machine.machineid}`
}
// Fetch the declared map overlays (ADR-010) and each overlay's per-asset // Fetch the declared map overlays (ADR-010) and each overlay's per-asset
// decoration data, keyed by assetid for a fast join during rendering. // decoration data, keyed by assetid for a fast join during rendering.
async function loadOverlays() { async function loadOverlays() {
@@ -452,7 +436,7 @@ function renderMarkers() {
const leafletX = item.mapx const leafletX = item.mapx
// Determine color based on mode // Determine color based on mode
let color, typeName, displayName, detailRoute let color, typeName, displayName
if (props.assetTypeMode) { if (props.assetTypeMode) {
// Unified asset mode - use subtype colors when a type is selected // Unified asset mode - use subtype colors when a type is selected
@@ -470,13 +454,11 @@ function renderMarkers() {
if (item.dualpathpartner) { if (item.dualpathpartner) {
displayName = `${item.assetnumber} / ${item.dualpathpartner}` displayName = `${item.assetnumber} / ${item.dualpathpartner}`
} }
detailRoute = getAssetDetailRoute(item)
} else { } else {
// Legacy machine mode // Legacy machine mode
typeName = item.machinetype || '' typeName = item.machinetype || ''
color = getTypeColor(typeName) color = getTypeColor(typeName)
displayName = item.alias || item.machinenumber || 'Unknown' displayName = item.alias || item.machinenumber || 'Unknown'
detailRoute = getDetailRoute(item)
} }
// Use circleMarker instead of divIcon marker - renders on canvas // Use circleMarker instead of divIcon marker - renders on canvas
@@ -542,40 +524,11 @@ function renderMarkers() {
className: 'marker-tooltip' className: 'marker-tooltip'
}) })
// Click popup (detailed info) // Hover is a glance; the click belongs to the consumer. No popup is bound:
let popupContent // MapView routes to the detail page on click, so a popup opened and was
if (props.assetTypeMode) { // discarded by the navigation in the same tick - it was never visible. In
popupContent = ` // the editor and the picker forms it DID render, where a 'View Details'
<div class="marker-popup"> // link only served to pull the user off an unsaved form.
<strong>${displayName}</strong>
<div class="popup-details">
<div><span class="label">Asset #:</span> ${item.assetnumber || '-'}</div>
<div><span class="label">Type:</span> ${item.assettype || '-'}</div>
<div><span class="label">Status:</span> ${item.status || '-'}</div>
<div><span class="label">Location:</span> ${item.location || '-'}</div>
${item.primaryip ? `<div><span class="label">IP:</span> ${item.primaryip}</div>` : ''}
</div>
<a href="${detailRoute}" class="popup-link">View Details</a>
</div>
`
} else {
popupContent = `
<div class="marker-popup">
<strong>${displayName}</strong>
<div class="popup-details">
<div><span class="label">Number:</span> ${item.machinenumber || '-'}</div>
<div><span class="label">Type:</span> ${typeName || '-'}</div>
<div><span class="label">Category:</span> ${item.category || '-'}</div>
<div><span class="label">Status:</span> ${item.status || '-'}</div>
<div><span class="label">Vendor:</span> ${item.vendor || '-'}</div>
<div><span class="label">Model:</span> ${item.model || '-'}</div>
</div>
<a href="${detailRoute}" class="popup-link">View Details</a>
</div>
`
}
marker.bindPopup(popupContent)
marker.on('click', () => emit('markerClick', item)) marker.on('click', () => emit('markerClick', item))
marker.addTo(map) marker.addTo(map)
@@ -596,11 +549,6 @@ function renderMarkers() {
applyFilters() applyFilters()
} }
// Get detail route for unified asset format (shared util = single source).
function getAssetDetailRoute(asset) {
return assetDetailRoute(asset)
}
function applyFilters() { function applyFilters() {
const searchTerm = filters.value.search.toLowerCase() const searchTerm = filters.value.search.toLowerCase()
@@ -796,39 +744,6 @@ onUnmounted(() => {
font-size: 1.125rem; font-size: 1.125rem;
} }
:deep(.marker-popup) {
min-width: 320px;
}
:deep(.marker-popup strong) {
display: block;
margin-bottom: 0.625rem;
font-size: 1.5rem;
}
:deep(.popup-details) {
font-size: 1.125rem;
line-height: 1.9;
}
:deep(.popup-details .label) {
color: #666;
font-weight: 500;
}
:deep(.popup-link) {
display: inline-block;
margin-top: 1rem;
color: #1976d2;
text-decoration: none;
font-size: 1.125rem;
font-weight: 500;
}
:deep(.popup-link:hover) {
text-decoration: underline;
}
:deep(.machine-marker) { :deep(.machine-marker) {
background: transparent !important; background: transparent !important;
border: none !important; border: none !important;