feat: add travelling branch and GPX to home map (active trip mode)

This commit is contained in:
2026-06-21 01:43:24 +02:00
parent b1cffca953
commit 8edbfd2dd3
+70 -19
View File
@@ -1,21 +1,25 @@
{% extends 'partials/base.html.twig' %}
{% block content %}
{% set slug = config.site.active_trip %}
{% set trip = grav.pages.find('/trips/' ~ slug) %}
{% set dailies_page = grav.pages.find('/trips/' ~ slug ~ '/dailies') %}
{% set stories_page = grav.pages.find('/trips/' ~ slug ~ '/stories') %}
{% set trip_route = config.site.active_trip %}
{% set trip = grav.pages.find(trip_route) %}
{% if config.site.travelling %}
{# ══════════════════════════════════════════════════════════ ACTIVE TRIP MODE #}
{% set dailies_page = grav.pages.find(trip_route ~ '/dailies') %}
{% set stories_page = grav.pages.find(trip_route ~ '/stories') %}
{% set journal_entries = dailies_page ? dailies_page.children.published() : [] %}
{% set story_entries = stories_page ? stories_page.children.published() : [] %}
{% set all_items = [] %}
{% for e in journal_entries %}
{% set all_items = all_items|merge([{'type': 'journal', 'page': e, 'date': e.date}]) %}
{% set all_items = all_items|merge([{'type': 'journal', 'page': e, 'date': e.header.date}]) %}
{% endfor %}
{% for s in story_entries %}
{% set all_items = all_items|merge([{'type': 'story', 'page': s, 'date': s.date}]) %}
{% set all_items = all_items|merge([{'type': 'story', 'page': s, 'date': s.header.date}]) %}
{% endfor %}
{% set all_items = all_items|sort((a, b) => a.date < b.date ? 1 : -1) %}
{% set all_items = all_items|sort_by_key('date', 3) %}
{% set journal_count = journal_entries|length %}
{% set story_count = story_entries|length %}
@@ -28,11 +32,21 @@
'lng': item.page.header.lng|number_format(6, '.', ''),
'slug': item.page.slug,
'title': item.page.title,
'url': item.page.url
'url': item.page.url,
'force_connect': item.page.header.force_connect ? true : false
}]) %}
{% endif %}
{% endfor %}
{% set home_gpx_urls = [] %}
{% if trip %}
{% for name, media in trip.media.all %}
{% if name|split('.')|last == 'gpx' %}
{% set home_gpx_urls = home_gpx_urls|merge([trip.url ~ '/' ~ name]) %}
{% endif %}
{% endfor %}
{% endif %}
<div class="home-layout">
<div class="home-map-col">
<div class="home-map" id="home-map"></div>
@@ -40,7 +54,7 @@
<div class="home-feed-col">
<div class="home-trip-header">
<h1 class="home-trip-name">{{ trip ? trip.title : slug }}</h1>
<h1 class="home-trip-name">{{ trip ? trip.title : trip_route }}</h1>
<span class="home-trip-counts">
{{ journal_count }} journal {{ journal_count == 1 ? 'entry' : 'entries' }}
{% if story_count > 0 %} · {{ story_count }} {{ story_count == 1 ? 'story' : 'stories' }}{% endif %}
@@ -108,15 +122,15 @@
{% set hero = entry.media.images|first %}
{% endif %}
<a class="entry-card entry-card--story" id="entry-{{ entry.slug }}" href="{{ entry.url }}">
{% if hero %}
<div class="entry-card-photo entry-card-photo--story">
<img src="{{ hero.cropResize(720, 405).url }}" alt="{{ entry.title }}" loading="lazy">
</div>
{% endif %}
<div class="entry-card-body">
<span class="story-badge">✦ Story</span>
<h2 class="entry-title">{{ entry.title }}</h2>
</div>
{% if hero %}
<div class="entry-card-photo entry-card-photo--story">
<img src="{{ hero.cropResize(720, 405).url }}" alt="{{ entry.title }}" loading="lazy">
</div>
{% endif %}
<div class="entry-card-body">
<span class="story-badge">✦ Story</span>
<h2 class="entry-title">{{ entry.title }}</h2>
</div>
</a>
{% endif %}
{% endfor %}
@@ -130,9 +144,13 @@
{% if map_entries|length > 0 %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@4/dist/maplibre-gl.css">
<script src="https://cdn.jsdelivr.net/npm/maplibre-gl@4/dist/maplibre-gl.js"></script>
{% if home_gpx_urls|length > 0 %}
<script src="https://cdn.jsdelivr.net/npm/@mapbox/togeojson@0.16.2/togeojson.min.js"></script>
{% endif %}
<script src="{{ url('theme://js/maplibre-utils.js') }}"></script>
<script>
var HOME_ENTRIES = {{ map_entries|json_encode|raw }};
var HOME_ENTRIES = {{ map_entries|json_encode|raw }};
var HOME_GPX_URLS = {{ home_gpx_urls|json_encode|raw }};
var homeMap = new maplibregl.Map({
container: 'home-map',
@@ -166,6 +184,7 @@ homeMap.on('load', function () {
new maplibregl.Marker({ element: el }).setLngLat(lngLat).addTo(homeMap);
});
/* Draw simple journey line immediately; replaced below if GPX is present */
MapUtils.addJourneyLine(homeMap, coords, 'home-journey');
if (HOME_ENTRIES.length === 1) {
@@ -175,7 +194,39 @@ homeMap.on('load', function () {
}
setTimeout(function () { homeMap.resize(); }, 100);
if (HOME_GPX_URLS.length > 0) {
Promise.all(HOME_GPX_URLS.map(function (url, idx) {
return fetch(url)
.then(function (r) { return r.text(); })
.then(function (text) {
var xml = new DOMParser().parseFromString(text, 'text/xml');
var geojson = toGeoJSON.gpx(xml);
var sid = 'home-gpx-' + idx;
homeMap.addSource(sid, { type: 'geojson', data: geojson });
homeMap.addLayer({
id: sid + '-line', type: 'line', source: sid,
layout: { 'line-join': 'round', 'line-cap': 'round' },
paint: { 'line-color': MapUtils.ACCENT, 'line-width': 2, 'line-opacity': 0.7 }
});
return MapUtils.extractTrackpoints(geojson);
})
.catch(function (err) { console.warn('GPX load failed:', url, err); return []; });
})).then(function (allTrackpoints) {
if (homeMap.getLayer('home-journey')) homeMap.removeLayer('home-journey');
if (homeMap.getSource('home-journey')) homeMap.removeSource('home-journey');
var valid = allTrackpoints.filter(function (tp) { return tp.length > 0; });
var segments = MapUtils.buildJourneySegments(HOME_ENTRIES, valid, 10);
MapUtils.addJourneySegments(homeMap, segments, 'home-journey');
});
}
});
</script>
{% endif %}
{% else %}
{# ════════════════════════════════════════════════ BETWEEN-TRIPS MODE (Task 3) #}
<p class="feed-empty" style="padding: 2rem;">Off season — highlights coming in Task 3.</p>
{% endif %}
{% endblock %}