Skip to content

feat(collections): desktop GIS downloads and a table view for the datasets page - #359

Open
jirhiker wants to merge 2 commits into
feature/geothermal-map-layersfrom
feature/gis-artifact-downloads
Open

feat(collections): desktop GIS downloads and a table view for the datasets page#359
jirhiker wants to merge 2 commits into
feature/geothermal-map-layersfrom
feature/gis-artifact-downloads

Conversation

@jirhiker

@jirhiker jirhiker commented Aug 23, 2026

Copy link
Copy Markdown
Member

Base branch

This targets feature/geothermal-map-layers (#356), not staging — it edits the same collections page. #356 in turn targets #355. Retarget down the stack as each merges.

What

Two commits.

feat(collections): offer desktop GIS downloads on the datasets page — the API serves ready-made QGIS and ArcGIS Pro files for our OGC API layers; nothing in the UI surfaced them.

  • A panel above the datasets: QGIS connections file download, the QGIS import path (Browser panel → right-click WFS / OGC API - FeaturesLoad Connections), and a copyable service_url for ArcGIS Pro, which has no importable connection file from us.
  • QGIS / ArcGIS Pro download buttons on every dataset entry, in both the table and card layouts, matched on the catalogue's collection field against the collection id the page already resolves.
  • The authenticated internal-connections file, gated on AMP viewer access.

feat(collections): add a table view and make it the default — the card grid buried the catalogue: four group cards, each a column of paragraphs, so comparing datasets meant scrolling past descriptions.

  • Table is now the default; a Cards/Table toggle in the header gets the old layout back.
  • Group membership is carried by row tint plus a labelled band per group, not a repeated column.
  • The collection id is dropped from the dataset column — machine detail; the title is what a reader scans by.
  • The page runs wider than the old lg container: full width up to a widescreen monitor, then ten of twelve columns so rows do not span a very wide display.
  • The "Admin View" overline is gone; the nav already gates who gets here.

Contract doc added at docs/gis-artifact-downloads-contract.md.

Following the contract

  • No hardcoded layer ids. Grep the source for water-level-trend and you get nothing; layers come from API-side YAML config and are expected to change.
  • No constructed URLs. href is used verbatim, so staging, production and an ephemeral preview API all resolve correctly.
  • Filenames come from the catalogue. CORS on the API sets no expose_headers, so Content-Disposition is unreadable from JS even though it is on the wire.
  • Anonymous downloads are plain anchors, not blob round-trips — the browser keeps its native save dialog, progress and error handling. Only the token-bearing internal file goes through axiosInstance with responseType: 'blob'.

The types are hand-written zod, deliberately

The committed openapi-auth.json has no /gis paths — the endpoints live on the unmerged API branch feat/ogc-desktop-gis-artifacts. I dumped the spec from that branch to see what a refresh would cost: it adds the five /gis paths, but also two unrelated unreleased endpoints (/chemistry/results, /observation/transducer-groundwater-level/block) and changes eight existing schemas, WellResponse, ThingResponse and SpringResponse among them — schemas the rest of the app validates against.

Regenerating all of that on a branch stacked two deep to reach one new surface was the wrong trade, so src/utils/gisArtifacts.ts carries zod for the catalogue only, scoped to this surface and marked for replacement. When the API branch merges and deploys: refresh the spec, npm run openapi:generate, drop those schemas for the generated ones. Nothing else depends on them.

One gap this exposes on the API side

/gis?f=json lists only anonymous artifacts, so /gis/qgis/connections-internal.xml is not in the catalogue at all. deriveInternalGisConnection derives it from the public entry's href — string surgery of exactly the kind the contract says to avoid, and the only place the rule is broken. Cleanest fix is the API listing the internal connection; the helper is marked for deletion when it does.

Verification

  • npm run typecheck — clean.
  • 20 tests across src/test/utils/gisArtifacts.test.ts, src/test/utils/collectionsView.test.ts and src/test/components/GisArtifacts.test.tsx: catalogue parses, layers index by collection, a download control carries the exact href and filename from the fixture, the internal control is hidden without the role and shown with it, and rows flatten out of the groups with the group key and GIS layer attached.
  • Schema checked against a real payload, not just a fixture: generated _index_payload() from the API branch (6 layers, 2 downloads each) and parsed it with zGisCatalog — clean.
  • Biome: per-file diagnostics on the pre-existing files match the base exactly; new files are clean.
  • Driven in the browser against a live local API: table renders 24 datasets under four tinted group bands, per-row QGIS/ArcGIS Pro links carry the real hrefs and download filenames, the toggle switches to cards and back, and the layout widens correctly at 1280 and 1680. No console errors.

🤖 Generated with Claude Code

The API now serves ready-made QGIS and ArcGIS Pro artifacts for our OGC API
layers, so a user can open our data in a desktop GIS without configuring a
connection by hand. Nothing in the UI surfaced them.

Adds a panel above the dataset groups with the QGIS connections file, the QGIS
import instructions, and a copyable service URL for ArcGIS Pro, which has no
importable connection file. Per-layer .qlr / .lyrx downloads render on the
collection row they belong to, matched on the catalogue's `collection` field
against the collection id the page already resolves.

Layer ids are API-side config and change, so nothing here hardcodes them, and
hrefs and filenames are used verbatim from the catalogue: CORS on the API
exposes no headers, so `Content-Disposition` is unreadable from JS. Anonymous
artifacts are plain anchors; the authenticated internal-connections file is the
one blob round-trip, gated on AMP viewer access.

Types are hand-written zod for now. The committed openapi-auth.json snapshot has
no /gis paths, and the only source for them is an unmerged API branch whose spec
also carries unrelated unreleased endpoints and eight changed schemas, including
WellResponse and ThingResponse. Refreshing the whole snapshot to reach /gis
would regenerate all of that here. src/utils/gisArtifacts.ts is scoped to the
GIS surface and marked for replacement once /gis is in the deployed spec.

Contract and the follow-up notes: docs/gis-artifact-downloads-contract.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

The card grid buries the catalogue: four group cards, each a column of
paragraphs, so comparing datasets means scrolling past descriptions. A table
puts all 24 on one screen — which is what this page is for — so it is now the
default, with a Cards/Table toggle in the header to get the old layout back.

Group membership is carried by row tint plus a labelled band per group rather
than a repeated column, and the collection id is dropped from the dataset
column: it is machine detail, and the title is what a reader scans by.

The page also runs wider than the old `lg` container, which left the table
cramped — full width up to a widescreen monitor, then ten of twelve columns so
rows do not run the whole span of a very wide display. The "Admin View"
overline is gone; the nav already gates who gets here.

buildCollectionRows and the shared collection field resolution live in
src/utils/collectionsView.ts so both views agree on what a dataset is called.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jirhiker jirhiker changed the title feat(collections): offer desktop GIS downloads on the datasets page feat(collections): desktop GIS downloads and a table view for the datasets page Aug 23, 2026
@github-actions

Copy link
Copy Markdown

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