Conversation
|
Preview deployment: https://featxstations-snowobs-overlay.preview.avy-fx.org |
741803f to
11a2f7f
Compare
…page Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01YDHvoY5YQsE8iV24NuUqcL
Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01YDHvoY5YQsE8iV24NuUqcL
Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01YDHvoY5YQsE8iV24NuUqcL
11a2f7f to
fcf73f3
Compare
Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01YDHvoY5YQsE8iV24NuUqcL
…apshot, and read the station pages from them Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01BBfZ9kTcLyGMhsgFwYBiGi
Migration Safety CheckFound 5 potential issues: 20260918_203650_station_pages.ts Warning (line 19): DELETE keyword detected - review for data loss FOREIGN KEY (\`tenant_id\`) REFERENCES \`tenants\`(\`id\`) ON UPDATE no action ON DELETE set nullWarning (line 38): DELETE keyword detected - review for data loss FOREIGN KEY (\`parent_id\`) REFERENCES \`weather_station_settings\`(\`id\`) ON UPDATE no action ON DELETE cascadeWarning (line 54): DELETE keyword detected - review for data loss FOREIGN KEY (\`tenant_id\`) REFERENCES \`tenants\`(\`id\`) ON UPDATE no action ON DELETE set nullWarning (line 67): ALTER keyword detected - review for data loss sql`ALTER TABLE \`payload_locked_documents_rels\` ADD \`station_pages_id\` integer REFERENCES station_pages(id);`,Warning (line 70): ALTER keyword detected - review for data loss sql`ALTER TABLE \`payload_locked_documents_rels\` ADD \`weather_station_settings_id\` integer REFERENCES weather_station_settings(id);`,Review these patterns and add backup/restore logic if needed. See |
…ream-owned identity Station page slugs are URLs, so (tenant, slug) is now a unique index alongside the (tenant, source, stid) one on stations. The SnowObs identity fields were read-only in the admin but writable through the API; field-level access now refuses updates, and the sync and seed keep writing through the local API. Co-Authored-By: Claude Fable 5.1 <[email protected]>
The snapshot is the whole SnowObs catalogue, so the migration was creating seven rows nothing shows: a logger retired in 2019 and six 5-minute duplicates of hourly stations. The sync never deletes, so they would have sat in the Stations list for good. Now only the 53 stations on a page become rows. Co-Authored-By: Claude Fable 5.1 <[email protected]>
…ets a precip columns tab The stations table now keeps the search visible under the rows with an Add button, shows the SnowObs id beside the name, and heads the name column "Name". The per-center settings document is labelled "Page Config", its precip list is "Stations", and a Precipitation Columns tab chooses which columns the Accumulated Precipitation table shows after the station name (trailing windows, last update, latitude, longitude, elevation); an empty choice shows them all. Migration regenerated for the new select. Verified on a fresh seed: the admin renders both tabs, Add is disabled until a station is chosen and appends on click, and choosing 24H, 72H and Elevation leaves the public table with four columns. Co-Authored-By: Claude Fable 5.1 <[email protected]>
The per-center station settings document is labelled "Page Settings" and takes its title from the tenant's name through a virtual field, so the edit view and the list read "Northwest Avalanche Center" rather than "ID: 1". No schema change: the field is virtual. Co-Authored-By: Claude Fable 5.1 <[email protected]>
… its height
The search under the stations table takes one or several stations and Add
appends them in the order picked ("Add 2" when more than one). It has an
"Add station" label, sits at 32rem rather than full width, and the button
matches the control's single-line height and stays at the top as chosen
stations wrap.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
33 of NWAC's 52 listed stations have no gauge and showed as "missing" rows. A station whose response carries no precipitation series is now left off; one whose series is present but empty still shows as missing. The setting's description says so. Co-Authored-By: Claude Fable 5.1 <[email protected]>
Payload gives a tabs field a top margin unless it is the first field, and the hidden title input made it second. Co-Authored-By: Claude Fable 5.1 <[email protected]>
…marked, seed lists the 19 gauges The tracked-stations endpoint now joins station/data/current/ so each station carries the variables in its latest observation. A stations field can name a required variable; the precip list needs precip_accum_one_hour, so its picker offers only stations reporting it and a listed station that has stopped is noted in its row, next to the "not tracked" note. Picker entries read "Name · source". The seed's precip list is the 19 loggers with a gauge, in page order, rather than every logger on a live page. Co-Authored-By: Claude Fable 5.1 <[email protected]>
The flag and legend duplicated what the station page shows; the table reads cleaner without them. Co-Authored-By: Claude Fable 5.1 <[email protected]>
The builder still sorted rows by latitude as the legacy page did, so dragging a station in the settings changed nothing on the page. Rows now keep the order requested; the header sort still works on top. Co-Authored-By: Claude Fable 5.1 <[email protected]>
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The tab's own text says what the list does; the field's description is now optional and this one has none. Co-Authored-By: Claude Fable 5.1 <[email protected]>
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
Closing in favour of a stack built from this branch's final tree: #1315 (station pages collection, picker, center-dynamic routes, the station_pages migration) and #1316 on top of it (the index page in Payload, Page Settings for the precipitation table; no migration, handled by hand). The history here stays for reference. |
Description
Makes the weather station pages center-aware, moves the
/weather/stationsindex into Payload, gives each station page an editable, ordered list of the SnowObs stations it shows, and gives the Accumulated Precipitation table its own per-center setting. NWAC renders exactly as before.AvyWeb stores only what SnowObs cannot know: the pages, which stations each one shows and in what order, and which gauges the precip table shows. A station is a
(source, stid)reference and nothing more. Names, elevations and coordinates are read live from SnowObs on the public page and in the admin, where the stations field is a table of the page's stations with a search over the center's SnowObs tracking list and an Add button (station/tracking/, which is scoped by the token's client across every source: NWAC 213, SAC 139). There is no local copy of the station list and nothing to sync. See ADR 021 for the reasoning and the API findings behind it.Everything that assumed NWAC now takes the center: the SnowObs service reads the center's token from its AFP config and sends
sourceas the distinct sources of the stations requested, so a page can mixnwac,snotelandmesowestloggers in one request. Routes 404 for a center with no pages. The/weather/stationsindex is a normal page under the Weather dropdown, so the URL is unchanged and an editor owns the content. The detail, precipitation and map routes stay native.Related Issues
Closes #1169. Supersedes #1308 (closed; the sync it added is unnecessary once nothing is mirrored) and the closed #1202. Follow-ups: #1303, #1304.
Key Changes
fields/stations:stationsField(), a JSON field of ordered{ stid, source }pairs withStationsInput: a table of the chosen stations (live name, id, source, elevation, partner) with drag-to-reorder and a remove button per row, and under it a search over the tracking list with an Add button; the search reads "Name · source" and takes one or several picks. A field can name a required variable: the precip list needsprecip_accum_one_hour, so its picker offers only stations reporting it and a listed station that has stopped is marked in its row. A station that has left tracking is marked in its row; when SnowObs is unreachable the table shows stored ids and adding is disabled.validateStationskeeps the value to well-formed pairs with no repeats.collections/StationPages:displayName,slug(unique per tenant),archived,stations.hooks/ensureStationsUniquekeeps a station on one page per tenant and names the other page on conflict.collections/WeatherStationSettings("Page Settings" in the admin): one document per center (unique tenant, ADR 016). The Precipitation Table tab holds the stations list; the precip page shows exactly that, top to bottom, dropping a station with no precipitation series and showing "missing" for a gauge that reported none. Station note icons are gone from that table. The Precipitation Columns tab picks which columns the table shows after the station name (services/stations/precipColumns; empty means all).getWeatherStationSettingscaches both under the station-pages tag.StationPages/endpoints/trackedStations:GET /api/stationPages/tracked-stations?center=<slug>, signed-in only, proxiesstation/tracking/joined withstation/data/current/(so each station carries the variables in its latest observation) with the center's token, cached an hour.services/snowobs/access.ts: token resolution andSnowObsError, free of the Payload config so collection code can import it.snowobs.ts:fetchStationTimeseries(centerSlug, StationRef[], options).stationTracking.ts: the tracking fetch.services/stations/: assemble pages from the array, cache per center, revalidate on change;allStations()maps a bare stid back to its source for the graph-data and CSV routes.services/snowobs/deriveColumns.ts: table columns from the variables the stations report, variable-major.constants/weatherStations.ts, the built-inweather/stations/page.tsxand thestationscollection are gone. The seed gives NWAC astationspage instead of the built-in row.How to test
pnpm seed, thenpnpm dev.2a. Admin → Weather → Page Settings: one document, titled with the center name. The Precipitation Table tab lists 52 stations; remove one and reload
/weather/stations/accumulated-precipitation; its row is gone. The Precipitation Columns tab: pick 24H, 72H and Elevation only, save, reload; the table has four columns.nwac.localhost:3000/weather/stations: the "Weather Data" Payload page, reached from the Weather dropdown./weather/stations/alpentaland/weather/stations/accumulated-precipitation: as on main. Reorder the rows on Alpental and reload; the columns follow.sac.localhost:3000/weather/stations/alpental: 404./weather/stations/mapstill renders.Prod: the
stationspage under Weather in the NWAC admin already exists; point the nav at it and delete the "Weather Data" built-in row.Screenshots / Demo video
TODO: the Alpental edit form with the add search open, and the settings document.
Migration Explanation
20260918_203650_station_pagescreatesstation_pages(unique(tenant, slug),stationsas JSON) andweather_station_settings(unique tenant, with itsprecip_columnsselect table), then for thenwactenant seeds the 32 pages and their station references frommigrations/data/nwacStationPages.ts, a settings document whose precip list is the 19 stations with a gauge in page order, and adds both collections to each center's Admin role. Idempotent: a page or settings document that exists is left alone. The.jsonbeside it is Payload's full schema snapshot, as with every migration. The migration-safety bot flags theON DELETE set nullforeign keys and theALTER TABLE … ADDonpayload_locked_documents_rels; those are Payload's standard clauses.Future enhancements / Questions
variable/tracking/serves per-center units and rounding; it would replaceSENSOR_LABELS,UNIT_LABELSandmetricUnits.ts(SnowObs says wind's metric unit is m/s; we hardcode km/h).station/tracking/stays readable with the public token.🤖 Generated with Claude Code
https://claude.ai/code/session_01YDHvoY5YQsE8iV24NuUqcL