Repository navigation
algorithm-catalog: live preview of the event page as it will look on the Disasters Portal - #253
Merged
Merged
Conversation
…the Disasters Portal The page preview used the catalog's own styling and only appeared in Review. It is now a replica of the portal page itself — header, hero masthead, sidebar tags, Overview and Event Data Gallery, with the portal's fonts, colors and proportions measured off the live California page — rendered at its 1280px desktop width and scaled to fit. - Docked beside the Submit form (sticky, toggleable, remembered per browser) and updated on every keystroke; Events -> Page preview shows the same. - The gallery shows the portal's REAL data cards for each product, snapshotted by scripts/sync_portal_cards.py into data/portal-cards.json + public/portal/. - Text goes through the same typographic() transform as the generated portal file, so the preview shows exactly what the portal will (curly quotes too).
… inferred Images: Page content gains an Images block — a Google Drive file link per image, placed as the hero (masthead + card thumbnail) or inline in the Overview, with required alt text and an optional caption. The live preview loads them from Drive and says plainly when a file isn't shared. When the portal PR opens, portal_pr.mjs downloads each into public/img/event/, sniffs the bytes (an unshared Drive file returns an HTML page), reads the real width/height the portal's image block needs, and writes image blocks; a failed image is listed in the PR instead of breaking it. Rules mirrored in rules.ts/validate_data.py with parity fixtures (folder links, placement, alt, one hero). Page address: the portal page id is no longer an input. A new page's id is derived from the event name, so the name must follow the portal convention "<Event> <Month> <YYYY>" (error), with a warning when it disagrees with the start date. Existing portal pages keep their recorded id. "U.S." now slugs to "us", matching us-winter-storm-jan-2026.
…ad; no address field - The masthead is always the portal's default event image, so the hero option is gone. Instead there is ONE optional image after the intro, matching the Venezuela / Typhoon Sinlaku pages: a Google Drive file link + required alt text + an optional caption (with credit). It becomes the portal's image block between the Overview text and the Event Data Gallery; the preview's caption is styled as measured on the live portal. - The page address field is removed from the form entirely. It is derived from the event name (whose "<Month> <YYYY>" ending is enforced) and shown only in the live preview's header.
…andard The portal's image standard (disasters-portal #556, refined by #654) is: real WebP via `cwebp -q 80 -m 6 -metadata none`, at most 1920px wide, under 500 KB. The Drive image the portal PR adds now always meets it: - toPortalWebp(): a WebP that already complies is kept byte for byte (re-encoding lossy WebP only loses quality); anything else is encoded at q80, capped at 1920px, and stepped down in width only if still over 500 KB. Body images are not capped at 1280px (#654 dropped that rule: it blurred high-DPI screenshots). GIFs are refused with a clear message. - The PR body records each conversion, e.g. "11,594 KB PNG -> 292 KB WebP (q80, 3943 -> 1920px)". The workflow installs cwebp. - The preview's card snapshots use the same encoding (480px WebP): 1.38 MB of JPEG -> 878 KB, and the sync script prunes files it no longer references.
…ucts right) The picker was one long scrolling list of every sensor and its products. It is now a vertical tablist of sensors (catalog order, modality icon and accent, selected/total count, status badge) beside the selected sensor's products. Search filters both columns, and an All matches entry lists every hit grouped by sensor. - Status badge is generic: any non-production status, labelled through a STATUS_LABEL map (prototype, external = no algorithm yet), else raw. - Keyboard: Down from search enters the list; Up/Down/Home/End move sensors; Right/Enter go into products; Up/Down/Left inside; Esc closes from anywhere (document listener). After an add, focus moves to the next addable row instead of dropping to body. - Sizing scoped to .req-prodpick so PlacePicker's .req-picker is unchanged: up to 760px wide (capped by viewport minus the anchor's x), fixed height, columns scroll independently; under 560px the sensors become a horizontal strip and hazards wrap under each product. - e2e: sensor count equals algorithm count, Sentinel-2 vs Landsat, swir search + add, keyboard add, Esc closes.
…g/live-portal-preview
…rithm yet A product made outside this catalog (OPERA, UAVSAR, Planet, ...) can now be listed so a request can ask for it and the event page links its Disasters Portal card, without pretending a DPS job exists. - types: AlgorithmStatus gains "external"; Modality gains "model" (GAIA, GPM IMERG: neither one optical nor one SAR sensor), with its colour/icon. - drafts: autoProducts skips external, so a hazard never auto-selects one. - picker, chips, Algorithms cards and detail: badged "no algorithm yet"; detail hides DPS name/inputs/resources and links the portal data page. - What this will run: says the layer is produced outside the catalog and no DPS job is created. - validate_data.py: status vocabulary; external must declare no inputs. - e2e: lazy thumbnails are scrolled into view before measuring; new checks that OPERA DSWx is never auto-selected, can be added by hand, is labelled, and shows its real portal card in the live preview.
…ed (59/59) Adds the 40 data-gallery products that had no algorithm here, as 16 status:"external" entries grouped by source: OPERA, UAVSAR, AVIRIS-3, PlanetScope, Vantor, SkySat, ECOSTRESS, GPM IMERG, HydroSAR, NISAR, GAIA, WB-57 DyNAMITE, Black Marble composites, Sentinel-1 damage assessment, Sentinel-1+2 burn severity and Sentinel-2 change products. Each product's label is its portal card title, portalData its card constant, hazards its portal categories mapped through hazards.json (tsunami dropped), primaryHazards empty. Dates not stated on the cards are approximate mission or record starts. Thumbnails are the portal card images, 600x400 <=150 KB, credited in thumbs/CREDITS.md. portal-cards.json re-synced: 59 cards.
…g/live-portal-preview # Conflicts: # algorithm-catalog/data/portal-cards.json # algorithm-catalog/scripts/e2e.mjs # algorithm-catalog/src/request/ProductPicker.tsx
Each product's stacAsset (the product-specific asset key on the live items, e.g. "truecolor", "colorir", "backscatter", "blackmarble_hd") and stacCollections are now GENERATED by scripts/sync_stac_assets.py from the live Disasters STAC. They are never hand-edited and the app offers no way to edit them. cog_default and the rendered_preview/dashboard assets are not asset names and are never used. Collections are matched to products by rule, with ranked claims; a tie is assigned to nobody and reported, never guessed. 52 of 71 products are linked. The picker shows the STAC asset name as the product token, and a product no live collection carries shows its own token, dashed. validate_data.py rejects a hand-edited shape; `sync_stac_assets.py --check` detects drift from live STAC. Also: the e2e picker test anchors on the exact "Sentinel-2" sensor title, since the merged catalog now has three Sentinel-2-named sensors.
…pped from the preview - "+ Add products": an added product's row stays clickable. Clicking its ✓ (hover shows a red −) removes it, through the same removeProduct as the chip's ×. Previously added rows were disabled, so there was no way to de-select from the picker. - Live preview: a picked product with no Disasters Portal Data Gallery card (e.g. Umbra gamma-naught, Black Marble NOAA-20) now shows as a dashed draft card in the Event Data Gallery, saying the published page won't show it until the portal adds an entry. This replaces the easy-to-miss footnote. Real cards render unchanged. - Products step: each sensor group's heading carries its modality accent (icon + coloured rule) and is larger and heavier than the product chips under it, so the sensor names no longer blend into the chips.
…added The selected products are listed above the "Add products" button, so every product added from the open picker grew the page above it and pushed the picker down: 26-66 px per add, off screen after a few. Now the picker's position is recorded just before each add/remove made from it, and the page is scrolled by exactly the difference after the list re-renders, so the picker stays under the cursor. A scroll the user makes themselves is never undone. e2e: adds four products from different sensors and removes one, asserting 0 px picker drift per change. Without the fix it reports 26, 66, 66, 66 px.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The Page content fields now drive a live preview of the page as it will look on science.data.nasa.gov/disasters, docked beside the form and updated on every keystroke.
--color-*tokens and proportions were measured off the live California page. It renders at the portal's 1280px desktop width, and<PortalFrame>scales it to fit.portalDatacard is shown with its real title, description, tags (including the portal's "+ N more ...") and thumbnail.scripts/sync_portal_cards.pysnapshots them intodata/portal-cards.jsonandpublic/portal/(1.4 MB, thumbnails downsized), because the app never fetches at run time. Layers with no portal card are listed under the preview.typographic()transform as the generated portal file, curly quotes included.EventPage.tsxand its.page-*CSS are removed.Verified
validate_data.pyandrules_parity_test.pypass, as donpm run typecheckandnpm run build.scripts/e2e.mjspasses 35/35 in Chromium. The new checks: the preview is docked; it updates live (sub-title with curly quotes, Need tag, intro); it shows the real "Landsat True Color Imagery" card with its thumbnail decoded.portal_pr.mjs --dry-runagainstdisasters-portal@developstill passes the portal's ownlint:ciandtypecheckafter thetypographic()refactor.