Commit Graph

11 Commits

Author SHA1 Message Date
Superset Dev
adbf5bcff8 feat(plugin-chart-country-map): ship all 33 NE worldviews at Admin 0
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>
2026-05-13 09:10:04 -07:00
Superset Dev
ae7a947bc0 fix: prettier on remaining country-map files
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 00:15:38 -07:00
Superset Dev
69afb7653b fix(plugin-chart-country-map): trailing newlines + correct theme/t imports
- Add trailing newline to all 220 geo.json outputs to satisfy
  end-of-file-fixer pre-commit hook
- build.py: post-process step ensures future regens emit trailing newlines
- CountryMap.tsx: import t/useTheme from @apache-superset/core
  (matches the rest of the codebase) and use antd theme tokens
  (colorBgSpotlight, colorTextLightSolid, colorErrorText, etc.)
  instead of legacy theme.colors.* paths

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 23:37:57 -07:00
Superset Dev
ae61f2f507 fix(plugin-chart-country-map): clear remaining CI issues
- 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>
2026-05-12 23:14:10 -07:00
Superset Dev
cbb8477d47 fix(plugin-chart-country-map): resolve TypeScript lint errors
- 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>
2026-05-12 23:03:58 -07:00
Evan Rusackas
9fd7fd441a fix(country-map): CI failures — license headers, lockfile sync, reproducible build
Three coordinated fixes for the 25 CI failures on the initial PR push:

1. **Lockfile sync.** Added @superset-ui/plugin-chart-country-map as
   a workspace dep in the previous commit but didn't update
   package-lock.json. CI's `npm ci` failed across frontend-build,
   cypress (12 jobs), playwright (4 jobs), docker (2 jobs), and
   frontend-check-translations. Re-ran `npm install --package-lock-only`
   to add the new workspace's 71 lock entries.

2. **License headers added** to 13 new files flagged by License Check:
   - 5 markdown READMEs / SIP_DRAFT (HTML-comment headers)
   - 5 YAML config files (`# Licensed ...`)
   - 2 Python files (`# Licensed ...`)
   - 1 shell script (preserves shebang)

3. **Reproducible build outputs.** The regen workflow detected drift
   on manifest.json + ukr_admin1_CAN.geo.json. Two root causes:
   - `build_timestamp_utc` field made manifest non-deterministic →
     dropped from the schema
   - Floating mapshaper version (`npx --yes mapshaper`) caused subtle
     simplification differences across runners → pinned to
     `mapshaper@0.7.15` via `npx --yes mapshaper@<version>`

Verified locally: rebuild from clean cache reproduces every output
byte-identically except the manifest (which now also matches once
the timestamp is gone).

Files changed:
  .gitignore                           — re-include rule for static dir
  superset-frontend/package-lock.json  — +71 lines for new workspace
  13 new files                         — ASF headers
  build.py                             — pin mapshaper, drop timestamp
  manifest.json (× 2)                  — regenerate w/o timestamp
  README.md (in static dir)            — header

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 22:32:51 -07:00
Evan Rusackas
f1ff71e849 feat(country-map): port click-to-zoom interaction from legacy plugin
Click a region: viewport zooms in (4x) centered on its centroid.
Click again or click the empty background: zoom back out.
600ms CSS transition on the SVG group.

Implementation note: zoom state lives on the DOM (zoomedFeature
local + group transform attribute) rather than React state. Two
reasons:
- Cleaner unmount (the transition completes naturally; no orphaned
  React state)
- Avoids a re-render cycle on every click that would re-fit the
  projection and undo the zoom

Background rect added to capture clicks outside any feature.

Cross-filter integration intentionally NOT added in this commit —
that needs the chart props' setDataMask path and a settings UI for
which feature property to use as the filter key. Separate concern,
follow-up commit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 17:33:40 -07:00
Evan Rusackas
5efb93b99b feat(country-map): manifest-driven control choices
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>
2026-05-12 17:32:52 -07:00
Evan Rusackas
f696fe1e05 feat(country-map): full control panel — worldview, admin level, region filters, language
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>
2026-05-12 17:00:08 -07:00
Evan Rusackas
b296345332 feat(country-map): port D3 renderer to modern modules + new features
Replace the placeholder renderer with a real D3-based choropleth.
Modernizes the legacy plugin's rendering in three ways:

1. **Modern D3 modules** (d3-geo, d3-array, d3-color) instead of the
   d3 v3 monolith. No more @ts-nocheck — fully typed.

2. **Built-in include/exclude filtering** (formData.region_includes /
   region_excludes) before render. Projection auto-fits the FILTERED
   feature set, so excluding Russia from a Europe view actually zooms
   to Europe (the "fit to selection" behavior).

3. **Multi-language display names** via name_language formData field.
   Falls back through name_<lang> → name → '' so any worldview/dataset
   degrades gracefully.

Other changes:
- Tooltip is React state instead of D3-driven HTML (cleaner unmount,
  no XSS surface from .html())
- Color scale uses sequential scheme registry from @superset-ui/core
  (same path as legacy)
- Cleanup on unmount via useEffect cleanup function

Stubbed for follow-ups:
- Click-to-zoom (legacy had this; revisit after deprecation banner)
- Cross-filter integration
- Composite projection support (geoAlbersUsa for USA, etc.) — falls
  back to plain Mercator + build-time repositioning for now
- Flying-islands toggle: feature-tagging in the build pipeline still
  needs to land before the toggle can drop them at render time

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 16:58:38 -07:00
Evan Rusackas
07532ae1a7 feat(country-map): scaffold modern plugin shell
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>
2026-05-12 16:44:43 -07:00