Show off-map selection in left info panel

This commit is contained in:
Morten V. Christiansen 2026-04-05 12:59:27 +02:00
parent 0547c451a5
commit 1774d97aa2
3 changed files with 51 additions and 12 deletions

View File

@ -19,6 +19,7 @@ L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
const statusEl = document.getElementById("status");
const alertsEl = document.getElementById("presenceAlerts");
const selectedVehicleInfoEl = document.getElementById("selectedVehicleInfo");
const offmapIndicatorsEl = document.getElementById("offmapIndicators");
const playBtn = document.getElementById("playBtn");
const pauseBtn = document.getElementById("pauseBtn");
@ -33,6 +34,23 @@ function highlightOffmapIndicator(name) {
});
}
function renderSelectedVehicleInfo(v, sourceLabel = "kort") {
if (!v) {
selectedVehicleInfoEl.textContent = "Klik på et køretøj eller en hjørneindikator for detaljer.";
return;
}
selectedVehicleInfoEl.innerHTML = `
<strong>${v.name} · valgt fra ${sourceLabel}</strong>
Tid: ${fmtTs(v.current.ts)}<br>
Position: ${v.displayLat.toFixed(5)}, ${v.displayLon.toFixed(5)}<br>
Hastighed: ${v.current.speedMps} m/s<br>
Retning: ${v.displayHeading.toFixed(0)}°<br>
Usikkerhed: ${v.current.uncertaintyM} m<br>
Status: ${v.presenceStateLabel || "ja"}
`;
}
function flashVehicleMarker(v) {
const markerEl = v.marker.getElement();
if (!markerEl) return;
@ -48,6 +66,7 @@ function openVehiclePopup(name) {
forcedPopupVehicle = name;
highlightOffmapIndicator(name);
renderSelectedVehicleInfo(v, "hjørneindikator");
if (!map.hasLayer(v.marker)) {
v.marker.addTo(map);
@ -354,6 +373,11 @@ for (const name of vehicleNames) {
};
marker.bindPopup(popupHtml(name, vehicles[name]));
marker.on("click", () => {
forcedPopupVehicle = name;
highlightOffmapIndicator(null);
renderSelectedVehicleInfo(vehicles[name], "kort");
});
setHeading(marker, first.headingDeg);
}
@ -365,6 +389,9 @@ const TIME_SCALE = 0.175;
function resetDemo() {
simTime = 0;
lastFrameTime = null;
forcedPopupVehicle = null;
highlightOffmapIndicator(null);
renderSelectedVehicleInfo(null);
for (const name of vehicleNames) {
const v = vehicles[name];
@ -585,6 +612,7 @@ map.on("popupclose", (event) => {
if (popupVehicle && forcedPopupVehicle === popupVehicle.name) {
forcedPopupVehicle = null;
highlightOffmapIndicator(null);
renderSelectedVehicleInfo(null);
updateVehicleDisplay(popupVehicle);
}
});

View File

@ -42,6 +42,22 @@
white-space: pre-line;
}
.hud .selection {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid rgba(0,0,0,0.08);
max-width: 320px;
font: 12px/1.4 system-ui, sans-serif;
color: #1f2937;
}
.hud .selection strong {
display: block;
margin-bottom: 4px;
font-size: 13px;
color: #111827;
}
.hud .alerts {
margin-top: 8px;
display: grid;
@ -162,6 +178,7 @@
<button id="resetBtn">Reset</button>
</div>
<div class="status" id="status"></div>
<div class="selection" id="selectedVehicleInfo">Klik på et køretøj eller en hjørneindikator for detaljer.</div>
<div class="alerts" id="presenceAlerts"></div>
</div>

View File

@ -91,7 +91,7 @@ test.describe('kort7 vehicle map', () => {
await expect(alerts).not.toContainText('Bil 8');
});
test('opens vehicle popup when clicking an off-map corner indicator', async ({ page }) => {
test('updates left info panel when clicking an off-map corner indicator', async ({ page }) => {
await page.goto('/kort7.html');
await page.getByRole('button', { name: 'Pause' }).click();
@ -99,16 +99,10 @@ test.describe('kort7 vehicle map', () => {
await expect(indicator).toBeVisible();
await indicator.click();
const popup = page.locator('.leaflet-popup');
await expect(popup).toBeVisible();
await expect(popup).toContainText('Bil 9');
await expect(popup).toContainText('Usikkerhed:');
await expect(popup).toContainText('På kortet:');
await expect(page.locator('.leaflet-popup')).toBeVisible();
const popupBox = await page.locator('.leaflet-popup').boundingBox();
expect(popupBox).not.toBeNull();
expect(popupBox.y).toBeLessThan(220);
const selection = page.locator('#selectedVehicleInfo');
await expect(selection).toContainText('Bil 9');
await expect(selection).toContainText('valgt fra hjørneindikator');
await expect(selection).toContainText('Usikkerhed: 9000 m');
await expect(indicator).toHaveClass(/active/);
});
});