Show off-map selection in left info panel
This commit is contained in:
parent
0547c451a5
commit
1774d97aa2
28
kort7/app.js
28
kort7/app.js
|
|
@ -19,6 +19,7 @@ L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||||
|
|
||||||
const statusEl = document.getElementById("status");
|
const statusEl = document.getElementById("status");
|
||||||
const alertsEl = document.getElementById("presenceAlerts");
|
const alertsEl = document.getElementById("presenceAlerts");
|
||||||
|
const selectedVehicleInfoEl = document.getElementById("selectedVehicleInfo");
|
||||||
const offmapIndicatorsEl = document.getElementById("offmapIndicators");
|
const offmapIndicatorsEl = document.getElementById("offmapIndicators");
|
||||||
const playBtn = document.getElementById("playBtn");
|
const playBtn = document.getElementById("playBtn");
|
||||||
const pauseBtn = document.getElementById("pauseBtn");
|
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) {
|
function flashVehicleMarker(v) {
|
||||||
const markerEl = v.marker.getElement();
|
const markerEl = v.marker.getElement();
|
||||||
if (!markerEl) return;
|
if (!markerEl) return;
|
||||||
|
|
@ -48,6 +66,7 @@ function openVehiclePopup(name) {
|
||||||
|
|
||||||
forcedPopupVehicle = name;
|
forcedPopupVehicle = name;
|
||||||
highlightOffmapIndicator(name);
|
highlightOffmapIndicator(name);
|
||||||
|
renderSelectedVehicleInfo(v, "hjørneindikator");
|
||||||
|
|
||||||
if (!map.hasLayer(v.marker)) {
|
if (!map.hasLayer(v.marker)) {
|
||||||
v.marker.addTo(map);
|
v.marker.addTo(map);
|
||||||
|
|
@ -354,6 +373,11 @@ for (const name of vehicleNames) {
|
||||||
};
|
};
|
||||||
|
|
||||||
marker.bindPopup(popupHtml(name, vehicles[name]));
|
marker.bindPopup(popupHtml(name, vehicles[name]));
|
||||||
|
marker.on("click", () => {
|
||||||
|
forcedPopupVehicle = name;
|
||||||
|
highlightOffmapIndicator(null);
|
||||||
|
renderSelectedVehicleInfo(vehicles[name], "kort");
|
||||||
|
});
|
||||||
setHeading(marker, first.headingDeg);
|
setHeading(marker, first.headingDeg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -365,6 +389,9 @@ const TIME_SCALE = 0.175;
|
||||||
function resetDemo() {
|
function resetDemo() {
|
||||||
simTime = 0;
|
simTime = 0;
|
||||||
lastFrameTime = null;
|
lastFrameTime = null;
|
||||||
|
forcedPopupVehicle = null;
|
||||||
|
highlightOffmapIndicator(null);
|
||||||
|
renderSelectedVehicleInfo(null);
|
||||||
|
|
||||||
for (const name of vehicleNames) {
|
for (const name of vehicleNames) {
|
||||||
const v = vehicles[name];
|
const v = vehicles[name];
|
||||||
|
|
@ -585,6 +612,7 @@ map.on("popupclose", (event) => {
|
||||||
if (popupVehicle && forcedPopupVehicle === popupVehicle.name) {
|
if (popupVehicle && forcedPopupVehicle === popupVehicle.name) {
|
||||||
forcedPopupVehicle = null;
|
forcedPopupVehicle = null;
|
||||||
highlightOffmapIndicator(null);
|
highlightOffmapIndicator(null);
|
||||||
|
renderSelectedVehicleInfo(null);
|
||||||
updateVehicleDisplay(popupVehicle);
|
updateVehicleDisplay(popupVehicle);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,22 @@
|
||||||
white-space: pre-line;
|
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 {
|
.hud .alerts {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
@ -162,6 +178,7 @@
|
||||||
<button id="resetBtn">Reset</button>
|
<button id="resetBtn">Reset</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="status" id="status"></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 class="alerts" id="presenceAlerts"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ test.describe('kort7 vehicle map', () => {
|
||||||
await expect(alerts).not.toContainText('Bil 8');
|
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.goto('/kort7.html');
|
||||||
await page.getByRole('button', { name: 'Pause' }).click();
|
await page.getByRole('button', { name: 'Pause' }).click();
|
||||||
|
|
||||||
|
|
@ -99,16 +99,10 @@ test.describe('kort7 vehicle map', () => {
|
||||||
await expect(indicator).toBeVisible();
|
await expect(indicator).toBeVisible();
|
||||||
await indicator.click();
|
await indicator.click();
|
||||||
|
|
||||||
const popup = page.locator('.leaflet-popup');
|
const selection = page.locator('#selectedVehicleInfo');
|
||||||
await expect(popup).toBeVisible();
|
await expect(selection).toContainText('Bil 9');
|
||||||
await expect(popup).toContainText('Bil 9');
|
await expect(selection).toContainText('valgt fra hjørneindikator');
|
||||||
await expect(popup).toContainText('Usikkerhed:');
|
await expect(selection).toContainText('Usikkerhed: 9000 m');
|
||||||
await expect(popup).toContainText('På kortet:');
|
await expect(indicator).toHaveClass(/active/);
|
||||||
|
|
||||||
await expect(page.locator('.leaflet-popup')).toBeVisible();
|
|
||||||
|
|
||||||
const popupBox = await page.locator('.leaflet-popup').boundingBox();
|
|
||||||
expect(popupBox).not.toBeNull();
|
|
||||||
expect(popupBox.y).toBeLessThan(220);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue