Skip to content

Add Algorithm Catalog app: filter NASA Disasters algorithms + submit activations - #226

Merged
kyle-lesinger merged 1 commit into
mainfrom
feat/algorithm-catalog
Aug 14, 2026
Merged

Add Algorithm Catalog app: filter NASA Disasters algorithms + submit activations#226
kyle-lesinger merged 1 commit into
mainfrom
feat/algorithm-catalog

Conversation

@kyle-lesinger

Copy link
Copy Markdown
Member

A sixth Netlify dashboard ("Pattern B"). It answers "a wildfire just activated — which products should I deploy?" without reading nine algorithm_config.yaml files, and turns an activation request into a prefilled PR.

Three tabs

Tab What it does
📝 Submit The request form (landing tab). Event → hazards → locations → products → prefilled PR. The user never sees a DPS concept — no queues, no run_command, no ram_min, no secrets.
🌀 Events Event catalog: published activations from events.json plus submitted requests, badged published / submitted. Search + hazard + date filters.
🛰 Algorithms Filter by hazard / sensor / product / modality / date / activation event, via two entry modes — "start from hazard" and "start from sensor & product" — that share one filter state, so switching never loses selections.

Data

Hand-curated from Disasters-Learning-Portal/disasters-product-algorithms@dev: 8 algorithms, 33 products, 3 seed activations, 10 hazards.

Products carry two hazard lists on purpose:

  • hazards — broad, drives discovery (a false negative is worse than a false positive when you're searching)
  • primaryHazards — sparse, drives the form's auto-selection

That split is why picking Fire now proposes 7 products instead of 21.

Standards enforcement — the point of the app

Upstream, hazard is a free-text token in slot 2 of an activation_event string and nothing ever checked it. That is why Fire/Wildfire and Quake/Earthquake both exist in the wild today.

Here the rules live once in src/rules.ts, are mirrored 1:1 in scripts/validate_data.py, kept honest by scripts/rules_parity_test.py, and gated in CI. Three layers:

  1. Live in the form — inline errors naming the rule with a valid example; submit stays disabled while any error stands.
  2. Over the committed datavalidate_data.py also checks referential integrity (every event layer resolves, primaryHazards ⊆ hazards, every thumbnail exists on disk).
  3. CIalgorithm-catalog-validate.yml fails the PR, so hand-written files can't route around the form.

One deliberate divergence from upstream

The STAC event-name rule requires exactly two underscores. Upstream's regex ends in .+, so the location slot swallows extras — 202501_Tropical_Cyclone_CA passes there while silently parsing as hazard="Tropical" and writing that as the GeoTIFF HAZARD tag. This also rejects 202501_Flood_CA_extra, an explicit upstream pass case (tests/integration/test_dps_validate.sh:41-48).

Diverging this way is the safe direction: every name we accept, DPS accepts too. We only refuse names that mis-slot the hazard. Cost: multi-word locations need CamelCase too (202512_Hurricane_GulfOfMexico), and the error message quotes back what the name would otherwise have been read as.

Conventions followed

  • Vite React SPA cloned from dse-hub; zero new runtime deps (React + ReactDOM only — no router, no date lib, no icon lib)
  • HDS (NASA Horizon Design System) over USWDS, light-only
  • Thumbnails are public-domain NASA Worldview/GIBS + JPL imagery, bundled and credited in public/thumbs/CREDITS.md
  • Root .gitignore gets ! negation lines rather than dse-hub's git add -f route, so a plain git add algorithm-catalog/ picks the JSON up

Verification

  • validate_data.py → exit 0, 0 errors, 0 warnings
  • rules_parity_test.py → exit 0 (constants character-identical + 51 behavioural fixtures)
  • npm run typecheck / npm run build → clean
  • 16/16 Playwright checks against the dev server: tab order, live filtering (8 → 2 on search), all 8 thumbnails loading, and five negative event-name cases that must each block submission

Netlify (manual, after merge)

Create a new site from this repo with base directory = algorithm-catalog. Deploy after this merges — a base dir that doesn't yet exist on the built branch fails with "base directory not found".

…activations

A sixth Netlify dashboard ("Pattern B"). Answers "a wildfire just activated —
which products should I deploy?" without reading nine algorithm_config.yaml
files, and turns an activation request into a prefilled PR.

Three tabs: Submit (the form, landing tab), Events (event catalog = published
activations + submitted requests), Algorithms (filter by hazard / sensor /
product / modality / date / event, via two entry modes that share one filter
state).

Catalog data is hand-curated from disasters-product-algorithms@dev: 8
algorithms, 33 products, 3 seed activations, 10 hazards. Products carry both
`hazards` (broad — drives discovery) and `primaryHazards` (sparse — drives the
form's auto-selection, so picking Fire proposes 7 products, not 21).

Standards enforcement is the point of the app. Upstream, hazard is a free-text
token in slot 2 of an activation_event string and nothing ever checked it,
which is why Fire/Wildfire and Quake/Earthquake both exist in the wild. Here
the rules live once in src/rules.ts, are mirrored 1:1 in
scripts/validate_data.py, kept honest by scripts/rules_parity_test.py, and
gated in CI. They are enforced live in the form (submit disabled while any
error stands), over the committed data, and on every PR.

The STAC event-name rule is deliberately STRICTER than upstream: it requires
exactly two underscores. Upstream's regex ends in `.+`, so the location slot
swallows extras and 202501_Tropical_Cyclone_CA passes while silently parsing
as hazard="Tropical". This also rejects 202501_Flood_CA_extra, an explicit
upstream pass case. Diverging this way is safe — every name we accept, DPS
accepts too.

- Vite React SPA, zero new runtime deps (React + ReactDOM only)
- HDS (NASA Horizon Design System) over USWDS, light-only
- Thumbnails are public-domain NASA Worldview/GIBS + JPL imagery, bundled
- .gitignore gets `!` negations rather than dse-hub's `git add -f` route, so
  a plain `git add algorithm-catalog/` picks the JSON up

Verified: validate_data.py and rules_parity_test.py exit 0, typecheck and
build clean, and a 16-check Playwright pass against the dev server covering
the tab order, live filtering, thumbnail loading, and five negative
event-name cases that must each block submission.
@netlify

netlify Bot commented Aug 14, 2026

Copy link
Copy Markdown

Deploy Preview for veda-github-actions canceled.

Name Link
🔨 Latest commit 9568cc5
🔍 Latest deploy log https://app.netlify.com/projects/veda-github-actions/deploys/6a7efc2a6823410008d289c2

@netlify

netlify Bot commented Aug 14, 2026

Copy link
Copy Markdown

Deploy Preview for veda-pr-dashboard canceled.

Name Link
🔨 Latest commit 9568cc5
🔍 Latest deploy log https://app.netlify.com/projects/veda-pr-dashboard/deploys/6a7efc2aca90940008a6e26b

@netlify

netlify Bot commented Aug 14, 2026

Copy link
Copy Markdown

Deploy Preview for veda-aws-dashboard canceled.

Name Link
🔨 Latest commit 9568cc5
🔍 Latest deploy log https://app.netlify.com/projects/veda-aws-dashboard/deploys/6a7efc2a519bbe000838d4d6

@netlify

netlify Bot commented Aug 14, 2026

Copy link
Copy Markdown

Deploy Preview for veda-leave-dashboard canceled.

Name Link
🔨 Latest commit 9568cc5
🔍 Latest deploy log https://app.netlify.com/projects/veda-leave-dashboard/deploys/6a7efc2a35b83d0008f758f7

@netlify

netlify Bot commented Aug 14, 2026

Copy link
Copy Markdown

Deploy Preview for veda-dse-hub canceled.

Name Link
🔨 Latest commit 9568cc5
🔍 Latest deploy log https://app.netlify.com/projects/veda-dse-hub/deploys/6a7efc2a5950fc0009033d10

@kyle-lesinger
kyle-lesinger merged commit e5d1a87 into main Aug 14, 2026
22 checks passed
@kyle-lesinger
kyle-lesinger deleted the feat/algorithm-catalog branch August 14, 2026 11:34
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