Regions: their second filters panel was missing, and it carries two of their bugs
The expanded filters panel was the largest interactive surface never compared to theirs, and comparing it found a whole panel absent. Measured on their live country page: TWO .filters__panel blocks and THREE .filter-toggle buttons — Adopted, Engaged, Exact Search — against our one panel and zero toggles. The dropdowns already matched exactly, four of them, with their country dropdown correctly hidden by lockCountryCode. A tell I had missed: the search already read active.exact for the Fuse threshold, so Exact Search's BEHAVIOUR was ported while the control that sets it never was. Ported their panel, their three toggles, their toggle semantics (a second click removes the filter), their activeFilters shape so each toggle also renders as a chip, and .filter-toggle styled from the MEASURED computed values of their live button rather than by chasing tokens. The labels needed no new keys — Adopted and Engaged were already translated in all eight locales. Two of their bugs are cloned deliberately, both measured on their live /regions/india at 855 rows: - ENGAGED RETURNS ZERO. Their branch filters on u.people_praying, and people_praying is not in the field list they request — they fetch people_committed. The field is always undefined, so the filter matches nothing: their page goes 855 to 0. Reading people_committed instead would make us differ, and the ruling is that what exists on DX-life must match. The upstream fix is one word in their file. - THE ACTIVE STATE IS WHITE ON WHITE. Their rule sets background-color var(--color-surface-brand-lighter, rgba(0,80,160,0.05)) with color var(--color-white), and --color-surface-brand-lighter is not defined in their token files. Their active button computes background rgb(255,255,255) and color rgb(255,255,255) — an invisible label, now visible in our screenshot too. Defining that one token upstream fixes both sides. Both are flagged for the Driver rather than quietly corrected: a bar chart was already removed under this ruling for the opposite reason, being in ours and not theirs. Proof: _probe-filter-toggles.mjs, all assertions pass — two panels, three toggles, nine measured style properties, Adopted narrowing 24 to 2 and appearing as a chip, a second click restoring, Engaged emptying to 0 exactly as theirs does, Exact Search changing nothing alone. Regression: 22 suites green.
This commit is contained in:
parent
81cb8ad235
commit
a32097751b
7 changed files with 131 additions and 60 deletions
|
|
@ -86,6 +86,8 @@ const T = computed(() => ({
|
|||
total: t('Total'),
|
||||
alternate_name: t('Alternate Names'),
|
||||
exact_filter: t('Exact Search'),
|
||||
adopted_filter: t('Adopted'),
|
||||
engaged_filter: t('Engaged'),
|
||||
}))
|
||||
|
||||
const rows = ref([])
|
||||
|
|
@ -95,7 +97,11 @@ const searchTerm = ref('')
|
|||
const filtersExpanded = ref(false)
|
||||
const shown = ref(props.perPage)
|
||||
// Their filter set, minus `country` — a locked country hides that one (their own rule).
|
||||
const active = ref({ wagf_region: null, wagf_block: null, rop1: null, religion: null })
|
||||
// adopted / engaged / exact live in the SAME activeFilters object theirs uses, not a separate
|
||||
// flag set, because their applyDropdownFilters() iterates that object and branches on the
|
||||
// field name — and their chips row renders whatever is in it, toggles included.
|
||||
const active = ref({ wagf_region: null, wagf_block: null, rop1: null, religion: null,
|
||||
adopted: null, engaged: null, exact: null })
|
||||
|
||||
const label = (f) => (f && typeof f === 'object' ? f.label : f) || ''
|
||||
const value = (f) => (f && typeof f === 'object' ? f.value : f) || ''
|
||||
|
|
@ -166,7 +172,22 @@ const byPath = (o, path) => path.split('.').reduce((a, k) => (a == null ? undefi
|
|||
// Their dropdown filters AND first, then the term. (Their filterUUPGs, same order.)
|
||||
const preFiltered = computed(() => rows.value.filter((p) => {
|
||||
for (const [k, v] of Object.entries(active.value)) {
|
||||
if (v && value(p[k]) !== v.value) return false
|
||||
if (!v) continue
|
||||
// THEIR applyDropdownFilters branches, verbatim (UupgsList.vue:190-205).
|
||||
if (k === 'adopted') { if (!((p.adopted_by_churches ?? 0) > 0)) return false; continue }
|
||||
// ★ THEIR BUG, CLONED ON PURPOSE. Their branch is
|
||||
// filtered.filter(u => (u.people_praying ?? 0) > 0)
|
||||
// and `people_praying` is NOT in the field list they request — they fetch
|
||||
// people_committed. So the field is always undefined and the filter matches nothing.
|
||||
// MEASURED on their live /regions/india: 855 rows before, 0 after clicking Engaged.
|
||||
// The scope ruling is "it exists on DX-life and must MATCH", so this reproduces their
|
||||
// result rather than quietly correcting it. Reading people_committed instead would make
|
||||
// us DIFFER. Flagged for the Driver: the upstream fix is one word, in their file.
|
||||
if (k === 'engaged') { if (!((p.people_praying ?? 0) > 0)) return false; continue }
|
||||
// Their `exact` branch is `filtered = filtered` — a no-op here. It only changes the FUSE
|
||||
// threshold once a search term exists, which is where we already read active.exact.
|
||||
if (k === 'exact') continue
|
||||
if (value(p[k]) !== v.value) return false
|
||||
}
|
||||
return true
|
||||
}))
|
||||
|
|
@ -244,6 +265,12 @@ const showMore = computed(() => filtered.value.length > shown.value)
|
|||
function loadMore() { shown.value += (props.morePerPage || props.perPage) }
|
||||
watch([searchTerm, active], () => { shown.value = props.perPage }, { deep: true })
|
||||
|
||||
// Their toggleAdopted / toggleEngaged / toggleExact (UupgsList.vue:169-188): a second click
|
||||
// REMOVES the filter, and each sets a {value:'yes', label} pair so it also appears as a chip.
|
||||
function toggleFlag(name, label) {
|
||||
active.value = { ...active.value, [name]: active.value[name] ? null : { value: 'yes', label } }
|
||||
}
|
||||
|
||||
function onFilterChange(e) { if (e && e.name) active.value = { ...active.value, [e.name]: { value: e.value, label: e.label } } }
|
||||
function onFilterClear(e) { if (e && e.name) active.value = { ...active.value, [e.name]: null } }
|
||||
function clearAll() { active.value = { wagf_region: null, wagf_block: null, rop1: null, religion: null } }
|
||||
|
|
@ -289,6 +316,25 @@ useShadowStyles(
|
|||
' display:inline-flex; align-items:center; gap:7.5188px; margin-inline:auto; color:var(--dx-text); }' +
|
||||
'.filters__toggle svg{ transition:transform 200ms ease; }' +
|
||||
'.filters__toggle[aria-expanded="true"] svg{ transform:rotate(180deg); }' +
|
||||
// .filter-toggle — their _filters.scss:218 composed with .input and .fit-content, taken
|
||||
// from the MEASURED computed style of their live button rather than by chasing tokens:
|
||||
// padding 5.65323px 13.3px, font-size 15.625px, radius 8px, 1px solid rgb(128,128,128),
|
||||
// white ground, ink rgb(42,51,42), width fit-content, and a 150ms border/background
|
||||
// transition.
|
||||
'.filter-toggle{ padding:5.65323px 13.3px; cursor:pointer; font:inherit;' +
|
||||
' font-size:15.625px; color:#2a332a; border:1px solid rgb(128,128,128); border-radius:8px;' +
|
||||
' background-color:#fff; width:fit-content;' +
|
||||
' transition:border-color 150ms ease, background-color 150ms ease; }' +
|
||||
'.filter-toggle:hover{ border-color:#92b195; }' +
|
||||
// ★ THEIR ACTIVE STATE IS WHITE-ON-WHITE, CLONED ON PURPOSE. Their rule is
|
||||
// background-color: var(--color-surface-brand-lighter, rgba(0,80,160,0.05));
|
||||
// color: var(--color-white);
|
||||
// and --color-surface-brand-lighter is NOT DEFINED in their token files, so the 5%-alpha
|
||||
// fallback lands on white while the ink turns white. MEASURED on their live page: the
|
||||
// active button computes backgroundColor rgb(255,255,255) and color rgb(255,255,255) —
|
||||
// an invisible label. Reproduced so the clone matches; flagged for the Driver, because
|
||||
// defining that one token upstream fixes it for them and for us at once.
|
||||
'.filter-toggle[data-active]{ background-color:rgba(0, 80, 160, 0.05); color:#fff; }' +
|
||||
'.filters__panel{ display:flex; flex-wrap:wrap; gap:13.3px; justify-content:center;' +
|
||||
' align-items:flex-start; }' +
|
||||
'.filters__active{ display:flex; flex-wrap:wrap; gap:7.5188px; align-items:center;' +
|
||||
|
|
@ -409,6 +455,31 @@ useShadowStyles(
|
|||
/>
|
||||
</div>
|
||||
|
||||
<!-- THEIR SECOND PANEL (UupgsList.vue:541-560). We shipped only the dropdown panel, so
|
||||
three of their filter controls were simply absent — measured on their live country
|
||||
page: two .filters__panel blocks and three .filter-toggle buttons against our one
|
||||
and zero. -->
|
||||
<div v-if="filtersExpanded" class="filters__panel">
|
||||
<button
|
||||
type="button"
|
||||
class="filter-toggle"
|
||||
:data-active="active.adopted ? '' : undefined"
|
||||
@click="toggleFlag('adopted', T.adopted_filter)"
|
||||
>{{ T.adopted_filter }}</button>
|
||||
<button
|
||||
type="button"
|
||||
class="filter-toggle"
|
||||
:data-active="active.engaged ? '' : undefined"
|
||||
@click="toggleFlag('engaged', T.engaged_filter)"
|
||||
>{{ T.engaged_filter }}</button>
|
||||
<button
|
||||
type="button"
|
||||
class="filter-toggle"
|
||||
:data-active="active.exact ? '' : undefined"
|
||||
@click="toggleFlag('exact', T.exact_filter)"
|
||||
>{{ T.exact_filter }}</button>
|
||||
</div>
|
||||
|
||||
<div v-if="activeChips.length" class="filters__active">
|
||||
<span v-for="c in activeChips" :key="c.name" class="filter-chip">
|
||||
{{ c.label }}
|
||||
|
|
|
|||
2
public/doxa-maps/index.html
generated
2
public/doxa-maps/index.html
generated
File diff suppressed because one or more lines are too long
8
public/doxa-maps/manifest.json
generated
8
public/doxa-maps/manifest.json
generated
|
|
@ -856,7 +856,7 @@
|
|||
"bundle": "regions-dashboard",
|
||||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"output": "doxa-maps/regions-dashboard/regions-dashboard.js",
|
||||
"integrity": "sha384-f2Bf2Le3VRKjVFXcXhuRzEpHcuIXiCQDY2MSdKQG/ZKsRP2+a7I2/82myqQQb6aa",
|
||||
"integrity": "sha384-/0xJsdPMt2izpGpElmMftHWA/ckwtU/VwVbrUrXMaSPeZ0EK86HfggXZmp/vHtGi",
|
||||
"elements": [
|
||||
"regions-dashboard"
|
||||
],
|
||||
|
|
@ -876,7 +876,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": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-f2Bf2Le3VRKjVFXcXhuRzEpHcuIXiCQDY2MSdKQG/ZKsRP2+a7I2/82myqQQb6aa\" 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": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-/0xJsdPMt2izpGpElmMftHWA/ckwtU/VwVbrUrXMaSPeZ0EK86HfggXZmp/vHtGi\" 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>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -890,7 +890,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-f2Bf2Le3VRKjVFXcXhuRzEpHcuIXiCQDY2MSdKQG/ZKsRP2+a7I2/82myqQQb6aa\" 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-/0xJsdPMt2izpGpElmMftHWA/ckwtU/VwVbrUrXMaSPeZ0EK86HfggXZmp/vHtGi\" 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>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -904,7 +904,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": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-f2Bf2Le3VRKjVFXcXhuRzEpHcuIXiCQDY2MSdKQG/ZKsRP2+a7I2/82myqQQb6aa\" 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": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-/0xJsdPMt2izpGpElmMftHWA/ckwtU/VwVbrUrXMaSPeZ0EK86HfggXZmp/vHtGi\" 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>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -29,7 +29,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-f2Bf2Le3VRKjVFXcXhuRzEpHcuIXiCQDY2MSdKQG/ZKsRP2+a7I2/82myqQQb6aa" crossorigin="anonymous"></script>
|
||||
<script src="../regions-dashboard.js" integrity="sha384-/0xJsdPMt2izpGpElmMftHWA/ckwtU/VwVbrUrXMaSPeZ0EK86HfggXZmp/vHtGi" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
100
public/doxa-maps/regions-dashboard/regions-dashboard.js
generated
100
public/doxa-maps/regions-dashboard/regions-dashboard.js
generated
File diff suppressed because one or more lines are too long
|
|
@ -29,7 +29,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-f2Bf2Le3VRKjVFXcXhuRzEpHcuIXiCQDY2MSdKQG/ZKsRP2+a7I2/82myqQQb6aa" crossorigin="anonymous"></script>
|
||||
<script src="../regions-dashboard.js" integrity="sha384-/0xJsdPMt2izpGpElmMftHWA/ckwtU/VwVbrUrXMaSPeZ0EK86HfggXZmp/vHtGi" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -40,7 +40,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-f2Bf2Le3VRKjVFXcXhuRzEpHcuIXiCQDY2MSdKQG/ZKsRP2+a7I2/82myqQQb6aa" crossorigin="anonymous"></script>
|
||||
<script src="../regions-dashboard.js" integrity="sha384-/0xJsdPMt2izpGpElmMftHWA/ckwtU/VwVbrUrXMaSPeZ0EK86HfggXZmp/vHtGi" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
Loading…
Reference in a new issue