Skip to content

feat(explorer): consolidate diagnostic content into per-collection YAML#16

Merged
lewisjared merged 16 commits intomainfrom
consolidate-diagnostic-content
Mar 8, 2026
Merged

feat(explorer): consolidate diagnostic content into per-collection YAML#16
lewisjared merged 16 commits intomainfrom
consolidate-diagnostic-content

Conversation

@lewisjared
Copy link
Contributor

Summary

  • Migrate explorer card definitions from 5 hardcoded TSX theme files into 25 per-collection YAML files served by a new backend API
  • Each AFT collection gets its own YAML file in backend/static/collections/ containing metadata, diagnostic links, and explorer card configurations
  • A themes.yaml file maps theme slugs to ordered lists of collection IDs
  • Frontend now fetches card data from the API instead of embedding it in source code, making content editable without frontend changes

Changes

Backend

  • 25 collection YAML files + themes.yaml in backend/static/collections/ consolidating data from the AFT CSV, ref_mapping.yaml, and TSX theme files
  • core/collections.py: Pydantic models (AFTCollectionDetail, AFTCollectionCard, AFTCollectionCardContent, ThemeDetail, etc.) and loader functions with lru_cache
  • api/routes/explorer.py: 4 new endpoints — GET /explorer/collections/, GET /explorer/collections/{id}, GET /explorer/themes/, GET /explorer/themes/{slug}
  • 28 new tests (18 loader + 10 API) covering happy paths, error cases, snake_case serialization, placeholder cards, theme aggregation

Frontend

  • Regenerated client SDK with new explorer endpoint hooks
  • Rewrote thematicContent.tsx to fetch theme data from API with snake_case-to-camelCase mapping functions at the boundary
  • Fixed yMin/yMax passthrough bug in ensembleChartContent.tsx — these props were never passed to EnsembleChart
  • Deleted 5 static theme TSX files (atmosphere.tsx, earthSystem.tsx, impactAndAdaptation.tsx, land.tsx, sea.tsx)

Key decisions

  • All API responses use snake_case (matching existing backend convention); mapping to camelCase happens in thematicContent.tsx
  • Cross-collection cards split into per-collection cards (Ocean State → AMOC + SST&SSS, Climate Sensitivity → ECS/Lambda + TCR, etc.)
  • isolate_ids/exclude_ids preserved verbatim in other_filters for sea ice charts
  • ENSO placeholder card in collection 1.3, visible in both ocean and earth-system themes
  • Existing AFT API endpoints unchanged

Test plan

  • uv run pytest tests/ — 28/28 new tests pass
  • npx tsc --noEmit — TypeScript passes
  • npm run build — Frontend builds
  • npx @biomejs/biome check . — Lint passes
  • All pre-commit hooks pass (ruff, mypy, biome, tsc)
  • Visual comparison: explorer pages render identically before and after

Migrate explorer card definitions from 5 hardcoded TSX theme files into
25 per-collection YAML files served by a new backend API. This makes
diagnostic content easy to edit without touching frontend code.

Backend:
- Add 25 collection YAML files + themes.yaml in backend/static/collections/
- Add Pydantic models and loader in core/collections.py
- Add explorer API routes (/collections/, /themes/) in api/routes/explorer.py
- Add 28 tests (18 loader + 10 API)

Frontend:
- Regenerate client SDK with new explorer endpoints
- Rewrite thematicContent.tsx to fetch cards from API with snake_case
  to camelCase mapping at the boundary
- Fix yMin/yMax passthrough bug in ensembleChartContent.tsx
- Delete 5 static theme TSX files (atmosphere, earthSystem,
  impactAndAdaptation, land, sea)
@netlify
Copy link

netlify bot commented Mar 6, 2026

Deploy Preview for climate-ref ready!

Name Link
🔨 Latest commit aa0c02c
🔍 Latest deploy log https://app.netlify.com/projects/climate-ref/deploys/69ad2869598463000803444b
😎 Deploy Preview https://deploy-preview-16--climate-ref.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Remove the AFT CSV and ref_mapping.yaml in favor of the per-collection
YAML files that already contain all the same data plus richer content
(why_it_matters, takeaway, plain_language, explorer_cards).

core/aft.py now delegates to load_all_collections() from
core/collections.py instead of parsing CSV/YAML files directly.
The public API is preserved with identical signatures and return types.
- Fix load_theme_mapping to iterate dict items instead of keys, matching
  the actual themes.yaml mapping format (slug as key, not as field)
- Fix fallback default from [] to {} for dict data
- Fix duplicate collection ID ValueError being silently swallowed by
  broad except Exception; replaced with explicit warning + continue
- Narrow theme iteration exception handler to (KeyError, TypeError)
- Cache get_aft_diagnostics_index to avoid model_dump round-trips per request
- Remove dead executionId code in executionsTable.tsx
- Update all theme test fixtures to use correct dict format
…bs navigation

- Bump climate-ref to 0.12.2 for new plain language and provider link fields
- Add CollectionHeader component to display per-collection context
- Replace theme button links with Tabs component for cleaner navigation
- Add plain language / technical toggle for collections with summaries
- Refactor ExplorerThemeLayout to render cards grouped by collection
- Fix CSS min-height classes (h-min-32 -> min-h-8)
- Remove Card wrapper from themes route in favor of page-level layout
- Regenerate client SDK from updated OpenAPI spec
Replace Recharts SVG-based rendering with HTML5 Canvas for dramatically
better performance with 500+ series. Key changes:

- Canvas-based line rendering with single draw pass instead of per-series SVG
- Grid-based spatial index (30px cells) for O(1) nearest-point lookup
- Ref-based hover updates to avoid React re-renders of canvas
- Rich tooltip with dimensions, reference delta, rank, and units
- Dark mode support for canvas axes, grid, and tooltip
- Crosshair with dashed vertical line and colored dot
- Smart axis formatting (integer ticks for year/month/day axes)
- Y axis label shows metric name and units
- React.memo on SeriesCanvas and SeriesLegend to prevent re-render cascade
- Shared ChartDataPoint type and isIntegerAxis utility to eliminate duplication
- Canvas DPR optimization to avoid GPU buffer reallocation on hover redraws
…ove layout

Rename component to better reflect its role as a group of content items.
Add section dividers between collection groups, constrain text width
with max-w-prose, and add horizontal margin to the explorer layout.
Auto-detect and apply well-known category orderings (e.g., seasons
DJF, MAM, JJA, SON) to preserve meaningful x-axis order in ensemble
charts. Also adds an explicit categoryOrder prop for custom orderings.
… gallery

- Remove commented-out CardTemplateGenerator blocks and unused imports
  from scalars.tsx and series.tsx
- Remove unused destructured variables (currentFilters,
  currentGroupingConfig, isolateIds, excludeIds) from both files
- Add useMemo for selectorDimensions, allFigures, and filteredFigures
  to avoid recomputation on unrelated renders
- Hoist regex compilation out of per-figure filter loop
…llection

Add explorer_cards definitions for annual-cycle, cloud-scatterplots,
TCRE, zero-emissions-commitment, historical-changes, and fire-climate-drivers
collections. Remove the empty ocean-heat-content (1.5) collection and
its reference from themes.yaml.
…face reference datasets

- Split monolithic metadata.yaml into per-provider files (pmp.yaml,
  esmvaltool.yaml, ilamb.yaml) with directory-based loading
- Enrich explorer card content with reference dataset badges from
  diagnostic metadata at collection load time
- Replace linear scan in get_aft_for_ref_diagnostic with O(1) reverse index
- Remove duplicate interpretation field from BoxWhiskerChartContent type
- Eliminate duplicate useSuspenseQuery call in ThematicContent
- Update generate_metadata script to output per-provider files
Use SelectorFilterPanel with multi-select (string[]) filters and
matchesSelectorFilters, removing the duplicate inline Select-based
filter UI and the now-dead extractSelectorDimensions function.
- Add SeriesMetadata type annotation to test fixture to fix TS2345 error
  where heterogeneous dimension objects inferred metric?: undefined
- Clear _build_ref_to_aft_index lru_cache in test fixture to prevent
  cached results leaking between tests
@lewisjared lewisjared merged commit 70aa9c3 into main Mar 8, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant