Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work
# Conflicts: # public/dx-maps/doxa-maps-spa/manifest.json # public/dx-maps/gospel-resources/charts/index.html # public/dx-maps/gospel-resources/data-tables/index.html # public/dx-maps/gospel-resources/gospel-dashboard/index.html # public/dx-maps/gospel-resources/gospel-resources.js # public/dx-maps/gospel-resources/resources-list/index.html # public/dx-maps/gospel-resources/resources-map/index.html # public/dx-maps/manifest.json
This commit is contained in:
commit
29f4ab7097
88 changed files with 1779 additions and 1160 deletions
|
|
@ -117,6 +117,8 @@ and a change here can break other maps.
|
|||
`import … from '@map/composables/useAvatarGenerator.js'`
|
||||
- **useCountryOutline** — useCountryOutline.js — country boundary OUTLINE overlay on country search.
|
||||
`import … from '@map/composables/useCountryOutline.js'`
|
||||
- **useDashboardLayout** — useDashboardLayout.js — reusable drag-resize + persistence engine for the CMV dashboard grid.
|
||||
`import … from '@map/composables/useDashboardLayout.js'`
|
||||
- **useDocumentFont** — useDocumentFont.js — register a self-hosted @font-face at DOCUMENT level, once per page.
|
||||
`import … from '@map/composables/useDocumentFont.js'`
|
||||
- **useEdgeScrollAffordance** — useEdgeScrollAffordance — the gray "you can scroll past this" edge strips.
|
||||
|
|
|
|||
166
internal/check-no-silent-engine-substitution.mjs
Normal file
166
internal/check-no-silent-engine-substitution.mjs
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* check-no-silent-engine-substitution — a profile must never fall back to a DIFFERENT map engine than
|
||||
* the one its provider asked for.
|
||||
*
|
||||
* THE DEFECT, found by regions' C3 read and routed by dx-shepherd (END-SHEP-C3C, 2026-09-26):
|
||||
*
|
||||
* const gl = engineGlobal(provider) || window.mapboxgl
|
||||
*
|
||||
* That `||` looks like ordinary defensive coding and is not. engineGlobal() ALREADY resolves mapbox's own
|
||||
* global for the mapbox case — useMapInstance.js:115 is
|
||||
* `ENGINES[provider]?.global || ENGINES.mapbox.global`, which falls back to mapbox's NAME only for an
|
||||
* UNKNOWN provider name, never for a missing engine. So the expression can fire in exactly ONE situation:
|
||||
* the page asked for 'maplibre' and MapLibre failed to load. It then hands back MAPBOX — the token-gated
|
||||
* engine — to a page that explicitly asked for the keyless one, breaking the keyless contract
|
||||
* research-map.instances.json documents.
|
||||
*
|
||||
* ★ AND THE SUBSTITUTE IS BROKEN BY CONSTRUCTION, which is what makes this worth a gate rather than a
|
||||
* one-line fix. These profiles gate `gl.accessToken = token` on `if (!isMaplibre)`, so a maplibre request
|
||||
* that fell through to Mapbox got Mapbox WITHOUT a token: 401s on every tile instead of a legible failure.
|
||||
* A fallback that cannot produce a working map even in principle is strictly worse than no fallback,
|
||||
* because it converts a diagnosable error into a mysterious one.
|
||||
*
|
||||
* ⚠ WHY THE THREE EXISTING ENGINE GATES DID NOT CATCH IT, and why this is not a duplicate of them:
|
||||
* check-leaf-engine-per-provider — a leaf loads the engine its provider asks for
|
||||
* check-provider-switch — the page-level switch reaches a raw-built map
|
||||
* check-auto-engine — 'auto' resolves to Mapbox with a token, MapLibre without
|
||||
* All three assert the HAPPY PATH: what happens when engines load. This bug only appears when one does
|
||||
* NOT load, so all three were green for as long as it existed. The property here is the negative one —
|
||||
* "when the requested engine is absent, no other engine is substituted" — and nothing asserted it.
|
||||
*
|
||||
* ⚠ IT IS A SOURCE CHECK, ON PURPOSE. Reproducing it at the rendered layer means serving a leaf with
|
||||
* MapLibre deliberately blocked, which is a browser run for a defect whose whole signature is one
|
||||
* expression. The source is the authoritative place: the fallback either appears in the file or it does
|
||||
* not. A browser gate here would cost a slot to measure something a grep decides.
|
||||
*
|
||||
* Usage: node internal/check-no-silent-engine-substitution.mjs
|
||||
* node internal/check-no-silent-engine-substitution.mjs --self-test
|
||||
*/
|
||||
import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs'
|
||||
import { resolve, dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const HERE = dirname(fileURLToPath(import.meta.url))
|
||||
const REPO = process.env.DOXA_REPO || resolve(HERE, '..')
|
||||
const ROOT = join(REPO, 'plugin-designs')
|
||||
|
||||
// ⚠ FLAGS FILTERED FROM THE POSITIONAL READ. A bare `--self-test` was otherwise taken as a path, which
|
||||
// has bitten this repo three times (--self-test read as a leaf, --emit read as a baseUrl, --poison read
|
||||
// as a packet).
|
||||
const SELF_TEST = process.argv.includes('--self-test')
|
||||
|
||||
// The substitution to refuse: engineGlobal(...) OR-ed with a specific engine's global. Any of these
|
||||
// named globals on the right of a `||` after engineGlobal is a cross-engine fallback by definition —
|
||||
// engineGlobal already returns the RIGHT global for the requested provider, so the only thing an `||`
|
||||
// can add is a DIFFERENT engine.
|
||||
const ENGINE_GLOBALS = ['mapboxgl', 'maplibregl']
|
||||
const PATTERN = new RegExp(
|
||||
String.raw`engineGlobal\s*\([^)]*\)\s*\|\|\s*(?:window\.)?(${ENGINE_GLOBALS.join('|')})\b`,
|
||||
'g',
|
||||
)
|
||||
|
||||
function scan(text) {
|
||||
const hits = []
|
||||
const lines = text.split('\n')
|
||||
lines.forEach((line, i) => {
|
||||
// Skip comment lines: this file's own documentation quotes the bad pattern, and so does every fix
|
||||
// that explains what it removed. A gate that fails on its own explanation teaches people to delete
|
||||
// the explanation.
|
||||
const t = line.trim()
|
||||
if (t.startsWith('//') || t.startsWith('*') || t.startsWith('/*')) return
|
||||
PATTERN.lastIndex = 0
|
||||
let m
|
||||
while ((m = PATTERN.exec(line)) !== null) hits.push({ line: i + 1, engine: m[1], text: t.slice(0, 110) })
|
||||
})
|
||||
return hits
|
||||
}
|
||||
|
||||
if (SELF_TEST) {
|
||||
// ★ PROVE THE PATTERN FIRES BEFORE TRUSTING A GREEN RUN. A source gate that has never matched anything
|
||||
// is indistinguishable from a broken regex, and this one's whole value is that it matches.
|
||||
const should = [
|
||||
'const gl = engineGlobal(upgProvider) || window.mapboxgl',
|
||||
' const gl = engineGlobal(p)||maplibregl',
|
||||
'let gl = engineGlobal( provider ) || window.maplibregl;',
|
||||
]
|
||||
const shouldNot = [
|
||||
'const gl = engineGlobal(upgProvider)',
|
||||
'// const gl = engineGlobal(p) || window.mapboxgl <- the removed fallback',
|
||||
'const gl = engineGlobal(p) || null',
|
||||
'const token = mapboxToken?.value || profileConfig?.value?.tk || \'\'',
|
||||
]
|
||||
let bad = 0
|
||||
for (const s of should) {
|
||||
const n = scan(s).length
|
||||
console.log(` ${n ? 'MATCHED ' : 'MISSED '} ${s.trim().slice(0, 62)}`)
|
||||
if (!n) bad++
|
||||
}
|
||||
for (const s of shouldNot) {
|
||||
const n = scan(s).length
|
||||
console.log(` ${n ? 'FALSE+ ' : 'ignored '} ${s.trim().slice(0, 62)}`)
|
||||
if (n) bad++
|
||||
}
|
||||
if (bad) {
|
||||
console.error(`\nNO-SILENT-ENGINE-SUBSTITUTION --self-test: FAIL — ${bad} case(s) wrong.`)
|
||||
process.exit(1)
|
||||
}
|
||||
console.log('\nNO-SILENT-ENGINE-SUBSTITUTION --self-test: PASS — the pattern matches every real form '
|
||||
+ 'and ignores comments, a null fallback and an unrelated token chain.')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
if (!existsSync(ROOT)) {
|
||||
console.log(`NO-SILENT-ENGINE-SUBSTITUTION: NOT MEASURED — no plugin-designs tree at ${ROOT}`)
|
||||
process.exit(75)
|
||||
}
|
||||
|
||||
const findings = []
|
||||
let scanned = 0
|
||||
const walk = (dir) => {
|
||||
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
||||
const p = join(dir, e.name)
|
||||
if (e.isDirectory()) {
|
||||
if (e.name === 'node_modules' || e.name === 'dist' || e.name.startsWith('.')) continue
|
||||
walk(p)
|
||||
} else if (/\.(vue|js|mjs)$/.test(e.name)) {
|
||||
let text
|
||||
try { text = readFileSync(p, 'utf8') } catch { continue }
|
||||
if (!text.includes('engineGlobal')) continue
|
||||
scanned++
|
||||
for (const h of scan(text)) findings.push({ file: p.slice(REPO.length + 1), ...h })
|
||||
}
|
||||
}
|
||||
}
|
||||
walk(ROOT)
|
||||
|
||||
console.log('NO-SILENT-ENGINE-SUBSTITUTION')
|
||||
console.log(` ${scanned} file(s) call engineGlobal()`)
|
||||
|
||||
// ⚠ REFUSE TO JUDGE rather than pass vacuously. If nothing in the tree calls engineGlobal at all, the
|
||||
// pattern had nothing to match and a green result would mean "I found no files", not "the code is clean".
|
||||
if (!scanned) {
|
||||
console.log('NO-SILENT-ENGINE-SUBSTITUTION: NOT MEASURED — no file calls engineGlobal(), so there was '
|
||||
+ 'nothing to check. Exit 75 rather than 0: "found nothing" is not "found nothing wrong".')
|
||||
process.exit(75)
|
||||
}
|
||||
|
||||
if (findings.length) {
|
||||
console.error(`\nNO-SILENT-ENGINE-SUBSTITUTION: FAIL — ${findings.length} silent engine substitution(s).`)
|
||||
for (const f of findings) {
|
||||
console.error(` ✗ ${f.file}:${f.line} falls back to ${f.engine}`)
|
||||
console.error(` ${f.text}`)
|
||||
}
|
||||
console.error('\n engineGlobal() ALREADY returns the right global for the requested provider, so an `||`')
|
||||
console.error(' after it can only supply a DIFFERENT engine — and it fires only when the page asked for')
|
||||
console.error(' maplibre and maplibre failed to load. A page that asked for the KEYLESS engine then')
|
||||
console.error(' receives the TOKEN-GATED one, and because accessToken is gated on !isMaplibre it')
|
||||
console.error(' receives it WITHOUT a token: 401s instead of a legible error.')
|
||||
console.error('\n FIX: delete the fallback. Keep the requested engine, and let the profile\'s existing')
|
||||
console.error(' !gl branch fail visibly — console.warn plus the map\'s error/empty state, never a blank,')
|
||||
console.error(' and never another engine. Name the engine in the message so a partner can tell an')
|
||||
console.error(' honoured request from a silent downgrade.')
|
||||
process.exit(1)
|
||||
}
|
||||
console.log('NO-SILENT-ENGINE-SUBSTITUTION: PASS — every engineGlobal() call keeps the engine its provider '
|
||||
+ 'asked for.')
|
||||
548
library/composables/useDashboardLayout.js
Normal file
548
library/composables/useDashboardLayout.js
Normal file
|
|
@ -0,0 +1,548 @@
|
|||
/**
|
||||
* useDashboardLayout.js — reusable drag-resize + persistence engine for the CMV dashboard grid.
|
||||
*
|
||||
* ★ SHARED AS OF DASHBOARD-KIT LANDING 2. The second piece of Big Picture to become library code,
|
||||
* and the second on the same test: it imports nothing but `vue` and touches no domain field. The
|
||||
* four mentions of a people-groups grid below are comments naming an EXAMPLE of what a host stacks
|
||||
* underneath; nothing here reads a row.
|
||||
*
|
||||
* The body is what research-dashboard shipped, with one behaviour change that the spec asked for
|
||||
* BEFORE this file could be shared — see the storage-key note on `storageKey` below. Everything
|
||||
* else is verbatim.
|
||||
*
|
||||
* plugin-designs/research-dashboard/src/composables/useDashboardLayout.js re-exports this for one
|
||||
* cycle. See _qa-cycle/03-deployment-cycle/SPEC-DASHBOARD-KIT.md section 8, landing 2.
|
||||
*
|
||||
* A dashboard shell (see plugin-designs/research-dashboard/research-dashboard.vue) is a CSS
|
||||
* grid whose three flexible tracks are driven by CSS custom properties:
|
||||
* --facet-w (left facet-rail column width) default 296px
|
||||
* --rail-w (right charts-rail column width) default 296px — equals --facet-w, so the map column sits centred
|
||||
* --table-h (bottom table row height) default 34% (map above it is the 1fr hero)
|
||||
*
|
||||
* This composable OWNS those three vars: it exposes pointer-based drag handlers (one per edge),
|
||||
* clamps each to a sane min/max, writes the vars onto the shell root element as INLINE custom
|
||||
* properties, PERSISTS the chosen layout to localStorage on every drag-end, RESTORES it on init,
|
||||
* and offers reset() to clear the key and snap back to the exact defaults.
|
||||
*
|
||||
* SHELL vs. TABLE axis (page-scroll mode only — BUG-SHELL-HANDLE-BOUND-TO-WRONG-DIVIDER):
|
||||
* Two DIFFERENT questions look similar and must stay answered by two DIFFERENT handles.
|
||||
* "table" axis = the MAP/TABLE SPLIT. In page-scroll mode it redistributes height BETWEEN
|
||||
* the map and the table; the sum of the two (the element's total height)
|
||||
* does NOT change. This is the EXISTING map/table divider
|
||||
* (.rd-rz-table in research-dashboard.vue), unchanged in grid-mode.
|
||||
* "shell" axis = the ELEMENT'S OWN HEIGHT (page-scroll mode only) — a bar at the shell's
|
||||
* BOTTOM edge, the boundary between the whole research-dashboard element and
|
||||
* whatever a host stacks below it (e.g. the people-groups grid in
|
||||
* dashboard-plus-grid.vue). Dragging it changes --rd-shell-h, the total map+
|
||||
* table budget; the map/table SPLIT within that budget is untouched.
|
||||
* --rd-shell-h is the new independent variable; --rd-map-h is now the map's share of it, and
|
||||
* the table's share is derived as shellH - mapH (see the CSS in research-dashboard.vue). Before
|
||||
* this, --rd-map-h alone was BOTH "the map/table split" AND "the element's total height" — one
|
||||
* knob answering two questions, which is why dragging the map/table divider used to resize the
|
||||
* whole element as a side effect. Driver: "you improperly bound that control to the separator
|
||||
* line between the map and the table... that's not the request I was making to resize the
|
||||
* height of the page."
|
||||
*
|
||||
* COMPOSITION with the collapse-table fix (do NOT regress):
|
||||
* The shell's DEFAULT rows are `52px auto 42px 1fr var(--table-h,34%)` while the collapsed rule
|
||||
* `.rd-shell.rd-table-collapsed{ grid-template-rows:52px auto 42px 1fr 0 }` comes LATER in source
|
||||
* order (same specificity) so COLLAPSE WINS over --table-h. Because we only touch the CSS var
|
||||
* (never the collapsed row template), collapsing hides the table regardless of a dragged height,
|
||||
* and expanding restores the user's dragged --table-h. The center map is 1fr and already
|
||||
* self-resizes via DashboardMapPanel's ResizeObserver → map.resize(); we add no second resize.
|
||||
*
|
||||
* NON-REGRESSION with the responsive slim rails:
|
||||
* `.rd-shell.rd-slim-rail{ --rail-w:228px }` / `.rd-shell.rd-slim-facet{ --facet-w:250px }` are
|
||||
* medium-width niceties set via CLASS. Inline styles always beat class rules, so we apply inline
|
||||
* vars ONLY once the layout is customized (restored-from-storage or dragged). An untouched
|
||||
* dashboard writes no inline vars → the slim classes and the exact CSS defaults are preserved.
|
||||
* reset() removes the inline vars entirely, fully handing control back to the stylesheet.
|
||||
*
|
||||
* DESKTOP-ONLY: every drag is gated on `!isNarrow`; narrow/mobile never resizes or persists.
|
||||
*
|
||||
* Library-parameterizable — the profile's identity (defaults + storage key) lives in options, not
|
||||
* here. Any dashboard grid exposing the same three vars can reuse this unchanged.
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {import('vue').Ref<HTMLElement|null>} options.shellRef ref holding the .rd-shell root el
|
||||
* @param {object=} options.bus selection bus; when given, listens bus.on('resetLayout', reset)
|
||||
* @param {import('vue').Ref<boolean>|boolean=} options.isNarrow desktop gate (true = mobile/narrow)
|
||||
* @param {import('vue').Ref<boolean>|boolean=} options.pageScroll when true, the table axis drives
|
||||
* --rd-map-h (px) instead of --table-h — see the PAGE-SCROLL AXIS SWITCH note below.
|
||||
* @param {string=} options.storageKey localStorage key (default 'rd-dashboard-layout')
|
||||
* @param {{facetW?:number, railW?:number, tableH?:string, mapH?:number, shellH?:number}=} options.defaults default track sizes
|
||||
* @param {{facetW?:[number,number], railW?:[number,number], tableH?:[number,number], mapH?:[number,number], shellH?:[number,number]}=} options.clamps
|
||||
* min/max — facetW/railW/mapH/shellH in px, tableH in percent-of-shell-height
|
||||
*
|
||||
* @returns {{
|
||||
* facetW: import('vue').Ref<number>, railW: import('vue').Ref<number>, tableH: import('vue').Ref<string>,
|
||||
* mapH: import('vue').Ref<number>, shellH: import('vue').Ref<number>,
|
||||
* startFacetResize:(e:PointerEvent)=>void, startRailResize:(e:PointerEvent)=>void,
|
||||
* startTableResize:(e:PointerEvent)=>void, startShellResize:(e:PointerEvent)=>void,
|
||||
* reset:()=>void, applyVars:()=>void, customized:import('vue').Ref<boolean>,
|
||||
* stepResize:(axis:'facet'|'rail'|'table'|'shell', dir:-1|1, toExtreme?:boolean)=>void,
|
||||
* onResizeKeydown:(axis:'facet'|'rail'|'table'|'shell', e:KeyboardEvent)=>void
|
||||
* }}
|
||||
*/
|
||||
import { ref, unref, onMounted, onBeforeUnmount } from 'vue'
|
||||
|
||||
// The single key every dashboard shared before landing 2 namespaced them. Kept ONLY so a reader's
|
||||
// existing layout survives the change; nothing writes to it. Delete it once no reader can plausibly
|
||||
// still be carrying one.
|
||||
const LEGACY_SHARED_KEY = 'rd-dashboard-layout'
|
||||
|
||||
// Tree rail WIDER than the charts rail — see the rail-balance note in research-dashboard.vue.
|
||||
// These must stay in lockstep with the CSS `:host` defaults, since reset() snaps back to them.
|
||||
// mapH mirrors the CSS fallback 40svh (~360px at a 900px viewport — see the page-scroll note
|
||||
// below); it is only ever WRITTEN once the user drags, so an untouched embed stays on the
|
||||
// viewport-relative svh default and keeps resizing with the window, exactly like every other var.
|
||||
// ★ 58svh (522px) was the ORIGINAL default and left the page-scroll band taller than one desktop
|
||||
// viewport (BUG-DASHBOARD-BAND-GROWS-ENORMOUS: chrome 137px + map 522px + table 552px = 1211px
|
||||
// against 900px). 40svh is the value that makes chrome + map(X) + table(X + bar-height) fit <=900px.
|
||||
// shellH default (720) is the SUM the old single-knob mapH(360) used to imply — map 360 + table
|
||||
// budget 360 (328 grid + 32 bar) — so first paint is pixel-identical to before this axis split;
|
||||
// only DRAGGING behaves differently now (see the SHELL vs. TABLE axis note above).
|
||||
// ★ shellH 720 -> 602 so the table OPENS at seven data rows (Driver 2026-09-23: "the table needs to
|
||||
// only show SEVEN rows by DEFAULT height"). 602 = map 360 + bar 32 + 7 rows x 26 + foot 28.
|
||||
// ★ A DEFAULT, NOT A LOCK — and the distinction is the whole correction. My first attempt hard-capped
|
||||
// the keyhole at 7 rows in CSS, which read as the same thing and was not: nothing writes
|
||||
// --rd-table-rows, while the drag handles write --rd-shell-h and --rd-map-h, so the cap could not
|
||||
// be reached by any gesture. The Driver lost BOTH resizes at once and said so: "I didn't want the
|
||||
// table set to 7. Only the table needs to be resizable. We've set it to where I can't even resize."
|
||||
// Setting the STARTING VALUE instead leaves the derivation intact: the keyhole stays
|
||||
// shell - map - bar - foot, so dragging either handle still moves the table, and seven rows is
|
||||
// merely where it opens.
|
||||
// ★ RECLAIM PASS 2 (Driver 2026-09-23: "it is a priority to reclaim height... so I can see half
|
||||
// of the first row of the people groups grid"). mapH 360 -> 300 and shellH follows the same
|
||||
// arithmetic as before: 300 map + 32 bar + 7x26 rows + 28 foot = 542. The seven-row table
|
||||
// promise is unchanged; only the map's share shrinks -- and the map compensates by DEFAULTING
|
||||
// MORE ZOOMED OUT with the world-floor released on the globe (see DashboardMapPanel), so a
|
||||
// shorter map shows MORE world, not less.
|
||||
// shellH 502 -> 542 (Driver 2026-09-23: "the dashboard should be taller by about 40px"). The
|
||||
// extra 40px flows to the TABLE via the standing derivation (table = shell - map - bar - foot);
|
||||
// the map row stays pinned at mapH. One owner: this number, with the CSS var fallbacks in
|
||||
// research-dashboard.vue kept byte-equal at 542.
|
||||
// mapH 260 -> 300 (Driver 2026-09-23 follow-up: the +40px was to be "added to the map -- map is
|
||||
// 40px taller display room"). shellH stays 542, so the table's derived share returns to its
|
||||
// pre-+40 height and the whole gain lands in the map row.
|
||||
// +40px again (Driver 2026-09-23 second raise: "go taller with the dashboard by another 40px,
|
||||
// add that to the height of the map"): shellH 542 -> 582 and mapH 300 -> 340 move together, so
|
||||
// the whole gain lands in the map row and the table's derived share stays put.
|
||||
// Driver fine-tune 2026-09-23: "almost perfect height -- keep the map the same height, but
|
||||
// decrease the height of the dashboard by about 20px". Map stays 340; the 20px comes out of
|
||||
// the table's derived share (shell - map - bar - foot).
|
||||
const DEFAULTS = { facetW: 296, railW: 296, tableH: '34%', mapH: 340, shellH: 562 }
|
||||
const CLAMPS = { facetW: [160, 420], railW: [200, 520], tableH: [12, 70], mapH: [220, 1400], shellH: [400, 2600] }
|
||||
|
||||
// Mirrors the CSS fallback --rd-table-bar-h (research-dashboard.vue's .rd-table-bar budget calc) —
|
||||
// the table's header bar (count + Export CSV) sits ABOVE its scrollport and is not itself
|
||||
// resizable, so the map/table split must always leave it at least this much room, or the divider
|
||||
// could drag the table's usable grid to zero while its outer cell still looks non-empty.
|
||||
const TABLE_BAR_H = 32
|
||||
const TABLE_MIN_H = 120 // grid's own floor below the bar — a table smaller than this is unusable
|
||||
|
||||
const clamp = (v, [lo, hi]) => Math.min(hi, Math.max(lo, v))
|
||||
const pctNum = (v, fallback) => {
|
||||
const n = parseFloat(String(v))
|
||||
return Number.isFinite(n) ? n : fallback
|
||||
}
|
||||
|
||||
export function useDashboardLayout(options = {}) {
|
||||
const {
|
||||
shellRef,
|
||||
bus = null,
|
||||
isNarrow = false,
|
||||
pageScroll = false,
|
||||
// ★ KEY VERSIONED v2 (2026-09-23). The Driver reported "sidebars are not equally spaced" on
|
||||
// his machine AFTER the symmetric-rail change landed -- because his browser restores a layout
|
||||
// SAVED under the old defaults (rail 264), and a restored value outranks any new default by
|
||||
// design. When defaults change materially, the old saved layouts are prescriptions from a
|
||||
// different bottle: bump the key so every reader starts from the new defaults once, and a
|
||||
// fresh drag re-personalises from there. The v1 blob is left in place, inert.
|
||||
// v2 -> v3: retire stored layouts so the new 542 default is actually SEEN -- a persisted
|
||||
// shellH:502 from the previous default would silently mask this change on the Driver's browser.
|
||||
// ★ NAMESPACED PER DASHBOARD, AND THAT IS THE ONE BEHAVIOUR CHANGE IN THIS MOVE.
|
||||
// SPEC-DASHBOARD-KIT section 8 named it as landing 2's risk: this key was a single constant, so
|
||||
// the moment a page carries TWO dashboards they read and write one another's layout. Dragging a
|
||||
// divider in one would move the other's on next load, and neither would be wrong on its own.
|
||||
// While there was exactly one dashboard that was invisible; sharing the engine is precisely
|
||||
// what makes a second one possible, so the fix belongs in the commit that shares it rather than
|
||||
// in the commit that first trips over it.
|
||||
// The caller passes its own id (the shell uses config.id). The default keeps a caller that
|
||||
// passes nothing working, and still namespaces it away from any caller that does.
|
||||
storageKey = 'rd-dashboard-layout-v6',
|
||||
} = options
|
||||
|
||||
const defaults = { ...DEFAULTS, ...(options.defaults || {}) }
|
||||
const clamps = { ...CLAMPS, ...(options.clamps || {}) }
|
||||
|
||||
const facetW = ref(defaults.facetW) // px
|
||||
const railW = ref(defaults.railW) // px
|
||||
const tableH = ref(defaults.tableH) // string, e.g. '34%'
|
||||
const mapH = ref(defaults.mapH) // px — only meaningful/applied in page-scroll mode
|
||||
const shellH = ref(defaults.shellH) // px — page-scroll ELEMENT total height (map+table budget)
|
||||
const customized = ref(false) // has the user (or a restored layout) diverged from CSS defaults?
|
||||
const mapHCustomized = ref(false) // page-scroll's own inline var is written independently of
|
||||
// customized (below), since an untouched grid-mode drag
|
||||
// must never suddenly pin --rd-map-h and vice versa.
|
||||
const shellHCustomized = ref(false) // same independence, one level up: the shell handle is a
|
||||
// separate drag from the map/table split and must not fire
|
||||
// just because the OTHER page-scroll var was touched.
|
||||
|
||||
const narrow = () => !!unref(isNarrow)
|
||||
const inPageScroll = () => !!unref(pageScroll)
|
||||
|
||||
// ── what --rd-shell-h CURRENTLY RESOLVES TO (BUG-SHELL-HANDLE-SNAPS-144PX) ───────────────────
|
||||
// The shell drag must anchor on the budget the CSS is resolving RIGHT NOW, or the first frame
|
||||
// "corrects" from a wrong anchor and the user sees height they did not drag. Two sources, in
|
||||
// priority order, because the variable and the rendered size legitimately disagree:
|
||||
//
|
||||
// 1. THE COMPUTED VARIABLE, whenever it is set. --rd-shell-h is a CEILING — it feeds the
|
||||
// table grid's max-height — and a ceiling is not a floor: if the table has fewer rows than
|
||||
// the budget allows, the element renders SMALLER than the variable says. MEASURED with a
|
||||
// restored shellH of 983: the element was 1126 while map+table summed to only 743, because
|
||||
// the grid had ~240px of budget and no rows to fill it. Anchoring on that 743 snapped the
|
||||
// variable 983 -> 744 on the first frame — a -239px jump, the mirror image of the +144 one
|
||||
// this card started from. Whatever the CSS already holds is what the drag must continue
|
||||
// from, so the pointer only ever ADDS to a value that is already in effect.
|
||||
// 2. THE MEASURED map + table, only when the variable is unset. Before the first drag the CSS
|
||||
// is on its stylesheet fallback (`80svh`), which shellH.value cannot stand in for: the 720
|
||||
// default only equals 80svh at a 900px viewport, so trusting it would jump by the
|
||||
// difference at any other window height.
|
||||
//
|
||||
// Measuring map + table rather than the shell's own box is deliberate — the shell is
|
||||
// `height:auto` here and includes the chrome the variable does not budget for. Summing the two
|
||||
// regions lands on the same span calc(shell-h - map-h - bar - foot) works from, without
|
||||
// restating the chrome's height as a second number that could drift from the stylesheet.
|
||||
function currentShellBudget() {
|
||||
const el = shellRef && shellRef.value
|
||||
if (!el) return shellH.value
|
||||
const declared = parseFloat(getComputedStyle(el).getPropertyValue('--rd-shell-h'))
|
||||
if (Number.isFinite(declared) && declared > 0) return Math.round(declared)
|
||||
const mapEl = el.querySelector('[data-region="map"]')
|
||||
const tableEl = el.querySelector('[data-region="table"]')
|
||||
if (!mapEl || !tableEl) return shellH.value
|
||||
const h = mapEl.getBoundingClientRect().height + tableEl.getBoundingClientRect().height
|
||||
// A collapsed/hidden region measures 0; fall back rather than anchoring the drag on nothing.
|
||||
return h > 0 ? Math.round(h) : shellH.value
|
||||
}
|
||||
|
||||
// ── write / clear the inline CSS custom properties on the shell root ──
|
||||
// --rd-map-h is applied independently of `customized` (grid-mode's facet/rail/table-h gate):
|
||||
// page-scroll is a different layout entirely, with its own untouched-vs-dragged state, so
|
||||
// gating it on the grid vars' flag would either apply it before any page-scroll drag ever
|
||||
// happened, or (worse) suppress a real page-scroll drag because the grid vars were untouched.
|
||||
function applyVars() {
|
||||
const el = shellRef && shellRef.value
|
||||
if (!el) return
|
||||
if (customized.value) {
|
||||
el.style.setProperty('--facet-w', facetW.value + 'px')
|
||||
el.style.setProperty('--rail-w', railW.value + 'px')
|
||||
el.style.setProperty('--table-h', tableH.value)
|
||||
}
|
||||
if (mapHCustomized.value) {
|
||||
el.style.setProperty('--rd-map-h', mapH.value + 'px')
|
||||
}
|
||||
if (shellHCustomized.value) {
|
||||
el.style.setProperty('--rd-shell-h', shellH.value + 'px')
|
||||
}
|
||||
}
|
||||
function clearVars() {
|
||||
const el = shellRef && shellRef.value
|
||||
if (!el) return
|
||||
el.style.removeProperty('--facet-w')
|
||||
el.style.removeProperty('--rail-w')
|
||||
el.style.removeProperty('--table-h')
|
||||
el.style.removeProperty('--rd-map-h')
|
||||
el.style.removeProperty('--rd-shell-h')
|
||||
}
|
||||
|
||||
// ── persistence ──
|
||||
function persist() {
|
||||
try {
|
||||
localStorage.setItem(storageKey, JSON.stringify({
|
||||
facetW: facetW.value, railW: railW.value, tableH: tableH.value, mapH: mapH.value, shellH: shellH.value,
|
||||
}))
|
||||
} catch (_) { /* storage blocked / SSR — layout still works this session */ }
|
||||
}
|
||||
function restore() {
|
||||
try {
|
||||
// ★ A ONE-TIME READ-THROUGH FROM THE OLD SHARED KEY, so namespacing does not silently reset
|
||||
// every reader's saved layout. Read-only and never written back: the new key is written on
|
||||
// the next drag-end, and the old value is simply left where it is rather than migrated and
|
||||
// deleted — a migration that also deletes is one that cannot be rolled back.
|
||||
const raw = localStorage.getItem(storageKey) || localStorage.getItem(LEGACY_SHARED_KEY)
|
||||
if (!raw) return false
|
||||
const s = JSON.parse(raw)
|
||||
if (Number.isFinite(s.facetW)) facetW.value = clamp(s.facetW, clamps.facetW)
|
||||
if (Number.isFinite(s.railW)) railW.value = clamp(s.railW, clamps.railW)
|
||||
if (s.tableH != null) tableH.value = clamp(pctNum(s.tableH, pctNum(defaults.tableH, 34)), clamps.tableH) + '%'
|
||||
customized.value = true
|
||||
// shellH restores BEFORE mapH so the mapH clamp below (which bounds map to <= shellH, see
|
||||
// startResize's isTablePageScroll branch) has the right ceiling on first paint too.
|
||||
if (Number.isFinite(s.shellH)) { shellH.value = clamp(s.shellH, clamps.shellH); shellHCustomized.value = true }
|
||||
if (Number.isFinite(s.mapH)) { mapH.value = clamp(s.mapH, clamps.mapH); mapHCustomized.value = true }
|
||||
return true
|
||||
} catch (_) { return false }
|
||||
}
|
||||
|
||||
// ── reset: clear the key + snap back to the EXACT defaults (hand control to the stylesheet) ──
|
||||
function reset() {
|
||||
try { localStorage.removeItem(storageKey) } catch (_) { /* ignore */ }
|
||||
facetW.value = defaults.facetW
|
||||
railW.value = defaults.railW
|
||||
tableH.value = defaults.tableH
|
||||
mapH.value = defaults.mapH
|
||||
shellH.value = defaults.shellH
|
||||
customized.value = false
|
||||
mapHCustomized.value = false
|
||||
shellHCustomized.value = false
|
||||
clearVars()
|
||||
}
|
||||
|
||||
// ── drag-live signalling (BUG-RESIZE-STROBE) ──────────────────────────────
|
||||
// Two channels, because two different consumers need it:
|
||||
// 1. `data-rd-resizing` on the shell root — a pure-CSS hook so transitions/animations can be
|
||||
// killed for the duration of the drag (no JS needed, works inside shadow DOM).
|
||||
// 2. bus 'layoutResizing' — lets the map panel downgrade to a cheap canvas resize while the
|
||||
// drag is live, then do the one expensive re-fit on drag end.
|
||||
// Both are no-ops when absent, so this composable stays usable without a bus.
|
||||
const resizing = ref(false)
|
||||
function beginDrag() {
|
||||
if (resizing.value) return
|
||||
resizing.value = true
|
||||
const el = shellRef && shellRef.value
|
||||
if (el) el.setAttribute('data-rd-resizing', '1')
|
||||
if (bus && typeof bus.emit === 'function') { try { bus.emit('layoutResizing', true) } catch (_) {} }
|
||||
}
|
||||
function endDrag() {
|
||||
if (!resizing.value) return
|
||||
resizing.value = false
|
||||
const el = shellRef && shellRef.value
|
||||
if (el) el.removeAttribute('data-rd-resizing')
|
||||
if (bus && typeof bus.emit === 'function') { try { bus.emit('layoutResizing', false) } catch (_) {} }
|
||||
}
|
||||
|
||||
// ── generic pointer drag; axis ∈ 'facet' | 'rail' | 'table' ──
|
||||
function startResize(axis, e) {
|
||||
if (narrow()) return
|
||||
const el = shellRef && shellRef.value
|
||||
if (!el) return
|
||||
e.preventDefault()
|
||||
const rect = el.getBoundingClientRect()
|
||||
const startX = e.clientX
|
||||
const startFacet = facetW.value
|
||||
const startRail = railW.value
|
||||
const handleEl = e.currentTarget
|
||||
// ── PAGE-SCROLL AXIS SWITCH (BUG-TABLE-RESIZE-HANDLE-DOES-NOTHING) ──────────────────────
|
||||
// In page-scroll mode (research-dashboard.vue's pageScroll / dashboard-plus-grid.vue) the
|
||||
// shell is `height:auto` and grows with its content, so `rect` above is NOT one screen tall
|
||||
// — `rect.bottom` can sit thousands of px below the viewport. --table-h is force-set to
|
||||
// `auto` by the .rd-page-scroll stylesheet rule and no longer drives ANY layout: the map's
|
||||
// height instead comes from --rd-map-h (default 40svh as of BUG-DASHBOARD-BAND-GROWS-ENORMOUS;
|
||||
// see the CSS note beside it), and the table's own max-height comes from --rd-table-max-h.
|
||||
// Writing tableH in this mode is a complete no-op — MEASURED (at the prior 58svh default):
|
||||
// map height 522px before and after a real 200px drag, every
|
||||
// frame. The fix is to drive --rd-map-h directly, from the MAP ELEMENT's own top edge
|
||||
// (not the unbounded shell rect), so growing the map is a plain function of where the
|
||||
// pointer is relative to where the map starts.
|
||||
//
|
||||
// ★ THE map/table SPLIT vs. THE shell's OWN HEIGHT (BUG-SHELL-HANDLE-BOUND-TO-WRONG-DIVIDER)
|
||||
// — this handle must move height BETWEEN map and table, never grow the total. mapH is now
|
||||
// clamped to leave the table at least TABLE_BAR_H + TABLE_MIN_H of the FIXED shellH budget,
|
||||
// so dragging this divider can only redistribute the two, exactly like resizing an internal
|
||||
// pane split rather than the window itself.
|
||||
const isTablePageScroll = axis === 'table' && inPageScroll()
|
||||
const isShellResize = axis === 'shell' && inPageScroll()
|
||||
let startMapTop = 0
|
||||
let mapHCeiling = clamps.mapH[1]
|
||||
if (isTablePageScroll) {
|
||||
const mapEl = el.querySelector('[data-region="map"]')
|
||||
const mapRect = mapEl ? mapEl.getBoundingClientRect() : null
|
||||
startMapTop = mapRect ? mapRect.top : (e.clientY - mapH.value)
|
||||
mapHCeiling = Math.max(clamps.mapH[0], shellH.value - (TABLE_BAR_H + TABLE_MIN_H))
|
||||
}
|
||||
// ★ DELTA-ANCHORED ON THE LIVE BUDGET (BUG-SHELL-HANDLE-SNAPS-144PX-ON-FIRST-FRAME).
|
||||
// MEASURED at 1440x900: a 1px drag grew the element 144px. TWO defects stacked here, and
|
||||
// fixing only the first leaves the number bit-for-bit unchanged — which is the clue that
|
||||
// named the second.
|
||||
//
|
||||
// 1. POINTER-ABSOLUTE math. The old line set shellH to (pointerY - shellTop), treating the
|
||||
// cursor's Y AS the new height. That is only correct if the handle sits exactly shellH
|
||||
// px below the shell's top, and it does not. Fixed by anchoring on a start value and
|
||||
// adding the pointer DELTA.
|
||||
// 2. THE WRONG ANCHOR — the actual source of the 144. Anchoring on the element's measured
|
||||
// height is the obvious move and is wrong, because --rd-shell-h IS NOT THE ELEMENT'S
|
||||
// HEIGHT. The shell is `height:auto` in page-scroll mode (.rd-shell.rd-page-scroll) and
|
||||
// nothing reads --rd-shell-h as a height; its ONLY consumer is the table grid's
|
||||
// max-height: calc(--rd-shell-h - --rd-map-h - bar - foot). So the variable budgets
|
||||
// MAP + TABLE and excludes the chrome above them (topbar 52 + filters 55 + stats 30 =
|
||||
// 141px measured). Seeding it with the measured 863 published a budget 144px too large:
|
||||
// the grid's max-height jumped 300 -> 444 on the FIRST frame and the element grew with
|
||||
// it. 863 - 719 = 144 is not a coincidence — it is the chrome, double-counted.
|
||||
const startShellY = e.clientY
|
||||
const startShellH = isShellResize ? currentShellBudget() : shellH.value
|
||||
try { handleEl && handleEl.setPointerCapture && handleEl.setPointerCapture(e.pointerId) } catch (_) {}
|
||||
|
||||
// ── A11Y / PHOTOSENSITIVITY (BUG-RESIZE-STROBE): mark the drag as LIVE ──
|
||||
// Writing the CSS vars every pointermove reflows the grid, which fires the map panel's
|
||||
// ResizeObserver → map.resize() → MapLibre's own 'resize' event → useMapInstance's
|
||||
// _onResize → setMinZoom/setZoom. Because the zoom FLOOR is derived from the container
|
||||
// HEIGHT, a vertical drag re-snapped the camera on EVERY frame — a ~60Hz full-canvas
|
||||
// re-render that reads as strobing. Flagging the drag lets the map coalesce to a single
|
||||
// cheap canvas resize while dragging and do the one expensive re-fit on drag END.
|
||||
beginDrag()
|
||||
|
||||
// Coalesce the inline-var writes to one per animation frame. pointermove can fire faster
|
||||
// than the compositor on high-polling-rate mice, so without this the grid could reflow
|
||||
// several times per painted frame — wasted work that makes the strobe worse.
|
||||
let frame = 0
|
||||
let pending = null
|
||||
function flush() {
|
||||
frame = 0
|
||||
if (!pending) return
|
||||
const ev = pending
|
||||
pending = null
|
||||
if (axis === 'facet') {
|
||||
// left facet edge → dragging right widens the facet column
|
||||
facetW.value = Math.round(clamp(startFacet + (ev.clientX - startX), clamps.facetW))
|
||||
customized.value = true
|
||||
} else if (axis === 'rail') {
|
||||
// right rail's LEFT edge → dragging left widens the rail column
|
||||
railW.value = Math.round(clamp(startRail - (ev.clientX - startX), clamps.railW))
|
||||
customized.value = true
|
||||
} else if (isTablePageScroll) {
|
||||
// page-scroll: the handle sits pinned to the MAP's own bottom edge (.rd-rz-table is
|
||||
// align-self:end on the map grid-area — see the CSS below), whose top never moves. The
|
||||
// pointer's new Y position IS the map's new bottom edge, so the new height is simply the
|
||||
// distance from the map's (fixed) top to the cursor — a direct 1:1 follow, exactly like
|
||||
// dragging the corner of a window. Re-derived fresh every frame from startMapTop (not
|
||||
// summed from a delta), so it can never drift from the cursor across a long drag.
|
||||
// Clamped to mapHCeiling (not the raw clamps.mapH max) — the ceiling reserves the table's
|
||||
// bar + a usable minimum out of the FIXED shellH budget, so this drag only ever moves
|
||||
// height between map and table and can never grow the element's total height. That is
|
||||
// the shell axis's job (see isShellResize below), not this one's.
|
||||
mapH.value = Math.round(clamp(ev.clientY - startMapTop, [clamps.mapH[0], mapHCeiling]))
|
||||
mapHCustomized.value = true
|
||||
} else if (axis === 'table') {
|
||||
// map/table divider → dragging up grows the table (height measured from shell bottom)
|
||||
const pct = ((rect.bottom - ev.clientY) / rect.height) * 100
|
||||
tableH.value = Math.round(clamp(pct, clamps.tableH)) + '%'
|
||||
customized.value = true
|
||||
} else if (isShellResize) {
|
||||
// The NEW shell handle — spans the whole element's bottom edge (research-dashboard.vue's
|
||||
// .rd-rz-shell), the boundary with whatever a host stacks below (e.g. the people-groups
|
||||
// grid in dashboard-plus-grid.vue). Same fixed-top / 1:1-follow pattern as the map handle
|
||||
// above. This is the ONLY axis that changes --rd-shell-h, i.e. the only handle that
|
||||
// changes the element's total height — the map/table divider above must never do this
|
||||
// (see its own comment).
|
||||
// DELTA from the live start budget, NOT the pointer's absolute Y: unlike the map handle,
|
||||
// this variable is not a distance from a fixed top edge, so there is no "pointer Y IS the
|
||||
// new value" identity to exploit — assuming one produced the 144px snap (see the note on
|
||||
// startShellH above).
|
||||
shellH.value = Math.round(clamp(startShellH + (ev.clientY - startShellY), clamps.shellH))
|
||||
shellHCustomized.value = true
|
||||
}
|
||||
applyVars()
|
||||
}
|
||||
function move(ev) {
|
||||
// keep only the LATEST position; the rAF does the single write for this frame
|
||||
pending = { clientX: ev.clientX, clientY: ev.clientY }
|
||||
if (!frame) frame = requestAnimationFrame(flush)
|
||||
}
|
||||
function up(ev) {
|
||||
window.removeEventListener('pointermove', move)
|
||||
window.removeEventListener('pointerup', up)
|
||||
window.removeEventListener('pointercancel', up)
|
||||
if (frame) { cancelAnimationFrame(frame); frame = 0 }
|
||||
flush() // land the final position even if the last frame never ran
|
||||
try { handleEl && handleEl.releasePointerCapture && handleEl.releasePointerCapture(ev.pointerId) } catch (_) {}
|
||||
persist()
|
||||
endDrag()
|
||||
}
|
||||
window.addEventListener('pointermove', move)
|
||||
window.addEventListener('pointerup', up)
|
||||
window.addEventListener('pointercancel', up)
|
||||
}
|
||||
|
||||
const startFacetResize = (e) => startResize('facet', e)
|
||||
const startRailResize = (e) => startResize('rail', e)
|
||||
const startTableResize = (e) => startResize('table', e)
|
||||
const startShellResize = (e) => startResize('shell', e)
|
||||
|
||||
// ── keyboard step-resize (a11y: role="separator" needs an operable equivalent to the drag) ──
|
||||
// Reuses the SAME refs/clamps/persist/applyVars as the pointer path — no parallel math. One
|
||||
// discrete step per keypress (no rAF coalescing needed; a keydown can't fire faster than a frame).
|
||||
// `table` axis mirrors startResize's own page-scroll branch: in page-scroll mode it steps mapH
|
||||
// (the map/table split within the FIXED shellH budget), otherwise it steps the grid-mode tableH
|
||||
// percentage. `shell` steps shellH directly — the only axis that changes the element's total height.
|
||||
const STEP = { facet: 16, rail: 16, table: 24, mapH: 24, shellH: 24 } // px per arrow-key press (tableH in %)
|
||||
// `toExtreme` bypasses the per-step delta entirely and clamps straight to lo/hi — Home/End jump,
|
||||
// not a long walk of individual steps (which would also mean 200 localStorage writes per keypress).
|
||||
function stepResize(axis, dir, toExtreme) {
|
||||
if (narrow()) return
|
||||
if (axis === 'facet') {
|
||||
facetW.value = toExtreme ? (dir < 0 ? clamps.facetW[0] : clamps.facetW[1])
|
||||
: Math.round(clamp(facetW.value + dir * STEP.facet, clamps.facetW))
|
||||
customized.value = true
|
||||
} else if (axis === 'rail') {
|
||||
// Same "left edge, dragging left widens" sense as the pointer path: ArrowLeft (dir -1)
|
||||
// widens the rail, so the rail's step direction is inverted relative to facet's.
|
||||
railW.value = toExtreme ? (dir < 0 ? clamps.railW[1] : clamps.railW[0])
|
||||
: Math.round(clamp(railW.value - dir * STEP.rail, clamps.railW))
|
||||
customized.value = true
|
||||
} else if (axis === 'table' && inPageScroll()) {
|
||||
// Same ceiling as the pointer path (startResize's mapHCeiling): reserve the table's bar +
|
||||
// usable minimum out of the CURRENT shellH so a keyboard drag can redistribute but never
|
||||
// grow the total either.
|
||||
const ceiling = Math.max(clamps.mapH[0], shellH.value - (TABLE_BAR_H + TABLE_MIN_H))
|
||||
mapH.value = toExtreme ? (dir < 0 ? clamps.mapH[0] : ceiling)
|
||||
: Math.round(clamp(mapH.value + dir * STEP.mapH, [clamps.mapH[0], ceiling]))
|
||||
mapHCustomized.value = true
|
||||
} else if (axis === 'table') {
|
||||
const pct = toExtreme ? (dir < 0 ? clamps.tableH[0] : clamps.tableH[1])
|
||||
: clamp(pctNum(tableH.value, pctNum(defaults.tableH, 34)) - dir * STEP.table / 4, clamps.tableH)
|
||||
tableH.value = Math.round(pct) + '%'
|
||||
customized.value = true
|
||||
} else if (axis === 'shell' && inPageScroll()) {
|
||||
shellH.value = toExtreme ? (dir < 0 ? clamps.shellH[0] : clamps.shellH[1])
|
||||
: Math.round(clamp(shellH.value + dir * STEP.shellH, clamps.shellH))
|
||||
shellHCustomized.value = true
|
||||
}
|
||||
applyVars()
|
||||
persist()
|
||||
}
|
||||
// ArrowUp/Left = grow toward the start edge, ArrowDown/Right = grow toward the end edge, matching
|
||||
// each handle's drag SENSE (facet/rail are col-resize, table/map/shell are row-resize). Home/End
|
||||
// jump to the axis's clamp extremes in one write (not a walk of individual steps).
|
||||
function onResizeKeydown(axis, e) {
|
||||
const K = e.key
|
||||
let dir = 0
|
||||
if (axis === 'table' || axis === 'shell') { if (K === 'ArrowUp') dir = -1; else if (K === 'ArrowDown') dir = 1 }
|
||||
else { if (K === 'ArrowLeft') dir = -1; else if (K === 'ArrowRight') dir = 1 }
|
||||
if (dir) { e.preventDefault(); stepResize(axis, dir); return }
|
||||
if (K === 'Home' || K === 'End') {
|
||||
e.preventDefault()
|
||||
stepResize(axis, K === 'Home' ? -1 : 1, true)
|
||||
}
|
||||
}
|
||||
|
||||
// ── lifecycle: restore + apply after the shell el exists; wire the reset bus event ──
|
||||
let offReset = null
|
||||
onMounted(() => {
|
||||
if (restore()) applyVars()
|
||||
if (bus && typeof bus.on === 'function') offReset = bus.on('resetLayout', reset)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
try { offReset && offReset() } catch (_) {}
|
||||
// If the component tears down mid-drag, release the suppression so a re-mounted map
|
||||
// is never left permanently in the cheap "resizing" mode.
|
||||
try { endDrag() } catch (_) {}
|
||||
})
|
||||
|
||||
return {
|
||||
facetW, railW, tableH, mapH, shellH, customized, resizing,
|
||||
startFacetResize, startRailResize, startTableResize, startShellResize,
|
||||
startResize, reset, applyVars, stepResize, onResizeKeydown,
|
||||
}
|
||||
}
|
||||
|
|
@ -7,14 +7,12 @@
|
|||
* change. Everything below is the file as research-dashboard shipped it — not a rewrite, not a
|
||||
* generalisation. A move that also edits is a move nobody can verify.
|
||||
*
|
||||
* plugin-designs/research-dashboard/src/composables/useSelectionBus.js still exists and
|
||||
* re-exports this file for one cycle, so nothing breaks mid-flight; that shim is deleted in the
|
||||
* next landing. See _qa-cycle/03-deployment-cycle/SPEC-DASHBOARD-KIT.md sections 5.2 and 8.
|
||||
* research-dashboard's old copy re-exported this file for one cycle so nothing broke mid-flight;
|
||||
* that shim is now deleted. See _qa-cycle/03-deployment-cycle/SPEC-DASHBOARD-KIT.md sections 5.2 and 8.
|
||||
*
|
||||
* ONE THING IS STILL COMING, and it is deliberately NOT in this commit: SPEC-DASHBOARD-KIT D1
|
||||
* makes `filterSet` multi-value (an array meaning OR-within-key, AND-across-keys). That changes
|
||||
* this file's CONTENTS; this commit changes only its LOCATION. Keeping the two apart is what
|
||||
* makes 'Big Picture is unchanged' provable rather than asserted.
|
||||
* The move and SPEC-DASHBOARD-KIT D1 (multi-value `filterSet`: an array means OR-within-key,
|
||||
* AND-across-keys) landed as separate commits, the move first, so 'Big Picture is unchanged' by the
|
||||
* move stayed provable rather than asserted.
|
||||
*
|
||||
* Two DISTINCT global reactive objects, two distinct visual languages (plan §INTERACTION):
|
||||
* - filterSet : active facet predicates (tree node / map region / chart slice).
|
||||
|
|
|
|||
|
|
@ -8,5 +8,14 @@
|
|||
"upg100WallIntro": "وزّع مهمة الصلاة في مجموعات من خمسين ومئة — كما أطعم يسوع الخمسة آلاف (لوقا ٩:١٤). كل ملصق هو قائمة من 100 يمكنك أن تصلي بها وتطبعها وتعلّقها على الحائط — مصلّيًا لأجلهم <strong>باسم شعبهم</strong>.",
|
||||
"loadingNamed": "جارٍ تحميل {name}…",
|
||||
"couldNotLoadNamed": "تعذّر تحميل {name}.",
|
||||
"engineMissing": "لم يتم تحميل محرك الخرائط {engine}."
|
||||
"engineMissing": "لم يتم تحميل محرك الخرائط {engine}.",
|
||||
"packetFailed": "فشل إنشاء الكُتيّب: {reason}",
|
||||
"selectionPacketFailed": "فشل إنشاء كُتيّب التحديد: {reason}",
|
||||
"posterOneTerritory": "الملصق يطبع منطقة واحدة في كل مرة — {count} محددة.",
|
||||
"selectionPosterFailed": "فشل إنشاء ملصق التحديد: {reason}",
|
||||
"mapUnavailable": "الخريطة غير متاحة",
|
||||
"copied": "تم النسخ!",
|
||||
"copyFailed": "فشل النسخ — اضغط Ctrl/Cmd-C",
|
||||
"engineNotLoaded": "لم يتم تحميل محرك الخريطة",
|
||||
"engineNotLoadedDetail": "لم يتم تحميل محرك الخريطة {engine}. القائمة ووسيلة الإيضاح غير متأثرتين."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,14 @@
|
|||
"upg100WallIntro": "Teilen Sie die Gebetsaufgabe in Gruppen zu fünfzig und hundert auf — so wie Jesus die 5.000 speiste (Lukas 9,14). Jedes Poster ist eine 100er-Liste, die Sie beten, drucken und an die Wand hängen können — und für sie <strong>mit dem Namen ihrer Volksgruppe</strong> beten.",
|
||||
"loadingNamed": "{name} wird geladen…",
|
||||
"couldNotLoadNamed": "{name} konnte nicht geladen werden.",
|
||||
"engineMissing": "Die Karten-Engine {engine} wurde nicht geladen."
|
||||
"engineMissing": "Die Karten-Engine {engine} wurde nicht geladen.",
|
||||
"packetFailed": "Heft fehlgeschlagen: {reason}",
|
||||
"selectionPacketFailed": "Heft der Auswahl fehlgeschlagen: {reason}",
|
||||
"posterOneTerritory": "Das Plakat druckt ein Gebiet auf einmal — {count} ausgewählt.",
|
||||
"selectionPosterFailed": "Plakat der Auswahl fehlgeschlagen: {reason}",
|
||||
"mapUnavailable": "Karte nicht verfügbar",
|
||||
"copied": "Kopiert!",
|
||||
"copyFailed": "Kopieren fehlgeschlagen — Strg/Cmd-C drücken",
|
||||
"engineNotLoaded": "Karten-Engine nicht geladen",
|
||||
"engineNotLoadedDetail": "Die Karten-Engine {engine} wurde nicht geladen. Liste und Legende sind nicht betroffen."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,14 @@
|
|||
"upg100WallIntro": "Hand away the prayer task in clusters of fifties and hundreds — the way Jesus fed the 5,000 (Luke 9:14). Each poster is a 100-list you can pray, print, and put on a wall — praying for them <strong>by their people group name</strong>.",
|
||||
"loadingNamed": "Loading {name}…",
|
||||
"couldNotLoadNamed": "Could not load {name}.",
|
||||
"engineMissing": "The {engine} map engine did not load."
|
||||
"engineMissing": "The {engine} map engine did not load.",
|
||||
"packetFailed": "Packet failed: {reason}",
|
||||
"selectionPacketFailed": "Selection packet failed: {reason}",
|
||||
"posterOneTerritory": "Poster prints one territory at a time — {count} selected.",
|
||||
"selectionPosterFailed": "Selection poster failed: {reason}",
|
||||
"mapUnavailable": "Map unavailable",
|
||||
"copied": "Copied!",
|
||||
"copyFailed": "Copy failed — press Ctrl/Cmd-C",
|
||||
"engineNotLoaded": "map engine not loaded",
|
||||
"engineNotLoadedDetail": "The {engine} map engine did not load. The list and legend are unaffected."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,14 @@
|
|||
"upg100WallIntro": "Reparte la tarea de la oración en grupos de cincuenta y de cien, como Jesús alimentó a los 5.000 (Lucas 9:14). Cada cartel es una lista de 100 que puedes orar, imprimir y poner en la pared — orando por ellos <strong>por el nombre de su pueblo</strong>.",
|
||||
"loadingNamed": "Cargando {name}…",
|
||||
"couldNotLoadNamed": "No se pudo cargar {name}.",
|
||||
"engineMissing": "El motor de mapas {engine} no se cargó."
|
||||
"engineMissing": "El motor de mapas {engine} no se cargó.",
|
||||
"packetFailed": "Error al generar el cuadernillo: {reason}",
|
||||
"selectionPacketFailed": "Error al generar el cuadernillo de la selección: {reason}",
|
||||
"posterOneTerritory": "El cartel imprime un territorio a la vez: {count} seleccionados.",
|
||||
"selectionPosterFailed": "Error al generar el cartel de la selección: {reason}",
|
||||
"mapUnavailable": "Mapa no disponible",
|
||||
"copied": "¡Copiado!",
|
||||
"copyFailed": "Error al copiar: pulsa Ctrl/Cmd-C",
|
||||
"engineNotLoaded": "motor de mapas no cargado",
|
||||
"engineNotLoadedDetail": "El motor de mapas {engine} no se cargó. La lista y la leyenda no se ven afectadas."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,14 @@
|
|||
"upg100WallIntro": "Répartissez la tâche de la prière par groupes de cinquante et de cent — comme Jésus a nourri les 5 000 (Luc 9:14). Chaque affiche est une liste de 100 que vous pouvez prier, imprimer et afficher au mur — en priant pour eux <strong>par le nom de leur peuple</strong>.",
|
||||
"loadingNamed": "Chargement de {name}…",
|
||||
"couldNotLoadNamed": "Impossible de charger {name}.",
|
||||
"engineMissing": "Le moteur de carte {engine} ne s’est pas chargé."
|
||||
"engineMissing": "Le moteur de carte {engine} ne s’est pas chargé.",
|
||||
"packetFailed": "Échec du livret : {reason}",
|
||||
"selectionPacketFailed": "Échec du livret de la sélection : {reason}",
|
||||
"posterOneTerritory": "L’affiche imprime un territoire à la fois — {count} sélectionnés.",
|
||||
"selectionPosterFailed": "Échec de l’affiche de la sélection : {reason}",
|
||||
"mapUnavailable": "Carte indisponible",
|
||||
"copied": "Copié !",
|
||||
"copyFailed": "Échec de la copie — appuyez sur Ctrl/Cmd-C",
|
||||
"engineNotLoaded": "moteur cartographique non chargé",
|
||||
"engineNotLoadedDetail": "Le moteur cartographique {engine} ne s’est pas chargé. La liste et la légende ne sont pas affectées."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,14 @@
|
|||
"upg100WallIntro": "प्रार्थना के काम को पचास-पचास और सौ-सौ के समूहों में बाँटें — जैसे यीशु ने 5,000 लोगों को खिलाया (लूका 9:14)। हर पोस्टर 100 की एक सूची है जिसके लिए आप प्रार्थना कर सकते हैं, छाप सकते हैं और दीवार पर लगा सकते हैं — उनके लिए <strong>उनके जनसमूह के नाम से</strong> प्रार्थना करते हुए।",
|
||||
"loadingNamed": "{name} लोड हो रहा है…",
|
||||
"couldNotLoadNamed": "{name} लोड नहीं हो सका।",
|
||||
"engineMissing": "{engine} नक्शा इंजन लोड नहीं हुआ।"
|
||||
"engineMissing": "{engine} नक्शा इंजन लोड नहीं हुआ।",
|
||||
"packetFailed": "पुस्तिका विफल: {reason}",
|
||||
"selectionPacketFailed": "चयन की पुस्तिका विफल: {reason}",
|
||||
"posterOneTerritory": "पोस्टर एक समय में एक क्षेत्र छापता है — {count} चयनित।",
|
||||
"selectionPosterFailed": "चयन का पोस्टर विफल: {reason}",
|
||||
"mapUnavailable": "मानचित्र अनुपलब्ध",
|
||||
"copied": "कॉपी हो गया!",
|
||||
"copyFailed": "कॉपी विफल — Ctrl/Cmd-C दबाएँ",
|
||||
"engineNotLoaded": "मानचित्र इंजन लोड नहीं हुआ",
|
||||
"engineNotLoadedDetail": "{engine} मानचित्र इंजन लोड नहीं हुआ। सूची और लेजेंड अप्रभावित हैं।"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,14 @@
|
|||
"upg100WallIntro": "Distribuisci il compito della preghiera in gruppi di cinquanta e di cento — come Gesù sfamò i 5.000 (Luca 9:14). Ogni poster è una lista di 100 che puoi pregare, stampare e appendere al muro — pregando per loro <strong>con il nome del loro popolo</strong>.",
|
||||
"loadingNamed": "Caricamento di {name}…",
|
||||
"couldNotLoadNamed": "Impossibile caricare {name}.",
|
||||
"engineMissing": "Il motore di mappa {engine} non è stato caricato."
|
||||
"engineMissing": "Il motore di mappa {engine} non è stato caricato.",
|
||||
"packetFailed": "Libretto non riuscito: {reason}",
|
||||
"selectionPacketFailed": "Libretto della selezione non riuscito: {reason}",
|
||||
"posterOneTerritory": "Il manifesto stampa un territorio alla volta — {count} selezionati.",
|
||||
"selectionPosterFailed": "Manifesto della selezione non riuscito: {reason}",
|
||||
"mapUnavailable": "Mappa non disponibile",
|
||||
"copied": "Copiato!",
|
||||
"copyFailed": "Copia non riuscita — premi Ctrl/Cmd-C",
|
||||
"engineNotLoaded": "motore di mappe non caricato",
|
||||
"engineNotLoadedDetail": "Il motore di mappe {engine} non si è caricato. L’elenco e la legenda non sono interessati."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,14 @@
|
|||
"upg100WallIntro": "Reparta a tarefa da oração em grupos de cinquenta e de cem — como Jesus alimentou os 5.000 (Lucas 9:14). Cada cartaz é uma lista de 100 que pode orar, imprimir e pôr na parede — orando por eles <strong>pelo nome do seu povo</strong>.",
|
||||
"loadingNamed": "Carregando {name}…",
|
||||
"couldNotLoadNamed": "Não foi possível carregar {name}.",
|
||||
"engineMissing": "O motor de mapa {engine} não foi carregado."
|
||||
"engineMissing": "O motor de mapa {engine} não foi carregado.",
|
||||
"packetFailed": "Falha ao gerar o caderno: {reason}",
|
||||
"selectionPacketFailed": "Falha ao gerar o caderno da seleção: {reason}",
|
||||
"posterOneTerritory": "O cartaz imprime um território de cada vez — {count} selecionados.",
|
||||
"selectionPosterFailed": "Falha ao gerar o cartaz da seleção: {reason}",
|
||||
"mapUnavailable": "Mapa indisponível",
|
||||
"copied": "Copiado!",
|
||||
"copyFailed": "Falha ao copiar — pressione Ctrl/Cmd-C",
|
||||
"engineNotLoaded": "motor de mapas não carregado",
|
||||
"engineNotLoadedDetail": "O motor de mapas {engine} não carregou. A lista e a legenda não são afetadas."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,14 @@
|
|||
"upg100WallIntro": "Împarte sarcina rugăciunii în grupuri de câte cincizeci și o sută — așa cum Isus a hrănit cei 5.000 (Luca 9:14). Fiecare afiș este o listă de 100 pe care o poți ruga, tipări și pune pe perete — rugându-te pentru ei <strong>pe numele poporului lor</strong>.",
|
||||
"loadingNamed": "Se încarcă {name}…",
|
||||
"couldNotLoadNamed": "Nu s-a putut încărca {name}.",
|
||||
"engineMissing": "Motorul de hartă {engine} nu s-a încărcat."
|
||||
"engineMissing": "Motorul de hartă {engine} nu s-a încărcat.",
|
||||
"packetFailed": "Broșura a eșuat: {reason}",
|
||||
"selectionPacketFailed": "Broșura selecției a eșuat: {reason}",
|
||||
"posterOneTerritory": "Afișul tipărește un teritoriu pe rând — {count} selectate.",
|
||||
"selectionPosterFailed": "Afișul selecției a eșuat: {reason}",
|
||||
"mapUnavailable": "Harta indisponibilă",
|
||||
"copied": "Copiat!",
|
||||
"copyFailed": "Copierea a eșuat — apasă Ctrl/Cmd-C",
|
||||
"engineNotLoaded": "motorul de hărți nu s-a încărcat",
|
||||
"engineNotLoadedDetail": "Motorul de hărți {engine} nu s-a încărcat. Lista și legenda nu sunt afectate."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,14 @@
|
|||
"upg100WallIntro": "Разделите молитвенный труд на группы по пятьдесят и по сто — так Иисус накормил 5000 (Луки 9:14). Каждый плакат — это список из 100, о котором можно молиться, распечатать и повесить на стену, молясь о них <strong>по имени их народа</strong>.",
|
||||
"loadingNamed": "Загрузка {name}…",
|
||||
"couldNotLoadNamed": "Не удалось загрузить {name}.",
|
||||
"engineMissing": "Картографический движок {engine} не загрузился."
|
||||
"engineMissing": "Картографический движок {engine} не загрузился.",
|
||||
"packetFailed": "Не удалось создать буклет: {reason}",
|
||||
"selectionPacketFailed": "Не удалось создать буклет выбора: {reason}",
|
||||
"posterOneTerritory": "Плакат печатает по одной территории — выбрано {count}.",
|
||||
"selectionPosterFailed": "Не удалось создать плакат выбора: {reason}",
|
||||
"mapUnavailable": "Карта недоступна",
|
||||
"copied": "Скопировано!",
|
||||
"copyFailed": "Не удалось скопировать — нажмите Ctrl/Cmd-C",
|
||||
"engineNotLoaded": "движок карты не загружен",
|
||||
"engineNotLoadedDetail": "Движок карты {engine} не загрузился. Список и легенда не затронуты."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,14 @@
|
|||
"upg100WallIntro": "將禱告的工作分成五十人、一百人一組 — 就像耶穌餵飽五千人那樣(路加福音 9:14)。每一張海報都是一份 100 人名單,你可以為他們禱告、列印出來、貼在牆上 — <strong>按著他們族群的名字</strong>為他們禱告。",
|
||||
"loadingNamed": "正在加载{name}…",
|
||||
"couldNotLoadNamed": "无法加载{name}。",
|
||||
"engineMissing": "{engine} 地图引擎未能加载。"
|
||||
"engineMissing": "{engine} 地图引擎未能加载。",
|
||||
"packetFailed": "祷告册生成失败:{reason}",
|
||||
"selectionPacketFailed": "所选内容的祷告册生成失败:{reason}",
|
||||
"posterOneTerritory": "海报一次只能打印一个区域——已选 {count} 个。",
|
||||
"selectionPosterFailed": "所选内容的海报生成失败:{reason}",
|
||||
"mapUnavailable": "地图不可用",
|
||||
"copied": "已复制!",
|
||||
"copyFailed": "复制失败——请按 Ctrl/Cmd-C",
|
||||
"engineNotLoaded": "地图引擎未加载",
|
||||
"engineNotLoadedDetail": "{engine} 地图引擎未能加载。列表和图例不受影响。"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@
|
|||
"check:kpi-unit": "node internal/check-kpi-unit-once.mjs",
|
||||
"check:label-joins": "node internal/check-label-joins.mjs",
|
||||
"check:language-code-link": "node plugin-designs/doxa-research-map/scripts/check-language-code-link.mjs",
|
||||
"check:layout-key-namespaced": "node plugin-designs/research-dashboard/scripts/check-layout-key-namespaced.mjs",
|
||||
"check:leaf-engine-per-provider": "node internal/check-leaf-engine-per-provider.mjs",
|
||||
"check:leaf-english-leaks": "node internal/check-leaf-english-leaks.mjs",
|
||||
"check:leaf-english-leaks:self-test": "node internal/check-leaf-english-leaks.mjs --self-test",
|
||||
|
|
@ -147,6 +148,8 @@
|
|||
"check:no-free-identifiers": "node plugin-designs/research-map-plus-grid/scripts/check-no-free-identifiers.mjs",
|
||||
"check:no-orphan-gates": "node internal/check-no-orphan-gates.mjs",
|
||||
"check:no-public-binds": "node internal/check-no-public-binds.mjs",
|
||||
"check:no-silent-engine": "node internal/check-no-silent-engine-substitution.mjs",
|
||||
"check:no-silent-engine:self-test": "node internal/check-no-silent-engine-substitution.mjs --self-test",
|
||||
"check:one-palette": "node internal/check-one-palette.mjs",
|
||||
"check:one-palette:self-test": "node internal/check-one-palette.mjs --self-test",
|
||||
"check:packet-browser": "node internal/check-packet-browser.mjs",
|
||||
|
|
@ -325,6 +328,7 @@
|
|||
"check:i18n-never-translated": "a key PRESENT in all 11 catalogs but IDENTICAL in all of them is copied, not translated. check:i18n-parity asserts presence; presence and translatedness are different properties. Carries an allowlist for keys correctly identical everywhere (pure format strings, brand names, ISO designations) — each with a reason, so the list records decisions rather than silencing findings.",
|
||||
"check:i18n-treeshake": "each built bundle carries every translation area its code asks for: every area-prefixed key literal in <bundle>.js belongs to an area the build included (the build narrows library/i18n's catalogue glob per bundle, internal/i18n-areas.mjs). Headless.",
|
||||
"check:language-code-link": "the map's language selection reaches the grid as a locale-stable CODE, or narrows nothing at all. rega measured Languages > Language > \"Arabic\" taking the grid 2,107 -> 0 in BOTH locales: the emitter looked for a row whose language LABEL equalled the selected name, but a language tier's label is derived by splitting the API label at the comma, and no row reads \"Arabic\" - they read \"Arabic, Sudanese\", \"Arabic, Levantine\", 22 codes in all. Lifts the emitter's match rule and the composite's gridLanguage() from the shipping source (never re-typed) and runs them against a committed fixture of the 864 distinct language label/value pairs: the emitter's rule must agree with the legend's own three-arm filter on every (label, tier) pair, every tier must select at least one row, a tier covering one code must emit it, a tier covering several must emit NONE and leave the axis unfiltered. No network, no browser; --refresh-fixture re-takes the fixture.",
|
||||
"check:layout-key-namespaced": "two dashboards on one page must not share a saved layout. useDashboardLayout persists the four divider positions to localStorage, and until kit landing 2 the key was a single constant — invisible while there was exactly one dashboard, and SHARING THE ENGINE IS WHAT MAKES A SECOND ONE POSSIBLE, so SPEC-DASHBOARD-KIT section 8 named it as that landing's risk. The failure is quiet rather than loud: drag a divider in one dashboard, reload, and the other has moved. Asserts the shell passes no bare literal, EVALUATES the real expression with two different dashboard ids to prove the key varies (never a retyped copy of the rule), and that the pre-namespacing key is READ and never written — namespacing must not silently discard a reader's layout, and a migration that also deletes cannot be rolled back. Static; no DOM, no browser.",
|
||||
"check:leaf-engine-per-provider": "every leaf in the manifest at ?provider=maplibre makes ZERO requests to any *.mapbox.com host and a map leaf still draws; at its default every map leaf draws with the engine it drew with before (read from the canvas that drew). --baseline <tree> compares against another tree (e.g. main). Browser gate, @browser-slot-max-hold 2700.",
|
||||
"check:leaves-mount": "DID THE ELEMENT ACTUALLY MOUNT, on all five gospel leaves. Exists because a ReferenceError thrown during setup dies INSIDE the custom-element boundary: the page loads, every asset returns 200, pageerror fires zero times, and the element sits there with an empty shadow root. A healthy-looking dead page. This asks the cheap unambiguous question the rich gates are too slow to ask on every leaf — is anything there — in five steps that each name their own failure: tag defined, host present, shadowRoot attached, shadow root non-empty, visible text rendered. It does NOT trust the absence of console errors; zero errors is not the same as working. --poison for the negative test.",
|
||||
"check:legend-export-reachable": "the Export affordance must be reachable at BOTH widths. Selects a leaf row first (the control is gated on selectedNode) and opens the mobile sheet first (it starts closed). Asserts a REAL BOX, not CSS visibility — on mobile the elements report visibility:visible at 0x0. PASSES at both widths since the mobile sheet was given :export-enabled and :tabs. SKIPs when nothing is served.",
|
||||
|
|
@ -352,6 +356,7 @@
|
|||
"check:no-cross-plugin-imports": "no plugin imports from another plugin's folder (src/, utils, data) by a relative path; shared code goes through library/ (@map/\u2026). A composite may mount another bundle's PUBLIC profile .vue. --self-test plants a crossing import.",
|
||||
"check:no-eval": "no built bundle contains new Function or eval (a strict CSP without 'unsafe-eval' must work), and vue-i18n in JIT mode renders real catalogue messages in en and ar with eval blocked. Headless.",
|
||||
"check:no-free-identifiers": "every name a .vue script uses is imported, declared, a parameter or a known global (scope-aware, across plugin-designs and library). A free identifier compiles and then throws at runtime in exactly the path nobody clicked.",
|
||||
"check:no-silent-engine": "A profile must NEVER fall back to a different map engine than its provider asked for. `engineGlobal(provider) || window.mapboxgl` looks defensive and is not: engineGlobal already returns the right global for the requested provider (useMapInstance.js:115 falls back to mapbox's NAME only for an UNKNOWN provider, never a missing engine), so the || fires in exactly one case — the page asked for maplibre and maplibre failed to load — and hands back the TOKEN-GATED engine to a page that asked for the KEYLESS one. Worse, accessToken is gated on !isMaplibre, so the substitute arrives WITHOUT a token: 401s on every tile instead of a legible failure. Found by regions' C3 read 2026-09-26; 2 offenders remained (cities-internet, gospel-resources) after my-upg-100-list was fixed. NOT a duplicate of check:leaf-engine-per-provider / check:provider-switch / check:auto-engine — all three assert the HAPPY path (what loads) and this bug only appears when something does NOT load, so all three were green while it existed. A SOURCE check on purpose: reproducing it live means serving a leaf with MapLibre deliberately blocked, spending a browser slot on what a grep decides. Exits 75 when no file calls engineGlobal — 'found nothing' is not 'found nothing wrong'. Run :self-test to prove the pattern still matches.",
|
||||
"check:packet-browser": "the packet the READER gets — the legend's Export > Prayer packet path, proving the shared renderer runs in a BROWSER. Asserts the same 12 points / 12 wheel labels / page-1 geography / print layer as check:packet-render, which it did not until 2026-09-24. CONDITIONAL: SKIPs without a server over the repo root (python3 -m http.server 4898) and a reachable records API.",
|
||||
"check:packet-fixture": "the committed fixture must still match clusters.json and must never carry image_url (CI would fetch 43 photos from someone else's CDN).",
|
||||
"check:packet-render:expect-funnel": "check:packet-render with the page-2 FUNNEL declared REQUIRED. Exists because of a real near-miss: a merge resolved with `git checkout --ours` deleted the printPacket call site that supplies the funnel data (60 lines) and EVERY GATE STAYED GREEN — it had to, because the funnel page is OPTIONAL by design (buildPacket omits it when the arg is null), so a packet without page 2 is not malformed, just smaller. Always requiring it would be the wrong fix: the 11 pre-funnel laos packets and any host with no funnel data would go red, and a false red costs as much as a false green. So the CALLER, which knows whether this packet was built with funnel data, declares it — an absence is then either declared (no flag) or a failure (flag passed, page missing), never a silent nothing. Pass it for any packet from a profile that wires packetFunnel(). Browser gate.",
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import ShareButton from '@map/components/map-controls/ShareButton.vue'
|
|||
import { resolveAssetsBase } from '@map/utils/embedBase.js'
|
||||
import { resolveMapProvider } from '@map/composables/useMapProvider.js'
|
||||
import { ensureEngineScript, engineGlobal, ensureEngineCSS, engineStylesheetUrl, engineUiLocale } from '@map/composables/useMapInstance.js'
|
||||
import { localizeBasemapLabels } from '@map/maps/localize-labels.js'
|
||||
import { resolveNamedStyle } from '@map/styles/registry.js'
|
||||
import { installRtlTextPlugin } from '@map/maps/rtl-text.js'
|
||||
// People-group dots open the SAME detail panel as Prayer Progress (doxa-simple-map): the
|
||||
|
|
@ -372,9 +373,9 @@ onMounted(async () => {
|
|||
if (!gl) {
|
||||
const engine = ciProvider === 'maplibre' ? 'MapLibre' : 'Mapbox'
|
||||
console.warn(`[connectivity-map] the ${engine} engine did not load; refusing to substitute another engine.`)
|
||||
// messages.engineNotLoadedDetail arrives with upg100's ade12e4c; until it does, English is the fallback.
|
||||
const msg = t('messages.engineNotLoadedDetail', { engine })
|
||||
err.value = msg && msg !== 'messages.engineNotLoadedDetail' ? msg : `The ${engine} map engine did not load. The list and legend are unaffected.`
|
||||
// messages.engineMissing is the shared key (studio's landing 3); English only if a host has no catalogue.
|
||||
const msg = t('messages.engineMissing', { engine })
|
||||
err.value = msg && msg !== 'messages.engineMissing' ? msg : `The ${engine} map engine did not load.`
|
||||
return
|
||||
}
|
||||
if (!mapEl.value) { err.value = 'map engine not loaded'; return }
|
||||
|
|
@ -417,6 +418,10 @@ onMounted(async () => {
|
|||
// countries carrying a real attribution requirement (India CC BY 2.5 IN, etc).
|
||||
addMapAttribution(map, { boundaries: true })
|
||||
map.once('load', async () => {
|
||||
// The BASEMAP's place names in the reader's language (Mapbox setLanguage / MapLibre name:<lang>),
|
||||
// the library's own helper. useMapInstance applies it for every map built through it; this map is
|
||||
// built raw, so it was the one map whose country and city names stayed English under ar.
|
||||
try { localizeBasemapLabels(map, readerLang()) } catch (_) { /* a nicety lost, never a broken map */ }
|
||||
paint(map, adm0)
|
||||
selectedPin.initialize()
|
||||
await groupsLoaded
|
||||
|
|
|
|||
|
|
@ -571,6 +571,62 @@ useShadowStyles(
|
|||
// embedded. Verify in a constrained host, never on the bare leaf.
|
||||
'.stl-panel{--stl-top:8px!important}' +
|
||||
'.upg-root:has(.mapboxgl-ctrl-geocoder) .stl-panel{--stl-top:58px!important}' +
|
||||
|
||||
// ── RTL: WHAT THE LIBRARY DOES NOT DO ──────────────────────────────────────
|
||||
// ⚠ THE TWO POSITION RULES THAT USED TO LIVE HERE ARE GONE, deleted deliberately rather than left as a
|
||||
// belt-and-braces duplicate. studio's c79aae95 converts BOTH physical insets in SemanticTreeLegend to
|
||||
// logical ones — :619 .stl-panel and :925 .stl-reopen are now `inset-inline-start: 8px` — so the panel
|
||||
// and its reopen button mirror for EVERY profile, not just this one. Two mechanisms doing one job is
|
||||
// worse than either: the next reader cannot tell which is load-bearing, and deleting the wrong one
|
||||
// looks safe.
|
||||
// WHAT REMAINS BELOW IS ONLY WHAT c79aae95 DOES NOT COVER — verified by reading it, twice:
|
||||
// · .upg-detail-panel is THIS file's own CSS (:449), not a legend class. The library cannot reach it,
|
||||
// and it must swap or it collides with the now-mirrored legend on the other side.
|
||||
// · content DIRECTION. c79aae95 has ZERO occurrences of direction:rtl or unicode-bidi. It mirrors the
|
||||
// panel's POSITION; these set its CONTENT direction, which is a different property. repo reported
|
||||
// BOTH symptoms — "the panel is on the left" AND "the rows stay LTR" — so dropping these would fix
|
||||
// the first and silently restore the second.
|
||||
// ⚠ AND THIS PAIR MAY YET BECOME REDUNDANT: studio's argument is that dir on .profile-loader
|
||||
// (ProfileLoader.vue:282) inherits into the legend, since `direction` is an inherited property that
|
||||
// crosses the shadow boundary. That is plausible and they declined to add a library rule without a
|
||||
// measurement — correctly. rega will read the rows on Simple Research and Prayer Progress, which
|
||||
// have NO override, after landing 5. If they read RTL there, DELETE the two rules below too.
|
||||
// ── the original finding, kept because it explains the shape ────────────────
|
||||
// Driver-reported via repo, 2026-09-26, from the README's Arabic picture: under ?lang=ar the legend
|
||||
// panel stayed on the LEFT and the map controls sat on top of its top-left corner.
|
||||
//
|
||||
// ★ THE CAUSE IS ONE COMPONENT BEING RTL-AWARE AND ITS NEIGHBOUR NOT. MapToolbar.vue:42 already uses
|
||||
// `inset-inline-end: 3px`, a LOGICAL property, so under dir=rtl it correctly mirrors to the LEFT.
|
||||
// SemanticTreeLegend.vue:619 uses `position:absolute; left:8px` — a PHYSICAL property, which ignores
|
||||
// dir entirely. So the toolbar moves left, the panel never leaves, and they land on top of each other.
|
||||
// The overlap is not a z-index or spacing bug; it is two coordinate systems disagreeing.
|
||||
//
|
||||
// ⚠ THIS IS A WORKAROUND FOR A LIBRARY DEFECT AND I AM SAYING SO RATHER THAN QUIETLY PAPERING IT.
|
||||
// The real fix is one character class in SemanticTreeLegend — `left:8px` -> `inset-inline-start:8px` —
|
||||
// which would mirror for EVERY profile automatically. That file is library/, so under rule 5B it is
|
||||
// studio's; reported. Until then every other profile with an RTL locale has this same collision, and
|
||||
// this override fixes only mine.
|
||||
//
|
||||
// Scoped to [dir=rtl] so the LTR layout is untouched: ProfileLoader.vue:282 binds dir on the
|
||||
// .profile-loader wrapper from RTL_LOCALES, so this activates exactly when the document says so.
|
||||
// The detail panel is the legend's mirror image (it sits top-RIGHT in LTR), so it has to swap too or
|
||||
// the two would trade places and collide on the other side.
|
||||
'[dir="rtl"] .upg-detail-panel{right:auto!important;left:8px!important}' +
|
||||
// ⚠ AND THE ROWS THEMSELVES. dir on the wrapper does NOT reach content that sets its own direction,
|
||||
// and the legend's rows render zone names + numbers that must read right-to-left as a unit. Without
|
||||
// this the panel mirrors but its contents stay LTR — which is what the picture shows.
|
||||
'[dir="rtl"] .stl-panel,[dir="rtl"] .stl-panel *{direction:rtl}' +
|
||||
// Numbers stay LTR inside an RTL line: a count or a percentage is a left-to-right run even in Arabic,
|
||||
// and without isolation the bidi algorithm reorders a run that STARTS with a digit. Same fix the
|
||||
// packet needed for scripture references.
|
||||
'[dir="rtl"] .stl-panel .stl-count,[dir="rtl"] .stl-panel .stl-pop{direction:ltr;unicode-bidi:isolate}' +
|
||||
// ⚠ AND THE REOPEN BUTTON, which I missed on my first pass and repo caught. SemanticTreeLegend has
|
||||
// TWO physical `left:8px` rules, not one: :619 for the panel and :921 for .stl-reopen, the button that
|
||||
// brings the panel back after it is collapsed. Mirroring only the panel would leave the button on the
|
||||
// opposite side from the thing it opens — a worse state than the original bug, because it looks
|
||||
// deliberate.
|
||||
// The lesson is mine: I told studio to sweep for other physical insets and did not run the sweep
|
||||
// myself before reporting. `grep -nE '(^|[^-])(left|right):' library/components/legends/*.vue`.
|
||||
// Geocoder suggestion metadata layout (clone — bold field labels for PG rows).
|
||||
'.dg-main{font:13px/1.3 ui-monospace,monospace}' +
|
||||
'.dg-meta{margin-top:2px;font-size:11px;color:#475569;display:flex;flex-wrap:wrap;gap:8px}' +
|
||||
|
|
@ -808,8 +864,12 @@ async function copySelection() {
|
|||
} catch (err) {
|
||||
ok = legacyCopy(text) // secure-context / permission failure → fallback
|
||||
}
|
||||
copyFlash.value = ok ? 'Copied!' : 'Copy failed — press Ctrl/Cmd-C'
|
||||
setTimeout(() => { if (copyFlash.value.startsWith('Copied')) copyFlash.value = '' }, 1800)
|
||||
// ⚠ THE OLD GUARD ONLY MATCHED THE SUCCESS BRANCH — `startsWith('Copied')` — so "Copy failed" NEVER
|
||||
// CLEARED, in English, before any of this was translated. A pre-existing bug that the prose fix would
|
||||
// have widened to both branches in ten languages. Found by exp-shepherd sweeping the whole tree for the
|
||||
// PATTERN (a branch on a user-visible string's content) after I had only grepped for the exact shape I
|
||||
// already knew, `status.value.startsWith` — which is why I missed the ternary form in my own file.
|
||||
flashRef(copyFlash, ok ? t('messages.copied') : t('messages.copyFailed'), 1800)
|
||||
}
|
||||
|
||||
// textarea + execCommand('copy') fallback (non-secure context, no clipboard API).
|
||||
|
|
@ -1266,8 +1326,7 @@ const packetPrints = usePosterPrints({
|
|||
watch(packetPrints.exportState, (st) => {
|
||||
if (!st) { if (/packet/i.test(status.value)) status.value = ''; return; }
|
||||
if (st.phase === 'error') {
|
||||
status.value = `Packet failed: ${st.message}`;
|
||||
setTimeout(() => { if (status.value.startsWith('Packet failed')) status.value = ''; }, 4000);
|
||||
flashStatus(t('messages.packetFailed', { reason: st.message }), 4000);
|
||||
return;
|
||||
}
|
||||
status.value = st.phase === 'done' ? '' : `${st.message}…`;
|
||||
|
|
@ -1309,6 +1368,18 @@ async function packetMapSvg(zoneId, R) {
|
|||
} catch { return ''; }
|
||||
}
|
||||
|
||||
// ⚠ A TRANSIENT STATUS CLEARS BY IDENTITY, NOT BY ITS ENGLISH PREFIX. Each of these messages used to be
|
||||
// cleared by `if (status.value.startsWith('Packet failed'))` — a guard that reads the PROSE. The moment
|
||||
// the prose is translated (exp-shepherd's universal-props row, 2026-09-26) that guard stops matching and
|
||||
// the status never clears in any non-English locale: a stuck error message, in ten languages, from a fix
|
||||
// that looked purely cosmetic. Same family as counting prayer points by matching the English word
|
||||
// "prayer". So compare against the exact string we set instead — locale-independent by construction.
|
||||
function flashRef(target, text, ms) {
|
||||
target.value = text;
|
||||
setTimeout(() => { if (target.value === text) target.value = ''; }, ms);
|
||||
}
|
||||
const flashStatus = (text, ms) => flashRef(status, text, ms);
|
||||
|
||||
async function printPrayerPacket(zoneId) {
|
||||
const zone = allLists().find((z) => z.id === zoneId);
|
||||
if (!zone) return;
|
||||
|
|
@ -1436,10 +1507,21 @@ const batchBusy = ref(false);
|
|||
// list objects carry the selectors the packet needs; resolve back to those rather than
|
||||
// re-deriving membership from the map, which would be a second source of truth.
|
||||
function selectedLists() {
|
||||
const want = new Set(selectedTerritories.value
|
||||
// ⚠ SELECTION ORDER, NOT CATALOGUE ORDER. This used to be
|
||||
// allLists().filter((l) => want.has(l.id))
|
||||
// which returns the lists in clusters.json order and silently DISCARDS the order the reader chose —
|
||||
// even though selectedTerritories is documented at :186 as "an ORDERED list … (insertion order)".
|
||||
// rega measured the consequence (NEEDS-EYES row 45, main 52eeb0db): selecting Laos, then West Africa,
|
||||
// then Europe produced a packet headed "West Africa + Laos + Europe", because west-africa is index 0
|
||||
// in the catalogue and laos is index 4. Reproduced exactly from the data.
|
||||
// It matters because the label's whole job is to "name the territories they actually chose rather than
|
||||
// inventing a title for their selection" (the comment on selectionAsList). A cover that reorders the
|
||||
// reader's own choices is inventing a title, quietly.
|
||||
const ids = selectedTerritories.value
|
||||
.filter((t) => t.kind === 'zone')
|
||||
.map((t) => String(t.key).replace(/^zone:/, '')));
|
||||
return allLists().filter((l) => want.has(l.id));
|
||||
.map((t) => String(t.key).replace(/^zone:/, ''));
|
||||
const byId = new Map(allLists().map((l) => [l.id, l]));
|
||||
return ids.map((id) => byId.get(id)).filter(Boolean);
|
||||
}
|
||||
|
||||
// A SYNTHETIC LIST standing for the whole selection, so every existing action works unchanged.
|
||||
|
|
@ -1502,8 +1584,7 @@ async function makeSelectionPacket() {
|
|||
funnel: funnel && lists.length === 1 ? funnel : (funnel ? { ...funnel, listCount: 0 } : null),
|
||||
});
|
||||
} catch (e) {
|
||||
status.value = `Selection packet failed: ${String(e?.message || e).slice(0, 90)}`;
|
||||
setTimeout(() => { if (status.value.startsWith('Selection packet failed')) status.value = ''; }, 4000);
|
||||
flashStatus(t('messages.selectionPacketFailed', { reason: String(e?.message || e).slice(0, 90) }), 4000);
|
||||
} finally { batchBusy.value = false; }
|
||||
}
|
||||
|
||||
|
|
@ -1518,15 +1599,12 @@ async function makeSelectionPoster() {
|
|||
// is exactly the wall's poster; with several, say so plainly instead of silently printing
|
||||
// the first zone's poster as though it covered the selection.
|
||||
if (lists.length > 1) {
|
||||
status.value = `Poster prints one territory at a time — ${lists.length} selected. `
|
||||
+ 'Pick one, or use the prayer packet for the whole selection.';
|
||||
setTimeout(() => { if (status.value.startsWith('Poster prints one')) status.value = ''; }, 5000);
|
||||
flashStatus(t('messages.posterOneTerritory', { count: lists.length }), 5000);
|
||||
return;
|
||||
}
|
||||
await packetPrints.printPoster(lists[0]);
|
||||
} catch (e) {
|
||||
status.value = `Selection poster failed: ${String(e?.message || e).slice(0, 90)}`;
|
||||
setTimeout(() => { if (status.value.startsWith('Selection poster failed')) status.value = ''; }, 4000);
|
||||
flashStatus(t('messages.selectionPosterFailed', { reason: String(e?.message || e).slice(0, 90) }), 4000);
|
||||
} finally { batchBusy.value = false; }
|
||||
}
|
||||
|
||||
|
|
@ -1848,7 +1926,18 @@ onMounted(async () => {
|
|||
bootstrapLegend()
|
||||
// Load the engine the PROVIDER selects, not the one this file used to assume.
|
||||
try { await ensureEngineScript(upgProvider) } catch (_) { /* fall through to the !gl notice below */ }
|
||||
const gl = engineGlobal(upgProvider) || window.mapboxgl
|
||||
// ★ NEVER SWITCH ENGINES SILENTLY. This read `engineGlobal(upgProvider) || window.mapboxgl`, and that
|
||||
// fallback can ONLY fire when the requested provider is 'maplibre' and MapLibre failed to load —
|
||||
// engineGlobal already resolves mapbox's own global for the mapbox case (useMapInstance.js:115 falls back
|
||||
// to ENGINES.mapbox.global only for an UNKNOWN provider name, not for a missing engine). So the `||`
|
||||
// silently handed back MAPBOX to a page that asked for the KEYLESS engine, breaking the keyless contract
|
||||
// that research-map.instances.json documents.
|
||||
// ⚠ AND THE FALLBACK COULD NOT EVEN WORK: `gl.accessToken = token` a few lines below is gated on
|
||||
// `if (!isMaplibre)`, so a maplibre request that fell through to Mapbox would get Mapbox WITHOUT a token
|
||||
// — 401s on every tile instead of a legible failure. Two defects in one expression.
|
||||
// Found by regions' C3 read, routed via dx-shepherd (END-SHEP-C3C). Same shape in all three raw-map
|
||||
// plugins.
|
||||
const gl = engineGlobal(upgProvider)
|
||||
// ★ SHAPE RTL BASEMAP LABELS — HERE, not in index.js, and not after the map exists.
|
||||
// This profile builds its map RAW (`new gl.Map` below) instead of going through
|
||||
// useMapInstance, so it inherits none of the entry's side effects. It appeared to work only
|
||||
|
|
@ -1871,8 +1960,16 @@ onMounted(async () => {
|
|||
// notice in the MAP CELL, and still enrich the legend with live population data
|
||||
// (a plain fetch — it needs no map). The list stays fully usable without tiles.
|
||||
if (!gl) {
|
||||
status.value = '⚠ map engine not loaded'
|
||||
mapError.value = 'The map engine did not load. The list and legend are unaffected.'
|
||||
// FAIL VISIBLY AND NAME THE ENGINE. The old copy said "The map engine" — true but undiagnosable:
|
||||
// a reader could not tell whether the keyless engine they asked for was even attempted. It now says
|
||||
// WHICH engine, so a partner who set ?provider=maplibre and sees "MapLibre did not load" knows their
|
||||
// request was honoured and the script is the problem, rather than suspecting a silent downgrade.
|
||||
// A console.warn too, because the on-screen notice is for the reader and this line is for whoever is
|
||||
// debugging the embed.
|
||||
console.warn(`[upg-100-list] ${upgProvider} engine global is missing — refusing to substitute another `
|
||||
+ 'engine. A page that asked for the keyless engine must not silently receive the token-gated one.')
|
||||
status.value = `⚠ ${t('messages.engineNotLoaded')}`
|
||||
mapError.value = t('messages.engineNotLoadedDetail', { engine: isMaplibre ? 'MapLibre' : 'Mapbox' })
|
||||
enrichLegendFromRecords()
|
||||
return
|
||||
}
|
||||
|
|
@ -1978,6 +2075,16 @@ onMounted(async () => {
|
|||
// toggleZoneSelection (the SAME union path a real row tap uses). Returns the
|
||||
// node's descendant zoneKeys (count) so the gate can recompute the expected
|
||||
// map-highlight feature count independently.
|
||||
// ⚠ THIS IS THE BATCH-UNION DRIVER, NOT A CLICK SIMULATOR — it calls toggleZoneSelection() directly,
|
||||
// so OUTSIDE batch mode it toggles a union nobody is displaying and the isolate filter stays
|
||||
// undefined. rega measured exactly that (NEEDS-EYES row 45) and asked whether it should isolate for a
|
||||
// single select.
|
||||
// IT SHOULD NOT, and widening it would be worse than the narrowness. A REAL click goes through
|
||||
// onLegendSelect(), which branches on batchMode — isolate when off, feed the union when on. If this
|
||||
// handle isolated on its own it would no longer EXERCISE that branch, and a gate built on it could go
|
||||
// green while the real click path was broken. A test handle that does more than the UI hides the UI.
|
||||
// So: use a real click to test isolation (rega's row-45 test A does, and it passes), and use this only
|
||||
// to drive batch selection. The name says Toggle, and toggling the union is what it does.
|
||||
toggleLegendRow: (label) => {
|
||||
const find = (nodes) => {
|
||||
for (const n of nodes) {
|
||||
|
|
@ -2437,7 +2544,7 @@ onBeforeUnmount(() => {
|
|||
the error — surface it exactly where the map would have been, the same way
|
||||
gospel-resources/resources-map.vue does with .gm-err. -->
|
||||
<div v-if="mapError" class="upg-map-err">
|
||||
<strong>Map unavailable</strong>{{ mapError }}
|
||||
<strong>{{ t('messages.mapUnavailable') }}</strong>{{ mapError }}
|
||||
</div>
|
||||
<!-- Edge scroll-affordance strips (the accessibility side bars). They live as
|
||||
direct siblings of the map container inside .upg-root — that element is the
|
||||
|
|
|
|||
|
|
@ -67,7 +67,28 @@ const instanceId = computed(() => cfg.value?.instanceId || 'upg-100-mfe')
|
|||
const spec = computed(() => ({
|
||||
id: 'upg-100-mfe',
|
||||
tag: TAG,
|
||||
config: { profile: 'upg-100-list', dataSource: cfg.value?.dataSource || 'pray-tools', instanceId: instanceId.value },
|
||||
// ⚠ dataSource IS PASSED ONLY WHEN THE PARTNER SETS IT — no hardcoded default here. This read
|
||||
// `cfg.value?.dataSource || 'pray-tools'`, which is a composite-level constant standing in FRONT of the
|
||||
// pane's own lookup: ProfileLoader.vue:142 resolves
|
||||
// config.dataSource || sourcesConfig.activeSource || 'doxa-csv'
|
||||
// and sources.json's activeSource is 'pray-tools' today, so the two AGREE and this is a no-op refactor
|
||||
// (verified from source, per dx-shepherd END-SHEP-UPG-CONTRACT, not assumed).
|
||||
// It matters anyway, for two reasons. (a) The day activeSource changes, these panes would silently keep
|
||||
// using 'pray-tools' while every other consumer moved — a divergence nothing would report. (b) The
|
||||
// comment at ProfileLoader.vue:135-141 records this EXACT bug already happening once: a host embedding
|
||||
// without profile-config.dataSource fell through to 'doxa-csv', whose relative CSV path 404s off a CDN
|
||||
// origin, so the map loaded and no data fetch fired. `activeSource` was inserted to fix that, and a
|
||||
// hardcoded constant in front of it re-opens the hole it closed.
|
||||
// Regions hit the mirror image (a partner's dataSource silently DROPPED, f0aa5ab3); mine overrode a
|
||||
// partner's SILENCE. Same class — the composite deciding for the panes — opposite direction.
|
||||
config: {
|
||||
profile: 'upg-100-list',
|
||||
// profile and instanceId ARE this composite's own config, deliberately: the panes ARE profile
|
||||
// 'upg-100-list', and both share one instanceId so cross-pane events resolve to the same app.
|
||||
// Regions' gate forbids them in INHERITED_PAGE_KEYS (inherited FROM THE HOST), not here.
|
||||
instanceId: instanceId.value,
|
||||
...(cfg.value?.dataSource ? { dataSource: cfg.value.dataSource } : {}),
|
||||
},
|
||||
// RESOURCES FIRST, MAP SECOND (Driver 2026-09-23). "By default the first tab
|
||||
// shouldn't be the map. The first tab should be the prayer resources" — that pane
|
||||
// already explains what a UPG-100 list IS at the top and shows the posters, so it
|
||||
|
|
@ -140,7 +161,13 @@ const paneEls = {}
|
|||
// partner who asked for MapLibre a Mapbox map in every nested pane -- the pane reads
|
||||
// provider as undefined and falls back. Same shape of bug as the missing 'urlSync' here
|
||||
// before it: the inner map cannot honour a key the shell never passed down.
|
||||
const INHERITED_PAGE_KEYS = ['assetsBase', 'apiBaseUrl', 'locale', 'lang', 'isDark', 'qa', 'provider', 'list']
|
||||
// ⚠ tokenUrl IS FORWARDED EXPLICITLY. The panes already RECEIVE a token in practice — the outer
|
||||
// ProfileLoader fetches profile-config.tokenUrl and publishes a page-wide shared token — so this was
|
||||
// working by a side effect of something else rather than by this contract. exp-shepherd's
|
||||
// universal-props row (2026-09-26) flagged it for exactly that reason: a prop that arrives because a
|
||||
// neighbour happens to publish it is not forwarded, it is lucky, and it breaks silently the day the
|
||||
// neighbour stops. Naming it here makes the panes' token a consequence of this list.
|
||||
const INHERITED_PAGE_KEYS = ['assetsBase', 'apiBaseUrl', 'tokenUrl', 'locale', 'lang', 'isDark', 'qa', 'provider', 'list']
|
||||
|
||||
function paneElement(pane) {
|
||||
const el = document.createElement(TAG)
|
||||
|
|
|
|||
|
|
@ -582,7 +582,7 @@ const DERIVED_AXES = {
|
|||
const rowAxisValue = (u, field) => (DERIVED_AXES[field] ? DERIVED_AXES[field](u) : u[field])
|
||||
// ★ A SELECTION MAY BE SEVERAL VALUES (SPEC-DASHBOARD-KIT D1), and this is the end of the wire
|
||||
// that makes the "Arabic" case a real narrowing instead of an honest abstention. The language tier
|
||||
// "Arabic" covers 22 ISO codes, so no single value expresses it; until now the composite had to
|
||||
// "Arabic" covers 23 ISO codes, so no single value expresses it; until now the composite had to
|
||||
// send nothing and leave the axis unfiltered rather than show a fraction of the selection or an
|
||||
// empty grid. A comma-separated list is accepted here and matched as OR-within-the-axis, which is
|
||||
// exactly what the bus's facetMatches() does at the other end — one rule, two implementations,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import { tStatic } from '@map/i18n/index.js'
|
|||
const T = (key, en) => tStatic(key) || en
|
||||
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
|
||||
import { useDashboardShell, fmt } from './src/composables/useDashboardShell.js'
|
||||
import { useDashboardLayout } from './src/composables/useDashboardLayout.js'
|
||||
import { useDashboardLayout } from '@map/composables/useDashboardLayout.js'
|
||||
import {
|
||||
DashboardTopBar,
|
||||
DashboardResearchFilters,
|
||||
|
|
@ -253,7 +253,13 @@ const { startFacetResize, startRailResize, startTableResize, startShellResize, o
|
|||
// by the stylesheet and no longer drives any layout (see the pageScroll note above); the
|
||||
// composable needs to know so the table-axis handle can drive --rd-map-h instead.
|
||||
pageScroll,
|
||||
storageKey: 'rd-dashboard-layout',
|
||||
// ★ NAMESPACED PER DASHBOARD (kit landing 2). This was the single constant every dashboard
|
||||
// shared, which was harmless while there was only one and becomes a collision the moment a page
|
||||
// carries two — each would read and write the other's divider positions. config.id is the
|
||||
// profile's own identity, so a second dashboard on the same page gets its own drawer without its
|
||||
// author having to know this key exists. useDashboardLayout reads the old shared key once, so no
|
||||
// reader loses the layout they had.
|
||||
storageKey: 'rd-dashboard-layout:' + (mergedConfig.value?.id || 'default'),
|
||||
// MUST mirror the `:host` --facet-w/--rail-w defaults, or reset() would snap the rails to a
|
||||
// different balance than a fresh load shows. Tree wider than charts — see the rail-balance note.
|
||||
// mapH mirrors the page-scroll CSS fallback 40svh (~360px at a 900px viewport — see
|
||||
|
|
|
|||
|
|
@ -48,18 +48,38 @@
|
|||
* reads the URL first) — the engine is Mapbox, it simply has no key. A gate that fails a
|
||||
* product for a key the gate did not provide is measuring its own environment.
|
||||
* It now takes MAPBOX_TOKEN from the env (or vite.doxa-maps-build-config.json `token`, the
|
||||
* same ladder check:experimental-shelf uses) and injects it as window.MAP_TOKEN before
|
||||
* navigation, the way check:auto-engine and check:a11y-button-names do. With no token the
|
||||
* same ladder check:experimental-shelf uses) and supplies it on BOTH documented rungs — the
|
||||
* host global (window.MAP_TOKEN, injected before navigation the way check:auto-engine does)
|
||||
* and the ?tk= URL param — as two separate cases. See the CASES block below for why two.
|
||||
* With no token the
|
||||
* mapbox half is NOT MEASURED — reported as a SKIP line so run-parallel prints ⊘ rather than
|
||||
* counting it as a pass, because an always-taken skip is indistinguishable from an unwired
|
||||
* gate unless the runner says so.
|
||||
*
|
||||
* ★ WHY THE MAP PROBE ASKS THE ENGINE AND NOT THE DOM (2026-09-26, the second correction in a
|
||||
* day). This gate reported "NO map constructed" on a leaf where rega then measured 1 Mapbox map, 2
|
||||
* GL canvases and 3 search inputs, on BOTH token rungs. The product was never at fault; the
|
||||
* detection was. A DOM walk for a canvas is a chain of assumptions — every shadow root open, the
|
||||
* canvas carrying the class expected, existing by the time it is looked for — and when any link
|
||||
* breaks it reports ABSENCE, which is indistinguishable from a broken product. It now hooks the
|
||||
* engine's own Map.prototype.setStyle through both globals, which cannot be wrong about the DOM
|
||||
* because it never looks at it, and widens the bar selector to what a reader would call a search
|
||||
* box. Both borrowed from rega's tokrung.mjs.
|
||||
*
|
||||
* THE LESSON, recorded because it is the second time in two days that a probe accused a working
|
||||
* product: a measurement that yields ZERO when its own assumption is wrong will always blame the
|
||||
* thing it is measuring. Where a positive control exists that measures correctly, copy the control.
|
||||
*
|
||||
* ASSERTIONS, on the built tree:
|
||||
* maplibre ZERO requests to api.mapbox.com. (Measured with or without a token.)
|
||||
* If a bar is present it must produce suggestions; if it is absent, that is the
|
||||
* documented contract and is recorded as such.
|
||||
* mapbox the bar is PRESENT and produces suggestions. Requires a token; without one this
|
||||
* half is skipped, never failed. Mapbox traffic is expected here and not asserted on.
|
||||
* mapbox TWICE, once per token rung: a map CONSTRUCTS, the bar is PRESENT, and typing
|
||||
* produces suggestions. Requires a token; without one this half is skipped, never
|
||||
* failed. Mapbox traffic is expected here and not asserted on — but rejected
|
||||
* RESPONSES are recorded, because "21 requests and no map" is otherwise ambiguous
|
||||
* between a token never seen, a token refused, and a map that failed for its own
|
||||
* reasons, and those three have different owners.
|
||||
*
|
||||
* NEVER PRINTS THE TOKEN. Only its presence is reported.
|
||||
*
|
||||
|
|
@ -116,18 +136,71 @@ const browser = await chromium.launch({ args: ['--enable-unsafe-swiftshader', '-
|
|||
const fails = []
|
||||
const lines = []
|
||||
try {
|
||||
// The mapbox half needs a key. Measure maplibre either way — it is the headline claim and it is
|
||||
// fully measurable keyless, which is the whole point of the engine.
|
||||
const engines = TOKEN ? ['maplibre', 'mapbox'] : ['maplibre']
|
||||
for (const engine of engines) {
|
||||
// ★ THE MAPBOX HALF IS MEASURED ON BOTH TOKEN RUNGS, AND THAT IS A DELIBERATE EXPERIMENT.
|
||||
// rega, gates:post at 1a761741 WITH a token: the mapbox half reported "NO map constructed", 21
|
||||
// requests to api.mapbox.com, 0 bars — while rega's own probe of THIS leaf at
|
||||
// ?provider=mapbox&tk=<same token> constructed a Mapbox map. The suggested cause was that the
|
||||
// generated leaf overwrites the window.MAP_TOKEN this gate sets in addInitScript.
|
||||
//
|
||||
// IT DOES NOT. research-map/index.html reads it at line 70 (`HOST_TOKEN = window.MAP_TOKEN`) and
|
||||
// every assignment after it — lines 71, 109, 150 — is guarded by `!window.MAP_TOKEN`, so a
|
||||
// host-set value is read and never replaced. studio read the same lines independently. The
|
||||
// hypothesis is the obvious one and the source does not support it.
|
||||
//
|
||||
// So rather than switch channels on a mechanism nobody can point at, the gate now measures BOTH:
|
||||
// the host global that partners use, and the ?tk= URL rung. If both construct, the earlier
|
||||
// failure was this gate's and is gone. If ONLY ?tk= constructs, that is a PRODUCT defect on the
|
||||
// host-global rung — the one an embedding partner reaches for — and the gate will say so by
|
||||
// name instead of leaving a one-line change to look like a fix.
|
||||
//
|
||||
// The maplibre case carries NO token by either route: resolveMapProvider's `auto` rung reads a
|
||||
// token as "use Mapbox", and a present token is exactly the variable this gate holds at zero.
|
||||
const CASES = [{ id: 'maplibre', provider: 'maplibre', rung: 'none' }]
|
||||
if (TOKEN) CASES.push(
|
||||
{ id: 'mapbox/window.MAP_TOKEN', provider: 'mapbox', rung: 'global' },
|
||||
{ id: 'mapbox/?tk=', provider: 'mapbox', rung: 'url' },
|
||||
)
|
||||
for (const c of CASES) {
|
||||
const engine = c.provider
|
||||
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } })
|
||||
const mapboxCalls = []
|
||||
// ★ STATUSES TOO, not just counts. "21 requests and no map" is ambiguous between a token that
|
||||
// was never seen, one that was REJECTED, and a map that failed for an unrelated reason — and
|
||||
// the three have different owners. A 401 says the key, not the code.
|
||||
const mapboxBad = []
|
||||
page.on('request', (r) => { const u = r.url(); if (u.includes('api.mapbox.com')) mapboxCalls.push(u) })
|
||||
// ★ ONLY under mapbox. Injecting a token into the maplibre run would change what is being
|
||||
// measured: resolveMapProvider's `auto` rung reads a token as "use Mapbox", and even with an
|
||||
// explicit ?provider=maplibre a present token is a variable this gate exists to hold at zero.
|
||||
if (engine === 'mapbox') await page.addInitScript((tk) => { window.MAP_TOKEN = tk }, TOKEN)
|
||||
await page.goto(`${LEAF}?provider=${engine}`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
||||
page.on('response', (r) => { if (r.url().includes('api.mapbox.com') && r.status() >= 400) mapboxBad.push(r.status()) })
|
||||
if (c.rung === 'global') await page.addInitScript((tk) => { window.MAP_TOKEN = tk }, TOKEN)
|
||||
// ★ ASK THE ENGINE, NOT THE DOM, WHETHER A MAP EXISTS. See the header note; borrowed from
|
||||
// rega's tokrung.mjs, which measured this leaf correctly while this gate did not. Both globals
|
||||
// are hooked because the leaf loads only the engine its provider asks for.
|
||||
await page.addInitScript(() => {
|
||||
window.__mapsBuilt = { mapbox: 0, maplibre: 0 }
|
||||
const hook = (name) => {
|
||||
let real
|
||||
Object.defineProperty(window, name, {
|
||||
configurable: true,
|
||||
get: () => real,
|
||||
set: (gl) => {
|
||||
real = gl
|
||||
try {
|
||||
const Ctor = gl && gl.Map
|
||||
if (Ctor && !Ctor.__counted) {
|
||||
Ctor.__counted = true
|
||||
const setStyle = Ctor.prototype.setStyle
|
||||
Ctor.prototype.setStyle = function (...a) {
|
||||
window.__mapsBuilt[name === 'mapboxgl' ? 'mapbox' : 'maplibre']++
|
||||
return setStyle.apply(this, a)
|
||||
}
|
||||
}
|
||||
} catch (_) { /* a hook must never be the reason a page fails */ }
|
||||
},
|
||||
})
|
||||
}
|
||||
hook('mapboxgl'); hook('maplibregl')
|
||||
})
|
||||
const url = `${LEAF}?provider=${engine}` + (c.rung === 'url' ? `&tk=${encodeURIComponent(TOKEN)}` : '')
|
||||
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
||||
await page.waitForTimeout(20000)
|
||||
|
||||
const search = await page.evaluate(async () => {
|
||||
|
|
@ -137,14 +210,26 @@ try {
|
|||
if (!root || seen.has(root)) return
|
||||
seen.add(root)
|
||||
for (const el of root.querySelectorAll('*')) {
|
||||
if (el.matches && el.matches('input.mapboxgl-ctrl-geocoder--input, input.maplibregl-ctrl-geocoder--input')) hits.push(el)
|
||||
// ★ WIDER THAN THE PLUGIN'S OWN CLASS. This matched only
|
||||
// input.mapboxgl-ctrl-geocoder--input and reported 0 bars on a leaf carrying three
|
||||
// visible search inputs. Whether the miss was the class or the shadow walk cannot be told
|
||||
// from here, and that is the point: a selector narrow enough that one wrong assumption
|
||||
// yields ZERO accuses the product of being broken when it is only wrong about a name.
|
||||
if (el.matches && el.matches(
|
||||
'input.mapboxgl-ctrl-geocoder--input, input.maplibregl-ctrl-geocoder--input,'
|
||||
+ ' .mapboxgl-ctrl-geocoder input, .maplibregl-ctrl-geocoder input,'
|
||||
+ ' input[type="search"], input[placeholder*="Search" i]')) hits.push(el)
|
||||
if (el.shadowRoot) walk(el.shadowRoot)
|
||||
}
|
||||
}
|
||||
// Did an engine actually construct a map? A canvas is the one artefact both engines share,
|
||||
// and it tells "the bar was removed" apart from "there was never a map to hang it on".
|
||||
let mapReady = false
|
||||
for (const root of seen) { if (root.querySelector && root.querySelector('canvas.mapboxgl-canvas, canvas.maplibregl-canvas, .mapboxgl-map canvas, .maplibregl-map canvas')) { mapReady = true; break } }
|
||||
// The engine hook is the answer; the canvas walk stays only as a second opinion, so an engine
|
||||
// that stops routing through setStyle degrades to the old behaviour instead of accusing the
|
||||
// product.
|
||||
const built = window.__mapsBuilt || {}
|
||||
let mapReady = !!(built.mapbox || built.maplibre)
|
||||
if (!mapReady) for (const root of seen) { if (root.querySelector && root.querySelector('canvas.mapboxgl-canvas, canvas.maplibregl-canvas, .mapboxgl-map canvas, .maplibregl-map canvas')) { mapReady = true; break } }
|
||||
if (!hits.length) return { bars: 0, suggestions: 0, mapReady }
|
||||
const input = hits[0]
|
||||
input.focus()
|
||||
|
|
@ -160,13 +245,14 @@ try {
|
|||
})
|
||||
await page.close()
|
||||
|
||||
lines.push(` · ${engine.padEnd(9)} api.mapbox.com requests: ${mapboxCalls.length} · search bars: ${search.bars} · suggestions for "Afar": ${search.suggestions}${engine === 'mapbox' ? ' · token: supplied' : ''}`)
|
||||
const bad = mapboxBad.length ? ` · REJECTED responses: ${mapboxBad.length} (${[...new Set(mapboxBad)].join(', ')})` : ''
|
||||
lines.push(` · ${c.id.padEnd(22)} api.mapbox.com requests: ${mapboxCalls.length} · map: ${search.mapReady ? 'yes' : 'NO'} · search bars: ${search.bars} · suggestions for "Afar": ${search.suggestions}${bad}`)
|
||||
|
||||
if (engine === 'maplibre') {
|
||||
// THE HEADLINE. One request sends the visitor's IP to Mapbox and breaks the keyless promise,
|
||||
// whatever the page looks like afterwards.
|
||||
if (mapboxCalls.length) {
|
||||
fails.push(`under maplibre the leaf made ${mapboxCalls.length} request(s) to api.mapbox.com:`)
|
||||
fails.push(`[${c.id}] the leaf made ${mapboxCalls.length} request(s) to api.mapbox.com:`)
|
||||
for (const u of [...new Set(mapboxCalls)].slice(0, 8)) fails.push(` ${u.slice(0, 150)}`)
|
||||
}
|
||||
// A bar is OPTIONAL here and its absence is the documented contract (see the header). What is
|
||||
|
|
@ -182,11 +268,16 @@ try {
|
|||
// `mapReady` separates "the bar was removed" from "the map never constructed", which are
|
||||
// different bugs with the same symptom — and the second one is how this gate misread itself.
|
||||
if (!search.bars) {
|
||||
fails.push(search.mapReady
|
||||
? 'under mapbox the map constructed but rendered NO search bar — hasGeocoder or the GeocoderComponent mount is broken.'
|
||||
: 'under mapbox NO map constructed (so the bar\'s v-if could never fire). The token was supplied, so this is the product or the leaf, not a missing key.')
|
||||
const rung = c.rung === 'global' ? 'the HOST GLOBAL rung (window.MAP_TOKEN, what an embedding partner sets)' : 'the ?tk= URL rung'
|
||||
if (!search.mapReady) {
|
||||
fails.push(mapboxBad.length
|
||||
? `[${c.id}] NO map constructed and ${mapboxBad.length} api.mapbox.com response(s) came back ${[...new Set(mapboxBad)].join('/')} — the token reached Mapbox and was REFUSED. That is the key, not the code.`
|
||||
: `[${c.id}] NO map constructed, via ${rung}, with a token supplied and no rejected responses. The leaf never overwrites a host-set window.MAP_TOKEN (index.html:70 reads it, :71/:109/:150 are all guarded), so if the other rung constructs and this one does not, this is a PRODUCT defect on the rung partners use — not this gate.`)
|
||||
} else {
|
||||
fails.push(`[${c.id}] the map constructed but rendered NO search bar — hasGeocoder or the GeocoderComponent mount is broken.`)
|
||||
}
|
||||
} else if (!search.suggestions) {
|
||||
fails.push('under mapbox the search bar rendered but typing produced no suggestions.')
|
||||
fails.push(`[${c.id}] the search bar rendered but typing produced no suggestions.`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -210,4 +301,4 @@ if (!TOKEN) {
|
|||
console.log(' Set MAPBOX_TOKEN in the environment, or `token` in vite.doxa-maps-build-config.json, to measure it.')
|
||||
process.exit(0)
|
||||
}
|
||||
console.log(`${TAG}: PASS — MapLibre calls Mapbox zero times, and Mapbox still searches.`)
|
||||
console.log(`${TAG}: PASS — MapLibre calls Mapbox zero times, and Mapbox searches on both token rungs.`)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* check-layout-key-namespaced.mjs — two dashboards on one page must not share a saved layout.
|
||||
*
|
||||
* useDashboardLayout persists the four divider positions to localStorage. Until kit landing 2 the
|
||||
* key was a single constant, so every dashboard wrote to the same slot. That was invisible while
|
||||
* there was exactly one dashboard — and SHARING THE ENGINE IS PRECISELY WHAT MAKES A SECOND ONE
|
||||
* POSSIBLE, which is why SPEC-DASHBOARD-KIT section 8 named it as landing 2's risk and why the fix
|
||||
* belongs in the commit that shares the engine rather than in the one that first trips over it.
|
||||
*
|
||||
* The failure it prevents is quiet and confusing rather than loud: drag a divider in dashboard A,
|
||||
* reload, and dashboard B has moved. Neither is wrong on its own, nothing errors, and the reader
|
||||
* has no reason to suspect the other element on the page.
|
||||
*
|
||||
* WHAT IT CHECKS, statically — no DOM, no browser:
|
||||
* A. the shell does not pass a BARE STRING as storageKey; the key must be derived from something
|
||||
* per-dashboard (the profile's own `id`).
|
||||
* B. two different dashboard ids produce two different keys, by evaluating the expression the
|
||||
* shell actually passes rather than a retyped copy of it.
|
||||
* C. the legacy shared key is READ and never WRITTEN — namespacing must not silently reset a
|
||||
* reader's saved layout, and a migration that also deletes cannot be rolled back.
|
||||
*
|
||||
* NEGATIVE-TESTED: putting a bare literal back fails A; making the expression ignore the id fails
|
||||
* B; adding a setItem on the legacy key fails C.
|
||||
*/
|
||||
import { readFileSync, existsSync } from 'node:fs'
|
||||
import { resolve, dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const TAG = 'LAYOUT-KEY-NAMESPACED'
|
||||
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', '..')
|
||||
const SHELL = join(ROOT, 'plugin-designs/research-dashboard/research-dashboard.vue')
|
||||
const ENGINE = join(ROOT, 'library/composables/useDashboardLayout.js')
|
||||
const fails = []
|
||||
const notes = []
|
||||
|
||||
if (!existsSync(ENGINE)) { console.log(`${TAG}: SKIP — no ${ENGINE.replace(ROOT + '/', '')} (kit landing 2 not applied).`); process.exit(0) }
|
||||
|
||||
// ── A + B. the key the shell passes ──────────────────────────────────────────────────────────
|
||||
{
|
||||
const src = readFileSync(SHELL, 'utf8')
|
||||
const m = /storageKey:\s*([^\n]+?),\s*$/m.exec(src)
|
||||
if (!m) {
|
||||
fails.push('A research-dashboard.vue passes no storageKey — the engine would fall back to its shared default and every dashboard on the page would collide.')
|
||||
} else {
|
||||
const expr = m[1].trim()
|
||||
if (/^'[^']*'$/.test(expr) || /^"[^"]*"$/.test(expr)) {
|
||||
fails.push(`A storageKey is the bare literal ${expr} — a second dashboard on the same page reads and writes this one's layout.`)
|
||||
} else {
|
||||
// Evaluate the REAL expression with two different configs rather than retyping the rule: a
|
||||
// gate carrying its own copy of the thing it checks passes while the product is broken.
|
||||
try {
|
||||
const keyFor = new Function('mergedConfig', `return ${expr}`)
|
||||
const a = keyFor({ value: { id: 'doxa-research-dashboard' } })
|
||||
const b = keyFor({ value: { id: 'gospel-internet' } })
|
||||
const none = keyFor({ value: {} })
|
||||
if (a === b) fails.push(`B two different dashboard ids produce the SAME key (${JSON.stringify(a)}) — the expression does not actually vary with the dashboard.`)
|
||||
if (!String(a).includes('doxa-research-dashboard')) fails.push(`B the key ${JSON.stringify(a)} does not carry the dashboard id, so it cannot be unique per dashboard.`)
|
||||
if (!none) fails.push('B a config with no id yields an empty key — a dashboard that forgets its id must still get a usable slot, not localStorage[""].')
|
||||
if (!fails.some((f) => f.startsWith('B'))) notes.push(`key: ${JSON.stringify(a)} vs ${JSON.stringify(b)} — distinct per dashboard`)
|
||||
} catch (e) {
|
||||
fails.push(`B could not evaluate the storageKey expression (${e.message}) — it may be correct, but this gate cannot prove it, which is the same as not being checked.`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── C. the legacy key is read, never written ─────────────────────────────────────────────────
|
||||
{
|
||||
const src = readFileSync(ENGINE, 'utf8')
|
||||
const legacy = /const LEGACY_SHARED_KEY = '([^']+)'/.exec(src)
|
||||
if (!legacy) {
|
||||
fails.push('C useDashboardLayout no longer reads the pre-namespacing key — every reader who had dragged a divider silently loses their layout on upgrade.')
|
||||
} else {
|
||||
const name = 'LEGACY_SHARED_KEY'
|
||||
if (!new RegExp(`getItem\\(\\s*${name}\\s*\\)`).test(src)) fails.push(`C ${name} is declared but never read, so it protects nobody.`)
|
||||
if (new RegExp(`(setItem|removeItem)\\(\\s*${name}`).test(src)) {
|
||||
fails.push(`C ${name} is WRITTEN or REMOVED. The read-through exists so namespacing does not reset a saved layout; a migration that also deletes cannot be rolled back.`)
|
||||
}
|
||||
if (!fails.some((f) => f.startsWith('C'))) notes.push(`legacy key ${JSON.stringify(legacy[1])}: read once, never written`)
|
||||
}
|
||||
}
|
||||
|
||||
for (const n of notes) console.log(' · ' + n)
|
||||
if (fails.length) {
|
||||
console.error(`\n${TAG}: FAIL`)
|
||||
for (const f of fails) console.error(' ✗ ' + f)
|
||||
process.exit(1)
|
||||
}
|
||||
console.log(`${TAG}: PASS — each dashboard owns its saved layout, and upgrading does not discard one.`)
|
||||
|
|
@ -1,518 +1,11 @@
|
|||
/**
|
||||
* useDashboardLayout.js — reusable drag-resize + persistence engine for the CMV dashboard grid.
|
||||
* useDashboardLayout.js — RE-EXPORT SHIM (dashboard-kit landing 2).
|
||||
*
|
||||
* A dashboard shell (see plugin-designs/doxa-research-dashboards/research-dashboards.vue) is a CSS
|
||||
* grid whose three flexible tracks are driven by CSS custom properties:
|
||||
* --facet-w (left facet-rail column width) default 296px
|
||||
* --rail-w (right charts-rail column width) default 296px — equals --facet-w, so the map column sits centred
|
||||
* --table-h (bottom table row height) default 34% (map above it is the 1fr hero)
|
||||
* The engine now lives at library/composables/useDashboardLayout.js. Same one-cycle contract as
|
||||
* landing 1's bus shim: every importer keeps working unchanged while the move is verified on its
|
||||
* own, and this file is deleted in the next landing.
|
||||
*
|
||||
* This composable OWNS those three vars: it exposes pointer-based drag handlers (one per edge),
|
||||
* clamps each to a sane min/max, writes the vars onto the shell root element as INLINE custom
|
||||
* properties, PERSISTS the chosen layout to localStorage on every drag-end, RESTORES it on init,
|
||||
* and offers reset() to clear the key and snap back to the exact defaults.
|
||||
*
|
||||
* SHELL vs. TABLE axis (page-scroll mode only — BUG-SHELL-HANDLE-BOUND-TO-WRONG-DIVIDER):
|
||||
* Two DIFFERENT questions look similar and must stay answered by two DIFFERENT handles.
|
||||
* "table" axis = the MAP/TABLE SPLIT. In page-scroll mode it redistributes height BETWEEN
|
||||
* the map and the table; the sum of the two (the element's total height)
|
||||
* does NOT change. This is the EXISTING map/table divider
|
||||
* (.rd-rz-table in research-dashboard.vue), unchanged in grid-mode.
|
||||
* "shell" axis = the ELEMENT'S OWN HEIGHT (page-scroll mode only) — a bar at the shell's
|
||||
* BOTTOM edge, the boundary between the whole research-dashboard element and
|
||||
* whatever a host stacks below it (e.g. the people-groups grid in
|
||||
* dashboard-plus-grid.vue). Dragging it changes --rd-shell-h, the total map+
|
||||
* table budget; the map/table SPLIT within that budget is untouched.
|
||||
* --rd-shell-h is the new independent variable; --rd-map-h is now the map's share of it, and
|
||||
* the table's share is derived as shellH - mapH (see the CSS in research-dashboard.vue). Before
|
||||
* this, --rd-map-h alone was BOTH "the map/table split" AND "the element's total height" — one
|
||||
* knob answering two questions, which is why dragging the map/table divider used to resize the
|
||||
* whole element as a side effect. Driver: "you improperly bound that control to the separator
|
||||
* line between the map and the table... that's not the request I was making to resize the
|
||||
* height of the page."
|
||||
*
|
||||
* COMPOSITION with the collapse-table fix (do NOT regress):
|
||||
* The shell's DEFAULT rows are `52px auto 42px 1fr var(--table-h,34%)` while the collapsed rule
|
||||
* `.rd-shell.rd-table-collapsed{ grid-template-rows:52px auto 42px 1fr 0 }` comes LATER in source
|
||||
* order (same specificity) so COLLAPSE WINS over --table-h. Because we only touch the CSS var
|
||||
* (never the collapsed row template), collapsing hides the table regardless of a dragged height,
|
||||
* and expanding restores the user's dragged --table-h. The center map is 1fr and already
|
||||
* self-resizes via DashboardMapPanel's ResizeObserver → map.resize(); we add no second resize.
|
||||
*
|
||||
* NON-REGRESSION with the responsive slim rails:
|
||||
* `.rd-shell.rd-slim-rail{ --rail-w:228px }` / `.rd-shell.rd-slim-facet{ --facet-w:250px }` are
|
||||
* medium-width niceties set via CLASS. Inline styles always beat class rules, so we apply inline
|
||||
* vars ONLY once the layout is customized (restored-from-storage or dragged). An untouched
|
||||
* dashboard writes no inline vars → the slim classes and the exact CSS defaults are preserved.
|
||||
* reset() removes the inline vars entirely, fully handing control back to the stylesheet.
|
||||
*
|
||||
* DESKTOP-ONLY: every drag is gated on `!isNarrow`; narrow/mobile never resizes or persists.
|
||||
*
|
||||
* Library-parameterizable — the profile's identity (defaults + storage key) lives in options, not
|
||||
* here. Any dashboard grid exposing the same three vars can reuse this unchanged.
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {import('vue').Ref<HTMLElement|null>} options.shellRef ref holding the .rd-shell root el
|
||||
* @param {object=} options.bus selection bus; when given, listens bus.on('resetLayout', reset)
|
||||
* @param {import('vue').Ref<boolean>|boolean=} options.isNarrow desktop gate (true = mobile/narrow)
|
||||
* @param {import('vue').Ref<boolean>|boolean=} options.pageScroll when true, the table axis drives
|
||||
* --rd-map-h (px) instead of --table-h — see the PAGE-SCROLL AXIS SWITCH note below.
|
||||
* @param {string=} options.storageKey localStorage key (default 'rd-dashboard-layout')
|
||||
* @param {{facetW?:number, railW?:number, tableH?:string, mapH?:number, shellH?:number}=} options.defaults default track sizes
|
||||
* @param {{facetW?:[number,number], railW?:[number,number], tableH?:[number,number], mapH?:[number,number], shellH?:[number,number]}=} options.clamps
|
||||
* min/max — facetW/railW/mapH/shellH in px, tableH in percent-of-shell-height
|
||||
*
|
||||
* @returns {{
|
||||
* facetW: import('vue').Ref<number>, railW: import('vue').Ref<number>, tableH: import('vue').Ref<string>,
|
||||
* mapH: import('vue').Ref<number>, shellH: import('vue').Ref<number>,
|
||||
* startFacetResize:(e:PointerEvent)=>void, startRailResize:(e:PointerEvent)=>void,
|
||||
* startTableResize:(e:PointerEvent)=>void, startShellResize:(e:PointerEvent)=>void,
|
||||
* reset:()=>void, applyVars:()=>void, customized:import('vue').Ref<boolean>,
|
||||
* stepResize:(axis:'facet'|'rail'|'table'|'shell', dir:-1|1, toExtreme?:boolean)=>void,
|
||||
* onResizeKeydown:(axis:'facet'|'rail'|'table'|'shell', e:KeyboardEvent)=>void
|
||||
* }}
|
||||
* It re-exports; it does not duplicate. A second copy would drift silently while both halves kept
|
||||
* passing their gates.
|
||||
*/
|
||||
import { ref, unref, onMounted, onBeforeUnmount } from 'vue'
|
||||
|
||||
// Tree rail WIDER than the charts rail — see the rail-balance note in research-dashboard.vue.
|
||||
// These must stay in lockstep with the CSS `:host` defaults, since reset() snaps back to them.
|
||||
// mapH mirrors the CSS fallback 40svh (~360px at a 900px viewport — see the page-scroll note
|
||||
// below); it is only ever WRITTEN once the user drags, so an untouched embed stays on the
|
||||
// viewport-relative svh default and keeps resizing with the window, exactly like every other var.
|
||||
// ★ 58svh (522px) was the ORIGINAL default and left the page-scroll band taller than one desktop
|
||||
// viewport (BUG-DASHBOARD-BAND-GROWS-ENORMOUS: chrome 137px + map 522px + table 552px = 1211px
|
||||
// against 900px). 40svh is the value that makes chrome + map(X) + table(X + bar-height) fit <=900px.
|
||||
// shellH default (720) is the SUM the old single-knob mapH(360) used to imply — map 360 + table
|
||||
// budget 360 (328 grid + 32 bar) — so first paint is pixel-identical to before this axis split;
|
||||
// only DRAGGING behaves differently now (see the SHELL vs. TABLE axis note above).
|
||||
// ★ shellH 720 -> 602 so the table OPENS at seven data rows (Driver 2026-09-23: "the table needs to
|
||||
// only show SEVEN rows by DEFAULT height"). 602 = map 360 + bar 32 + 7 rows x 26 + foot 28.
|
||||
// ★ A DEFAULT, NOT A LOCK — and the distinction is the whole correction. My first attempt hard-capped
|
||||
// the keyhole at 7 rows in CSS, which read as the same thing and was not: nothing writes
|
||||
// --rd-table-rows, while the drag handles write --rd-shell-h and --rd-map-h, so the cap could not
|
||||
// be reached by any gesture. The Driver lost BOTH resizes at once and said so: "I didn't want the
|
||||
// table set to 7. Only the table needs to be resizable. We've set it to where I can't even resize."
|
||||
// Setting the STARTING VALUE instead leaves the derivation intact: the keyhole stays
|
||||
// shell - map - bar - foot, so dragging either handle still moves the table, and seven rows is
|
||||
// merely where it opens.
|
||||
// ★ RECLAIM PASS 2 (Driver 2026-09-23: "it is a priority to reclaim height... so I can see half
|
||||
// of the first row of the people groups grid"). mapH 360 -> 300 and shellH follows the same
|
||||
// arithmetic as before: 300 map + 32 bar + 7x26 rows + 28 foot = 542. The seven-row table
|
||||
// promise is unchanged; only the map's share shrinks -- and the map compensates by DEFAULTING
|
||||
// MORE ZOOMED OUT with the world-floor released on the globe (see DashboardMapPanel), so a
|
||||
// shorter map shows MORE world, not less.
|
||||
// shellH 502 -> 542 (Driver 2026-09-23: "the dashboard should be taller by about 40px"). The
|
||||
// extra 40px flows to the TABLE via the standing derivation (table = shell - map - bar - foot);
|
||||
// the map row stays pinned at mapH. One owner: this number, with the CSS var fallbacks in
|
||||
// research-dashboard.vue kept byte-equal at 542.
|
||||
// mapH 260 -> 300 (Driver 2026-09-23 follow-up: the +40px was to be "added to the map -- map is
|
||||
// 40px taller display room"). shellH stays 542, so the table's derived share returns to its
|
||||
// pre-+40 height and the whole gain lands in the map row.
|
||||
// +40px again (Driver 2026-09-23 second raise: "go taller with the dashboard by another 40px,
|
||||
// add that to the height of the map"): shellH 542 -> 582 and mapH 300 -> 340 move together, so
|
||||
// the whole gain lands in the map row and the table's derived share stays put.
|
||||
// Driver fine-tune 2026-09-23: "almost perfect height -- keep the map the same height, but
|
||||
// decrease the height of the dashboard by about 20px". Map stays 340; the 20px comes out of
|
||||
// the table's derived share (shell - map - bar - foot).
|
||||
const DEFAULTS = { facetW: 296, railW: 296, tableH: '34%', mapH: 340, shellH: 562 }
|
||||
const CLAMPS = { facetW: [160, 420], railW: [200, 520], tableH: [12, 70], mapH: [220, 1400], shellH: [400, 2600] }
|
||||
|
||||
// Mirrors the CSS fallback --rd-table-bar-h (research-dashboard.vue's .rd-table-bar budget calc) —
|
||||
// the table's header bar (count + Export CSV) sits ABOVE its scrollport and is not itself
|
||||
// resizable, so the map/table split must always leave it at least this much room, or the divider
|
||||
// could drag the table's usable grid to zero while its outer cell still looks non-empty.
|
||||
const TABLE_BAR_H = 32
|
||||
const TABLE_MIN_H = 120 // grid's own floor below the bar — a table smaller than this is unusable
|
||||
|
||||
const clamp = (v, [lo, hi]) => Math.min(hi, Math.max(lo, v))
|
||||
const pctNum = (v, fallback) => {
|
||||
const n = parseFloat(String(v))
|
||||
return Number.isFinite(n) ? n : fallback
|
||||
}
|
||||
|
||||
export function useDashboardLayout(options = {}) {
|
||||
const {
|
||||
shellRef,
|
||||
bus = null,
|
||||
isNarrow = false,
|
||||
pageScroll = false,
|
||||
// ★ KEY VERSIONED v2 (2026-09-23). The Driver reported "sidebars are not equally spaced" on
|
||||
// his machine AFTER the symmetric-rail change landed -- because his browser restores a layout
|
||||
// SAVED under the old defaults (rail 264), and a restored value outranks any new default by
|
||||
// design. When defaults change materially, the old saved layouts are prescriptions from a
|
||||
// different bottle: bump the key so every reader starts from the new defaults once, and a
|
||||
// fresh drag re-personalises from there. The v1 blob is left in place, inert.
|
||||
// v2 -> v3: retire stored layouts so the new 542 default is actually SEEN -- a persisted
|
||||
// shellH:502 from the previous default would silently mask this change on the Driver's browser.
|
||||
storageKey = 'rd-dashboard-layout-v6',
|
||||
} = options
|
||||
|
||||
const defaults = { ...DEFAULTS, ...(options.defaults || {}) }
|
||||
const clamps = { ...CLAMPS, ...(options.clamps || {}) }
|
||||
|
||||
const facetW = ref(defaults.facetW) // px
|
||||
const railW = ref(defaults.railW) // px
|
||||
const tableH = ref(defaults.tableH) // string, e.g. '34%'
|
||||
const mapH = ref(defaults.mapH) // px — only meaningful/applied in page-scroll mode
|
||||
const shellH = ref(defaults.shellH) // px — page-scroll ELEMENT total height (map+table budget)
|
||||
const customized = ref(false) // has the user (or a restored layout) diverged from CSS defaults?
|
||||
const mapHCustomized = ref(false) // page-scroll's own inline var is written independently of
|
||||
// customized (below), since an untouched grid-mode drag
|
||||
// must never suddenly pin --rd-map-h and vice versa.
|
||||
const shellHCustomized = ref(false) // same independence, one level up: the shell handle is a
|
||||
// separate drag from the map/table split and must not fire
|
||||
// just because the OTHER page-scroll var was touched.
|
||||
|
||||
const narrow = () => !!unref(isNarrow)
|
||||
const inPageScroll = () => !!unref(pageScroll)
|
||||
|
||||
// ── what --rd-shell-h CURRENTLY RESOLVES TO (BUG-SHELL-HANDLE-SNAPS-144PX) ───────────────────
|
||||
// The shell drag must anchor on the budget the CSS is resolving RIGHT NOW, or the first frame
|
||||
// "corrects" from a wrong anchor and the user sees height they did not drag. Two sources, in
|
||||
// priority order, because the variable and the rendered size legitimately disagree:
|
||||
//
|
||||
// 1. THE COMPUTED VARIABLE, whenever it is set. --rd-shell-h is a CEILING — it feeds the
|
||||
// table grid's max-height — and a ceiling is not a floor: if the table has fewer rows than
|
||||
// the budget allows, the element renders SMALLER than the variable says. MEASURED with a
|
||||
// restored shellH of 983: the element was 1126 while map+table summed to only 743, because
|
||||
// the grid had ~240px of budget and no rows to fill it. Anchoring on that 743 snapped the
|
||||
// variable 983 -> 744 on the first frame — a -239px jump, the mirror image of the +144 one
|
||||
// this card started from. Whatever the CSS already holds is what the drag must continue
|
||||
// from, so the pointer only ever ADDS to a value that is already in effect.
|
||||
// 2. THE MEASURED map + table, only when the variable is unset. Before the first drag the CSS
|
||||
// is on its stylesheet fallback (`80svh`), which shellH.value cannot stand in for: the 720
|
||||
// default only equals 80svh at a 900px viewport, so trusting it would jump by the
|
||||
// difference at any other window height.
|
||||
//
|
||||
// Measuring map + table rather than the shell's own box is deliberate — the shell is
|
||||
// `height:auto` here and includes the chrome the variable does not budget for. Summing the two
|
||||
// regions lands on the same span calc(shell-h - map-h - bar - foot) works from, without
|
||||
// restating the chrome's height as a second number that could drift from the stylesheet.
|
||||
function currentShellBudget() {
|
||||
const el = shellRef && shellRef.value
|
||||
if (!el) return shellH.value
|
||||
const declared = parseFloat(getComputedStyle(el).getPropertyValue('--rd-shell-h'))
|
||||
if (Number.isFinite(declared) && declared > 0) return Math.round(declared)
|
||||
const mapEl = el.querySelector('[data-region="map"]')
|
||||
const tableEl = el.querySelector('[data-region="table"]')
|
||||
if (!mapEl || !tableEl) return shellH.value
|
||||
const h = mapEl.getBoundingClientRect().height + tableEl.getBoundingClientRect().height
|
||||
// A collapsed/hidden region measures 0; fall back rather than anchoring the drag on nothing.
|
||||
return h > 0 ? Math.round(h) : shellH.value
|
||||
}
|
||||
|
||||
// ── write / clear the inline CSS custom properties on the shell root ──
|
||||
// --rd-map-h is applied independently of `customized` (grid-mode's facet/rail/table-h gate):
|
||||
// page-scroll is a different layout entirely, with its own untouched-vs-dragged state, so
|
||||
// gating it on the grid vars' flag would either apply it before any page-scroll drag ever
|
||||
// happened, or (worse) suppress a real page-scroll drag because the grid vars were untouched.
|
||||
function applyVars() {
|
||||
const el = shellRef && shellRef.value
|
||||
if (!el) return
|
||||
if (customized.value) {
|
||||
el.style.setProperty('--facet-w', facetW.value + 'px')
|
||||
el.style.setProperty('--rail-w', railW.value + 'px')
|
||||
el.style.setProperty('--table-h', tableH.value)
|
||||
}
|
||||
if (mapHCustomized.value) {
|
||||
el.style.setProperty('--rd-map-h', mapH.value + 'px')
|
||||
}
|
||||
if (shellHCustomized.value) {
|
||||
el.style.setProperty('--rd-shell-h', shellH.value + 'px')
|
||||
}
|
||||
}
|
||||
function clearVars() {
|
||||
const el = shellRef && shellRef.value
|
||||
if (!el) return
|
||||
el.style.removeProperty('--facet-w')
|
||||
el.style.removeProperty('--rail-w')
|
||||
el.style.removeProperty('--table-h')
|
||||
el.style.removeProperty('--rd-map-h')
|
||||
el.style.removeProperty('--rd-shell-h')
|
||||
}
|
||||
|
||||
// ── persistence ──
|
||||
function persist() {
|
||||
try {
|
||||
localStorage.setItem(storageKey, JSON.stringify({
|
||||
facetW: facetW.value, railW: railW.value, tableH: tableH.value, mapH: mapH.value, shellH: shellH.value,
|
||||
}))
|
||||
} catch (_) { /* storage blocked / SSR — layout still works this session */ }
|
||||
}
|
||||
function restore() {
|
||||
try {
|
||||
const raw = localStorage.getItem(storageKey)
|
||||
if (!raw) return false
|
||||
const s = JSON.parse(raw)
|
||||
if (Number.isFinite(s.facetW)) facetW.value = clamp(s.facetW, clamps.facetW)
|
||||
if (Number.isFinite(s.railW)) railW.value = clamp(s.railW, clamps.railW)
|
||||
if (s.tableH != null) tableH.value = clamp(pctNum(s.tableH, pctNum(defaults.tableH, 34)), clamps.tableH) + '%'
|
||||
customized.value = true
|
||||
// shellH restores BEFORE mapH so the mapH clamp below (which bounds map to <= shellH, see
|
||||
// startResize's isTablePageScroll branch) has the right ceiling on first paint too.
|
||||
if (Number.isFinite(s.shellH)) { shellH.value = clamp(s.shellH, clamps.shellH); shellHCustomized.value = true }
|
||||
if (Number.isFinite(s.mapH)) { mapH.value = clamp(s.mapH, clamps.mapH); mapHCustomized.value = true }
|
||||
return true
|
||||
} catch (_) { return false }
|
||||
}
|
||||
|
||||
// ── reset: clear the key + snap back to the EXACT defaults (hand control to the stylesheet) ──
|
||||
function reset() {
|
||||
try { localStorage.removeItem(storageKey) } catch (_) { /* ignore */ }
|
||||
facetW.value = defaults.facetW
|
||||
railW.value = defaults.railW
|
||||
tableH.value = defaults.tableH
|
||||
mapH.value = defaults.mapH
|
||||
shellH.value = defaults.shellH
|
||||
customized.value = false
|
||||
mapHCustomized.value = false
|
||||
shellHCustomized.value = false
|
||||
clearVars()
|
||||
}
|
||||
|
||||
// ── drag-live signalling (BUG-RESIZE-STROBE) ──────────────────────────────
|
||||
// Two channels, because two different consumers need it:
|
||||
// 1. `data-rd-resizing` on the shell root — a pure-CSS hook so transitions/animations can be
|
||||
// killed for the duration of the drag (no JS needed, works inside shadow DOM).
|
||||
// 2. bus 'layoutResizing' — lets the map panel downgrade to a cheap canvas resize while the
|
||||
// drag is live, then do the one expensive re-fit on drag end.
|
||||
// Both are no-ops when absent, so this composable stays usable without a bus.
|
||||
const resizing = ref(false)
|
||||
function beginDrag() {
|
||||
if (resizing.value) return
|
||||
resizing.value = true
|
||||
const el = shellRef && shellRef.value
|
||||
if (el) el.setAttribute('data-rd-resizing', '1')
|
||||
if (bus && typeof bus.emit === 'function') { try { bus.emit('layoutResizing', true) } catch (_) {} }
|
||||
}
|
||||
function endDrag() {
|
||||
if (!resizing.value) return
|
||||
resizing.value = false
|
||||
const el = shellRef && shellRef.value
|
||||
if (el) el.removeAttribute('data-rd-resizing')
|
||||
if (bus && typeof bus.emit === 'function') { try { bus.emit('layoutResizing', false) } catch (_) {} }
|
||||
}
|
||||
|
||||
// ── generic pointer drag; axis ∈ 'facet' | 'rail' | 'table' ──
|
||||
function startResize(axis, e) {
|
||||
if (narrow()) return
|
||||
const el = shellRef && shellRef.value
|
||||
if (!el) return
|
||||
e.preventDefault()
|
||||
const rect = el.getBoundingClientRect()
|
||||
const startX = e.clientX
|
||||
const startFacet = facetW.value
|
||||
const startRail = railW.value
|
||||
const handleEl = e.currentTarget
|
||||
// ── PAGE-SCROLL AXIS SWITCH (BUG-TABLE-RESIZE-HANDLE-DOES-NOTHING) ──────────────────────
|
||||
// In page-scroll mode (research-dashboard.vue's pageScroll / dashboard-plus-grid.vue) the
|
||||
// shell is `height:auto` and grows with its content, so `rect` above is NOT one screen tall
|
||||
// — `rect.bottom` can sit thousands of px below the viewport. --table-h is force-set to
|
||||
// `auto` by the .rd-page-scroll stylesheet rule and no longer drives ANY layout: the map's
|
||||
// height instead comes from --rd-map-h (default 40svh as of BUG-DASHBOARD-BAND-GROWS-ENORMOUS;
|
||||
// see the CSS note beside it), and the table's own max-height comes from --rd-table-max-h.
|
||||
// Writing tableH in this mode is a complete no-op — MEASURED (at the prior 58svh default):
|
||||
// map height 522px before and after a real 200px drag, every
|
||||
// frame. The fix is to drive --rd-map-h directly, from the MAP ELEMENT's own top edge
|
||||
// (not the unbounded shell rect), so growing the map is a plain function of where the
|
||||
// pointer is relative to where the map starts.
|
||||
//
|
||||
// ★ THE map/table SPLIT vs. THE shell's OWN HEIGHT (BUG-SHELL-HANDLE-BOUND-TO-WRONG-DIVIDER)
|
||||
// — this handle must move height BETWEEN map and table, never grow the total. mapH is now
|
||||
// clamped to leave the table at least TABLE_BAR_H + TABLE_MIN_H of the FIXED shellH budget,
|
||||
// so dragging this divider can only redistribute the two, exactly like resizing an internal
|
||||
// pane split rather than the window itself.
|
||||
const isTablePageScroll = axis === 'table' && inPageScroll()
|
||||
const isShellResize = axis === 'shell' && inPageScroll()
|
||||
let startMapTop = 0
|
||||
let mapHCeiling = clamps.mapH[1]
|
||||
if (isTablePageScroll) {
|
||||
const mapEl = el.querySelector('[data-region="map"]')
|
||||
const mapRect = mapEl ? mapEl.getBoundingClientRect() : null
|
||||
startMapTop = mapRect ? mapRect.top : (e.clientY - mapH.value)
|
||||
mapHCeiling = Math.max(clamps.mapH[0], shellH.value - (TABLE_BAR_H + TABLE_MIN_H))
|
||||
}
|
||||
// ★ DELTA-ANCHORED ON THE LIVE BUDGET (BUG-SHELL-HANDLE-SNAPS-144PX-ON-FIRST-FRAME).
|
||||
// MEASURED at 1440x900: a 1px drag grew the element 144px. TWO defects stacked here, and
|
||||
// fixing only the first leaves the number bit-for-bit unchanged — which is the clue that
|
||||
// named the second.
|
||||
//
|
||||
// 1. POINTER-ABSOLUTE math. The old line set shellH to (pointerY - shellTop), treating the
|
||||
// cursor's Y AS the new height. That is only correct if the handle sits exactly shellH
|
||||
// px below the shell's top, and it does not. Fixed by anchoring on a start value and
|
||||
// adding the pointer DELTA.
|
||||
// 2. THE WRONG ANCHOR — the actual source of the 144. Anchoring on the element's measured
|
||||
// height is the obvious move and is wrong, because --rd-shell-h IS NOT THE ELEMENT'S
|
||||
// HEIGHT. The shell is `height:auto` in page-scroll mode (.rd-shell.rd-page-scroll) and
|
||||
// nothing reads --rd-shell-h as a height; its ONLY consumer is the table grid's
|
||||
// max-height: calc(--rd-shell-h - --rd-map-h - bar - foot). So the variable budgets
|
||||
// MAP + TABLE and excludes the chrome above them (topbar 52 + filters 55 + stats 30 =
|
||||
// 141px measured). Seeding it with the measured 863 published a budget 144px too large:
|
||||
// the grid's max-height jumped 300 -> 444 on the FIRST frame and the element grew with
|
||||
// it. 863 - 719 = 144 is not a coincidence — it is the chrome, double-counted.
|
||||
const startShellY = e.clientY
|
||||
const startShellH = isShellResize ? currentShellBudget() : shellH.value
|
||||
try { handleEl && handleEl.setPointerCapture && handleEl.setPointerCapture(e.pointerId) } catch (_) {}
|
||||
|
||||
// ── A11Y / PHOTOSENSITIVITY (BUG-RESIZE-STROBE): mark the drag as LIVE ──
|
||||
// Writing the CSS vars every pointermove reflows the grid, which fires the map panel's
|
||||
// ResizeObserver → map.resize() → MapLibre's own 'resize' event → useMapInstance's
|
||||
// _onResize → setMinZoom/setZoom. Because the zoom FLOOR is derived from the container
|
||||
// HEIGHT, a vertical drag re-snapped the camera on EVERY frame — a ~60Hz full-canvas
|
||||
// re-render that reads as strobing. Flagging the drag lets the map coalesce to a single
|
||||
// cheap canvas resize while dragging and do the one expensive re-fit on drag END.
|
||||
beginDrag()
|
||||
|
||||
// Coalesce the inline-var writes to one per animation frame. pointermove can fire faster
|
||||
// than the compositor on high-polling-rate mice, so without this the grid could reflow
|
||||
// several times per painted frame — wasted work that makes the strobe worse.
|
||||
let frame = 0
|
||||
let pending = null
|
||||
function flush() {
|
||||
frame = 0
|
||||
if (!pending) return
|
||||
const ev = pending
|
||||
pending = null
|
||||
if (axis === 'facet') {
|
||||
// left facet edge → dragging right widens the facet column
|
||||
facetW.value = Math.round(clamp(startFacet + (ev.clientX - startX), clamps.facetW))
|
||||
customized.value = true
|
||||
} else if (axis === 'rail') {
|
||||
// right rail's LEFT edge → dragging left widens the rail column
|
||||
railW.value = Math.round(clamp(startRail - (ev.clientX - startX), clamps.railW))
|
||||
customized.value = true
|
||||
} else if (isTablePageScroll) {
|
||||
// page-scroll: the handle sits pinned to the MAP's own bottom edge (.rd-rz-table is
|
||||
// align-self:end on the map grid-area — see the CSS below), whose top never moves. The
|
||||
// pointer's new Y position IS the map's new bottom edge, so the new height is simply the
|
||||
// distance from the map's (fixed) top to the cursor — a direct 1:1 follow, exactly like
|
||||
// dragging the corner of a window. Re-derived fresh every frame from startMapTop (not
|
||||
// summed from a delta), so it can never drift from the cursor across a long drag.
|
||||
// Clamped to mapHCeiling (not the raw clamps.mapH max) — the ceiling reserves the table's
|
||||
// bar + a usable minimum out of the FIXED shellH budget, so this drag only ever moves
|
||||
// height between map and table and can never grow the element's total height. That is
|
||||
// the shell axis's job (see isShellResize below), not this one's.
|
||||
mapH.value = Math.round(clamp(ev.clientY - startMapTop, [clamps.mapH[0], mapHCeiling]))
|
||||
mapHCustomized.value = true
|
||||
} else if (axis === 'table') {
|
||||
// map/table divider → dragging up grows the table (height measured from shell bottom)
|
||||
const pct = ((rect.bottom - ev.clientY) / rect.height) * 100
|
||||
tableH.value = Math.round(clamp(pct, clamps.tableH)) + '%'
|
||||
customized.value = true
|
||||
} else if (isShellResize) {
|
||||
// The NEW shell handle — spans the whole element's bottom edge (research-dashboard.vue's
|
||||
// .rd-rz-shell), the boundary with whatever a host stacks below (e.g. the people-groups
|
||||
// grid in dashboard-plus-grid.vue). Same fixed-top / 1:1-follow pattern as the map handle
|
||||
// above. This is the ONLY axis that changes --rd-shell-h, i.e. the only handle that
|
||||
// changes the element's total height — the map/table divider above must never do this
|
||||
// (see its own comment).
|
||||
// DELTA from the live start budget, NOT the pointer's absolute Y: unlike the map handle,
|
||||
// this variable is not a distance from a fixed top edge, so there is no "pointer Y IS the
|
||||
// new value" identity to exploit — assuming one produced the 144px snap (see the note on
|
||||
// startShellH above).
|
||||
shellH.value = Math.round(clamp(startShellH + (ev.clientY - startShellY), clamps.shellH))
|
||||
shellHCustomized.value = true
|
||||
}
|
||||
applyVars()
|
||||
}
|
||||
function move(ev) {
|
||||
// keep only the LATEST position; the rAF does the single write for this frame
|
||||
pending = { clientX: ev.clientX, clientY: ev.clientY }
|
||||
if (!frame) frame = requestAnimationFrame(flush)
|
||||
}
|
||||
function up(ev) {
|
||||
window.removeEventListener('pointermove', move)
|
||||
window.removeEventListener('pointerup', up)
|
||||
window.removeEventListener('pointercancel', up)
|
||||
if (frame) { cancelAnimationFrame(frame); frame = 0 }
|
||||
flush() // land the final position even if the last frame never ran
|
||||
try { handleEl && handleEl.releasePointerCapture && handleEl.releasePointerCapture(ev.pointerId) } catch (_) {}
|
||||
persist()
|
||||
endDrag()
|
||||
}
|
||||
window.addEventListener('pointermove', move)
|
||||
window.addEventListener('pointerup', up)
|
||||
window.addEventListener('pointercancel', up)
|
||||
}
|
||||
|
||||
const startFacetResize = (e) => startResize('facet', e)
|
||||
const startRailResize = (e) => startResize('rail', e)
|
||||
const startTableResize = (e) => startResize('table', e)
|
||||
const startShellResize = (e) => startResize('shell', e)
|
||||
|
||||
// ── keyboard step-resize (a11y: role="separator" needs an operable equivalent to the drag) ──
|
||||
// Reuses the SAME refs/clamps/persist/applyVars as the pointer path — no parallel math. One
|
||||
// discrete step per keypress (no rAF coalescing needed; a keydown can't fire faster than a frame).
|
||||
// `table` axis mirrors startResize's own page-scroll branch: in page-scroll mode it steps mapH
|
||||
// (the map/table split within the FIXED shellH budget), otherwise it steps the grid-mode tableH
|
||||
// percentage. `shell` steps shellH directly — the only axis that changes the element's total height.
|
||||
const STEP = { facet: 16, rail: 16, table: 24, mapH: 24, shellH: 24 } // px per arrow-key press (tableH in %)
|
||||
// `toExtreme` bypasses the per-step delta entirely and clamps straight to lo/hi — Home/End jump,
|
||||
// not a long walk of individual steps (which would also mean 200 localStorage writes per keypress).
|
||||
function stepResize(axis, dir, toExtreme) {
|
||||
if (narrow()) return
|
||||
if (axis === 'facet') {
|
||||
facetW.value = toExtreme ? (dir < 0 ? clamps.facetW[0] : clamps.facetW[1])
|
||||
: Math.round(clamp(facetW.value + dir * STEP.facet, clamps.facetW))
|
||||
customized.value = true
|
||||
} else if (axis === 'rail') {
|
||||
// Same "left edge, dragging left widens" sense as the pointer path: ArrowLeft (dir -1)
|
||||
// widens the rail, so the rail's step direction is inverted relative to facet's.
|
||||
railW.value = toExtreme ? (dir < 0 ? clamps.railW[1] : clamps.railW[0])
|
||||
: Math.round(clamp(railW.value - dir * STEP.rail, clamps.railW))
|
||||
customized.value = true
|
||||
} else if (axis === 'table' && inPageScroll()) {
|
||||
// Same ceiling as the pointer path (startResize's mapHCeiling): reserve the table's bar +
|
||||
// usable minimum out of the CURRENT shellH so a keyboard drag can redistribute but never
|
||||
// grow the total either.
|
||||
const ceiling = Math.max(clamps.mapH[0], shellH.value - (TABLE_BAR_H + TABLE_MIN_H))
|
||||
mapH.value = toExtreme ? (dir < 0 ? clamps.mapH[0] : ceiling)
|
||||
: Math.round(clamp(mapH.value + dir * STEP.mapH, [clamps.mapH[0], ceiling]))
|
||||
mapHCustomized.value = true
|
||||
} else if (axis === 'table') {
|
||||
const pct = toExtreme ? (dir < 0 ? clamps.tableH[0] : clamps.tableH[1])
|
||||
: clamp(pctNum(tableH.value, pctNum(defaults.tableH, 34)) - dir * STEP.table / 4, clamps.tableH)
|
||||
tableH.value = Math.round(pct) + '%'
|
||||
customized.value = true
|
||||
} else if (axis === 'shell' && inPageScroll()) {
|
||||
shellH.value = toExtreme ? (dir < 0 ? clamps.shellH[0] : clamps.shellH[1])
|
||||
: Math.round(clamp(shellH.value + dir * STEP.shellH, clamps.shellH))
|
||||
shellHCustomized.value = true
|
||||
}
|
||||
applyVars()
|
||||
persist()
|
||||
}
|
||||
// ArrowUp/Left = grow toward the start edge, ArrowDown/Right = grow toward the end edge, matching
|
||||
// each handle's drag SENSE (facet/rail are col-resize, table/map/shell are row-resize). Home/End
|
||||
// jump to the axis's clamp extremes in one write (not a walk of individual steps).
|
||||
function onResizeKeydown(axis, e) {
|
||||
const K = e.key
|
||||
let dir = 0
|
||||
if (axis === 'table' || axis === 'shell') { if (K === 'ArrowUp') dir = -1; else if (K === 'ArrowDown') dir = 1 }
|
||||
else { if (K === 'ArrowLeft') dir = -1; else if (K === 'ArrowRight') dir = 1 }
|
||||
if (dir) { e.preventDefault(); stepResize(axis, dir); return }
|
||||
if (K === 'Home' || K === 'End') {
|
||||
e.preventDefault()
|
||||
stepResize(axis, K === 'Home' ? -1 : 1, true)
|
||||
}
|
||||
}
|
||||
|
||||
// ── lifecycle: restore + apply after the shell el exists; wire the reset bus event ──
|
||||
let offReset = null
|
||||
onMounted(() => {
|
||||
if (restore()) applyVars()
|
||||
if (bus && typeof bus.on === 'function') offReset = bus.on('resetLayout', reset)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
try { offReset && offReset() } catch (_) {}
|
||||
// If the component tears down mid-drag, release the suppression so a re-mounted map
|
||||
// is never left permanently in the cheap "resizing" mode.
|
||||
try { endDrag() } catch (_) {}
|
||||
})
|
||||
|
||||
return {
|
||||
facetW, railW, tableH, mapH, shellH, customized, resizing,
|
||||
startFacetResize, startRailResize, startTableResize, startShellResize,
|
||||
startResize, reset, applyVars, stepResize, onResizeKeydown,
|
||||
}
|
||||
}
|
||||
export { useDashboardLayout } from '@map/composables/useDashboardLayout.js'
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
/**
|
||||
* useSelectionBus.js — RE-EXPORT SHIM (dashboard-kit landing 1).
|
||||
*
|
||||
* The bus now lives at library/composables/useSelectionBus.js. This file exists so the move and
|
||||
* its consumers do not have to land in the same commit: every importer keeps working unchanged for
|
||||
* one cycle, and the ones that still point here are migrated in the next landing, after which this
|
||||
* file is deleted.
|
||||
*
|
||||
* WHY A SHIM AND NOT A SIMULTANEOUS REWRITE. The extraction's governing constraint is that Big
|
||||
* Picture must not change, and the only way to prove that for nine landings in a row is to make
|
||||
* each one small enough to verify on its own. A landing that moves a file AND rewrites every
|
||||
* import is two changes whose failures look identical from the outside.
|
||||
*
|
||||
* NOT A SECOND COPY. It re-exports; it does not duplicate. A copy would drift silently and both
|
||||
* halves would keep passing their gates — which is the exact failure check:no-cross-plugin-imports
|
||||
* and check:shared-reached exist to stop.
|
||||
*/
|
||||
export { createSelectionBus, deriveHierarchy } from '@map/composables/useSelectionBus.js'
|
||||
|
|
@ -371,7 +371,7 @@ function onMapFiltered(ev) {
|
|||
function gridLanguage() {
|
||||
const codes = Array.isArray(linked.language.codes) ? linked.language.codes : []
|
||||
// ★ THE ABSTENTION IS OVER (SPEC-DASHBOARD-KIT D1). When the map reported a language TIER —
|
||||
// "Arabic", 22 ISO codes — there was no single value that meant it, so this left the axis
|
||||
// "Arabic", 23 ISO codes — there was no single value that meant it, so this left the axis
|
||||
// unfiltered: honest, and visibly incomplete, because the map narrowed and the grid did not.
|
||||
// The grid's valueMatches() now takes a LIST and matches OR-within-the-axis, so the whole
|
||||
// selection crosses as the codes it actually is. Still codes and never the tier NAME: the name
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <all-people-groups> custom element. -->
|
||||
<script src="../all-people-groups.js" integrity="sha384-F7hrqrJ4KE0p/exwEjI1p9qVYQdwbpxBUA+deOSOaCrfth0JejL6kDUTSj71y42E" crossorigin="anonymous"></script>
|
||||
<script src="../all-people-groups.js" integrity="sha384-SGOU2Dm5al25r7QWV/5qhkOHy9A63UjMCu3yHz7r+8gV3Rkfuu/ONqQd6zJGR2p8" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <cities-internet-map> custom element. -->
|
||||
<script src="../cities-internet.js" integrity="sha384-ml6QsBOXZOJUo0LFKCTgOQrNXYhP/kcUUc0gy2eZMaKuOnG7Zl88LWwjyimLc6xo" crossorigin="anonymous"></script>
|
||||
<script src="../cities-internet.js" integrity="sha384-Ik4dBvh88t0S21pog1AfTfbFlTfFOuplvtc4N7KeQYmhxJNVD/f0PFAEYKOUlM1s" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <cities-internet-map> custom element. -->
|
||||
<script src="../cities-internet.js" integrity="sha384-ml6QsBOXZOJUo0LFKCTgOQrNXYhP/kcUUc0gy2eZMaKuOnG7Zl88LWwjyimLc6xo" crossorigin="anonymous"></script>
|
||||
<script src="../cities-internet.js" integrity="sha384-Ik4dBvh88t0S21pog1AfTfbFlTfFOuplvtc4N7KeQYmhxJNVD/f0PFAEYKOUlM1s" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <cities-internet-map> custom element. -->
|
||||
<script src="../cities-internet.js" integrity="sha384-ml6QsBOXZOJUo0LFKCTgOQrNXYhP/kcUUc0gy2eZMaKuOnG7Zl88LWwjyimLc6xo" crossorigin="anonymous"></script>
|
||||
<script src="../cities-internet.js" integrity="sha384-Ik4dBvh88t0S21pog1AfTfbFlTfFOuplvtc4N7KeQYmhxJNVD/f0PFAEYKOUlM1s" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <country-posters-map> custom element. -->
|
||||
<script src="../country-posters.js" integrity="sha384-6mrJZnVotRNjXBio1AC4gVpK7RB62MHiWPflkmSIjfdrgh43auSCtL0SCx0lZNCM" crossorigin="anonymous"></script>
|
||||
<script src="../country-posters.js" integrity="sha384-qu854maZR+plzMvZ7VmIoJu5Y3acmyAFOnl0AN/1lYGOqVCNrHnagSjphPNdeG9l" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <country-posters-map> custom element. -->
|
||||
<script src="../country-posters.js" integrity="sha384-6mrJZnVotRNjXBio1AC4gVpK7RB62MHiWPflkmSIjfdrgh43auSCtL0SCx0lZNCM" crossorigin="anonymous"></script>
|
||||
<script src="../country-posters.js" integrity="sha384-qu854maZR+plzMvZ7VmIoJu5Y3acmyAFOnl0AN/1lYGOqVCNrHnagSjphPNdeG9l" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <country-posters-map> custom element. -->
|
||||
<script src="../country-posters.js" integrity="sha384-6mrJZnVotRNjXBio1AC4gVpK7RB62MHiWPflkmSIjfdrgh43auSCtL0SCx0lZNCM" crossorigin="anonymous"></script>
|
||||
<script src="../country-posters.js" integrity="sha384-qu854maZR+plzMvZ7VmIoJu5Y3acmyAFOnl0AN/1lYGOqVCNrHnagSjphPNdeG9l" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <dashboard-plus-grid> custom element. -->
|
||||
<script src="../../dashboard-plus-grid.js" integrity="sha384-EiM47KQgmavyRxJCBufmN+X5kPCYcj9FrG93XFOA4LSxLYukkolGT5q62vPlVAi2" crossorigin="anonymous"></script>
|
||||
<script src="../../dashboard-plus-grid.js" integrity="sha384-aEXRsVorVuFmdtMLGu09mEj6odlTMSYIEjfoBPXi3B1c3cFLlcHJDi/pbgbTBtuG" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <dashboard-plus-grid> custom element. -->
|
||||
<script src="../dashboard-plus-grid.js" integrity="sha384-EiM47KQgmavyRxJCBufmN+X5kPCYcj9FrG93XFOA4LSxLYukkolGT5q62vPlVAi2" crossorigin="anonymous"></script>
|
||||
<script src="../dashboard-plus-grid.js" integrity="sha384-aEXRsVorVuFmdtMLGu09mEj6odlTMSYIEjfoBPXi3B1c3cFLlcHJDi/pbgbTBtuG" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <demo-map> custom element. -->
|
||||
<script src="../demo-map.js" integrity="sha384-WckXsLe9WKaHEDl1dE7KrUI/9Ujs2kwSOyi2xe1mSLFAJKX4zM65YLqhbUreiu9G" crossorigin="anonymous"></script>
|
||||
<script src="../demo-map.js" integrity="sha384-kDD+fxrCLrQot3APFqTFz/X8207atst/kstyYS5NpsgfRUuNpXiEDLvswX8wVEQA" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <demo-map> custom element. -->
|
||||
<script src="../../demo-map.js" integrity="sha384-WckXsLe9WKaHEDl1dE7KrUI/9Ujs2kwSOyi2xe1mSLFAJKX4zM65YLqhbUreiu9G" crossorigin="anonymous"></script>
|
||||
<script src="../../demo-map.js" integrity="sha384-kDD+fxrCLrQot3APFqTFz/X8207atst/kstyYS5NpsgfRUuNpXiEDLvswX8wVEQA" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-maps-spa> custom element. -->
|
||||
<script src="../../doxa-maps-spa.js" integrity="sha384-KFz+my8n8OZeDip1uciLfveQNlV3E7eyYHiTJngZWtVWbC9+D3fGkPqo5vY1cLUl" crossorigin="anonymous"></script>
|
||||
<script src="../../doxa-maps-spa.js" integrity="sha384-fpwC0zTBhbE2VKKQwhs9q/81s/f0sTm5kVtkwiSA6mUHjNJTzS7go+dGxdSqEx1C" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-maps-spa> custom element. -->
|
||||
<script src="../doxa-maps-spa.js" integrity="sha384-KFz+my8n8OZeDip1uciLfveQNlV3E7eyYHiTJngZWtVWbC9+D3fGkPqo5vY1cLUl" crossorigin="anonymous"></script>
|
||||
<script src="../doxa-maps-spa.js" integrity="sha384-fpwC0zTBhbE2VKKQwhs9q/81s/f0sTm5kVtkwiSA6mUHjNJTzS7go+dGxdSqEx1C" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
"bundle": "all-people-groups",
|
||||
"scriptUrl": "./all-people-groups/all-people-groups.js",
|
||||
"output": "dx-maps/all-people-groups/all-people-groups.js",
|
||||
"integrity": "sha384-F7hrqrJ4KE0p/exwEjI1p9qVYQdwbpxBUA+deOSOaCrfth0JejL6kDUTSj71y42E",
|
||||
"integrity": "sha384-SGOU2Dm5al25r7QWV/5qhkOHy9A63UjMCu3yHz7r+8gV3Rkfuu/ONqQd6zJGR2p8",
|
||||
"elements": [
|
||||
"all-people-groups"
|
||||
],
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
"scriptUrl": "./all-people-groups/all-people-groups.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./all-people-groups/all-people-groups/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./all-people-groups/all-people-groups.js\" integrity=\"sha384-F7hrqrJ4KE0p/exwEjI1p9qVYQdwbpxBUA+deOSOaCrfth0JejL6kDUTSj71y42E\" crossorigin=\"anonymous\"></script>\n<all-people-groups profile-config='{\"profile\":\"all-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></all-people-groups>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./all-people-groups/all-people-groups.js\" integrity=\"sha384-SGOU2Dm5al25r7QWV/5qhkOHy9A63UjMCu3yHz7r+8gV3Rkfuu/ONqQd6zJGR2p8\" crossorigin=\"anonymous\"></script>\n<all-people-groups profile-config='{\"profile\":\"all-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></all-people-groups>"
|
||||
},
|
||||
"bundle": "all-people-groups"
|
||||
}
|
||||
|
|
@ -104,7 +104,7 @@
|
|||
"bundle": "cities-internet",
|
||||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"output": "dx-maps/cities-internet/cities-internet.js",
|
||||
"integrity": "sha384-ml6QsBOXZOJUo0LFKCTgOQrNXYhP/kcUUc0gy2eZMaKuOnG7Zl88LWwjyimLc6xo",
|
||||
"integrity": "sha384-Ik4dBvh88t0S21pog1AfTfbFlTfFOuplvtc4N7KeQYmhxJNVD/f0PFAEYKOUlM1s",
|
||||
"elements": [
|
||||
"cities-internet-map"
|
||||
],
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/connectivity-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-ml6QsBOXZOJUo0LFKCTgOQrNXYhP/kcUUc0gy2eZMaKuOnG7Zl88LWwjyimLc6xo\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-Ik4dBvh88t0S21pog1AfTfbFlTfFOuplvtc4N7KeQYmhxJNVD/f0PFAEYKOUlM1s\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -134,7 +134,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/connectivity-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-ml6QsBOXZOJUo0LFKCTgOQrNXYhP/kcUUc0gy2eZMaKuOnG7Zl88LWwjyimLc6xo\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-Ik4dBvh88t0S21pog1AfTfbFlTfFOuplvtc4N7KeQYmhxJNVD/f0PFAEYKOUlM1s\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -148,7 +148,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-ml6QsBOXZOJUo0LFKCTgOQrNXYhP/kcUUc0gy2eZMaKuOnG7Zl88LWwjyimLc6xo\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-Ik4dBvh88t0S21pog1AfTfbFlTfFOuplvtc4N7KeQYmhxJNVD/f0PFAEYKOUlM1s\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -157,7 +157,7 @@
|
|||
"bundle": "country-posters",
|
||||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"output": "dx-maps/country-posters/country-posters.js",
|
||||
"integrity": "sha384-6mrJZnVotRNjXBio1AC4gVpK7RB62MHiWPflkmSIjfdrgh43auSCtL0SCx0lZNCM",
|
||||
"integrity": "sha384-qu854maZR+plzMvZ7VmIoJu5Y3acmyAFOnl0AN/1lYGOqVCNrHnagSjphPNdeG9l",
|
||||
"elements": [
|
||||
"country-posters-map"
|
||||
],
|
||||
|
|
@ -177,7 +177,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/countries-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-6mrJZnVotRNjXBio1AC4gVpK7RB62MHiWPflkmSIjfdrgh43auSCtL0SCx0lZNCM\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"countries-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-qu854maZR+plzMvZ7VmIoJu5Y3acmyAFOnl0AN/1lYGOqVCNrHnagSjphPNdeG9l\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"countries-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -191,7 +191,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/country-poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-6mrJZnVotRNjXBio1AC4gVpK7RB62MHiWPflkmSIjfdrgh43auSCtL0SCx0lZNCM\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-qu854maZR+plzMvZ7VmIoJu5Y3acmyAFOnl0AN/1lYGOqVCNrHnagSjphPNdeG9l\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -205,7 +205,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/country-posters-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-6mrJZnVotRNjXBio1AC4gVpK7RB62MHiWPflkmSIjfdrgh43auSCtL0SCx0lZNCM\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-posters-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-qu854maZR+plzMvZ7VmIoJu5Y3acmyAFOnl0AN/1lYGOqVCNrHnagSjphPNdeG9l\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-posters-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -214,7 +214,7 @@
|
|||
"bundle": "dashboard-plus-grid",
|
||||
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"output": "dx-maps/dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"integrity": "sha384-EiM47KQgmavyRxJCBufmN+X5kPCYcj9FrG93XFOA4LSxLYukkolGT5q62vPlVAi2",
|
||||
"integrity": "sha384-aEXRsVorVuFmdtMLGu09mEj6odlTMSYIEjfoBPXi3B1c3cFLlcHJDi/pbgbTBtuG",
|
||||
"elements": [
|
||||
"dashboard-plus-grid"
|
||||
],
|
||||
|
|
@ -234,7 +234,7 @@
|
|||
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./dashboard-plus-grid/dashboard-plus-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-EiM47KQgmavyRxJCBufmN+X5kPCYcj9FrG93XFOA4LSxLYukkolGT5q62vPlVAi2\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-aEXRsVorVuFmdtMLGu09mEj6odlTMSYIEjfoBPXi3B1c3cFLlcHJDi/pbgbTBtuG\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -258,7 +258,7 @@
|
|||
"bundle": "demo-map",
|
||||
"scriptUrl": "./demo-map/demo-map.js",
|
||||
"output": "dx-maps/demo-map/demo-map.js",
|
||||
"integrity": "sha384-WckXsLe9WKaHEDl1dE7KrUI/9Ujs2kwSOyi2xe1mSLFAJKX4zM65YLqhbUreiu9G",
|
||||
"integrity": "sha384-kDD+fxrCLrQot3APFqTFz/X8207atst/kstyYS5NpsgfRUuNpXiEDLvswX8wVEQA",
|
||||
"elements": [
|
||||
"demo-map"
|
||||
],
|
||||
|
|
@ -274,7 +274,7 @@
|
|||
"scriptUrl": "./demo-map/demo-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./demo-map/demo-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./demo-map/demo-map.js\" integrity=\"sha384-WckXsLe9WKaHEDl1dE7KrUI/9Ujs2kwSOyi2xe1mSLFAJKX4zM65YLqhbUreiu9G\" crossorigin=\"anonymous\"></script>\n<demo-map profile-config='{\"profile\":\"demo-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></demo-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./demo-map/demo-map.js\" integrity=\"sha384-kDD+fxrCLrQot3APFqTFz/X8207atst/kstyYS5NpsgfRUuNpXiEDLvswX8wVEQA\" crossorigin=\"anonymous\"></script>\n<demo-map profile-config='{\"profile\":\"demo-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></demo-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -301,7 +301,7 @@
|
|||
"bundle": "doxa-maps-spa",
|
||||
"scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js",
|
||||
"output": "dx-maps/doxa-maps-spa/doxa-maps-spa.js",
|
||||
"integrity": "sha384-KFz+my8n8OZeDip1uciLfveQNlV3E7eyYHiTJngZWtVWbC9+D3fGkPqo5vY1cLUl",
|
||||
"integrity": "sha384-fpwC0zTBhbE2VKKQwhs9q/81s/f0sTm5kVtkwiSA6mUHjNJTzS7go+dGxdSqEx1C",
|
||||
"elements": [
|
||||
"doxa-maps-spa"
|
||||
],
|
||||
|
|
@ -326,7 +326,7 @@
|
|||
"scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./doxa-maps-spa/doxa-maps-spa/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-maps-spa/doxa-maps-spa.js\" integrity=\"sha384-KFz+my8n8OZeDip1uciLfveQNlV3E7eyYHiTJngZWtVWbC9+D3fGkPqo5vY1cLUl\" crossorigin=\"anonymous\"></script>\n<doxa-maps-spa profile-config='{\"profile\":\"doxa-maps-spa\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-maps-spa>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-maps-spa/doxa-maps-spa.js\" integrity=\"sha384-fpwC0zTBhbE2VKKQwhs9q/81s/f0sTm5kVtkwiSA6mUHjNJTzS7go+dGxdSqEx1C\" crossorigin=\"anonymous\"></script>\n<doxa-maps-spa profile-config='{\"profile\":\"doxa-maps-spa\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-maps-spa>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -353,7 +353,7 @@
|
|||
"bundle": "doxa-research-map",
|
||||
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
|
||||
"output": "dx-maps/doxa-research-map/doxa-research-map.js",
|
||||
"integrity": "sha384-MzlClGaRULOglVqOxnPibUpki8uJIq0hG5v9rhN+IgCMEHsXbzAfyVj2KMY+dpIT",
|
||||
"integrity": "sha384-R5R8R1AWeOs/yz/0q2U/ahJkgcbu+8//vyw3ZfvYVYFA3O1xiULksIhA7975VeOm",
|
||||
"elements": [
|
||||
"doxa-research-map"
|
||||
],
|
||||
|
|
@ -369,7 +369,7 @@
|
|||
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./doxa-research-map/research-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-MzlClGaRULOglVqOxnPibUpki8uJIq0hG5v9rhN+IgCMEHsXbzAfyVj2KMY+dpIT\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-R5R8R1AWeOs/yz/0q2U/ahJkgcbu+8//vyw3ZfvYVYFA3O1xiULksIhA7975VeOm\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -395,7 +395,7 @@
|
|||
"bundle": "doxa-simple-map",
|
||||
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
|
||||
"output": "dx-maps/doxa-simple-map/doxa-simple-map.js",
|
||||
"integrity": "sha384-/oNMjYlt4RgA4jH6x9TXCpTbzISI+FJQXmfVfPsnrfkJSSpiiyZ30hnmmPKlsfV+",
|
||||
"integrity": "sha384-hwuO0pWvI3B6X2EmGD+DI/xt6pRktnmNw83Mg9jG9OKgMHv/TTRKdX2hjVmtD2Wp",
|
||||
"elements": [
|
||||
"doxa-map",
|
||||
"doxa-simple-map"
|
||||
|
|
@ -412,7 +412,7 @@
|
|||
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./doxa-simple-map/doxa-simple-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-/oNMjYlt4RgA4jH6x9TXCpTbzISI+FJQXmfVfPsnrfkJSSpiiyZ30hnmmPKlsfV+\" crossorigin=\"anonymous\"></script>\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-hwuO0pWvI3B6X2EmGD+DI/xt6pRktnmNw83Mg9jG9OKgMHv/TTRKdX2hjVmtD2Wp\" crossorigin=\"anonymous\"></script>\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -578,7 +578,7 @@
|
|||
"bundle": "gospel-resources",
|
||||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"output": "dx-maps/gospel-resources/gospel-resources.js",
|
||||
"integrity": "sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O",
|
||||
"integrity": "sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH",
|
||||
"elements": [
|
||||
"gospel-resources-map"
|
||||
],
|
||||
|
|
@ -598,7 +598,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/charts/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -612,7 +612,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -626,7 +626,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/gospel-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -640,7 +640,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/resources-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -654,7 +654,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/resources-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -663,7 +663,7 @@
|
|||
"bundle": "my-upg-100-list",
|
||||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"output": "dx-maps/my-upg-100-list/my-upg-100-list.js",
|
||||
"integrity": "sha384-KrU2osR+kR7m0xQSmpTJRg323lxffls7/R+rd5ZgkXZ3GK/kBPM2AcEHpGWcyRda",
|
||||
"integrity": "sha384-6Q5uVnqbJ6t3NYnOUlyDhG5O5I2q9Ob+fp5qf8qLufOE6DqTgnjZnSxOU6Z1ml/c",
|
||||
"elements": [
|
||||
"my-upg-100-list-map"
|
||||
],
|
||||
|
|
@ -683,7 +683,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-KrU2osR+kR7m0xQSmpTJRg323lxffls7/R+rd5ZgkXZ3GK/kBPM2AcEHpGWcyRda\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-6Q5uVnqbJ6t3NYnOUlyDhG5O5I2q9Ob+fp5qf8qLufOE6DqTgnjZnSxOU6Z1ml/c\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -697,7 +697,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-KrU2osR+kR7m0xQSmpTJRg323lxffls7/R+rd5ZgkXZ3GK/kBPM2AcEHpGWcyRda\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-6Q5uVnqbJ6t3NYnOUlyDhG5O5I2q9Ob+fp5qf8qLufOE6DqTgnjZnSxOU6Z1ml/c\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -711,7 +711,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-KrU2osR+kR7m0xQSmpTJRg323lxffls7/R+rd5ZgkXZ3GK/kBPM2AcEHpGWcyRda\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-6Q5uVnqbJ6t3NYnOUlyDhG5O5I2q9Ob+fp5qf8qLufOE6DqTgnjZnSxOU6Z1ml/c\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -781,7 +781,7 @@
|
|||
"bundle": "plugin-studio",
|
||||
"scriptUrl": "./plugin-studio/plugin-studio.js",
|
||||
"output": "dx-maps/plugin-studio/plugin-studio.js",
|
||||
"integrity": "sha384-D/d9f5Hw2BwzKeV9gZ60HGMJysRYEDxvJ9ZloOJKXVsCyh+kiVcRObaRxtAvIDCJ",
|
||||
"integrity": "sha384-Jc2znVVtfkv01BBMY6IpyHr/W2r1JtqflWXd/s8LWPfJ+Ge62BgIK2vUbmvtvZH+",
|
||||
"elements": [
|
||||
"plugin-studio"
|
||||
],
|
||||
|
|
@ -809,7 +809,7 @@
|
|||
"scriptUrl": "./plugin-studio/plugin-studio.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./plugin-studio/plugin-studio/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-D/d9f5Hw2BwzKeV9gZ60HGMJysRYEDxvJ9ZloOJKXVsCyh+kiVcRObaRxtAvIDCJ\" crossorigin=\"anonymous\"></script>\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-Jc2znVVtfkv01BBMY6IpyHr/W2r1JtqflWXd/s8LWPfJ+Ge62BgIK2vUbmvtvZH+\" crossorigin=\"anonymous\"></script>\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -836,7 +836,7 @@
|
|||
"bundle": "pplr-data-maps",
|
||||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"output": "dx-maps/pplr-data-maps/pplr-data-maps.js",
|
||||
"integrity": "sha384-0qPFDkM9YuvkCxJFO0gmN7h+4G/qEcohCqfS6m1pJdYCtwsr3GR1awDrg7zoszgt",
|
||||
"integrity": "sha384-vlRYtuZbl8uLUdt3BdNYUz40tJIOHtMquV6MvU9oJsWN4cz26mvqvmr5J9IR3Xpw",
|
||||
"elements": [
|
||||
"pplr-data-maps"
|
||||
],
|
||||
|
|
@ -852,7 +852,7 @@
|
|||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./pplr-data-maps/pplr-data-maps/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-0qPFDkM9YuvkCxJFO0gmN7h+4G/qEcohCqfS6m1pJdYCtwsr3GR1awDrg7zoszgt\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-vlRYtuZbl8uLUdt3BdNYUz40tJIOHtMquV6MvU9oJsWN4cz26mvqvmr5J9IR3Xpw\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
},
|
||||
"bundle": "pplr-data-maps"
|
||||
}
|
||||
|
|
@ -887,7 +887,7 @@
|
|||
"bundle": "regions-dashboard",
|
||||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"output": "dx-maps/regions-dashboard/regions-dashboard.js",
|
||||
"integrity": "sha384-B1eho+1j5yy1/4tRwAtrJrZ4wRP4G1++BhfjItpoHYUyPQSUDtb4Z2qgtJFmLEnC",
|
||||
"integrity": "sha384-SnDDRSZmhUwrpNq6xopiym+7UVsMBxZQak3RVTox7+sZjZkMhmNAHK7y7eTyhTM2",
|
||||
"elements": [
|
||||
"regions-dashboard"
|
||||
],
|
||||
|
|
@ -907,7 +907,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/region-dashboards/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-B1eho+1j5yy1/4tRwAtrJrZ4wRP4G1++BhfjItpoHYUyPQSUDtb4Z2qgtJFmLEnC\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-SnDDRSZmhUwrpNq6xopiym+7UVsMBxZQak3RVTox7+sZjZkMhmNAHK7y7eTyhTM2\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -921,7 +921,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/regions-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-B1eho+1j5yy1/4tRwAtrJrZ4wRP4G1++BhfjItpoHYUyPQSUDtb4Z2qgtJFmLEnC\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-SnDDRSZmhUwrpNq6xopiym+7UVsMBxZQak3RVTox7+sZjZkMhmNAHK7y7eTyhTM2\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -935,7 +935,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/regions-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-B1eho+1j5yy1/4tRwAtrJrZ4wRP4G1++BhfjItpoHYUyPQSUDtb4Z2qgtJFmLEnC\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-SnDDRSZmhUwrpNq6xopiym+7UVsMBxZQak3RVTox7+sZjZkMhmNAHK7y7eTyhTM2\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -944,7 +944,7 @@
|
|||
"bundle": "research-dashboard",
|
||||
"scriptUrl": "./research-dashboard/research-dashboard.js",
|
||||
"output": "dx-maps/research-dashboard/research-dashboard.js",
|
||||
"integrity": "sha384-vqWLWM1MWqQaUqBuo0H4sQLrwNo+rSpsQbtum4qX/c9uxWH0MrhikJjOH/iKKgzj",
|
||||
"integrity": "sha384-1gpwTWBMcmXFqeNMcuUOcke40VSJ0kgW8n73UlvoMw/p6ElHD6wsdzAW2/R4sR7h",
|
||||
"elements": [
|
||||
"research-dashboard-map"
|
||||
],
|
||||
|
|
@ -960,7 +960,7 @@
|
|||
"scriptUrl": "./research-dashboard/research-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./research-dashboard/research-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-vqWLWM1MWqQaUqBuo0H4sQLrwNo+rSpsQbtum4qX/c9uxWH0MrhikJjOH/iKKgzj\" crossorigin=\"anonymous\"></script>\n<research-dashboard-map profile-config='{\"profile\":\"research-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-dashboard-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-1gpwTWBMcmXFqeNMcuUOcke40VSJ0kgW8n73UlvoMw/p6ElHD6wsdzAW2/R4sR7h\" crossorigin=\"anonymous\"></script>\n<research-dashboard-map profile-config='{\"profile\":\"research-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-dashboard-map>"
|
||||
},
|
||||
"bundle": "research-dashboard"
|
||||
}
|
||||
|
|
@ -1058,7 +1058,7 @@
|
|||
"bundle": "upg-neighbor",
|
||||
"scriptUrl": "./upg-neighbor/upg-neighbor.js",
|
||||
"output": "dx-maps/upg-neighbor/upg-neighbor.js",
|
||||
"integrity": "sha384-icPClI8iMFVBMLoBuE86RBs56W/gkKMAhcu9MmTd16vNs5KtOmjBxZ/rByI5ZvvN",
|
||||
"integrity": "sha384-K4uV9mi/tmckBtGQUsQd7IPBRy29oh0P82BAYEvo3ZoH3ptAvh8EPBdvTCRy9XI4",
|
||||
"elements": [
|
||||
"upg-neighbor"
|
||||
],
|
||||
|
|
@ -1074,7 +1074,7 @@
|
|||
"scriptUrl": "./upg-neighbor/upg-neighbor.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./upg-neighbor/upg-neighbor/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./upg-neighbor/upg-neighbor.js\" integrity=\"sha384-icPClI8iMFVBMLoBuE86RBs56W/gkKMAhcu9MmTd16vNs5KtOmjBxZ/rByI5ZvvN\" crossorigin=\"anonymous\"></script>\n<upg-neighbor profile-config='{\"profile\":\"upg-neighbor\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></upg-neighbor>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./upg-neighbor/upg-neighbor.js\" integrity=\"sha384-K4uV9mi/tmckBtGQUsQd7IPBRy29oh0P82BAYEvo3ZoH3ptAvh8EPBdvTCRy9XI4\" crossorigin=\"anonymous\"></script>\n<upg-neighbor profile-config='{\"profile\":\"upg-neighbor\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></upg-neighbor>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -1157,7 +1157,7 @@
|
|||
"bundle": "wall-of-people-groups",
|
||||
"scriptUrl": "./wall-of-people-groups/wall-of-people-groups.js",
|
||||
"output": "dx-maps/wall-of-people-groups/wall-of-people-groups.js",
|
||||
"integrity": "sha384-PNIwl+E2bUzXvCWSmBAlEHkr2RfaWc0ZxENwDhWO5J4X9pSuAEKEnr6UNK5Fjddj",
|
||||
"integrity": "sha384-DBf5SfneU3H95020XprfF9yJvywsVsS9Xd1oNP3xT1frhsLKMqz2M2fN3dXMPiUc",
|
||||
"elements": [
|
||||
"wall-of-people-groups"
|
||||
],
|
||||
|
|
@ -1173,7 +1173,7 @@
|
|||
"scriptUrl": "./wall-of-people-groups/wall-of-people-groups.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./wall-of-people-groups/wall-of-people-groups/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./wall-of-people-groups/wall-of-people-groups.js\" integrity=\"sha384-PNIwl+E2bUzXvCWSmBAlEHkr2RfaWc0ZxENwDhWO5J4X9pSuAEKEnr6UNK5Fjddj\" crossorigin=\"anonymous\"></script>\n<wall-of-people-groups profile-config='{\"profile\":\"wall-of-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></wall-of-people-groups>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./wall-of-people-groups/wall-of-people-groups.js\" integrity=\"sha384-DBf5SfneU3H95020XprfF9yJvywsVsS9Xd1oNP3xT1frhsLKMqz2M2fN3dXMPiUc\" crossorigin=\"anonymous\"></script>\n<wall-of-people-groups profile-config='{\"profile\":\"wall-of-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></wall-of-people-groups>"
|
||||
},
|
||||
"bundle": "wall-of-people-groups"
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-research-map> custom element. -->
|
||||
<script src="../doxa-research-map.js" integrity="sha384-MzlClGaRULOglVqOxnPibUpki8uJIq0hG5v9rhN+IgCMEHsXbzAfyVj2KMY+dpIT" crossorigin="anonymous"></script>
|
||||
<script src="../doxa-research-map.js" integrity="sha384-R5R8R1AWeOs/yz/0q2U/ahJkgcbu+8//vyw3ZfvYVYFA3O1xiULksIhA7975VeOm" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-research-map> custom element. -->
|
||||
<script src="../../doxa-research-map.js" integrity="sha384-MzlClGaRULOglVqOxnPibUpki8uJIq0hG5v9rhN+IgCMEHsXbzAfyVj2KMY+dpIT" crossorigin="anonymous"></script>
|
||||
<script src="../../doxa-research-map.js" integrity="sha384-R5R8R1AWeOs/yz/0q2U/ahJkgcbu+8//vyw3ZfvYVYFA3O1xiULksIhA7975VeOm" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-/oNMjYlt4RgA4jH6x9TXCpTbzISI+FJQXmfVfPsnrfkJSSpiiyZ30hnmmPKlsfV+" crossorigin="anonymous"></script>
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-hwuO0pWvI3B6X2EmGD+DI/xt6pRktnmNw83Mg9jG9OKgMHv/TTRKdX2hjVmtD2Wp" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-/oNMjYlt4RgA4jH6x9TXCpTbzISI+FJQXmfVfPsnrfkJSSpiiyZ30hnmmPKlsfV+" crossorigin="anonymous"></script>
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-hwuO0pWvI3B6X2EmGD+DI/xt6pRktnmNw83Mg9jG9OKgMHv/TTRKdX2hjVmtD2Wp" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
|
||||
<script src="../doxa-simple-map.js" integrity="sha384-/oNMjYlt4RgA4jH6x9TXCpTbzISI+FJQXmfVfPsnrfkJSSpiiyZ30hnmmPKlsfV+" crossorigin="anonymous"></script>
|
||||
<script src="../doxa-simple-map.js" integrity="sha384-hwuO0pWvI3B6X2EmGD+DI/xt6pRktnmNw83Mg9jG9OKgMHv/TTRKdX2hjVmtD2Wp" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-/oNMjYlt4RgA4jH6x9TXCpTbzISI+FJQXmfVfPsnrfkJSSpiiyZ30hnmmPKlsfV+" crossorigin="anonymous"></script>
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-hwuO0pWvI3B6X2EmGD+DI/xt6pRktnmNw83Mg9jG9OKgMHv/TTRKdX2hjVmtD2Wp" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -19,6 +19,6 @@
|
|||
</head>
|
||||
<body>
|
||||
<plugin-studio tree-base="."></plugin-studio>
|
||||
<script src="./plugin-studio/plugin-studio.js" integrity="sha384-D/d9f5Hw2BwzKeV9gZ60HGMJysRYEDxvJ9ZloOJKXVsCyh+kiVcRObaRxtAvIDCJ" crossorigin="anonymous"></script>
|
||||
<script src="./plugin-studio/plugin-studio.js" integrity="sha384-Jc2znVVtfkv01BBMY6IpyHr/W2r1JtqflWXd/s8LWPfJ+Ge62BgIK2vUbmvtvZH+" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -12,7 +12,7 @@
|
|||
"bundle": "all-people-groups",
|
||||
"scriptUrl": "./all-people-groups/all-people-groups.js",
|
||||
"output": "dx-maps/all-people-groups/all-people-groups.js",
|
||||
"integrity": "sha384-F7hrqrJ4KE0p/exwEjI1p9qVYQdwbpxBUA+deOSOaCrfth0JejL6kDUTSj71y42E",
|
||||
"integrity": "sha384-SGOU2Dm5al25r7QWV/5qhkOHy9A63UjMCu3yHz7r+8gV3Rkfuu/ONqQd6zJGR2p8",
|
||||
"elements": [
|
||||
"all-people-groups"
|
||||
],
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
"scriptUrl": "./all-people-groups/all-people-groups.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./all-people-groups/all-people-groups/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./all-people-groups/all-people-groups.js\" integrity=\"sha384-F7hrqrJ4KE0p/exwEjI1p9qVYQdwbpxBUA+deOSOaCrfth0JejL6kDUTSj71y42E\" crossorigin=\"anonymous\"></script>\n<all-people-groups profile-config='{\"profile\":\"all-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></all-people-groups>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./all-people-groups/all-people-groups.js\" integrity=\"sha384-SGOU2Dm5al25r7QWV/5qhkOHy9A63UjMCu3yHz7r+8gV3Rkfuu/ONqQd6zJGR2p8\" crossorigin=\"anonymous\"></script>\n<all-people-groups profile-config='{\"profile\":\"all-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></all-people-groups>"
|
||||
},
|
||||
"bundle": "all-people-groups"
|
||||
}
|
||||
|
|
@ -104,7 +104,7 @@
|
|||
"bundle": "cities-internet",
|
||||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"output": "dx-maps/cities-internet/cities-internet.js",
|
||||
"integrity": "sha384-ml6QsBOXZOJUo0LFKCTgOQrNXYhP/kcUUc0gy2eZMaKuOnG7Zl88LWwjyimLc6xo",
|
||||
"integrity": "sha384-Ik4dBvh88t0S21pog1AfTfbFlTfFOuplvtc4N7KeQYmhxJNVD/f0PFAEYKOUlM1s",
|
||||
"elements": [
|
||||
"cities-internet-map"
|
||||
],
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/connectivity-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-ml6QsBOXZOJUo0LFKCTgOQrNXYhP/kcUUc0gy2eZMaKuOnG7Zl88LWwjyimLc6xo\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-Ik4dBvh88t0S21pog1AfTfbFlTfFOuplvtc4N7KeQYmhxJNVD/f0PFAEYKOUlM1s\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -134,7 +134,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/connectivity-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-ml6QsBOXZOJUo0LFKCTgOQrNXYhP/kcUUc0gy2eZMaKuOnG7Zl88LWwjyimLc6xo\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-Ik4dBvh88t0S21pog1AfTfbFlTfFOuplvtc4N7KeQYmhxJNVD/f0PFAEYKOUlM1s\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -148,7 +148,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-ml6QsBOXZOJUo0LFKCTgOQrNXYhP/kcUUc0gy2eZMaKuOnG7Zl88LWwjyimLc6xo\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-Ik4dBvh88t0S21pog1AfTfbFlTfFOuplvtc4N7KeQYmhxJNVD/f0PFAEYKOUlM1s\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -157,7 +157,7 @@
|
|||
"bundle": "country-posters",
|
||||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"output": "dx-maps/country-posters/country-posters.js",
|
||||
"integrity": "sha384-6mrJZnVotRNjXBio1AC4gVpK7RB62MHiWPflkmSIjfdrgh43auSCtL0SCx0lZNCM",
|
||||
"integrity": "sha384-qu854maZR+plzMvZ7VmIoJu5Y3acmyAFOnl0AN/1lYGOqVCNrHnagSjphPNdeG9l",
|
||||
"elements": [
|
||||
"country-posters-map"
|
||||
],
|
||||
|
|
@ -177,7 +177,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/countries-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-6mrJZnVotRNjXBio1AC4gVpK7RB62MHiWPflkmSIjfdrgh43auSCtL0SCx0lZNCM\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"countries-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-qu854maZR+plzMvZ7VmIoJu5Y3acmyAFOnl0AN/1lYGOqVCNrHnagSjphPNdeG9l\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"countries-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -191,7 +191,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/country-poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-6mrJZnVotRNjXBio1AC4gVpK7RB62MHiWPflkmSIjfdrgh43auSCtL0SCx0lZNCM\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-qu854maZR+plzMvZ7VmIoJu5Y3acmyAFOnl0AN/1lYGOqVCNrHnagSjphPNdeG9l\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -205,7 +205,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/country-posters-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-6mrJZnVotRNjXBio1AC4gVpK7RB62MHiWPflkmSIjfdrgh43auSCtL0SCx0lZNCM\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-posters-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-qu854maZR+plzMvZ7VmIoJu5Y3acmyAFOnl0AN/1lYGOqVCNrHnagSjphPNdeG9l\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-posters-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -214,7 +214,7 @@
|
|||
"bundle": "dashboard-plus-grid",
|
||||
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"output": "dx-maps/dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"integrity": "sha384-EiM47KQgmavyRxJCBufmN+X5kPCYcj9FrG93XFOA4LSxLYukkolGT5q62vPlVAi2",
|
||||
"integrity": "sha384-aEXRsVorVuFmdtMLGu09mEj6odlTMSYIEjfoBPXi3B1c3cFLlcHJDi/pbgbTBtuG",
|
||||
"elements": [
|
||||
"dashboard-plus-grid"
|
||||
],
|
||||
|
|
@ -234,7 +234,7 @@
|
|||
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./dashboard-plus-grid/dashboard-plus-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-EiM47KQgmavyRxJCBufmN+X5kPCYcj9FrG93XFOA4LSxLYukkolGT5q62vPlVAi2\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-aEXRsVorVuFmdtMLGu09mEj6odlTMSYIEjfoBPXi3B1c3cFLlcHJDi/pbgbTBtuG\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -258,7 +258,7 @@
|
|||
"bundle": "demo-map",
|
||||
"scriptUrl": "./demo-map/demo-map.js",
|
||||
"output": "dx-maps/demo-map/demo-map.js",
|
||||
"integrity": "sha384-WckXsLe9WKaHEDl1dE7KrUI/9Ujs2kwSOyi2xe1mSLFAJKX4zM65YLqhbUreiu9G",
|
||||
"integrity": "sha384-kDD+fxrCLrQot3APFqTFz/X8207atst/kstyYS5NpsgfRUuNpXiEDLvswX8wVEQA",
|
||||
"elements": [
|
||||
"demo-map"
|
||||
],
|
||||
|
|
@ -274,7 +274,7 @@
|
|||
"scriptUrl": "./demo-map/demo-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./demo-map/demo-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./demo-map/demo-map.js\" integrity=\"sha384-WckXsLe9WKaHEDl1dE7KrUI/9Ujs2kwSOyi2xe1mSLFAJKX4zM65YLqhbUreiu9G\" crossorigin=\"anonymous\"></script>\n<demo-map profile-config='{\"profile\":\"demo-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></demo-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./demo-map/demo-map.js\" integrity=\"sha384-kDD+fxrCLrQot3APFqTFz/X8207atst/kstyYS5NpsgfRUuNpXiEDLvswX8wVEQA\" crossorigin=\"anonymous\"></script>\n<demo-map profile-config='{\"profile\":\"demo-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></demo-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -301,7 +301,7 @@
|
|||
"bundle": "doxa-maps-spa",
|
||||
"scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js",
|
||||
"output": "dx-maps/doxa-maps-spa/doxa-maps-spa.js",
|
||||
"integrity": "sha384-KFz+my8n8OZeDip1uciLfveQNlV3E7eyYHiTJngZWtVWbC9+D3fGkPqo5vY1cLUl",
|
||||
"integrity": "sha384-fpwC0zTBhbE2VKKQwhs9q/81s/f0sTm5kVtkwiSA6mUHjNJTzS7go+dGxdSqEx1C",
|
||||
"elements": [
|
||||
"doxa-maps-spa"
|
||||
],
|
||||
|
|
@ -326,7 +326,7 @@
|
|||
"scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./doxa-maps-spa/doxa-maps-spa/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-maps-spa/doxa-maps-spa.js\" integrity=\"sha384-KFz+my8n8OZeDip1uciLfveQNlV3E7eyYHiTJngZWtVWbC9+D3fGkPqo5vY1cLUl\" crossorigin=\"anonymous\"></script>\n<doxa-maps-spa profile-config='{\"profile\":\"doxa-maps-spa\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-maps-spa>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-maps-spa/doxa-maps-spa.js\" integrity=\"sha384-fpwC0zTBhbE2VKKQwhs9q/81s/f0sTm5kVtkwiSA6mUHjNJTzS7go+dGxdSqEx1C\" crossorigin=\"anonymous\"></script>\n<doxa-maps-spa profile-config='{\"profile\":\"doxa-maps-spa\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-maps-spa>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -353,7 +353,7 @@
|
|||
"bundle": "doxa-research-map",
|
||||
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
|
||||
"output": "dx-maps/doxa-research-map/doxa-research-map.js",
|
||||
"integrity": "sha384-MzlClGaRULOglVqOxnPibUpki8uJIq0hG5v9rhN+IgCMEHsXbzAfyVj2KMY+dpIT",
|
||||
"integrity": "sha384-R5R8R1AWeOs/yz/0q2U/ahJkgcbu+8//vyw3ZfvYVYFA3O1xiULksIhA7975VeOm",
|
||||
"elements": [
|
||||
"doxa-research-map"
|
||||
],
|
||||
|
|
@ -369,7 +369,7 @@
|
|||
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./doxa-research-map/research-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-MzlClGaRULOglVqOxnPibUpki8uJIq0hG5v9rhN+IgCMEHsXbzAfyVj2KMY+dpIT\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-R5R8R1AWeOs/yz/0q2U/ahJkgcbu+8//vyw3ZfvYVYFA3O1xiULksIhA7975VeOm\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -395,7 +395,7 @@
|
|||
"bundle": "doxa-simple-map",
|
||||
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
|
||||
"output": "dx-maps/doxa-simple-map/doxa-simple-map.js",
|
||||
"integrity": "sha384-/oNMjYlt4RgA4jH6x9TXCpTbzISI+FJQXmfVfPsnrfkJSSpiiyZ30hnmmPKlsfV+",
|
||||
"integrity": "sha384-hwuO0pWvI3B6X2EmGD+DI/xt6pRktnmNw83Mg9jG9OKgMHv/TTRKdX2hjVmtD2Wp",
|
||||
"elements": [
|
||||
"doxa-map",
|
||||
"doxa-simple-map"
|
||||
|
|
@ -412,7 +412,7 @@
|
|||
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./doxa-simple-map/doxa-simple-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-/oNMjYlt4RgA4jH6x9TXCpTbzISI+FJQXmfVfPsnrfkJSSpiiyZ30hnmmPKlsfV+\" crossorigin=\"anonymous\"></script>\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-hwuO0pWvI3B6X2EmGD+DI/xt6pRktnmNw83Mg9jG9OKgMHv/TTRKdX2hjVmtD2Wp\" crossorigin=\"anonymous\"></script>\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -578,7 +578,7 @@
|
|||
"bundle": "gospel-resources",
|
||||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"output": "dx-maps/gospel-resources/gospel-resources.js",
|
||||
"integrity": "sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O",
|
||||
"integrity": "sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH",
|
||||
"elements": [
|
||||
"gospel-resources-map"
|
||||
],
|
||||
|
|
@ -598,7 +598,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/charts/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -612,7 +612,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -626,7 +626,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/gospel-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -640,7 +640,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/resources-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -654,7 +654,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/resources-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-4bFgYoJlJYmruJr/x74YeAAhxVK77GiNJW7ojubIenmPnmji6Vt2slWhGeGxzQ2O\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-rLrn2W0aG06Yy7BW4gFLssT5frDKHwzABi3JxIz3IBsKwSzZc5wL/R757kTzKcFH\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -663,7 +663,7 @@
|
|||
"bundle": "my-upg-100-list",
|
||||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"output": "dx-maps/my-upg-100-list/my-upg-100-list.js",
|
||||
"integrity": "sha384-KrU2osR+kR7m0xQSmpTJRg323lxffls7/R+rd5ZgkXZ3GK/kBPM2AcEHpGWcyRda",
|
||||
"integrity": "sha384-6Q5uVnqbJ6t3NYnOUlyDhG5O5I2q9Ob+fp5qf8qLufOE6DqTgnjZnSxOU6Z1ml/c",
|
||||
"elements": [
|
||||
"my-upg-100-list-map"
|
||||
],
|
||||
|
|
@ -683,7 +683,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-KrU2osR+kR7m0xQSmpTJRg323lxffls7/R+rd5ZgkXZ3GK/kBPM2AcEHpGWcyRda\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-6Q5uVnqbJ6t3NYnOUlyDhG5O5I2q9Ob+fp5qf8qLufOE6DqTgnjZnSxOU6Z1ml/c\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -697,7 +697,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-KrU2osR+kR7m0xQSmpTJRg323lxffls7/R+rd5ZgkXZ3GK/kBPM2AcEHpGWcyRda\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-6Q5uVnqbJ6t3NYnOUlyDhG5O5I2q9Ob+fp5qf8qLufOE6DqTgnjZnSxOU6Z1ml/c\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -711,7 +711,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-KrU2osR+kR7m0xQSmpTJRg323lxffls7/R+rd5ZgkXZ3GK/kBPM2AcEHpGWcyRda\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-6Q5uVnqbJ6t3NYnOUlyDhG5O5I2q9Ob+fp5qf8qLufOE6DqTgnjZnSxOU6Z1ml/c\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -781,7 +781,7 @@
|
|||
"bundle": "plugin-studio",
|
||||
"scriptUrl": "./plugin-studio/plugin-studio.js",
|
||||
"output": "dx-maps/plugin-studio/plugin-studio.js",
|
||||
"integrity": "sha384-D/d9f5Hw2BwzKeV9gZ60HGMJysRYEDxvJ9ZloOJKXVsCyh+kiVcRObaRxtAvIDCJ",
|
||||
"integrity": "sha384-Jc2znVVtfkv01BBMY6IpyHr/W2r1JtqflWXd/s8LWPfJ+Ge62BgIK2vUbmvtvZH+",
|
||||
"elements": [
|
||||
"plugin-studio"
|
||||
],
|
||||
|
|
@ -809,7 +809,7 @@
|
|||
"scriptUrl": "./plugin-studio/plugin-studio.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./plugin-studio/plugin-studio/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-D/d9f5Hw2BwzKeV9gZ60HGMJysRYEDxvJ9ZloOJKXVsCyh+kiVcRObaRxtAvIDCJ\" crossorigin=\"anonymous\"></script>\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-Jc2znVVtfkv01BBMY6IpyHr/W2r1JtqflWXd/s8LWPfJ+Ge62BgIK2vUbmvtvZH+\" crossorigin=\"anonymous\"></script>\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -836,7 +836,7 @@
|
|||
"bundle": "pplr-data-maps",
|
||||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"output": "dx-maps/pplr-data-maps/pplr-data-maps.js",
|
||||
"integrity": "sha384-0qPFDkM9YuvkCxJFO0gmN7h+4G/qEcohCqfS6m1pJdYCtwsr3GR1awDrg7zoszgt",
|
||||
"integrity": "sha384-vlRYtuZbl8uLUdt3BdNYUz40tJIOHtMquV6MvU9oJsWN4cz26mvqvmr5J9IR3Xpw",
|
||||
"elements": [
|
||||
"pplr-data-maps"
|
||||
],
|
||||
|
|
@ -852,7 +852,7 @@
|
|||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./pplr-data-maps/pplr-data-maps/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-0qPFDkM9YuvkCxJFO0gmN7h+4G/qEcohCqfS6m1pJdYCtwsr3GR1awDrg7zoszgt\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-vlRYtuZbl8uLUdt3BdNYUz40tJIOHtMquV6MvU9oJsWN4cz26mvqvmr5J9IR3Xpw\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
},
|
||||
"bundle": "pplr-data-maps"
|
||||
}
|
||||
|
|
@ -887,7 +887,7 @@
|
|||
"bundle": "regions-dashboard",
|
||||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"output": "dx-maps/regions-dashboard/regions-dashboard.js",
|
||||
"integrity": "sha384-B1eho+1j5yy1/4tRwAtrJrZ4wRP4G1++BhfjItpoHYUyPQSUDtb4Z2qgtJFmLEnC",
|
||||
"integrity": "sha384-SnDDRSZmhUwrpNq6xopiym+7UVsMBxZQak3RVTox7+sZjZkMhmNAHK7y7eTyhTM2",
|
||||
"elements": [
|
||||
"regions-dashboard"
|
||||
],
|
||||
|
|
@ -907,7 +907,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/region-dashboards/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-B1eho+1j5yy1/4tRwAtrJrZ4wRP4G1++BhfjItpoHYUyPQSUDtb4Z2qgtJFmLEnC\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-SnDDRSZmhUwrpNq6xopiym+7UVsMBxZQak3RVTox7+sZjZkMhmNAHK7y7eTyhTM2\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -921,7 +921,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/regions-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-B1eho+1j5yy1/4tRwAtrJrZ4wRP4G1++BhfjItpoHYUyPQSUDtb4Z2qgtJFmLEnC\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-SnDDRSZmhUwrpNq6xopiym+7UVsMBxZQak3RVTox7+sZjZkMhmNAHK7y7eTyhTM2\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -935,7 +935,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/regions-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-B1eho+1j5yy1/4tRwAtrJrZ4wRP4G1++BhfjItpoHYUyPQSUDtb4Z2qgtJFmLEnC\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-SnDDRSZmhUwrpNq6xopiym+7UVsMBxZQak3RVTox7+sZjZkMhmNAHK7y7eTyhTM2\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -944,7 +944,7 @@
|
|||
"bundle": "research-dashboard",
|
||||
"scriptUrl": "./research-dashboard/research-dashboard.js",
|
||||
"output": "dx-maps/research-dashboard/research-dashboard.js",
|
||||
"integrity": "sha384-vqWLWM1MWqQaUqBuo0H4sQLrwNo+rSpsQbtum4qX/c9uxWH0MrhikJjOH/iKKgzj",
|
||||
"integrity": "sha384-1gpwTWBMcmXFqeNMcuUOcke40VSJ0kgW8n73UlvoMw/p6ElHD6wsdzAW2/R4sR7h",
|
||||
"elements": [
|
||||
"research-dashboard-map"
|
||||
],
|
||||
|
|
@ -960,7 +960,7 @@
|
|||
"scriptUrl": "./research-dashboard/research-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./research-dashboard/research-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-vqWLWM1MWqQaUqBuo0H4sQLrwNo+rSpsQbtum4qX/c9uxWH0MrhikJjOH/iKKgzj\" crossorigin=\"anonymous\"></script>\n<research-dashboard-map profile-config='{\"profile\":\"research-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-dashboard-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-1gpwTWBMcmXFqeNMcuUOcke40VSJ0kgW8n73UlvoMw/p6ElHD6wsdzAW2/R4sR7h\" crossorigin=\"anonymous\"></script>\n<research-dashboard-map profile-config='{\"profile\":\"research-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-dashboard-map>"
|
||||
},
|
||||
"bundle": "research-dashboard"
|
||||
}
|
||||
|
|
@ -1058,7 +1058,7 @@
|
|||
"bundle": "upg-neighbor",
|
||||
"scriptUrl": "./upg-neighbor/upg-neighbor.js",
|
||||
"output": "dx-maps/upg-neighbor/upg-neighbor.js",
|
||||
"integrity": "sha384-icPClI8iMFVBMLoBuE86RBs56W/gkKMAhcu9MmTd16vNs5KtOmjBxZ/rByI5ZvvN",
|
||||
"integrity": "sha384-K4uV9mi/tmckBtGQUsQd7IPBRy29oh0P82BAYEvo3ZoH3ptAvh8EPBdvTCRy9XI4",
|
||||
"elements": [
|
||||
"upg-neighbor"
|
||||
],
|
||||
|
|
@ -1074,7 +1074,7 @@
|
|||
"scriptUrl": "./upg-neighbor/upg-neighbor.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./upg-neighbor/upg-neighbor/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./upg-neighbor/upg-neighbor.js\" integrity=\"sha384-icPClI8iMFVBMLoBuE86RBs56W/gkKMAhcu9MmTd16vNs5KtOmjBxZ/rByI5ZvvN\" crossorigin=\"anonymous\"></script>\n<upg-neighbor profile-config='{\"profile\":\"upg-neighbor\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></upg-neighbor>"
|
||||
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./upg-neighbor/upg-neighbor.js\" integrity=\"sha384-K4uV9mi/tmckBtGQUsQd7IPBRy29oh0P82BAYEvo3ZoH3ptAvh8EPBdvTCRy9XI4\" crossorigin=\"anonymous\"></script>\n<upg-neighbor profile-config='{\"profile\":\"upg-neighbor\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></upg-neighbor>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -1157,7 +1157,7 @@
|
|||
"bundle": "wall-of-people-groups",
|
||||
"scriptUrl": "./wall-of-people-groups/wall-of-people-groups.js",
|
||||
"output": "dx-maps/wall-of-people-groups/wall-of-people-groups.js",
|
||||
"integrity": "sha384-PNIwl+E2bUzXvCWSmBAlEHkr2RfaWc0ZxENwDhWO5J4X9pSuAEKEnr6UNK5Fjddj",
|
||||
"integrity": "sha384-DBf5SfneU3H95020XprfF9yJvywsVsS9Xd1oNP3xT1frhsLKMqz2M2fN3dXMPiUc",
|
||||
"elements": [
|
||||
"wall-of-people-groups"
|
||||
],
|
||||
|
|
@ -1173,7 +1173,7 @@
|
|||
"scriptUrl": "./wall-of-people-groups/wall-of-people-groups.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./wall-of-people-groups/wall-of-people-groups/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./wall-of-people-groups/wall-of-people-groups.js\" integrity=\"sha384-PNIwl+E2bUzXvCWSmBAlEHkr2RfaWc0ZxENwDhWO5J4X9pSuAEKEnr6UNK5Fjddj\" crossorigin=\"anonymous\"></script>\n<wall-of-people-groups profile-config='{\"profile\":\"wall-of-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></wall-of-people-groups>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./wall-of-people-groups/wall-of-people-groups.js\" integrity=\"sha384-DBf5SfneU3H95020XprfF9yJvywsVsS9Xd1oNP3xT1frhsLKMqz2M2fN3dXMPiUc\" crossorigin=\"anonymous\"></script>\n<wall-of-people-groups profile-config='{\"profile\":\"wall-of-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></wall-of-people-groups>"
|
||||
},
|
||||
"bundle": "wall-of-people-groups"
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
|
||||
<script src="../my-upg-100-list.js" integrity="sha384-KrU2osR+kR7m0xQSmpTJRg323lxffls7/R+rd5ZgkXZ3GK/kBPM2AcEHpGWcyRda" crossorigin="anonymous"></script>
|
||||
<script src="../my-upg-100-list.js" integrity="sha384-6Q5uVnqbJ6t3NYnOUlyDhG5O5I2q9Ob+fp5qf8qLufOE6DqTgnjZnSxOU6Z1ml/c" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
|
||||
<script src="../my-upg-100-list.js" integrity="sha384-KrU2osR+kR7m0xQSmpTJRg323lxffls7/R+rd5ZgkXZ3GK/kBPM2AcEHpGWcyRda" crossorigin="anonymous"></script>
|
||||
<script src="../my-upg-100-list.js" integrity="sha384-6Q5uVnqbJ6t3NYnOUlyDhG5O5I2q9Ob+fp5qf8qLufOE6DqTgnjZnSxOU6Z1ml/c" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
|
||||
<script src="../my-upg-100-list.js" integrity="sha384-KrU2osR+kR7m0xQSmpTJRg323lxffls7/R+rd5ZgkXZ3GK/kBPM2AcEHpGWcyRda" crossorigin="anonymous"></script>
|
||||
<script src="../my-upg-100-list.js" integrity="sha384-6Q5uVnqbJ6t3NYnOUlyDhG5O5I2q9Ob+fp5qf8qLufOE6DqTgnjZnSxOU6Z1ml/c" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <plugin-studio> custom element. -->
|
||||
<script src="../plugin-studio.js" integrity="sha384-D/d9f5Hw2BwzKeV9gZ60HGMJysRYEDxvJ9ZloOJKXVsCyh+kiVcRObaRxtAvIDCJ" crossorigin="anonymous"></script>
|
||||
<script src="../plugin-studio.js" integrity="sha384-Jc2znVVtfkv01BBMY6IpyHr/W2r1JtqflWXd/s8LWPfJ+Ge62BgIK2vUbmvtvZH+" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <plugin-studio> custom element. -->
|
||||
<script src="../../plugin-studio.js" integrity="sha384-D/d9f5Hw2BwzKeV9gZ60HGMJysRYEDxvJ9ZloOJKXVsCyh+kiVcRObaRxtAvIDCJ" crossorigin="anonymous"></script>
|
||||
<script src="../../plugin-studio.js" integrity="sha384-Jc2znVVtfkv01BBMY6IpyHr/W2r1JtqflWXd/s8LWPfJ+Ge62BgIK2vUbmvtvZH+" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <pplr-data-maps> custom element. -->
|
||||
<script src="../pplr-data-maps.js" integrity="sha384-0qPFDkM9YuvkCxJFO0gmN7h+4G/qEcohCqfS6m1pJdYCtwsr3GR1awDrg7zoszgt" crossorigin="anonymous"></script>
|
||||
<script src="../pplr-data-maps.js" integrity="sha384-vlRYtuZbl8uLUdt3BdNYUz40tJIOHtMquV6MvU9oJsWN4cz26mvqvmr5J9IR3Xpw" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
|
||||
<script src="../regions-dashboard.js" integrity="sha384-B1eho+1j5yy1/4tRwAtrJrZ4wRP4G1++BhfjItpoHYUyPQSUDtb4Z2qgtJFmLEnC" crossorigin="anonymous"></script>
|
||||
<script src="../regions-dashboard.js" integrity="sha384-SnDDRSZmhUwrpNq6xopiym+7UVsMBxZQak3RVTox7+sZjZkMhmNAHK7y7eTyhTM2" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
|
||||
<script src="../regions-dashboard.js" integrity="sha384-B1eho+1j5yy1/4tRwAtrJrZ4wRP4G1++BhfjItpoHYUyPQSUDtb4Z2qgtJFmLEnC" crossorigin="anonymous"></script>
|
||||
<script src="../regions-dashboard.js" integrity="sha384-SnDDRSZmhUwrpNq6xopiym+7UVsMBxZQak3RVTox7+sZjZkMhmNAHK7y7eTyhTM2" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <regions-dashboard> custom element. -->
|
||||
<script src="../regions-dashboard.js" integrity="sha384-B1eho+1j5yy1/4tRwAtrJrZ4wRP4G1++BhfjItpoHYUyPQSUDtb4Z2qgtJFmLEnC" crossorigin="anonymous"></script>
|
||||
<script src="../regions-dashboard.js" integrity="sha384-SnDDRSZmhUwrpNq6xopiym+7UVsMBxZQak3RVTox7+sZjZkMhmNAHK7y7eTyhTM2" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <research-dashboard-map> custom element. -->
|
||||
<script src="../research-dashboard.js" integrity="sha384-vqWLWM1MWqQaUqBuo0H4sQLrwNo+rSpsQbtum4qX/c9uxWH0MrhikJjOH/iKKgzj" crossorigin="anonymous"></script>
|
||||
<script src="../research-dashboard.js" integrity="sha384-1gpwTWBMcmXFqeNMcuUOcke40VSJ0kgW8n73UlvoMw/p6ElHD6wsdzAW2/R4sR7h" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <upg-neighbor> custom element. -->
|
||||
<script src="../../upg-neighbor.js" integrity="sha384-icPClI8iMFVBMLoBuE86RBs56W/gkKMAhcu9MmTd16vNs5KtOmjBxZ/rByI5ZvvN" crossorigin="anonymous"></script>
|
||||
<script src="../../upg-neighbor.js" integrity="sha384-K4uV9mi/tmckBtGQUsQd7IPBRy29oh0P82BAYEvo3ZoH3ptAvh8EPBdvTCRy9XI4" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <upg-neighbor> custom element. -->
|
||||
<script src="../../upg-neighbor.js" integrity="sha384-icPClI8iMFVBMLoBuE86RBs56W/gkKMAhcu9MmTd16vNs5KtOmjBxZ/rByI5ZvvN" crossorigin="anonymous"></script>
|
||||
<script src="../../upg-neighbor.js" integrity="sha384-K4uV9mi/tmckBtGQUsQd7IPBRy29oh0P82BAYEvo3ZoH3ptAvh8EPBdvTCRy9XI4" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <upg-neighbor> custom element. -->
|
||||
<script src="../upg-neighbor.js" integrity="sha384-icPClI8iMFVBMLoBuE86RBs56W/gkKMAhcu9MmTd16vNs5KtOmjBxZ/rByI5ZvvN" crossorigin="anonymous"></script>
|
||||
<script src="../upg-neighbor.js" integrity="sha384-K4uV9mi/tmckBtGQUsQd7IPBRy29oh0P82BAYEvo3ZoH3ptAvh8EPBdvTCRy9XI4" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <upg-neighbor> custom element. -->
|
||||
<script src="../../upg-neighbor.js" integrity="sha384-icPClI8iMFVBMLoBuE86RBs56W/gkKMAhcu9MmTd16vNs5KtOmjBxZ/rByI5ZvvN" crossorigin="anonymous"></script>
|
||||
<script src="../../upg-neighbor.js" integrity="sha384-K4uV9mi/tmckBtGQUsQd7IPBRy29oh0P82BAYEvo3ZoH3ptAvh8EPBdvTCRy9XI4" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <upg-neighbor> custom element. -->
|
||||
<script src="../../upg-neighbor.js" integrity="sha384-icPClI8iMFVBMLoBuE86RBs56W/gkKMAhcu9MmTd16vNs5KtOmjBxZ/rByI5ZvvN" crossorigin="anonymous"></script>
|
||||
<script src="../../upg-neighbor.js" integrity="sha384-K4uV9mi/tmckBtGQUsQd7IPBRy29oh0P82BAYEvo3ZoH3ptAvh8EPBdvTCRy9XI4" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <upg-neighbor> custom element. -->
|
||||
<script src="../../upg-neighbor.js" integrity="sha384-icPClI8iMFVBMLoBuE86RBs56W/gkKMAhcu9MmTd16vNs5KtOmjBxZ/rByI5ZvvN" crossorigin="anonymous"></script>
|
||||
<script src="../../upg-neighbor.js" integrity="sha384-K4uV9mi/tmckBtGQUsQd7IPBRy29oh0P82BAYEvo3ZoH3ptAvh8EPBdvTCRy9XI4" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <wall-of-people-groups> custom element. -->
|
||||
<script src="../wall-of-people-groups.js" integrity="sha384-PNIwl+E2bUzXvCWSmBAlEHkr2RfaWc0ZxENwDhWO5J4X9pSuAEKEnr6UNK5Fjddj" crossorigin="anonymous"></script>
|
||||
<script src="../wall-of-people-groups.js" integrity="sha384-DBf5SfneU3H95020XprfF9yJvywsVsS9Xd1oNP3xT1frhsLKMqz2M2fN3dXMPiUc" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
Loading…
Reference in a new issue