Skip to content

feat: ephemeral measures UI for explore and canvas dashboards - #9864

Open
nishantmonu51 wants to merge 5 commits into
mainfrom
ephemeral_measures
Open

feat: ephemeral measures UI for explore and canvas dashboards#9864
nishantmonu51 wants to merge 5 commits into
mainfrom
ephemeral_measures

Conversation

@nishantmonu51

@nishantmonu51 nishantmonu51 commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

Frontend for ephemeral measures (labelled "Adhoc measures" in the UI) on top of the expression measure compute added in #9855: users define ad-hoc measures like profit = revenue - cost in the UI, without editing the metrics view YAML.

  • Explore: create and edit ephemeral measures from the measures selector and the pivot sidebar (EphemeralMeasureDialog). Definitions live on the explore state and are honored by every view: big numbers, time series, leaderboards, dimension table, time dimension detail, pivot (including comparison chips, conditional formatting and exports).
  • URL state and presets: definitions are encoded in the ephemeral URL param (name, display name, expression, optional format preset) and in ExplorePreset.ephemeral_measures, so shared links, bookmarks and the most-recent-state loader reproduce them. Invalid or unknown definitions are dropped with a user-visible error, along with any columns or sorts that reference them.
  • Canvas: components with measure fields (KPI, KPI grid, table/pivot, leaderboard, all charts) accept a calculated_measures renderer prop, editable from the inspector (EphemeralMeasureEditor) and offered inline from the field selectors. Requests attach the expression compute and labels/formatters resolve like for any spec measure.
  • Validation: a client-side parser (expression-parser.ts) mirrors the runtime allowlist (arithmetic, numeric literals, parentheses, unary minus, abs/round/floor/ceil/sqrt/ln/exp/power/coalesce/nullif/greatest/least) and gives inline errors. Names must not collide with metrics view fields or comparison accessor suffixes, and expressions can only reference plain measures (no window, required-dimension or time-comparison measures).
  • Sharing surfaces: public URLs keep only ephemeral measures whose referenced measures are visible to the recipient; alerts and scheduled reports never prefill an ephemeral measure since the saved query has no definition to resolve it against.
  • Adds EphemeralMeasure to the DashboardState proto for the legacy proto-state path.

Part of PLAT-135

Checklist:

  • Covered by tests
  • Ran it and it works as intended
  • Reviewed the diff before requesting a review
  • Checked for unhandled edge cases
  • Linked the issues it closes
  • Checked if the docs need to be updated. If so, create a separate Linear DOCS issue
  • Intend to cherry-pick into the release branch
  • I'm proud of this work!

Frontend for ephemeral (calculated) measures on top of the `expression`
measure compute: users define ad-hoc measures such as
`profit = revenue - cost` from the explore measure selector, the pivot
sidebar and the canvas inspector. Definitions live on the explore state
(encoded in the `ephemeral` URL param and explore preset) or on a canvas
component's `ephemeral_measures` prop, and every view attaches the
expression compute to matching request measures.

Claude-Session: https://claude.ai/code/session_01NW6ETnqzwL5jdoVCKQPHNf
The calc -> ephemeral rename also rewrote five CSS `calc(` tokens in
MeasureBigNumber.svelte. The i18n guard flagged hardcoded strings in the
ephemeral measure editors and in two files that now import messages, so
those strings move to the catalogs and the format preset list is shared.

Claude-Session: https://claude.ai/code/session_01NW6ETnqzwL5jdoVCKQPHNf
The YAML property on canvas components keeps the user-facing name
`calculated_measures`; the runtime validator and tests follow. Code
identifiers stay ephemeral-named.

Claude-Session: https://claude.ai/code/session_01NW6ETnqzwL5jdoVCKQPHNf
User-facing labels, titles and URL-state errors now say "adhoc measure"
instead of "calculated measure". Code identifiers and the canvas
`calculated_measures` property are unchanged.

Claude-Session: https://claude.ai/code/session_01NW6ETnqzwL5jdoVCKQPHNf
- Canvas chart validation accepts the chart's own ephemeral measures.
- The active (sort) measure resolves ephemeral measures so single-measure
  leaderboards format values instead of rendering blanks.
- The client expression parser uses the server's depth limit (32).
- "All measures visible" counts ephemeral measures, so a hidden spec measure
  is never reported as visible to public URLs, chat context or the editor.
- Public URLs keep pivot chips of ephemeral measures that survive sanitizing.
- Editing a scheduled report recovers ephemeral definitions from the saved
  request instead of a non-existent explore store.
- Removing the last visible measure re-seeds spec defaults.
- Aliases derived from display names always pass name validation (shared
  slugify), and URL-state validation reserves every metrics view field.

Claude-Session: https://claude.ai/code/session_01NW6ETnqzwL5jdoVCKQPHNf
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