Skip to content

FetchTimeseries: feature clicks to chart-series events - #294

Open
BhattaraiSijan wants to merge 11 commits into
feat/series-chartfrom
feat/fetch-timeseries
Open

FetchTimeseries: feature clicks to chart-series events#294
BhattaraiSijan wants to merge 11 commits into
feat/series-chartfrom
feat/fetch-timeseries

Conversation

@BhattaraiSijan

@BhattaraiSijan BhattaraiSijan commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds FetchTimeseries, a no-UI plugin bridging feature:click to the chart-series contract: on a vector feature click it reads the layer's variables.timeseries block over the bus (layers:getConfig), templates the fetch URL from the clicked feature ({properties.<key>}, {id}, {lon}, {lat} — unresolvable placeholders surface as named errors, not silent no-ops), fetches with abort-on-supersede, normalizes the response, and emits plugin:fetch-timeseries:* events for SeriesChart.

Normalization handles both response shapes the VEDA features API serves under content negotiation — GeoJSON FeatureCollections and flat rows — via loose properties.-prefix path resolution, plus groupBy (one series per parameter), unitKey, and auto-detected time/value keys.

Layers opt in per mission config; clicks on layers without the block do nothing. enabled: false disables without deleting. Charts persist until the next click replaces them (single chartId). The README documents the config schema and a working EPA AQS demo.

Merge order

  1. Emit feature:click on the bus for every vector feature click #292 feature:click core event — merge before this PR (runtime dependency; no compile dependency)
  2. SeriesChart: chart-series contract and single-variable chart plugin #293 SeriesChart (this PR's git base)
  3. this PR

Testing

tests/unit/fetchTimeseries.spec.js (31 cases): config gating incl. enabled:false, URL templating and its error cases, response mapping for both API shapes, grouping/units, payload building. Full unit suite green.

Manual: add the README's timeseries block to the AQS layer in Configure, click a station — loading → chart with the parameter picker. Station 54-39-20 ("Dixie St.") exercises 15 parameters across 5 units.

…he click

{lon}/{lat} fall back to the event latlng (vector-tile features carry empty geometry, so the placeholders threw on every click); {properties.*} takes nested dot-paths and rejects non-scalars. Wrong configured keys blame the config, not the API; paginated responses mark the title with first-N-of-M; xType is configurable so year columns stop charting as 1970; colliding slugs get suffixed ids; parallel arrays work at the response root as documented; container detection prefers populated arrays and key sampling skips leading metadata rows.
seriesReady drops its envelope to match the #293 contract. Fetches time out after 30s; destroy() emits seriesCleared so no spinner or stale card is stranded (the contract's first real seriesCleared emitter); the async click handler is caught and layers:getConfig goes through a hasHandler-guarded typed wrapper, so clicks during mission load are silent no-ops instead of unhandled rejections. First tests for the tool's I/O layer (mock bus + fetch): supersede, timeout, teardown, HTTP/template errors.
on:true in the profile, plus metadata startHidden/modernLayoutSupport so the no-UI tool loads and subscribes without rendering a blank tool card. With #293's enable, the end-to-end click-to-chart path now runs from a clean checkout. Config descriptions corrected alongside.
@BhattaraiSijan

Copy link
Copy Markdown
Collaborator Author

Addressed the review findings on this PR (branch re-based-by-merge on the updated feat/series-chart):

  • The feature shipped switched off — FetchTimeseries is now on in the full-demo mission, with a metadata: { startHidden, modernLayoutSupport } block so the no-UI tool loads and subscribes without rendering a blank tool card. Together with SeriesChart: chart-series contract and single-variable chart plugin #293's enable, the end-to-end click-to-chart path now runs from a clean checkout.
  • {lon}/{lat} threw on every vector-tile click (those features carry empty geometry) while the event's perfectly good location went unread — the placeholders now fall back to the click's latlng, zero coordinates count as present, and {id} is documented as source-data-dependent with {properties.<key>} as the steer. {properties.*} also resolves nested dot-paths and rejects non-scalar values with a named error.
  • The stuck-spinner trio: fetches now time out after 30s (a timer aborts the supersede controller; a flag keeps superseding clicks silent while timeouts speak), destroy() emits seriesCleared so teardown can't strand a spinner or stale card — which also makes it the contract's first real seriesCleared emitter, so the config description advertising it is finally true.
  • A click could die silently before error handling began — the async handler now has a .catch, and layers:getConfig goes through a typed, hasHandler-guarded wrapper in _shared, so clicks during mission load are silent no-ops instead of unhandled rejections.
  • seriesReady emits the ChartSeriesPayload flat, matching the SeriesChart: chart-series contract and single-variable chart plugin #293 contract change.
  • A wrong configured xKey/yKey was blamed on the API — it now throws "Configured xKey '…' matches nothing" instead of "no data".
  • Paginated responses were silently truncated — when numberMatched exceeds what was returned, the chart title carries "(first N of M points)".
  • Non-date data charted as 1970 timestamps — new xType layer config (time default, linear, category; unknown values degrade to time), documented with the ISO-or-epoch-ms requirement.
  • Mapping robustness: container detection prefers populated arrays over empty ones, key auto-detection scans a 25-item window past leading metadata rows, all-null values point at yKey instead of rendering an empty plot, ragged parallel arrays name the length mismatch, and parallel arrays now work at the response root exactly as the README example shows (it used to throw).
  • Colliding slugged group ids (e.g. two non-ASCII parameter names) get index suffixes so the chart's duplicate-id guard accepts them.
  • The kebab plugin id vs. core tool name distinction is documented in the tool header.
  • +21 specs, including first coverage of the tool's entire I/O layer (mock bus + stubbed fetch): supersede, timeout, teardown, HTTP/template errors, and the boot-window no-op.

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