Fix measurements in popup details

This commit is contained in:
2026-07-07 22:17:58 -05:00
parent 100340fbb4
commit 900e195926
2 changed files with 87 additions and 27 deletions
+60 -27
View File
@@ -5,6 +5,7 @@ const TILE_MAX_NATIVE_ZOOM = 19;
const MAP_MAX_ZOOM = 24; const MAP_MAX_ZOOM = 24;
const MAP_ZOOM_STEP = 0.25; const MAP_ZOOM_STEP = 0.25;
const WHEEL_PIXELS_PER_ZOOM_LEVEL = 240; const WHEEL_PIXELS_PER_ZOOM_LEVEL = 240;
const FEET_PER_METER = 3.280839895;
const TIMELINE_PRESETS = [ const TIMELINE_PRESETS = [
{ {
id: "purchase", id: "purchase",
@@ -330,7 +331,8 @@ function buildPopupContent(properties) {
const title = `<strong>${escapeHtml(name)}</strong>`; const title = `<strong>${escapeHtml(name)}</strong>`;
const subtitle = name === label ? "" : `<div>${escapeHtml(label)}</div>`; const subtitle = name === label ? "" : `<div>${escapeHtml(label)}</div>`;
const allEntries = [...lifecycleEntries, ...entries, ...relationshipEntries]; const allEntries = [...lifecycleEntries, ...entries, ...relationshipEntries];
if (allEntries.length === 0 && linkEntries.length === 0) { const measurementTable = buildMeasurementTable(details?.measurements);
if (allEntries.length === 0 && linkEntries.length === 0 && !measurementTable) {
return `${title}${subtitle}`; return `${title}${subtitle}`;
} }
@@ -341,12 +343,16 @@ function buildPopupContent(properties) {
.map((link) => `<div><a href="${escapeHtml(link.url)}" target="_blank" rel="noreferrer">Info</a></div>`) .map((link) => `<div><a href="${escapeHtml(link.url)}" target="_blank" rel="noreferrer">Info</a></div>`)
.join(""); .join("");
return `${title}${subtitle}<div>${detailRows}${linkRows}</div>`; return `${title}${subtitle}<div>${detailRows}${measurementTable}${linkRows}</div>`;
} }
function shouldShowDetailField(key, details = {}) { function shouldShowDetailField(key, details = {}) {
if (key === "measurements") {
return false;
}
if ( if (
Array.isArray(details.measurements) && hasDatedMeasurements(details.measurements) &&
(key === "canopyDiameter" || key === "height") (key === "canopyDiameter" || key === "height")
) { ) {
return false; return false;
@@ -382,12 +388,8 @@ function formatDetailLabel(key) {
} }
function formatDetailValue(key, value) { function formatDetailValue(key, value) {
if (key === "measurements") {
return formatPlantMeasurements(value);
}
if (key === "canopyDiameter" || key === "height") { if (key === "canopyDiameter" || key === "height") {
return `${value} m`; return formatMetersAsFeet(value);
} }
if (key === "offsetFeet" || key === "spacingFeet") { if (key === "offsetFeet" || key === "spacingFeet") {
@@ -397,32 +399,63 @@ function formatDetailValue(key, value) {
return String(value); return String(value);
} }
function formatPlantMeasurements(measurements) { function formatMetersAsFeet(value) {
if (!Array.isArray(measurements)) { return `${formatNumber(value * FEET_PER_METER)} ft`;
return String(measurements);
}
return measurements.map(formatPlantMeasurement).join("; ");
} }
function formatPlantMeasurement(measurement) { function formatNumber(value) {
const parts = []; return Number(value.toFixed(1)).toString();
}
if (measurement.measuredDate) { function buildMeasurementTable(measurements) {
parts.push(formatDetailValue("measuredDate", measurement.measuredDate)); const datedMeasurements = getDatedMeasurements(measurements);
if (!datedMeasurements.length) {
return "";
} }
if (measurement.canopyDiameter !== undefined) { const rows = datedMeasurements
parts.push( .map(
`canopy ${formatDetailValue("canopyDiameter", measurement.canopyDiameter)}`, (measurement) => `
); <tr>
<td>${escapeHtml(measurement.measuredDate)}</td>
<td>${escapeHtml(formatOptionalMeasurement(measurement.canopyDiameter))}</td>
<td>${escapeHtml(formatOptionalMeasurement(measurement.height))}</td>
</tr>
`,
)
.join("");
return `
<div class="measurement-table-block">
<div><span>${escapeHtml(formatDetailLabel("measurements"))}:</span></div>
<table class="measurement-table">
<thead>
<tr>
<th>Date</th>
<th>Canopy dia.</th>
<th>Height</th>
</tr>
</thead>
<tbody>${rows}</tbody>
</table>
</div>
`;
}
function formatOptionalMeasurement(value) {
return value === undefined ? "" : formatMetersAsFeet(value);
}
function hasDatedMeasurements(measurements) {
return getDatedMeasurements(measurements).length > 0;
}
function getDatedMeasurements(measurements) {
if (!Array.isArray(measurements)) {
return [];
} }
if (measurement.height !== undefined) { return measurements.filter((measurement) => measurement.measuredDate);
parts.push(`height ${formatDetailValue("height", measurement.height)}`);
}
return parts.join(", ");
} }
function escapeHtml(value) { function escapeHtml(value) {
+27
View File
@@ -129,6 +129,33 @@ main {
font-family: "Iowan Old Style", "Palatino Linotype", "URW Palladio L", serif; font-family: "Iowan Old Style", "Palatino Linotype", "URW Palladio L", serif;
} }
.measurement-table-block {
margin-top: 0.35rem;
}
.measurement-table {
width: 100%;
margin-top: 0.15rem;
border-collapse: collapse;
font-size: 0.92em;
}
.measurement-table th,
.measurement-table td {
padding: 0.12rem 0.35rem 0.12rem 0;
border-bottom: 1px solid rgba(87, 68, 38, 0.18);
text-align: left;
white-space: nowrap;
}
.measurement-table th {
font-weight: 700;
}
.measurement-table tbody tr:last-child td {
border-bottom: 0;
}
.timeline-control { .timeline-control {
display: grid; display: grid;
gap: 0.45rem; gap: 0.45rem;