UPG-100 batch selection: an India state or union territory now finds its people groups, from the served states table (fetched only once a state is selected, warmed on selection); China's provinces stay named as missing until they have a table. The gate asserts the wiring

This commit is contained in:
Doxa Maps 2026-09-30 21:33:43 +00:00
parent 39ded339fa
commit ba8dfad628
2 changed files with 21 additions and 3 deletions

View file

@ -123,9 +123,12 @@ const wired = {
'the Export CSV button': /@click="exportSelectionCsv">/.test(vue) && vue.includes("t('upgMap.exportCsv')"),
'the prefetch on batch mode': /if \(next\) selectionRecordsLoad\(\)/.test(vue),
'one detection for every action': (vue.match(/await selectionPeople\(\)/g) || []).length >= 2 && /selectionPeople\(\)\.then/.test(vue),
// India's states resolve through the served table (library/data/indiaStates.js), fetched only once a state is selected
'India states detected from the served table': /import \{ loadIndiaStates \} from '@map\/data\/indiaStates\.js'/.test(vue)
&& /india\.byShapeName\.get\(t\.name\)/.test(vue) && /t\.kind === 'adm1'\) indiaStates\(\)\.catch/.test(vue),
}
const missingWires = Object.entries(wired).filter(([, v]) => !v).map(([k]) => k)
ok(!missingWires.length, `the HUD is missing: ${missingWires.join(', ')}`, 'the HUD wires the swatches, hex input, Copy, Export CSV, and the prefetch')
ok(!missingWires.length, `the HUD is missing: ${missingWires.join(', ')}`, 'the HUD wires the swatches, hex input, Copy, Export CSV, the prefetch, and India\'s states from the served table')
// ── D. the strings, ×11 ──────────────────────────────────────────────────────────────────────────
const LANGS = ['en', 'es', 'fr', 'pt', 'de', 'it', 'ro', 'ru', 'ar', 'hi', 'zh']

View file

@ -284,6 +284,7 @@ function toggleTerritory(t) {
const idx = list.findIndex((x) => x.key === t.key)
if (idx >= 0) selectedTerritories.value = list.filter((_, i) => i !== idx) // toggle OFF
else selectedTerritories.value = [...list, t] // toggle ON
if (idx < 0 && t.kind === 'adm1') indiaStates().catch(() => {}) // warm India's table for Copy / CSV
refreshSelectionPaint()
copyFlash.value = ''
}
@ -498,6 +499,7 @@ import { useShadowStyles } from '@map/composables/useShadowStyles.js'
// non-useMapInstance profiles like this one can use it).
import { useEdgeScrollAffordance } from '@map/composables/useEdgeScrollAffordance.js'
import { resolveAssetsBase } from '@map/utils/embedBase.js'
import { loadIndiaStates } from '@map/data/indiaStates.js'
// Reads a GeoJSON source's features WITHOUT touching the engine-private _data, whose shape differs
// between MapLibre and Mapbox (see openPgDetail).
import { readSourceFeatures } from '@map/maps/pin-selection.js'
@ -1840,11 +1842,21 @@ function selectionRecordsLoad() {
// { records, from: Map(slug → the selected territories that contain it), missing: adm1 names } in the
// SELECTION'S order: a zone's groups, then a country's, each record once. Territory names are the HUD's own
// (selectedTerritories[].name), the same names the clipboard's first line carries.
// ★ INDIA'S STATES AND UNION TERRITORIES resolve through the served table (data/people-groups/india-states.json,
// library/data/indiaStates.js), fetched only once a state is selected. Any other ADM1 (China's provinces) has no
// table yet, so it stays `missing` and is NAMED to the reader, never silently dropped.
function indiaStates() { return loadIndiaStates(resolveAssetsBase(profileConfig.value)); }
async function selectionPeople() {
const lists = selectedLists();
const codes = selectedCountryCodes();
const adm1 = selectedAdm1Names();
if (!lists.length && !codes.length) {
let adm1 = selectedAdm1Names();
let india = null;
if (adm1.length) {
try { india = await indiaStates(); } catch (_) { india = null; } // unreachable table: every state stays missing
if (india) adm1 = adm1.filter((n) => !india.byShapeName.has(n));
}
const indiaCount = india ? selectedTerritories.value.filter((t) => t.kind === 'adm1' && india.byShapeName.has(t.name)).length : 0;
if (!lists.length && !codes.length && !indiaCount) {
// Name WHY when the only thing selected is a province — "nothing selected" would be a lie the
// reader can see is false.
if (adm1.length) throw keyedError('upgMap.selectionAdm1NoData', 'no people-group data for {names} — select the country instead', { names: formatList(adm1, { locale: packetLang() }) });
@ -1868,6 +1880,9 @@ async function selectionPeople() {
for (const s of slugs) add(s, t.name);
} else if (t.kind === 'adm0') {
for (const s of evaluate({ type: 'country_codes', values: [String(t.key).replace(/^adm0:/, '')] }, records)) add(s, t.name);
} else if (t.kind === 'adm1' && india) {
const st = india.byShapeName.get(t.name);
if (st) for (const s of st.slugs) add(s, t.name);
}
}
return { records: [...from.keys()].map((s) => bySlug.get(s)).filter(Boolean), from, missing: adm1 };