From 92b5559bc7880bea4fb695ab667ea81b2df6bcad Mon Sep 17 00:00:00 2001 From: swift-river542 Date: Wed, 16 Sep 2026 19:49:32 -0500 Subject: [PATCH] Research dashboard Language section buckets every row by derived language family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The API fills imb_language_family for 34 of 2,107 rows, so the Language Family facet listed 11 thin families and skipped the other 2,073 rows - The facet accessor now resolves the family the way the research map's legend does: useLanguageFamilyLegendData exports readLanguageFamily (API family when present, else derived from the primary-language label) and dashboard.config.js feeds it the raw row's imb_language_family + primary_language. Counts and the row-click filter share the accessor, so a family row narrows every linked panel - Gate (Firefox, dev playground, 2,107 rows): Language section 11 → 30 family rows, all with counts > 0 (Indo-European 677, Dravidian 306, Afro-Asiatic 222, Sino-Tibetan 151, Niger-Congo 146 …); clicking Indo-European narrows table and KPI to 677, clicking again restores 2,107. The map's legend is untouched (export only) --- app-profiles/research-dashboard/dashboard.config.js | 7 ++++++- library/composables/legends/useLanguageFamilyLegendData.js | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app-profiles/research-dashboard/dashboard.config.js b/app-profiles/research-dashboard/dashboard.config.js index b9279c8bf..961029559 100644 --- a/app-profiles/research-dashboard/dashboard.config.js +++ b/app-profiles/research-dashboard/dashboard.config.js @@ -9,6 +9,7 @@ * migrated bundle behaves identically. */ import { lbl } from './src/composables/useDashboardAggregations.js' +import { readLanguageFamily } from '@map/composables/legends/useLanguageFamilyLegendData.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 } @@ -41,7 +42,11 @@ export default { wagf_block: { label: 'Block', get: (r) => lbl(r.wagf_block) }, country_code: { label: 'Country', get: (r) => lbl(r.country_code), geoIso: (r) => r.country_code && r.country_code.value }, engagement_status: { label: 'Status', get: (r) => lbl(r.engagement_status) }, - language_family: { label: 'Language Family', get: (r) => lbl(r.imb_language_family) }, + // The API fills imb_language_family for only a few dozen rows, so the family is resolved + // the way the research map's legend buckets it: the API family when present, else derived + // from the primary-language label. The same accessor drives the counts and the row-click + // filter, so a family row narrows every linked panel. + language_family: { label: 'Language Family', get: (r) => readLanguageFamily({ languageFamily: r.imb_language_family, primary_language: r.primary_language }) }, primary_language: { label: 'Language', get: (r) => lbl(r.primary_language) }, // People tier accessors — key by CODE (DashboardFacetRail resolves code→human name via // useAffinityBlockLegendData). Mirrors research-map's affinity-block → cluster → PG hierarchy. diff --git a/library/composables/legends/useLanguageFamilyLegendData.js b/library/composables/legends/useLanguageFamilyLegendData.js index e75a67b08..68968dcc5 100644 --- a/library/composables/legends/useLanguageFamilyLegendData.js +++ b/library/composables/legends/useLanguageFamilyLegendData.js @@ -132,6 +132,11 @@ function readFamily(p) { } return 'Unknown' } +// Per-row family accessor for surfaces that aggregate RAW API rows (the research +// dashboard's facet rail). Same precedence as the legend buckets above: the API +// family when present, else derived from the primary-language label. Feed it +// { languageFamily, primary_language } (or any shape readFamily reads). +export const readLanguageFamily = readFamily function readLanguage(p) { // Read from _raw first (returns original API comma-inverted label like "Arabic, Sudanese"). // p.language may have been overwritten to the unwrapped value form by useMapData.