Show selected signals as a table with relative time data.

This commit is contained in:
Eli Ribble 2026-03-06 16:51:05 +00:00
parent 49a109ae85
commit 662188485e
No known key found for this signature in database
2 changed files with 126 additions and 20 deletions

View file

@ -0,0 +1,92 @@
/**
* Custom HTML element <time-relative> that displays relative time
* Usage: <time-relative time="2024-01-01T12:00:00Z"></time-relative>
*/
class TimeRelative extends HTMLElement {
constructor() {
super();
this.span = null;
}
static get observedAttributes() {
return ["time"];
}
connectedCallback() {
// Create the span element if it doesn't exist
if (!this.span) {
this.span = document.createElement("span");
this.span.className = "time-relative";
this.appendChild(this.span);
}
this.updateTime();
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === "time" && oldValue !== newValue) {
this.updateTime();
}
}
updateTime() {
if (this.span) {
const timeValue = this.getAttribute("time");
if (timeValue) {
this.span.textContent = this.formatRelativeTime(timeValue);
}
}
}
formatRelativeTime(timestamp) {
const now = new Date();
const date = new Date(timestamp);
const diffInSeconds = Math.floor((now - date) / 1000);
// Time units in seconds
const minute = 60;
const hour = minute * 60;
const day = hour * 24;
const week = day * 7;
const month = day * 30;
const year = day * 365;
if (diffInSeconds < minute) {
return "just now";
} else if (diffInSeconds < hour) {
const minutes = Math.floor(diffInSeconds / minute);
return `${minutes} ${minutes === 1 ? "minute" : "minutes"} ago`;
} else if (diffInSeconds < day) {
const hours = Math.floor(diffInSeconds / hour);
return `${hours} ${hours === 1 ? "hour" : "hours"} ago`;
} else if (diffInSeconds < week) {
const days = Math.floor(diffInSeconds / day);
return `${days} ${days === 1 ? "day" : "days"} ago`;
} else if (diffInSeconds < month) {
const weeks = Math.floor(diffInSeconds / week);
return `${weeks} ${weeks === 1 ? "week" : "weeks"} ago`;
} else if (diffInSeconds < year) {
const months = Math.floor(diffInSeconds / month);
return `${months} ${months === 1 ? "month" : "months"} ago`;
} else {
const years = Math.floor(diffInSeconds / year);
return `${years} ${years === 1 ? "year" : "years"} ago`;
}
}
// Property getter and setter for JavaScript access
get time() {
return this.getAttribute("time");
}
set time(value) {
if (value) {
this.setAttribute("time", value);
} else {
this.removeAttribute("time");
}
}
}
// Register the custom element
customElements.define("time-relative", TimeRelative);

View file

@ -6,13 +6,14 @@
type="text/javascript"
src="//unpkg.com/maplibre-gl@5.0.1/dist/maplibre-gl.js"
></script>
<script src="/static/js/map-arcgis-tile.js"></script>
<script src="/static/js/map-multipoint.js"></script>
<script
defer
src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"
></script>
<script src="https://unpkg.com/@esri/maplibre-arcgis@1.1.0/dist/umd/maplibre-arcgis.min.js"></script>
<script src="/static/js/map-arcgis-tile.js"></script>
<script src="/static/js/map-multipoint.js"></script>
<script src="/static/js/time-relative.js"></script>
<script>
// Return two points defining a bounding box for the given points
@ -43,7 +44,7 @@
);
}
function shortAddress(a) {
return a.number + " " + a.street + ", " + a.locality + ", " + a.region;
return a.number + " " + a.street + ", " + a.locality;
}
function updateMap(signals) {
const map = document.querySelector("map-multipoint");
@ -512,23 +513,36 @@
</div>
</template>
<ul class="small mt-2" x-show="selectedSignals.length > 0">
<template
x-for="signal in selectedSignals"
:key="signal.id"
>
<li>
<span x-text="signal.title"></span>
<button
@click="toggleSignal(signal)"
class="btn btn-sm btn-link text-danger p-0 ms-1"
style="font-size: 0.7rem;"
>
</button>
</li>
</template>
</ul>
<table
class="small mt-2 table"
x-show="selectedSignals.length > 0"
>
<tbody>
<template
x-for="signal in selectedSignals"
:key="signal.id"
>
<tr x-if="signal.type == 'flyover pool'">
<td>
<button
@click="toggleSignal(signal)"
class="btn btn-sm btn-link text-danger p-0 ms-1"
style="font-size: 0.7rem;"
>
<i class="bi bi-x"></i>
</button>
</td>
<td>Green pool</td>
<td>
<time-relative
:time="signal.created"
></time-relative>
</td>
<td x-text="shortAddress(signal.address)"></td>
</tr>
</template>
</tbody>
</table>
<button
x-show="selectedSignals.length > 0"