diff --git a/internal/check-batch-selection-export.mjs b/internal/check-batch-selection-export.mjs index 6d154b09f..0af60dc12 100644 --- a/internal/check-batch-selection-export.mjs +++ b/internal/check-batch-selection-export.mjs @@ -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'] diff --git a/plugin-designs/my-upg-100-list/upg-100-list.vue b/plugin-designs/my-upg-100-list/upg-100-list.vue index 0a09f174d..a8807637e 100644 --- a/plugin-designs/my-upg-100-list/upg-100-list.vue +++ b/plugin-designs/my-upg-100-list/upg-100-list.vue @@ -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 };