Skip to content

A gauge widget's options.invert has no observable effect, and nothing can say so — it is an undeclared key riding DashboardWidgetOptionsSchema.passthrough() #5709

Description

@os-sam

Filed from the hotcrm exemplar (objectstack-ai/hotcrm#1213), per the lane charter: a platform gap found while building the showcase app is filed upstream rather than papered over there. hotcrm has already fixed its own metadata, so nothing here is blocking that repo — what is left is a question this repo's seat owns.

I cannot see the renderer from where this was measured, so this card reports what was measured and what was read, and does not claim a cause. See "What I could not check" below.

What was measured

hotcrm's service dashboard shipped a gauge widget that plotted the SLA violation rate and asked for it to be flipped for display:

id: 'sla_compliance_gauge',title: 'SLA Compliance',type: 'gauge',dataset: 'case_metrics',values: ['avg_sla_violated'],// AVG(is_sla_violated)options: {format: '0%',invert: true,// value is sla_violated rate; gauge shows compliance = 1 - ratethresholds: [{value: 0.95,color: 'success'},],},

Driven in a browser against a fresh pnpm dev on 17.1.0, on a seeded org whose 8 closed cases are all within SLA (violation rate 0, compliance 100%), the widget rendered:

SLA 达成率
本期 SLA 内解决工单的占比
0.0%
SLA Violation Rate ← the measure's own label, printed under the number

That is the raw measure value, formatted by format: '0%', with no inversion applied. The complement (100%) was not rendered anywhere. The same page simultaneously showed violation rates of 40–70% in other tiles, so the gauge was the only reading that disagreed with the rest of the page.

What was read, in @objectstack/spec @ 17.1.0

packages/spec/src/ui/dashboard.zod.ts:217DashboardWidgetOptionsSchema ends in .passthrough(), described as "declared query keys + open renderer extras". invert is not among the declared keys. It therefore parses, validates and lints cleanly on the way through, and no validator, lint rule or gate in either repo is able to tell an author that the key does nothing — and none did. The comment beside it shows the author believed it was doing something.

The question this raises

Two coherent answers, and picking between them is this repo's call:

  1. The renderer should honour itinvert is a reasonable request for a gauge whose measure is stored as a complement, and the key should become declared and implemented.
  2. An undeclared key that does nothing should be refused, not accepted in silence — if invert is not a thing, the failure mode above (metadata that reads as correct, renders as wrong, and cannot be linted) is the cost of .passthrough() accepting arbitrary renderer extras. Some way for an author to learn that a key reached nothing would have caught this at authoring time instead of in a browser.

The second is the more general issue: invert is one key, and .passthrough() accepts any other.

Possibly the mechanism — for this repo's seat to confirm, not a claim

#4295 (closed, not_planned) measured that gauge / solid-gauge / bullet / kpi are all routed by construction to the single-value / metric path (METRIC_TYPES, METRIC_LIKE_TYPES, SINGLE_VALUE_CHART_TYPES), because no dial/arc/target renderer exists yet — a gauge renders as a plain number, deliberately. The observation above is consistent with that: what rendered was a plain formatted number. If a gauge never reaches a gauge renderer, then gauge-specific options plausibly have nowhere to be applied. Whether that is actually why invert had no effect is exactly what I cannot verify.

What I could not check

The console renderer package is not installed in either the hotcrm or the objectstack checkout this was worked from, so I did not read the gauge/metric render path at all. I am not asserting that the console ignores invert; I am reporting a rendered value that matches the un-inverted measure, plus the schema fact that the key is undeclared. The cause determination belongs here.

Context


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatched

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions