From 2f26f61ea4358ebe9198702dbf0f0dde970ed8f9 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Mon, 28 Sep 2026 20:04:07 +0000 Subject: [PATCH] Draw the set charts at all, and give their figures room to be drawn in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neither chart drew anything. createBoardMap already awaits the map's load event and resolves after it, so attaching a second load handler waited for something that had already happened: the layer setup never ran, each map held only its basemap layers, and the panel showed an empty whiteboard. It failed silently, which is why the visible-failure branch did not catch it. Nothing threw — the map was fine, the source was simply never added. A guard that reports errors cannot report an absence of work. The setup now runs directly after the await, and still binds once('load') if a future engine resolves earlier. That keeps the fix correct rather than merely right today. The figures also grow from a zero basis instead of from their content. The map inside is absolutely positioned and has no intrinsic width, so a basis of auto asks for a content size of nothing and the legend takes the column — the figure was measured at 39 pixels across while the decoder had the rest. This was hidden behind the first bug: an empty chart and a chart with no room look the same. --- .../gospel-internet/src/components/GiBoundedSet.vue | 2 +- .../src/components/GiBoundedSetMap.vue | 11 +++++++++-- .../gospel-internet/src/components/GiCenteredSet.vue | 7 ++++++- .../src/components/GiCenteredSetMap.vue | 11 +++++++++-- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/plugin-designs/gospel-internet/src/components/GiBoundedSet.vue b/plugin-designs/gospel-internet/src/components/GiBoundedSet.vue index fd7164abe..bfe735d83 100644 --- a/plugin-designs/gospel-internet/src/components/GiBoundedSet.vue +++ b/plugin-designs/gospel-internet/src/components/GiBoundedSet.vue @@ -74,7 +74,7 @@ useShadowStyles( // can never push the figure out of its pane the way the legend did on the centered set. '.gbs{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;' + 'justify-content:center;padding:46px 10px 10px;box-sizing:border-box;overflow:hidden;background:#f3f3f1}' + - '.gbs-fig{position:relative;flex:1 1 auto;align-self:stretch;min-height:0;min-width:0}' + + '.gbs-fig{position:relative;flex:1 1 0%;align-self:stretch;min-height:240px;min-width:0}' + '.gbs-ring{fill:none;stroke:#3b463d;stroke-width:1.5}' + '.gbs-in{fill:#92b195}.gbs-out{fill:#6d766e;opacity:.65}' + '.gbs-cross-halo{stroke:var(--gbs-bg,#f3f3f1);stroke-width:7;stroke-linecap:square}' + diff --git a/plugin-designs/gospel-internet/src/components/GiBoundedSetMap.vue b/plugin-designs/gospel-internet/src/components/GiBoundedSetMap.vue index 0724c469c..492fef198 100644 --- a/plugin-designs/gospel-internet/src/components/GiBoundedSetMap.vue +++ b/plugin-designs/gospel-internet/src/components/GiBoundedSetMap.vue @@ -59,7 +59,13 @@ onMounted(async () => { { whiteboard: true, boundaries: false, center: [0, 0], zoom: 1 }) const map = markRaw(made.map || made) mapRef.value = map - map.on('load', () => { + // ★ createBoardMap ALREADY AWAITS LOAD. boardEngine resolves only after + // `await new Promise(res => map.once('load', res))`, so by the time this runs the event has + // fired and will not fire again — a second `map.on('load', …)` never runs and the layers are + // never added. The chart then draws a basemap-less whiteboard with no source on it: empty, + // silent, and with nothing thrown for a failure branch to catch. + // Guarded rather than assumed: if a future engine resolves earlier, once('load') still fires. + const setup = () => { handle.value = markRaw(addTieredPointLayers(map, { data: data.value, sourceId: 'gbsm', @@ -79,7 +85,8 @@ onMounted(async () => { }, font: labelFont, })) - }) + } + if (map.loaded()) setup(); else map.once('load', setup) } catch (e) { failed.value = String(e?.message || e) } diff --git a/plugin-designs/gospel-internet/src/components/GiCenteredSet.vue b/plugin-designs/gospel-internet/src/components/GiCenteredSet.vue index ea099fc3e..29a7d752f 100644 --- a/plugin-designs/gospel-internet/src/components/GiCenteredSet.vue +++ b/plugin-designs/gospel-internet/src/components/GiCenteredSet.vue @@ -127,7 +127,12 @@ useShadowStyles( // when the same rule is written twice. // min-height in the narrow column: a flex child with auto content can resolve to zero height, // which is what a 0x0 chart is. rega measured exactly that at 390px. - '.gcs-fig{position:relative;flex:1 1 auto;align-self:stretch;min-width:0;min-height:240px;' + + // flex-basis 0, not auto. The map inside is position:absolute, so the figure has NO intrinsic + // width to be sized from — with basis auto it asks for its content, the content is nothing, and + // the legend beside it takes the column. rega measured the figure at 39px across while the + // decoder card had the rest. Growing from zero makes the figure take the remaining space + // whatever it happens to contain. + '.gcs-fig{position:relative;flex:1 1 0%;align-self:stretch;min-width:0;min-height:240px;' + 'display:flex;flex-direction:column;align-items:center;justify-content:center;overflow:hidden}' + '.gcs-aside{flex:0 1 340px;min-width:0;min-height:0;overflow:auto;display:flex;align-items:flex-start}' + '.gcs-legend-toggle{width:100%;padding:6px 10px;border:1px solid #d1d4cd;border-radius:8px;' + diff --git a/plugin-designs/gospel-internet/src/components/GiCenteredSetMap.vue b/plugin-designs/gospel-internet/src/components/GiCenteredSetMap.vue index 8c5c0210a..87f0176a7 100644 --- a/plugin-designs/gospel-internet/src/components/GiCenteredSetMap.vue +++ b/plugin-designs/gospel-internet/src/components/GiCenteredSetMap.vue @@ -79,7 +79,13 @@ onMounted(async () => { { whiteboard: true, boundaries: false, center: [0, 0], zoom: 1 }) const map = markRaw(made.map || made) mapRef.value = map - map.on('load', () => { + // ★ createBoardMap ALREADY AWAITS LOAD. boardEngine resolves only after + // `await new Promise(res => map.once('load', res))`, so by the time this runs the event has + // fired and will not fire again — a second `map.on('load', …)` never runs and the layers are + // never added. The chart then draws a basemap-less whiteboard with no source on it: empty, + // silent, and with nothing thrown for a failure branch to catch. + // Guarded rather than assumed: if a future engine resolves earlier, once('load') still fires. + const setup = () => { handle.value = markRaw(addTieredPointLayers(map, { data: data.value, sourceId: 'gcsm', @@ -96,7 +102,8 @@ onMounted(async () => { onClick: (id, f) => { const r = f?.properties?.ring; if (r != null) emit('select', r) }, })) ready.value = true - }) + } + if (map.loaded()) setup(); else map.once('load', setup) } catch (e) { // FAILS VISIBLY: an empty whiteboard is indistinguishable from a chart with no groups. failed.value = String(e?.message || e)