Search is TIERED: exact matches win outright, fuzzy is only the typo rescue
Some checks are pending
build-gate / build (push) Waiting to run

Driver: 'fuzzy search is too fuzzy -- Bhutan returns more results than
just the country, and there is no interoperability with the other
filters like selecting it as a place.' The first fuzzy pass was a
UNION (exact + every <=k-error neighbour), so the exact term Bhutan
counted 132 rows while Country=Bhutan counted 13 -- two controls
disagreeing about one place.

Now tiered, the conventional search contract: when a term has ANY
exact substring match, only exact matches return -- search agrees
with the facet (13 = 13). The k-errors pass runs solely when exact
yields zero (Bhutann -> 13, Banladesh -> Bangladesh). Applied in the
shared Fuse.search (grid) AND a filterRowsBySearch helper used by the
shell + all four panels (table, facet rail, charts rail, map), so
every surface computes the same tier.

Measured: Bhutan 132 -> 13 (grid 'Showing 13' agrees), Bhutann 13,
Banladesh rescued, gibberish 0, clear 2,107.
This commit is contained in:
doxa-maps-88655c70 2026-09-24 00:21:32 +00:00
parent 566ad4676e
commit 98cb50cc4b
21 changed files with 160 additions and 113 deletions

View file

@ -82,10 +82,25 @@ function approxIndices(haystack, needle, threshold) {
}
/**
* Low-level predicate shared with the dashboard's search matcher (useDashboardShell.js):
* does `text` match `term` under the DX-life Fuse contract (exact substring first, then
* k-errors fuzzy when term.length >= minMatchCharLength)? ONE matcher, every search surface.
* Low-level predicates shared with the dashboard's search matcher (useDashboardShell.js).
*
* ★ TIERED, NOT A UNION (Driver 2026-09-24: "fuzzy search is too fuzzy -- Bhutan returns more
* results than just the country, and there is no interoperability with the other filters like
* selecting it as a place"). The first fuzzy pass returned exact matches PLUS every <=k-error
* neighbour, so the EXACT term 'Bhutan' counted 132 rows while the Country filter counted 13 --
* two controls disagreeing about the same place. The conventional contract is tiered: when a
* term has exact matches, return ONLY those (search now agrees with the facet, 13 = 13); the
* k-errors pass exists solely as the ZERO-RESULT typo rescue ('Bhutann', 'Banladesh').
* Callers implement the tier over their row set: filter with exactMatches first, and only if
* that yields nothing, filter with fuzzyMatches.
*/
export function exactMatches(text, term) {
const raw = String(text ?? '')
const q = String(term ?? '').trim()
if (!q) return true
if (!raw) return false
return raw.toLowerCase().includes(q.toLowerCase())
}
export function fuzzyMatches(text, term, { threshold = 0.4, minMatchCharLength = 3 } = {}) {
const raw = String(text ?? '')
const q = String(term ?? '').trim()
@ -109,18 +124,30 @@ export default class Fuse {
if (!q) return this.list.map(item => ({ item, matches: [] }))
if (q.length < this.minMatchCharLength) return []
const exactOnly = this.threshold === 0
// TIER 1: exact substring across the whole list. If ANY item matches exactly, fuzzy never
// runs -- an exact term returns exactly the rows the equivalent facet filter selects
// (see the tiered-contract note on exactMatches above).
const exact = []
for (const item of this.list) {
const matches = []
for (const key of this.keys) {
const raw = getByPath(item, key)
if (typeof raw !== 'string' || !raw) continue
const indices = exactIndices(raw, q)
if (indices.length) matches.push({ key, indices })
}
if (matches.length) exact.push({ item, matches })
}
if (exact.length || exactOnly) return exact
// TIER 2: the zero-result typo rescue (k-errors edit distance).
const results = []
for (const item of this.list) {
const matches = []
for (const key of this.keys) {
const raw = getByPath(item, key)
if (typeof raw !== 'string' || !raw) continue
let indices = exactIndices(raw, q)
if (indices.length === 0 && !exactOnly) {
const fz = approxIndices(raw, q, this.threshold)
if (fz) indices = fz
}
if (indices.length) matches.push({ key, indices })
const fz = approxIndices(raw, q, this.threshold)
if (fz) matches.push({ key, indices: fz })
}
if (matches.length) results.push({ item, matches })
}

View file

@ -9,7 +9,7 @@
import { inject, computed, ref } from 'vue'
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
import { aggregate, buildDonut, buildBars, lbl, buildCountryRegionColors } from '../../composables/useDashboardAggregations.js'
import { buildSearchAccessors, makeSearchMatcher } from '../../composables/useDashboardShell.js'
import { buildSearchAccessors, makeSearchMatcher, filterRowsBySearch } from '../../composables/useDashboardShell.js'
/**
* ── THE RAIL'S TAB STRIP ──────────────────────────────────────────────────────────────────────
@ -55,7 +55,8 @@ function rowsExcluding(exclude) {
const keys = Object.keys(filterSet).filter((k) => !exclude.includes(k))
const hasText = !!(bus?.searchTerm?.value || '').trim()
if (!keys.length && !hasText) return rows
return rows.filter((r) => keys.every((k) => { const a = FACET_ACC[k]; return a ? a(r) === filterSet[k] : true }) && matchSearch(r))
const faceted = rows.filter((r) => keys.every((k) => { const a = FACET_ACC[k]; return a ? a(r) === filterSet[k] : true }))
return filterRowsBySearch(faceted, matchSearch)
}
// COUNTRY -> REGION hue (the Driver's "countries should match the colour of their regions").

View file

@ -13,7 +13,7 @@
*/
import { inject, ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
import { buildSearchAccessors, makeSearchMatcher } from '../../composables/useDashboardShell.js'
import { buildSearchAccessors, makeSearchMatcher, filterRowsBySearch } from '../../composables/useDashboardShell.js'
import { useCsvExport } from '../../composables/useCsvExport.js'
import { useTreeLegendLabels } from '../../composables/useTreeLegendLabels.js'
@ -104,7 +104,8 @@ const filtered = computed(() => {
const keys = Object.keys(filterSet)
const hasText = !!(bus?.searchTerm?.value || '').trim()
if (!keys.length && !hasText) return allRows.value
return allRows.value.filter((r) => keys.every((k) => matchFacet(r, k, filterSet[k])) && matchSearch(r))
const faceted = allRows.value.filter((r) => keys.every((k) => matchFacet(r, k, filterSet[k])))
return filterRowsBySearch(faceted, matchSearch)
})
/**

View file

@ -16,7 +16,7 @@
import { inject, ref, reactive, computed, onMounted } from 'vue'
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
import { aggregate, lbl } from '../../composables/useDashboardAggregations.js'
import { buildSearchAccessors, makeSearchMatcher } from '../../composables/useDashboardShell.js'
import { buildSearchAccessors, makeSearchMatcher, filterRowsBySearch } from '../../composables/useDashboardShell.js'
import { useTreeLegendColors } from '../../composables/useTreeLegendColors.js'
import { useTreeLegendLabels } from '../../composables/useTreeLegendLabels.js'
@ -58,7 +58,8 @@ function rowsExcluding(exclude) {
const keys = Object.keys(filterSet).filter((k) => !exclude.includes(k))
const hasText = !!(bus?.searchTerm?.value || '').trim()
if (!keys.length && !hasText) return rows
return rows.filter((r) => keys.every((k) => { const a = FACET_ACC[k]; return a ? a(r) === filterSet[k] : true }) && matchSearch(r))
const faceted = rows.filter((r) => keys.every((k) => { const a = FACET_ACC[k]; return a ? a(r) === filterSet[k] : true }))
return filterRowsBySearch(faceted, matchSearch)
}
// ── SECTION COLLAPSE STATE (BUG-DASHBOARD-BAND-GROWS-ENORMOUS-WITH-LIVE-DATA) ────────────────

View file

@ -22,7 +22,7 @@ import MapToolbar from '@map/components/map-controls/MapToolbar.vue'
import ZoomInButton from '@map/components/map-controls/ZoomInButton.vue'
import ZoomOutButton from '@map/components/map-controls/ZoomOutButton.vue'
import { lbl } from '../../composables/useDashboardAggregations.js'
import { buildSearchAccessors, makeSearchMatcher } from '../../composables/useDashboardShell.js'
import { buildSearchAccessors, makeSearchMatcher, filterRowsBySearch } from '../../composables/useDashboardShell.js'
// ── THE PRAYER COLOUR STRATEGY, REUSED NOT RE-DERIVED ──
// applyColor() returns the SAME 3-tier expression the prayer map paints with, keyed off the
// FULL_PRAYER_THRESHOLD that library/colors/prayer-progress.js owns. Importing it here means the
@ -50,7 +50,8 @@ const filteredRows = computed(() => {
const keys = Object.keys(filterSet)
const hasText = !!(bus?.searchTerm?.value || '').trim()
if (!keys.length && !hasText) return rows
return rows.filter((r) => keys.every((k) => { const a = FACET_ACC[k]; return a ? a(r) === filterSet[k] : true }) && matchSearch(r))
const faceted = rows.filter((r) => keys.every((k) => { const a = FACET_ACC[k]; return a ? a(r) === filterSet[k] : true }))
return filterRowsBySearch(faceted, matchSearch)
})
// Geo join is config-driven: geoFacet selects the facet whose `geoIso` accessor yields the ISO-3 join
// value (e.g. 'IND') for the choropleth, and whose `get` accessor yields the filter label (e.g. 'India').

View file

@ -23,7 +23,7 @@
* responsive switch, collapsible table dock, segmented mobile view, and the location.hash sync.
* Only the SOURCE of the per-dashboard constants changed: from hard-coded → config.
*/
import { fuzzyMatches } from '@map/components/search/fuzzy.js'
import { exactMatches, fuzzyMatches } from '@map/components/search/fuzzy.js'
import { provide, ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'
import { createSelectionBus } from './useSelectionBus.js'
import { useDashboardData } from './useDashboardData.js'
@ -67,15 +67,29 @@ export function makeSearchMatcher(bus, accessors) {
// silently lost that behaviour in the migration (measured: 'Bhutan' 13 rows, 'Bhutann' 0).
// It now delegates to the shared fuzzyMatches() in @map fuzzy.js -- the same matcher the
// grid's Fuse uses -- with the same DX-life options, so every search surface agrees.
return (row) => {
// Row-level predicates for the TIERED contract (see fuzzy.js exactMatches): the caller
// (filterRowsBySearch below) runs the exact tier over the whole row set first and falls back
// to the fuzzy tier only when exact yields nothing, so an exact term agrees with the facet.
const test = (row, pred) => {
const needle = (bus?.searchTerm?.value || '').trim()
if (!needle) return true
for (const acc of accessors) {
const v = acc(row)
if (v != null && fuzzyMatches(String(v), needle, { threshold: 0.4, minMatchCharLength: 3 })) return true
if (v != null && pred(String(v), needle, { threshold: 0.4, minMatchCharLength: 3 })) return true
}
return false
}
const matcher = (row) => test(row, fuzzyMatches)
matcher.exact = (row) => test(row, exactMatches)
matcher.active = () => !!(bus?.searchTerm?.value || '').trim()
return matcher
}
/** Apply the tiered search to a row set: exact tier first, fuzzy only as the typo rescue. */
export function filterRowsBySearch(rows, matcher) {
if (!matcher.active()) return rows
const exact = rows.filter(matcher.exact)
return exact.length ? exact : rows.filter(matcher)
}
/**
@ -248,9 +262,11 @@ export function useDashboardShell(config) {
const keys = Object.keys(bus.filterSet)
const hasText = !!(bus.searchTerm?.value || '').trim()
if (!keys.length && !hasText) return rows
return rows.filter((r) =>
keys.every((k) => { const a = FACET_ACC[k]; return a ? a(r) === bus.filterSet[k] : true }) && matchSearch(r)
)
const faceted = keys.length
? rows.filter((r) => keys.every((k) => { const a = FACET_ACC[k]; return a ? a(r) === bus.filterSet[k] : true }))
: rows
// Tiered search over the faceted scope: exact first, fuzzy only if exact finds nothing.
return filterRowsBySearch(faceted, matchSearch)
})
// linked KPI strip — recomputes on every brush.

File diff suppressed because one or more lines are too long

View file

@ -37,7 +37,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <bp-big-picture> custom element. -->
<script src="../../big-picture.js" integrity="sha384-MG/HIBfHvBjodOyOgVlzhgK5sZhEg2BI4DGPBc7yUmjGM9CDWI5JMvQh9nHRbJz4" crossorigin="anonymous"></script>
<script src="../../big-picture.js" integrity="sha384-LcTqxsi0hgbx7m3gsJQwpYSZkCHP1KDLkwUmBknrOBo6vvPxS10MhozDcVCdCwMG" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -37,7 +37,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <bp-big-picture> custom element. -->
<script src="../../big-picture.js" integrity="sha384-MG/HIBfHvBjodOyOgVlzhgK5sZhEg2BI4DGPBc7yUmjGM9CDWI5JMvQh9nHRbJz4" crossorigin="anonymous"></script>
<script src="../../big-picture.js" integrity="sha384-LcTqxsi0hgbx7m3gsJQwpYSZkCHP1KDLkwUmBknrOBo6vvPxS10MhozDcVCdCwMG" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -37,7 +37,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <bp-big-picture> custom element. -->
<script src="../big-picture.js" integrity="sha384-MG/HIBfHvBjodOyOgVlzhgK5sZhEg2BI4DGPBc7yUmjGM9CDWI5JMvQh9nHRbJz4" crossorigin="anonymous"></script>
<script src="../big-picture.js" integrity="sha384-LcTqxsi0hgbx7m3gsJQwpYSZkCHP1KDLkwUmBknrOBo6vvPxS10MhozDcVCdCwMG" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -40,7 +40,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-Cxz3IYNCaS4mySFmoH5wbVt8CKCDx6lmMDmgJcqPbj1g3vsZRDcoc2j7GsGCnrXZ" crossorigin="anonymous"></script>
<script src="../../dashboard-plus-grid.js" integrity="sha384-RwMGtLXZFtctic8xn5T2NZgovHMoiebxlDlXF6ywWqYIaei+Dr6Ujt+Zuf0HoS7X" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -40,7 +40,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-Cxz3IYNCaS4mySFmoH5wbVt8CKCDx6lmMDmgJcqPbj1g3vsZRDcoc2j7GsGCnrXZ" crossorigin="anonymous"></script>
<script src="../dashboard-plus-grid.js" integrity="sha384-RwMGtLXZFtctic8xn5T2NZgovHMoiebxlDlXF6ywWqYIaei+Dr6Ujt+Zuf0HoS7X" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -35,7 +35,7 @@
"bundle": "big-picture",
"scriptUrl": "./big-picture/big-picture.js",
"output": "doxa-maps/big-picture/big-picture.js",
"integrity": "sha384-MG/HIBfHvBjodOyOgVlzhgK5sZhEg2BI4DGPBc7yUmjGM9CDWI5JMvQh9nHRbJz4",
"integrity": "sha384-LcTqxsi0hgbx7m3gsJQwpYSZkCHP1KDLkwUmBknrOBo6vvPxS10MhozDcVCdCwMG",
"elements": [
"bp-big-picture",
"bp-research-header",
@ -57,7 +57,7 @@
"scriptUrl": "./big-picture/big-picture.js",
"embed": {
"iframe": "<iframe src=\"./big-picture/big-picture/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=\"./big-picture/big-picture.js\" integrity=\"sha384-MG/HIBfHvBjodOyOgVlzhgK5sZhEg2BI4DGPBc7yUmjGM9CDWI5JMvQh9nHRbJz4\" crossorigin=\"anonymous\"></script>\n<bp-big-picture profile-config='{\"profile\":\"big-picture\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></bp-big-picture>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./big-picture/big-picture.js\" integrity=\"sha384-LcTqxsi0hgbx7m3gsJQwpYSZkCHP1KDLkwUmBknrOBo6vvPxS10MhozDcVCdCwMG\" crossorigin=\"anonymous\"></script>\n<bp-big-picture profile-config='{\"profile\":\"big-picture\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></bp-big-picture>"
},
"instances": [
{
@ -193,7 +193,7 @@
"bundle": "dashboard-plus-grid",
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
"output": "doxa-maps/dashboard-plus-grid/dashboard-plus-grid.js",
"integrity": "sha384-Cxz3IYNCaS4mySFmoH5wbVt8CKCDx6lmMDmgJcqPbj1g3vsZRDcoc2j7GsGCnrXZ",
"integrity": "sha384-RwMGtLXZFtctic8xn5T2NZgovHMoiebxlDlXF6ywWqYIaei+Dr6Ujt+Zuf0HoS7X",
"elements": [
"dashboard-plus-grid"
],
@ -213,7 +213,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": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-Cxz3IYNCaS4mySFmoH5wbVt8CKCDx6lmMDmgJcqPbj1g3vsZRDcoc2j7GsGCnrXZ\" 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": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-RwMGtLXZFtctic8xn5T2NZgovHMoiebxlDlXF6ywWqYIaei+Dr6Ujt+Zuf0HoS7X\" 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": [
{
@ -680,7 +680,7 @@
"bundle": "people-groups-grid",
"scriptUrl": "./people-groups-grid/people-groups-grid.js",
"output": "doxa-maps/people-groups-grid/people-groups-grid.js",
"integrity": "sha384-SKWGRiLzac7kgXqwKmZ6zztgnwonaWQuelRXos+pToKjq9s7H1DgpKb/t+4zVsIq",
"integrity": "sha384-ktuMhVzpB05It1q3/X0mtY6H9bbjBSeamFjKx0BoQu1DuoNXNZBtDNs9itrbcHPG",
"elements": [
"people-groups-grid"
],
@ -696,7 +696,7 @@
"scriptUrl": "./people-groups-grid/people-groups-grid.js",
"embed": {
"iframe": "<iframe src=\"./people-groups-grid/people-groups-grid/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=\"./people-groups-grid/people-groups-grid.js\" integrity=\"sha384-SKWGRiLzac7kgXqwKmZ6zztgnwonaWQuelRXos+pToKjq9s7H1DgpKb/t+4zVsIq\" crossorigin=\"anonymous\"></script>\n<people-groups-grid profile-config='{\"profile\":\"people-groups-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></people-groups-grid>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./people-groups-grid/people-groups-grid.js\" integrity=\"sha384-ktuMhVzpB05It1q3/X0mtY6H9bbjBSeamFjKx0BoQu1DuoNXNZBtDNs9itrbcHPG\" crossorigin=\"anonymous\"></script>\n<people-groups-grid profile-config='{\"profile\":\"people-groups-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></people-groups-grid>"
},
"instances": [
{
@ -878,7 +878,7 @@
"bundle": "research-dashboard",
"scriptUrl": "./research-dashboard/research-dashboard.js",
"output": "doxa-maps/research-dashboard/research-dashboard.js",
"integrity": "sha384-DKCSj4V1+kZlJVOueTMVpDvbJEwExTr8HgLq+YiX+vMiaCmXRDsTfVdseKMRJ+Dw",
"integrity": "sha384-9/hF/6WuV7HVDQuZS1MbAOJCtvh+RsNVEcRoPBTbfTn8SUNYnW2A46OY8EXcznsO",
"elements": [
"research-dashboard-map"
],
@ -894,7 +894,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": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-DKCSj4V1+kZlJVOueTMVpDvbJEwExTr8HgLq+YiX+vMiaCmXRDsTfVdseKMRJ+Dw\" 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": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-9/hF/6WuV7HVDQuZS1MbAOJCtvh+RsNVEcRoPBTbfTn8SUNYnW2A46OY8EXcznsO\" 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"
}

File diff suppressed because one or more lines are too long

View file

@ -26,7 +26,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <people-groups-grid> custom element. -->
<script src="../../people-groups-grid.js" integrity="sha384-SKWGRiLzac7kgXqwKmZ6zztgnwonaWQuelRXos+pToKjq9s7H1DgpKb/t+4zVsIq" crossorigin="anonymous"></script>
<script src="../../people-groups-grid.js" integrity="sha384-ktuMhVzpB05It1q3/X0mtY6H9bbjBSeamFjKx0BoQu1DuoNXNZBtDNs9itrbcHPG" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -26,7 +26,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <people-groups-grid> custom element. -->
<script src="../people-groups-grid.js" integrity="sha384-SKWGRiLzac7kgXqwKmZ6zztgnwonaWQuelRXos+pToKjq9s7H1DgpKb/t+4zVsIq" crossorigin="anonymous"></script>
<script src="../people-groups-grid.js" integrity="sha384-ktuMhVzpB05It1q3/X0mtY6H9bbjBSeamFjKx0BoQu1DuoNXNZBtDNs9itrbcHPG" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -26,7 +26,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <people-groups-grid> custom element. -->
<script src="../../people-groups-grid.js" integrity="sha384-SKWGRiLzac7kgXqwKmZ6zztgnwonaWQuelRXos+pToKjq9s7H1DgpKb/t+4zVsIq" crossorigin="anonymous"></script>
<script src="../../people-groups-grid.js" integrity="sha384-ktuMhVzpB05It1q3/X0mtY6H9bbjBSeamFjKx0BoQu1DuoNXNZBtDNs9itrbcHPG" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -29,7 +29,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-DKCSj4V1+kZlJVOueTMVpDvbJEwExTr8HgLq+YiX+vMiaCmXRDsTfVdseKMRJ+Dw" crossorigin="anonymous"></script>
<script src="../research-dashboard.js" integrity="sha384-9/hF/6WuV7HVDQuZS1MbAOJCtvh+RsNVEcRoPBTbfTn8SUNYnW2A46OY8EXcznsO" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order: