Research dashboard Language section buckets every row by derived language family

- 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)
This commit is contained in:
swift-river542 2026-09-16 19:49:32 -05:00
parent a0d94c249a
commit 92b5559bc7
2 changed files with 11 additions and 1 deletions

View file

@ -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.

View file

@ -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.