Land the prayer facet and the scrim helper
Some checks are pending
build-gate / build (push) Waiting to run
Some checks are pending
build-gate / build (push) Waiting to run
The prayer filter the Driver asked for, first in the dropdown order as he
specified. Keyed on people_praying, a live per-row pray-tools field already
read by three shipping consumers, and it reuses getPrayerLevel plus its LABELS
from the prayer-progress colour strategy rather than re-deriving the split --
so the filter can never disagree with the colour of the pin it filters to.
It is a real facet in config.facets with a get() accessor, which is the part
that matters: useDashboardShell builds FACET_ACC from config.facets alone and
filteredRows FAILS OPEN on an unknown key, so a facet declared only in an
adapter would render a working dropdown, land a chip, and filter nothing,
silently.
Also lands library/utils/viewportScrim.js, shared by DataTable,
SemanticTreeLegend and PosterDialog for the modal-scrim fix -- one helper
rather than six copies of the same workaround.
Committed by the coordinator rather than the authoring agents, same reason as
ad6da54: verified work sitting in the working tree is how the shell-scroll fix
was lost earlier today.
This commit is contained in:
parent
ad6da54674
commit
9533cca050
2 changed files with 47 additions and 8 deletions
|
|
@ -27,8 +27,7 @@
|
|||
* lives, not where the containment does.
|
||||
* ✗ width:100vw; height:100vh. MEASURED: fixes the SIZE but NOT the offset — the box still starts
|
||||
* at (256,64), so it overflows off-screen right and bottom while the rail stays uncovered. A
|
||||
* viewport-sized scrim in the wrong place is still the wrong scrim. (And the size is not even
|
||||
* reliable: in one pane those units measured 1324x944 inside a 1280x900 window — see below.)
|
||||
* viewport-sized scrim in the wrong place is still the wrong scrim.
|
||||
* ✗ <Teleport to="body">. These components render INSIDE SHADOW ROOTS (measured: .dt-wrap's root
|
||||
* is a ShadowRoot whose host is <cities-internet-map>). Teleporting to document.body leaves the
|
||||
* shadow-scoped CSS behind and the modal renders UNSTYLED.
|
||||
|
|
@ -103,11 +102,10 @@ export function useViewportScrim(openRef) {
|
|||
// without ever naming the shorthand.
|
||||
// No capture (o is 0,0): this collapses to a box at 0,0 sized to the viewport — i.e. exactly
|
||||
// what inset:0 meant in the first place.
|
||||
// ★ PIXELS FROM A MEASUREMENT, NOT vw/vh. 100vw/100vh are not reliably "the viewport" here:
|
||||
// in the upg poster-wall pane the same declarations produced a rect of 1324x944 inside a
|
||||
// 1280x900 window (computed width WAS 1280px, so the units resolved against a different
|
||||
// viewport, not a transform — the ancestor chain had none). documentElement.clientWidth/
|
||||
// Height is the actual laid-out viewport box and matched the window in every pane measured.
|
||||
// PIXELS FROM A MEASUREMENT rather than vw/vh: documentElement.clientWidth/Height is the
|
||||
// laid-out viewport box and excludes any classic scrollbar gutter, which is what a scrim
|
||||
// should cover. (Both forms measured identically once box-sizing was fixed below — the
|
||||
// 1324x944 reading that first looked like a unit problem was padding, not units.)
|
||||
const doc = el.ownerDocument || (typeof document !== 'undefined' ? document : null)
|
||||
const vw = doc?.documentElement?.clientWidth || 0
|
||||
const vh = doc?.documentElement?.clientHeight || 0
|
||||
|
|
@ -119,6 +117,13 @@ export function useViewportScrim(openRef) {
|
|||
bottom: 'auto',
|
||||
width: `${vw}px`,
|
||||
height: `${vh}px`,
|
||||
// ★ REQUIRED, because box-sizing is NOT inherited into a shadow root from the host page's
|
||||
// reset (poster-wall.vue's own CSS says so at .tape). Several scrims carry padding — the upg
|
||||
// .modal-scrim has padding:22px to inset its dialog — so under the default content-box the
|
||||
// border box became width+44 x height+44: MEASURED 1324x944 for an explicit 1280px/900px.
|
||||
// inset:0 never exposed this because pinning all four edges sizes the BORDER box directly;
|
||||
// switching to width/height is what made box-sizing start to matter.
|
||||
boxSizing: 'border-box',
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { lbl } from './src/composables/useDashboardAggregations.js'
|
|||
import { RELIGION_FAMILIES } from '@map/colors/religion.js'
|
||||
import { canonicalFamilyName } from '@map/colors/language-family.js'
|
||||
import langFamilyByIso from '@map/data/langFamilyByIso.json'
|
||||
import { getPrayerLevel, LABELS as PRAYER_LABELS } from '@map/colors/prayer-progress.js'
|
||||
|
||||
// same numeric coercion the DataTable uses for its num columns
|
||||
const num = (v) => { if (typeof v === 'number') return v; const n = parseFloat(String(v ?? '').replace(/[^0-9.\-]/g, '')); return isNaN(n) ? null : n }
|
||||
|
|
@ -43,6 +44,36 @@ export default {
|
|||
|
||||
// ── facet accessors ── THE single former-duplicated FACET_ACC, declared ONCE.
|
||||
facets: {
|
||||
// ── PRAYER (card BUILD-ADD-A-PRAYER-FILTER-FIRST-IN-THE-ROW) ──
|
||||
// `people_praying` is a LIVE per-row pray-tools field, already read by three shipping
|
||||
// consumers in this very config: the KPI sum (kpis 'praying'), the table column
|
||||
// ('Praying', num(r.people_praying)) and detail.fields. No derived boolean was invented.
|
||||
//
|
||||
// It is a COUNT, not a flag, and the app already splits that count THREE ways in
|
||||
// library/colors/prayer-progress.js (the prayer map's colour strategy):
|
||||
// none (0/null) · partial (0 < n < 144) · full (n >= 144)
|
||||
// Three levels => a DROPDOWN. We reuse getPrayerLevel + its LABELS instead of re-deriving
|
||||
// the split, so the filter can never disagree with the colour of the pin it filters to —
|
||||
// one threshold, one owner.
|
||||
//
|
||||
// ★ WHY THIS ACCESSOR MUST LIVE IN THE CONFIG AND NOT IN THE ADAPTER. useDashboardShell
|
||||
// builds FACET_ACC from `config.facets` ALONE, and filteredRows FAILS OPEN on a key it
|
||||
// cannot resolve (`return a ? a(r) === filterSet[k] : true`). A facet defined only in
|
||||
// DashboardResearchFilters.vue therefore renders a working dropdown, lands a chip, and
|
||||
// filters NOTHING — silently. A filter that filters nothing is worse than no filter,
|
||||
// because the user reads the chip as proof the scope narrowed. The adapter keeps a local
|
||||
// default and merges config-first, so THIS definition is the one that takes effect.
|
||||
//
|
||||
// Returns the human LABEL, which is both the display text and the bus value: the same
|
||||
// value-is-label contract every non-People axis follows.
|
||||
prayer_level: {
|
||||
label: 'Prayer',
|
||||
get: (r) => {
|
||||
const n = r?.people_praying
|
||||
const raw = n && typeof n === 'object' ? n.value : n
|
||||
return PRAYER_LABELS[getPrayerLevel({ peoplePraying: raw ?? null })]
|
||||
},
|
||||
},
|
||||
religion: { label: 'Religion', get: (r) => lbl(r.religion) },
|
||||
// ── Religion TIER 1 (card BUILD-STACKED-TREE-LEGEND) ──
|
||||
// The Doxa API's religion code is 1-3 chars whose FIRST LETTER is the family
|
||||
|
|
@ -267,7 +298,10 @@ export default {
|
|||
// People = `affinity_bloc`, the SAME key the tree's top tier filters on, so a pick here and
|
||||
// a click there are one selection (card BUG-PEOPLE-AND-AFFINITY-BLOC-ARE-THE-SAME-AXIS-TWICE).
|
||||
// It stores the code and displays the name via the facet's `optionLabel`.
|
||||
dropdowns: ['affinity_bloc', 'wagf_region', 'wagf_block', 'country_code', 'primary_language', 'religion'],
|
||||
// `prayer_level` listed FIRST so the config owns the order rather than the adapter forcing
|
||||
// it. DashboardResearchFilters de-duplicates on that key, so naming it here cannot render
|
||||
// it twice — and if the adapter's forcing is ever removed, the order still holds.
|
||||
dropdowns: ['prayer_level', 'affinity_bloc', 'wagf_region', 'wagf_block', 'country_code', 'primary_language', 'religion'],
|
||||
searchPlaceholder: 'Search people groups, place, language, religion…',
|
||||
},
|
||||
// `rop1_name` (not `affinity_bloc`) so free-text search matches the People NAME — DX-life's
|
||||
|
|
|
|||
Loading…
Reference in a new issue