From 41fbe71a1f7c1f59b76cb2d0e54bd34e31484759 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Thu, 26 Feb 2026 15:00:28 +0100 Subject: [PATCH] feat: render full map content (image, intro, markers) in PagedJS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix template check 'carte' → 'map' so map subpages are served by API - Add parseMarker() and enrich parseCarte() with static image, intro, markers - Include map children in parseGeoformat() alongside chapters - Resolve map block references in chapters to full carte data - Update narrative store flattening with new carte fields - Replace MapBlock placeholder with full carte rendering (title, image, tags, intro, markers with icons and blocks) - Add default marker-pin.svg for markers without custom icon Co-Authored-By: Claude Opus 4.6 --- public/assets/svg/marker-pin.svg | 1 + public/site/templates/narrative.json.php | 58 +++++++++++++++----- src/components/PagedJsWrapper.vue | 70 ++++++++++++++++++++++-- src/components/blocks/MapBlock.vue | 60 +++++++++++++++++++- src/stores/narrative.js | 4 +- 5 files changed, 171 insertions(+), 22 deletions(-) create mode 100644 public/assets/svg/marker-pin.svg diff --git a/public/assets/svg/marker-pin.svg b/public/assets/svg/marker-pin.svg new file mode 100644 index 0000000..6df71cc --- /dev/null +++ b/public/assets/svg/marker-pin.svg @@ -0,0 +1 @@ + diff --git a/public/site/templates/narrative.json.php b/public/site/templates/narrative.json.php index e8388a8..08b067a 100644 --- a/public/site/templates/narrative.json.php +++ b/public/site/templates/narrative.json.php @@ -106,9 +106,14 @@ function parseBlocks($blocksField, $page) { break; case 'map': - $blockData['content'] = [ - 'map' => $block->map()->value() - ]; + $mapPage = $block->map()->toPages()->first(); + if ($mapPage) { + $blockData['content'] = parseCarte($mapPage); + } else { + $blockData['content'] = [ + 'map' => $block->map()->value() + ]; + } break; default: @@ -135,18 +140,40 @@ function parseChapter($chapter) { ]; } +/** + * Parse un marqueur + */ +function parseMarker($marker) { + return [ + 'title' => $marker->title()->value(), + 'cover' => resolveFileUrl($marker->cover(), $marker), + 'icon' => $marker->markerIcon()->toFile() ? $marker->markerIcon()->toFile()->url() : null, + 'iconSize' => $marker->markerIconSize()->value() ?? 40, + 'blocks' => parseBlocks($marker->text(), $marker) + ]; +} + /** * Parse une carte */ function parseCarte($carte) { + $markers = []; + foreach ($carte->children()->listed() as $child) { + if ($child->intendedTemplate()->name() === 'marker') { + $markers[] = parseMarker($child); + } + } + $staticImage = $carte->file('map-static.png'); return [ - 'id' => $carte->id(), - 'uuid' => $carte->uuid()->toString(), + 'id' => $carte->id(), + 'uuid' => $carte->uuid()->toString(), 'template' => 'carte', - 'title' => $carte->title()->value(), - 'slug' => $carte->slug(), - 'tags' => $carte->tags()->isNotEmpty() ? $carte->tags()->split() : [], - 'text' => resolveImagesInHtml($carte->text()->value(), $carte) + 'title' => $carte->title()->value(), + 'slug' => $carte->slug(), + 'tags' => $carte->tags()->isNotEmpty() ? $carte->tags()->split() : [], + 'image' => $staticImage ? $staticImage->url() : null, + 'intro' => resolveImagesInHtml($carte->text()->value(), $carte), + 'markers' => $markers ]; } @@ -154,10 +181,13 @@ function parseCarte($carte) { * Parse un geoformat */ function parseGeoformat($geoformat) { - $chapters = []; + $children = []; foreach ($geoformat->children()->listed() as $child) { - if ($child->intendedTemplate()->name() === 'chapter') { - $chapters[] = parseChapter($child); + $template = $child->intendedTemplate()->name(); + if ($template === 'chapter') { + $children[] = parseChapter($child); + } elseif ($template === 'map') { + $children[] = parseCarte($child); } } @@ -171,7 +201,7 @@ function parseGeoformat($geoformat) { 'tags' => $geoformat->tags()->isNotEmpty() ? $geoformat->tags()->split() : [], 'cover' => resolveFileUrl($geoformat->cover(), $geoformat), 'text' => resolveImagesInHtml($geoformat->text()->value(), $geoformat), - 'children' => $chapters + 'children' => $children ]; } @@ -197,7 +227,7 @@ foreach ($page->children()->listed() as $child) { if ($template === 'geoformat') { $data['children'][] = parseGeoformat($child); - } elseif ($template === 'carte') { + } elseif ($template === 'map') { $data['children'][] = parseCarte($child); } } diff --git a/src/components/PagedJsWrapper.vue b/src/components/PagedJsWrapper.vue index 8c749df..b7ef613 100644 --- a/src/components/PagedJsWrapper.vue +++ b/src/components/PagedJsWrapper.vue @@ -63,11 +63,41 @@ class="carte" :data-page-type="item.template" > -

{{ item.title }}

+

{{ item.title }}

+
{{ tag }}
-
+
+
+
+
+ + + {{ marker.title }} +
+ + +
+
@@ -186,9 +216,37 @@ const getBlockComponent = (type) => { } .block-map { - background: #f5f5f5; - padding: 2rem; - text-align: center; - border: 1px dashed #ccc; + break-before: page; +} + +.carte-image { + max-width: 100%; + height: auto; +} + +.marker { + margin-top: 1.5rem; +} + +.marker-title { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.marker-icon { + flex-shrink: 0; + object-fit: contain; +} + +.marker-icon--default { + width: 24px; + height: 24px; +} + +.marker-cover { + max-width: 100%; + height: auto; + margin: 0.5rem 0; } diff --git a/src/components/blocks/MapBlock.vue b/src/components/blocks/MapBlock.vue index 92f6041..e674ac2 100644 --- a/src/components/blocks/MapBlock.vue +++ b/src/components/blocks/MapBlock.vue @@ -1,14 +1,72 @@ diff --git a/src/stores/narrative.js b/src/stores/narrative.js index 6f19e88..0a5fb12 100644 --- a/src/stores/narrative.js +++ b/src/stores/narrative.js @@ -61,7 +61,9 @@ export const useNarrativeStore = defineStore('narrative', () => { template: 'carte', title: child.title, tags: child.tags, - text: child.text, + image: child.image, + intro: child.intro, + markers: child.markers, }); } }