From 3ab1c50cc8edc8434358d1abc04ea4b243976eea Mon Sep 17 00:00:00 2001 From: Jon Seager Date: Tue, 3 Feb 2026 15:10:21 +0000 Subject: [PATCH] refactor(timeline): remove map pin icon from timeline title Position is already shown as a clickable detail row in the card body, making the title icon redundant. Also removes the unused map_link field from TimelineEventView. --- scripts/bootstrap-db.sh | 7 +++++++ src/infrastructure/repositories/cafes.rs | 7 +++++++ src/presentation/web/views.rs | 18 +++++++++++++++++- templates/partials/timeline_month.html | 4 ++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/scripts/bootstrap-db.sh b/scripts/bootstrap-db.sh index 54a5c63..12a1487 100755 --- a/scripts/bootstrap-db.sh +++ b/scripts/bootstrap-db.sh @@ -1266,6 +1266,13 @@ WHERE entity_type = 'cafe' AND entity_id = (SELECT id FROM cafes WHERE name = 'F UPDATE timeline_events SET occurred_at = datetime('2026-01-11 14:00:00') WHERE entity_type = 'cafe' AND entity_id = (SELECT id FROM cafes WHERE name = 'Small Street Espresso'); +-- Rebuild cafe timeline details_json to include Position field +UPDATE timeline_events SET details_json = ( + SELECT '[{"label":"City","value":"' || c.city || '"},{"label":"Country","value":"' || c.country || '"},{"label":"Website","value":"' || COALESCE(NULLIF(c.website, ''), '—') || '"},{"label":"Position","value":"https://www.google.com/maps?q=' || c.latitude || ',' || c.longitude || '"}]' + FROM cafes c WHERE c.id = timeline_events.entity_id +) +WHERE entity_type = 'cafe'; + -- Bag timeline events (match bag created_at) UPDATE timeline_events SET occurred_at = datetime('2025-09-28 10:00:00') WHERE entity_type = 'bag' AND entity_id = (SELECT id FROM bags WHERE roast_id = (SELECT id FROM roasts WHERE name = 'Gatomboya')); diff --git a/src/infrastructure/repositories/cafes.rs b/src/infrastructure/repositories/cafes.rs index 0fa0b03..682ab87 100644 --- a/src/infrastructure/repositories/cafes.rs +++ b/src/infrastructure/repositories/cafes.rs @@ -86,6 +86,13 @@ impl SqlCafeRepository { label: "Website".to_string(), value: website_value, }, + TimelineEventDetail { + label: "Position".to_string(), + value: format!( + "https://www.google.com/maps?q={},{}", + cafe.latitude, cafe.longitude + ), + }, ]; serde_json::to_string(&details).map_err(|err| { diff --git a/src/presentation/web/views.rs b/src/presentation/web/views.rs index 8846caa..b4fcc6b 100644 --- a/src/presentation/web/views.rs +++ b/src/presentation/web/views.rs @@ -461,6 +461,7 @@ impl RoastView { pub struct TimelineEventDetailView { pub label: String, pub value: String, + pub link: Option, } /// Raw brew data for repeating a brew from the timeline. @@ -541,15 +542,30 @@ impl TimelineEventView { let mut mapped_details = Vec::new(); let mut external_link = None; for detail in details { - if detail.label.eq_ignore_ascii_case("homepage") { + if detail.label.eq_ignore_ascii_case("homepage") + || detail.label.eq_ignore_ascii_case("website") + { let trimmed = detail.value.trim(); if !trimmed.is_empty() && trimmed != "—" { external_link = Some(trimmed.to_string()); } + } else if detail.label.eq_ignore_ascii_case("position") { + let trimmed = detail.value.trim(); + if !trimmed.is_empty() { + let display = trimmed + .strip_prefix("https://www.google.com/maps?q=") + .unwrap_or(trimmed); + mapped_details.push(TimelineEventDetailView { + label: detail.label, + value: display.to_string(), + link: Some(trimmed.to_string()), + }); + } } else { mapped_details.push(TimelineEventDetailView { label: detail.label, value: detail.value, + link: None, }); } } diff --git a/templates/partials/timeline_month.html b/templates/partials/timeline_month.html index e241cbc..fffee63 100644 --- a/templates/partials/timeline_month.html +++ b/templates/partials/timeline_month.html @@ -89,7 +89,11 @@ {% for detail in event.details %}
{{ detail.label }}
+ {% if let Some(url) = detail.link %} +
{{ detail.value }}
+ {% else %}
{{ detail.value }}
+ {% endif %}
{% endfor %}