From 9296aa9cc69c89660194cc2482966983d4be8317 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Sun, 27 Sep 2026 18:57:26 +0000 Subject: [PATCH] WIP Gospel x Internet adopts the kit's useShareableView for its share links Query mode, the published names as an alias map (links already shared keep restoring), write only on our own leaves. The board's own writer now keeps only view/group/panel/tree. NOT READY: an old multi-value link (band=yes|partial) reads back as one value until the kit reads '|' on parse; the model check pins that case and fails until it does. --- plugin-designs/gospel-internet/board.vue | 7 +++ .../scripts/check-gospel-internet-model.mjs | 13 ++++++ plugin-designs/gospel-internet/src/model.js | 11 +++-- .../gospel-internet/src/useBoard.js | 9 ++-- public/dx-maps/doxa-maps-spa/manifest.json | 4 +- .../gospel-internet/board/board/index.html | 2 +- .../dx-maps/gospel-internet/board/index.html | 2 +- .../board/india-china/index.html | 2 +- .../board/language-tree/index.html | 2 +- .../board/platforms/index.html | 2 +- .../board/project-700/index.html | 2 +- .../gospel-internet/board/zero/index.html | 2 +- .../gospel-internet/gospel-internet.js | 46 +++++++++---------- public/dx-maps/manifest.json | 4 +- 14 files changed, 68 insertions(+), 40 deletions(-) diff --git a/plugin-designs/gospel-internet/board.vue b/plugin-designs/gospel-internet/board.vue index b1105c883..1e2195659 100644 --- a/plugin-designs/gospel-internet/board.vue +++ b/plugin-designs/gospel-internet/board.vue @@ -23,6 +23,8 @@ */ import { ref, computed, onMounted, onBeforeUnmount, watch, getCurrentInstance } from 'vue' import { useDashboardLayout } from '@map/composables/useDashboardLayout.js' +import { useShareableView } from '@map/composables/useShareableView.js' +import { SHARE_FACETS } from './src/model.js' import { useShadowStyles } from '@map/composables/useShadowStyles.js' import { listLabel } from '@map/lists/peopleGroupList.js' import { useBoard } from './src/useBoard.js' @@ -66,6 +68,11 @@ onBeforeUnmount(() => { if (selTimer) clearTimeout(selTimer) }) // board opens already in its state: no flash of the default view, and the first render mounts the panel // the preset asks for (the language tree included) where a headless mount check can see it. board.readUrl() +// SHARE LINKS FROM THE KIT (useShareableView, query mode): the filters and the typed search live in the +// URL under the board's published names (?access= ?band= ?country= …, the alias map keeps links already +// shared working), restored on every load, written ONLY on our own leaves (urlState:'query') so a +// partner's address bar is never rewritten. facetKeys is explicit: its default reads nothing on a cold load. +useShareableView(bus, { mode: 'query', write: board.profileConfig.value?.urlState === 'query', facetKeys: SHARE_FACETS }) // ── responsive: one panel at a time under 760px (ResizeObserver on the shell, not @container: a // container query cannot target the container itself, which is unreliable inside a shadow root) ────── diff --git a/plugin-designs/gospel-internet/scripts/check-gospel-internet-model.mjs b/plugin-designs/gospel-internet/scripts/check-gospel-internet-model.mjs index 3f2025ccc..00c15b66d 100644 --- a/plugin-designs/gospel-internet/scripts/check-gospel-internet-model.mjs +++ b/plugin-designs/gospel-internet/scripts/check-gospel-internet-model.mjs @@ -141,6 +141,19 @@ for (const n of ix.nodes) if (!n.p) { const x = scZero.get(n.id); gy += x.g + x. ok(gy === 0, `with only zero-access groups in scope, no family counts a green or yellow language (${gy})`) bus.clearFilters() +// 12. share links through the kit (useShareableView): the board's published names map to its bus keys, +// and a link already shared restores (single values, and multi-values written with '|') +const SV = await import(resolve(REPO, 'library/composables/useShareableView.js')) +const r1 = SV.parseQuery('?access=bridge&country=IND&wayin=deaf&app=Telegram%20Messenger', M.SHARE_FACETS) +ok(r1.filters.access_level === 'bridge' && r1.filters.country === 'IND' && r1.filters.way_in === 'deaf' && r1.filters.messaging === 'Telegram Messenger', + 'kit parser maps ?access= ?wayin= ?app= to the bus keys (old single-value links restore)') +const r2 = SV.parseQuery('?band=yes|partial', M.SHARE_FACETS) +ok(Array.isArray(r2.filters.band) && r2.filters.band.join(',') === 'yes,partial', `an old multi-value link (band=yes|partial) restores as two values (got ${JSON.stringify(r2.filters.band)})`) +const w = SV.serializeQuery({ access_level: 'bridge', band: ['yes', 'partial'] }, '', '?view=zero&utm_source=x', { facetKeys: M.SHARE_FACETS }) +ok(w.includes('access=bridge') && w.includes('view=zero') && w.includes('utm_source=x') && !w.includes('access_level'), `the kit writes the published names and keeps the board's own params (${w})`) +const mine = M.buildQuery({ view: 'zero', filterSet: { band: 'yes' }, keep: '?band=yes,partial', filters: false }) +ok(mine.includes('band=yes%2Cpartial') && mine.includes('view=zero'), 'the board\'s own writer leaves the filter params to the kit (filters:false)') + // 11. translation readiness: current against its snapshot, every roster language present, the no-NT set is // the tree's, the 31 codes Glottolog lacks read as UNKNOWN (null) not "none", and the signal count is a // recount of the five named facts (no hidden weighting) diff --git a/plugin-designs/gospel-internet/src/model.js b/plugin-designs/gospel-internet/src/model.js index f16731a9d..122fbde53 100644 --- a/plugin-designs/gospel-internet/src/model.js +++ b/plugin-designs/gospel-internet/src/model.js @@ -82,6 +82,9 @@ export const URL_KEYS = { app: 'messaging', } export const VIEWS = ['board', 'zero', 'province', 'platforms'] +/** The board's URL filter names -> bus keys, for the kit's useShareableView (query mode, alias map). + * The published names are kept so links already shared keep restoring. */ +export const SHARE_FACETS = Object.fromEntries(Object.entries(URL_KEYS)) /** Parse `?view=&access=…&group=` into { view, filters, group }. Unknown views fall back to board. */ export function parseQuery(search) { @@ -109,13 +112,15 @@ export function parseQuery(search) { } /** The inverse: filterSet + view + group -> a query string (no leading '?'), stable key order. */ -export function buildQuery({ view, filterSet, group, keep, panel, tree } = {}) { +export function buildQuery({ view, filterSet, group, keep, panel, tree, filters = true } = {}) { const q = new URLSearchParams(keep || '') - for (const name of [...Object.keys(URL_KEYS), 'view', 'group', 'panel', 'tree']) q.delete(name) + // filters:false = the FILTER params belong to another writer (the kit's useShareableView): neither + // delete nor write them, so the two writers never fight over one address bar + for (const name of [...(filters ? Object.keys(URL_KEYS) : []), 'view', 'group', 'panel', 'tree']) q.delete(name) if (view && view !== 'board') q.set('view', view) if (panel === 'tree') q.set('panel', 'tree') if (tree) q.set('tree', tree) - for (const [name, key] of Object.entries(URL_KEYS)) { + if (filters) for (const [name, key] of Object.entries(URL_KEYS)) { if (tree && key === 'language') continue const v = filterSet?.[key] if (v === undefined || v === null || v === '') continue diff --git a/plugin-designs/gospel-internet/src/useBoard.js b/plugin-designs/gospel-internet/src/useBoard.js index feb2c6b70..a7a4022b0 100644 --- a/plugin-designs/gospel-internet/src/useBoard.js +++ b/plugin-designs/gospel-internet/src/useBoard.js @@ -164,9 +164,12 @@ export function useBoard() { const q = M.parseQuery(location.search) const hostView = cfg().view setView(q.view !== 'board' ? q.view : (M.VIEWS.includes(hostView) ? hostView : 'board')) - // Explicit facets in the URL (or the host's profile-config `filters`) narrow the preset further. + // The host's profile-config `filters` narrow the preset; URL FILTER params are read by the kit's + // useShareableView (board.vue), except Gospel Resources' ?codes= / ?code=, which are this board's. const hostFilters = cfg().filters && typeof cfg().filters === 'object' ? cfg().filters : {} - for (const [k, v] of Object.entries({ ...hostFilters, ...q.filters })) if (k in M.FACET_ACC) bus.setFilter(k, v) + for (const [k, v] of Object.entries(hostFilters)) if (k in M.FACET_ACC) bus.setFilter(k, v) + const codes = [...new URLSearchParams(location.search).getAll('codes'), ...new URLSearchParams(location.search).getAll('code')].length ? q.filters.language : null + if (codes) bus.setFilter('language', codes) const group = q.group || cfg().group || '' if (group) pendingGroup = group const panel = q.panel === 'tree' || cfg().panel === 'tree' ? 'tree' : 'map' @@ -186,7 +189,7 @@ export function useBoard() { function syncUrl() { if (!writeUrl.value || typeof history === 'undefined') return const qs = M.buildQuery({ view: view.value, filterSet: bus.filterSet, group: openSlug.value, keep: location.search, - panel: centre.value, tree: treeNode.value }) + panel: centre.value, tree: treeNode.value, filters: false }) const next = location.pathname + (qs ? '?' + qs : '') + location.hash if (next !== location.pathname + location.search + location.hash) { try { history.replaceState(history.state, '', next) } catch (_) { /* sandboxed */ } diff --git a/public/dx-maps/doxa-maps-spa/manifest.json b/public/dx-maps/doxa-maps-spa/manifest.json index 8936e0a69..b2cf2c0f6 100644 --- a/public/dx-maps/doxa-maps-spa/manifest.json +++ b/public/dx-maps/doxa-maps-spa/manifest.json @@ -604,7 +604,7 @@ "bundle": "gospel-internet", "scriptUrl": "./gospel-internet/gospel-internet.js", "output": "dx-maps/gospel-internet/gospel-internet.js", - "integrity": "sha384-wRWCJhXf3QrvCUO5i22k46dpJFvQWnI8dmA1jLl2l4YkiomWTVYPjTfXlKz3HRez", + "integrity": "sha384-3be8zy4914UlmNZka99aGQPzEbp80c2Zr4ES+kvPMwW7SEzWNfxYEJgqgpbHr18d", "elements": [ "gospel-internet-board" ], @@ -623,7 +623,7 @@ "scriptUrl": "./gospel-internet/gospel-internet.js", "embed": { "iframe": "", - "script": "\n\n\n\n" + "script": "\n\n\n\n" }, "instances": [ { diff --git a/public/dx-maps/gospel-internet/board/board/index.html b/public/dx-maps/gospel-internet/board/board/index.html index 1b56433fc..675cb5873 100644 --- a/public/dx-maps/gospel-internet/board/board/index.html +++ b/public/dx-maps/gospel-internet/board/board/index.html @@ -36,7 +36,7 @@ - + - + - + - + - + - + - + \n\n" + "script": "\n\n\n\n" }, "instances": [ {