The control was removed earlier because it was a documented no-op —
the build pipeline repositioned features per flying_islands.yaml but
didn't tag them, so the runtime drop logic had nothing to filter on.
Now actually functional:
- build.py: apply_flying_islands sets `_flying: true` on every feature
it repositions (FRA's 5 DROMs, USA's Hawaii/Alaska/Puerto Rico, ESP
Canary Islands, NOR Svalbard, PRT Madeira/Azores, etc.)
- controlPanel.tsx: re-add the `show_flying_islands` checkbox (default
on, renderTrigger so the projection refits without re-querying)
- CountryMap.tsx: filterFeatures drops _flying-tagged features when the
toggle is off; fit-to-selection projection automatically zooms to
the remaining mainland
- types: declare optional `_flying` property
- Tests: assert control presence + default value; remove the
intentionally-absent assertion
- Regenerated 5 admin1 files + the france_overseas composite to embed
the new tags (only countries with flying_islands rules differ)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two user-visible bugs fixed:
1. **"No GeoJSON URL resolved" with admin_level + country set.** The
SelectControl serializes admin_level as a string ('0' / '1' /
'aggregated'), but transformProps was comparing against numbers
(`adminLevel === 1`), so real-world charts silently fell through
every branch and returned a null URL. Existing tests passed because
they used number values directly. Normalize to string at the top
of transformProps and compare against string constants; add two
regression tests that pass the string form-data values reality
actually sends.
2. **Default row_limit of 50000 exceeds many deployments' configured
ROW_LIMIT ceiling, blocking Update Chart.** Choropleths key one row
per region — even the densest country maps (France 101 departments,
India 36 states, US 51 territories) are well under 10k rows.
Override the shared default to 10000 via controlOverrides.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
After the composite-scoping refactor moved composite choices to a
country-aware mapStateToProps, COMPOSITE_CHOICES was orphaned and
tripped lint-frontend / validate-frontend tsc with TS6133.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Composites now declare their anchor country via base.adm0_a3 in
composite_maps.yaml; the build pipeline copies that into manifest.json
and the control panel uses it to:
- Hide the composite control entirely when the selected country has no
scoped composite (and there's no country-agnostic composite either)
- Narrow the composite dropdown to entries that actually apply to the
current country selection
Concretely: picking USA at the Country view no longer offers the
"France (with overseas territories)" composite — the control just
disappears. Picking FRA shows it.
Also updates the SIP's deprecation plan to reflect that no separate
"Switch to new Country Map" button is needed (the cross-viz form_data
hand-off via formDataOverrides + migrateFromLegacy already covers it),
and adds a Phase 2 DB migration that bulk-rewrites legacy charts.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two small UX wins on top of the previous control-panel fixes:
1. Rename admin_level options to "World" / "Country" / "Aggregated
regions" (from the technical "Countries (Admin 0)" / "Subdivisions
(Admin 1)"). The control's own label becomes "Map view" with an
explanatory description. Underlying form_data values stay 0 / 1 /
aggregated so saved charts don't break.
2. Auto-migrate form_data when a user switches a saved legacy
country_map chart's viz type to country_map_v2:
- select_country: 'france' → admin_level=1, country=FRA
- select_country: 'france_overseas' → composite=france_overseas
- select_country: 'turkey_regions' → admin_level=aggregated,
country=TUR, region_set=nuts_1
- …same pattern for france_regions / italy_regions /
philippines_regions and ~180 other legacy country files.
The mapping lives in src/plugin/migrateFromLegacy.ts (covered by
12 unit tests). Migration only fills fields the user hasn't already
set on the new chart, so explicit edits win over inferred values.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Four UX bugs reported on the new country map chart:
1. **"Country: cannot be empty" stuck on the Data tab even at Admin 0.**
The Country control had a hard `validators: [validateNonEmpty]`, but
it's only rendered (and only meaningful) when admin_level != 0 and no
composite is set. The validator was firing for the hidden empty value
and trapped the user — the Update Chart button was permanently
disabled with no visible control to satisfy. Switched to a dynamic
validator via mapStateToProps so it only fires when the field is
actually needed.
2. **"Aggregated regions" threw TypeError: t.map is not a function.**
The region_set control used `choices: ({ controls }) => ...`, but
SelectControl's `choices` must be a literal array. Moved the
country-dependent choice computation into `mapStateToProps` (same
pattern other plugins use).
3. **Composite map always visible and "sticky" overriding admin_level.**
At Admin 0 (world choropleth) the composite override produced a map
that didn't change when you toggled admin_level. Hidden composite
control at Admin 0 entirely, and hidden it whenever the build
pipeline didn't emit any composites — leaves room for future
per-country scoping (e.g. only show france_overseas when country=FRA).
4. **Show flying islands checkbox was a no-op.** The build pipeline
doesn't currently tag features as flying, so the runtime drop logic
had nothing to act on. Removed from the control set rather than ship
a misleading control; a single line brings it back once the build
tags features.
Tests updated to cover all four behaviors.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previously the build only emitted the ukr (Ukraine) worldview, so the
worldview dropdown had a single option even though it claimed otherwise.
Build now produces Admin 0 GeoJSON for every NE-published editorial:
default, arg, bdg, bra, chn, deu, egy, esp, fra, gbr, grc, idn, ind, iso,
isr, ita, jpn, kor, mar, nep, nld, pak, pol, prt, pse, rus, sau, swe, tur,
twn, ukr, usa, vnm (33 total).
NE does not publish per-worldview Admin 1 variants, so subdivisions within
a country come from a single shared file. The frontend now always points
Admin 1, regional aggregation, and composite URLs at the ukr-prefixed
shared outputs regardless of the selected worldview — the worldview
control only affects the world (Admin 0) map.
- build.py: expand WORLDVIEWS_ADMIN_0 to 33 worldviews; main() builds
Admin 0 for all of them, Admin 1 only for ukr
- transformProps.ts: introduce SHARED_ADMIN1_WORLDVIEW = 'ukr'; pin all
non-Admin-0 URLs to it
- controlPanel.tsx: WORLDVIEW_LABELS now covers all 33 codes; unrecognized
codes still fall back to raw code for forward-compat
- transformProps.test.ts: cover shared-Admin1 contract (admin1+chn still
resolves to ukr_admin1_*)
- pre-commit: exclude .geo.json from check-added-large-files (existing
rule only excluded .geojson and would block these ~2MB worldview files)
- README + SIP: document the worldview model and check off Phase 1 item
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- transformProps: read snake_case via rawFormData (ChartProps.formData
is camelCased), fixing 4 failing jest tests
- CountryMap.tsx: replace literal colors with theme tokens; wrap user
strings with t() for i18n
- build.py: add proper dict[str, Any] type params, drop unused type:ignore,
emit manifest.json with trailing newline for prettier/EOF parity
- test_build.py: top-of-file mypy ignore (unittest test scaffolding)
- pyproject.toml: per-file ruff ignores for the standalone build pipeline
(TID251/S310/S603/S607/E501/C901/PT009 all intentional/inapplicable)
- regen workflow: surface drift via PR comment + step summary instead of
failing — cross-platform mapshaper output reproducibility is still WIP
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Remove unused CategoricalColorNamespace import in CountryMap.tsx
- Remove unused isAdminSubdivision helper in controlPanel.tsx
- Add resolveJsonModule + include manifest.json in tsconfig
- Cast chartProps.formData to CountryMapFormData in transformProps
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace hardcoded WORLDVIEW / COUNTRY / REGION_SET / COMPOSITE choice
tables in controlPanel with options derived from the build pipeline's
manifest.json. Adding a new entry to a YAML config + re-running
./build.sh now populates the control automatically; no plugin code
change needed.
Build script: also writes manifest.json to the plugin's
src/data/manifest.json so controlPanel can `import` it synchronously
(no async fetch needed at chart-edit time). Data files (the actual
GeoJSONs) still live only at superset/static/assets/country-maps/ —
we don't want to bundle 17MB of choropleth data into the JS payload.
Lookup helpers preserve human-friendly labels:
- WORLDVIEW_LABELS — maps NE worldview codes (ukr, default, ind, ...)
to friendly names ("Ukraine (default — Crimea as Ukrainian)" etc.);
unmapped codes render as the raw code
- COUNTRY_LABELS — ISO_A3 → English country name (~85 entries);
formatCountry renders as "France (FRA)"; unmapped codes render raw
- REGION_SET_LABELS / COMPOSITE_LABELS — same pattern
Manifest's regional_aggregations array is grouped by country into
the {country: [(set_id, label), ...]} shape the control panel needs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace the placeholder control panel with the real form-data surface.
New controls (none of which exist on the legacy plugin):
- worldview: SelectControl, defaults to 'ukr' per documented editorial
choice; configurable per-deployment + per-chart
- admin_level: SelectControl (Admin 0 / Admin 1 / Aggregated regions)
- country: SelectControl, visible only when admin_level !== 0 and no
composite is selected
- region_set: SelectControl, visible only when admin_level === 'aggregated';
choices depend on selected country (sourced from the regional_aggregations
YAML's snapshot table)
- composite: SelectControl (france_overseas etc.); when set, overrides
admin_level + country
- region_includes / region_excludes: free-form multi-select for client-side
filtering at render time (these drive the projection refit too — the
renderer's `filterFeatures` uses them)
- show_flying_islands: CheckboxControl, default true
- name_language: SelectControl with 20 NE-supported languages
The choice tables (WORLDVIEW_CHOICES, COUNTRY_CHOICES, REGION_SET_CHOICES_
BY_COUNTRY, COMPOSITE_CHOICES) are hardcoded snapshots for the POC.
Follow-up commit will replace these with options pulled from the build
pipeline's manifest.json so adding a new worldview or country only
requires a build script run, not a plugin code change.
Standard query controls (entity, metric, adhoc_filters, row_limit,
linear_color_scheme, number_format) preserved from the legacy plugin.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bootstrap the new @superset-ui/plugin-chart-country-map package with
the modern ChartPlugin pattern. Mirrors plugin-chart-handlebars'
structure (the leanest existing modern plugin in the repo).
Files:
package.json — workspace pkg with d3-* deps
tsconfig.json — extends frontend root tsconfig,
references core/chart-controls
types/external.d.ts — ambient types for png/jpg/geojson
README.md — what this plugin is + status
src/
index.ts — package entry
types.ts — CountryMapFormData + transform props
CountryMap.tsx — placeholder renderer (real D3 port
in a follow-up commit)
plugin/
index.ts — ChartPlugin class with metadata
buildQuery.ts — modern chart/data query (this is
the core difference from the legacy
plugin's explore_json path)
controlPanel.tsx — minimal placeholder; full control
set (worldview / admin level /
country / region include-exclude /
fly-islands / language) ports next
transformProps.ts — derives geoJsonUrl from form_data
using the build-script's output
naming convention
Renderer scaffold fetches the resolved GeoJSON URL and shows a small
diagnostic block (URL + feature count + data row count + metric name)
so the plugin compiles end-to-end and can be wired to the chart-type
registry without a real D3 render. Real renderer + controls land in
the next commits.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>