@gravitee/gamma-lib-observability 1.40.0 → 2.0.0-feat-obs-41-http-dashboard-persistence.74f3ce8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/QUERYING.md +15 -3
- package/dist/dashboards/DashboardFilterChip.d.ts +32 -0
- package/dist/dashboards/DashboardFilterChip.d.ts.map +1 -0
- package/dist/dashboards/DashboardFilterChipPopover.d.ts +19 -0
- package/dist/dashboards/DashboardFilterChipPopover.d.ts.map +1 -0
- package/dist/dashboards/DashboardFilterChips.d.ts +29 -0
- package/dist/dashboards/DashboardFilterChips.d.ts.map +1 -0
- package/dist/dashboards/DashboardFilterValueForm.d.ts +32 -0
- package/dist/dashboards/DashboardFilterValueForm.d.ts.map +1 -0
- package/dist/dashboards/dashboard-filters.d.ts +79 -0
- package/dist/dashboards/dashboard-filters.d.ts.map +1 -0
- package/dist/dashboards/editor/DashboardEditorPage.d.ts +9 -1
- package/dist/dashboards/editor/DashboardEditorPage.d.ts.map +1 -1
- package/dist/dashboards/editor/DashboardFiltersEditor.d.ts +26 -0
- package/dist/dashboards/editor/DashboardFiltersEditor.d.ts.map +1 -0
- package/dist/dashboards/editor/dashboard-editor-state.d.ts +3 -0
- package/dist/dashboards/editor/dashboard-editor-state.d.ts.map +1 -1
- package/dist/dashboards/editor/locked-filter-conflicts.d.ts +29 -0
- package/dist/dashboards/editor/locked-filter-conflicts.d.ts.map +1 -0
- package/dist/dashboards/merge-filters.d.ts +12 -3
- package/dist/dashboards/merge-filters.d.ts.map +1 -1
- package/dist/dashboards/renderers/CartesianWidgetRenderer.d.ts.map +1 -1
- package/dist/dashboards/use-merged-widget-filters.d.ts +9 -4
- package/dist/dashboards/use-merged-widget-filters.d.ts.map +1 -1
- package/dist/data-sources/dashboard-errors.d.ts +42 -0
- package/dist/data-sources/dashboard-errors.d.ts.map +1 -0
- package/dist/data-sources/dashboard-wire.d.ts +85 -0
- package/dist/data-sources/dashboard-wire.d.ts.map +1 -0
- package/dist/data-sources/http-dashboard-persistence.d.ts +62 -0
- package/dist/data-sources/http-dashboard-persistence.d.ts.map +1 -0
- package/dist/data-sources/index.d.ts +2 -0
- package/dist/data-sources/index.d.ts.map +1 -1
- package/dist/filters/FilterBar.d.ts +8 -1
- package/dist/filters/FilterBar.d.ts.map +1 -1
- package/dist/filters/FilterChip.d.ts +16 -0
- package/dist/filters/FilterChip.d.ts.map +1 -1
- package/dist/filters/FilterPopoverForm.d.ts +21 -1
- package/dist/filters/FilterPopoverForm.d.ts.map +1 -1
- package/dist/filters/FilterValueField.d.ts +26 -0
- package/dist/filters/FilterValueField.d.ts.map +1 -0
- package/dist/filters/index.d.ts +1 -0
- package/dist/filters/index.d.ts.map +1 -1
- package/dist/filters/resolve-filter-label.d.ts +25 -0
- package/dist/filters/resolve-filter-label.d.ts.map +1 -0
- package/dist/filters/scope-ceiling.d.ts +33 -0
- package/dist/filters/scope-ceiling.d.ts.map +1 -0
- package/dist/filters/use-active-api-types.d.ts +18 -0
- package/dist/filters/use-active-api-types.d.ts.map +1 -0
- package/dist/filters/utils/build-filter-condition.d.ts.map +1 -1
- package/dist/filters/utils/filter-display.d.ts.map +1 -1
- package/dist/hooks/use-custom-dashboards.d.ts +3 -3
- package/dist/hooks/use-logs-query.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3537 -2830
- package/dist/logs/detail/components/LogDetailContextChart.d.ts.map +1 -1
- package/dist/persistence/local-storage-dashboard-persistence.d.ts +4 -4
- package/dist/providers/dashboard-persistence-provider.d.ts +4 -0
- package/dist/providers/dashboard-persistence-provider.d.ts.map +1 -1
- package/dist/providers/http-provider.d.ts +3 -2
- package/dist/providers/http-provider.d.ts.map +1 -1
- package/dist/routing/ObservabilityDashboardPage.d.ts.map +1 -1
- package/dist/routing/ObservabilityRoutes.d.ts.map +1 -1
- package/dist/styles/observability.css +1 -1
- package/dist/testing/graphene-core-icons-mock.d.ts +2 -0
- package/dist/testing/graphene-core-icons-mock.d.ts.map +1 -1
- package/dist/testing/graphene-core-mock.d.ts +6 -0
- package/dist/testing/graphene-core-mock.d.ts.map +1 -1
- package/dist/types/domain.d.ts +30 -1
- package/dist/types/domain.d.ts.map +1 -1
- package/dist/url-state/codec.d.ts.map +1 -1
- package/package.json +1 -1
package/QUERYING.md
CHANGED
|
@@ -229,11 +229,23 @@ series to keep a single left axis (backward compatible).
|
|
|
229
229
|
Filters merge in this order, later layers win on a field conflict:
|
|
230
230
|
|
|
231
231
|
```
|
|
232
|
-
|
|
232
|
+
dashboard definition (re-valuable default) → reader URL filters → dashboard definition (locked) → widget (widget.filters) → series/item (series[].filters / items[].filters)
|
|
233
233
|
```
|
|
234
234
|
|
|
235
|
-
|
|
236
|
-
|
|
235
|
+
**The host's context scope sits above all of it as a ceiling, not as a layer.** A module mounted with
|
|
236
|
+
`scopeApiTypes` (or explicit `contextFilters`) always carries that scope, and any condition on a
|
|
237
|
+
scoped field is intersected with it: a later layer can narrow inside the scope, never step outside
|
|
238
|
+
it. An intersection that comes out empty falls back to the host's own values rather than to no
|
|
239
|
+
condition at all, because a value-less condition is dropped before the request and would leave the
|
|
240
|
+
query unscoped. Only ceilings whose operator is `eq` or `in` are enforced this way. See
|
|
241
|
+
`clampToScope` in `src/filters/scope-ceiling.ts`.
|
|
242
|
+
|
|
243
|
+
Within a dashboard, a definition filter is locked or re-valuable (`editable`); see
|
|
244
|
+
`resolveDashboardFilters` for how a reader's URL filters are reconciled with it.
|
|
245
|
+
|
|
246
|
+
- The merged top-level filters are sent as the request `filters[]`. Item filters (`items[].filters`)
|
|
247
|
+
are sent as per-metric `filters[]`; series filters are merged into the top-level `filters[]` of
|
|
248
|
+
that series' own request, since each series is one request.
|
|
237
249
|
- Operators are mapped to the v2 wire format: `eq → EQ`, `in → IN`, `gte → GTE`, `lte → LTE`.
|
|
238
250
|
`eq`/`gte`/`lte` take a single value; `in` takes an array. Unsupported operators throw with a clear
|
|
239
251
|
error rather than silently dropping the filter.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FilterCondition } from '../types/domain';
|
|
2
|
+
export interface DashboardFilterChipProps {
|
|
3
|
+
readonly condition: FilterCondition;
|
|
4
|
+
/** Re-valuable slots show a chevron affordance; locked ones show a padlock. */
|
|
5
|
+
readonly revaluable: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* The reader has moved this slot off the author's value. Marked, because a
|
|
8
|
+
* shared link otherwise looks identical whether it carries the author's
|
|
9
|
+
* intent or somebody else's session.
|
|
10
|
+
*/
|
|
11
|
+
readonly changedByReader?: boolean;
|
|
12
|
+
/** Forwarded to {@link FilterChip}: whether the chip reacts to clicks at all. */
|
|
13
|
+
readonly editable?: boolean;
|
|
14
|
+
readonly active?: boolean;
|
|
15
|
+
readonly onEdit?: () => void;
|
|
16
|
+
/**
|
|
17
|
+
* Offers the X on hover and the Delete/Backspace shortcut, the gesture this
|
|
18
|
+
* app already uses for every other filter chip. The author's editor passes
|
|
19
|
+
* it; the reader's dashboard must not, since removing a dashboard filter is
|
|
20
|
+
* not theirs to do.
|
|
21
|
+
*/
|
|
22
|
+
readonly onRemove?: () => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Adapter that maps a dashboard-definition filter onto the generic
|
|
26
|
+
* {@link FilterChip}: an outline pill with a leading padlock (locked) or a
|
|
27
|
+
* trailing chevron (re-valuable), and `: Any` for an empty slot. This is the
|
|
28
|
+
* single place that owns the "dashboard chip" look. It composes FilterChip,
|
|
29
|
+
* it does not reimplement it.
|
|
30
|
+
*/
|
|
31
|
+
export declare const DashboardFilterChip: import('react').ForwardRefExoticComponent<DashboardFilterChipProps & import('react').RefAttributes<HTMLSpanElement>>;
|
|
32
|
+
//# sourceMappingURL=DashboardFilterChip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DashboardFilterChip.d.ts","sourceRoot":"","sources":["../../src/dashboards/DashboardFilterChip.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CAChC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,sHA4B9B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { FilterCondition } from '../types/domain';
|
|
3
|
+
export interface DashboardFilterChipPopoverProps {
|
|
4
|
+
readonly condition: FilterCondition;
|
|
5
|
+
readonly revaluable: boolean;
|
|
6
|
+
readonly changedByReader?: boolean;
|
|
7
|
+
/** When set, the chip also offers the X and the Delete shortcut. */
|
|
8
|
+
readonly onRemove?: () => void;
|
|
9
|
+
/** Renders the popover body; `close` dismisses it after apply/cancel. */
|
|
10
|
+
readonly renderForm: (close: () => void) => ReactNode;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A dashboard filter chip that opens a popover on click. It renders the shared
|
|
14
|
+
* {@link DashboardFilterChip} and anchors the popover to it via a virtual ref,
|
|
15
|
+
* the same pattern as `FilterBar`, so the edit / re-value form renders exactly
|
|
16
|
+
* like every other filter popover.
|
|
17
|
+
*/
|
|
18
|
+
export declare function DashboardFilterChipPopover({ condition, revaluable, changedByReader, onRemove, renderForm, }: DashboardFilterChipPopoverProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=DashboardFilterChipPopover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DashboardFilterChipPopover.d.ts","sourceRoot":"","sources":["../../src/dashboards/DashboardFilterChipPopover.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,yEAAyE;IACzE,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAC;CACvD;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,SAAS,EACT,UAAU,EACV,eAAe,EACf,QAAQ,EACR,UAAU,GACX,EAAE,+BAA+B,2CAwBjC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { FilterProvider } from '../filters/filter-provider';
|
|
2
|
+
import { FilterCondition } from '../types/domain';
|
|
3
|
+
export interface DashboardFilterChipsProps {
|
|
4
|
+
/** Locked dashboard filters: read-only, always applied. */
|
|
5
|
+
readonly lockedFilters: readonly FilterCondition[];
|
|
6
|
+
/** Re-valuable dashboard filters: the reader may change the value only. */
|
|
7
|
+
readonly revaluableFilters: readonly FilterCondition[];
|
|
8
|
+
/**
|
|
9
|
+
* The author's value for each re-valuable filter, aligned index by index.
|
|
10
|
+
* What a chip is compared against to know the reader has moved it.
|
|
11
|
+
*/
|
|
12
|
+
readonly revaluableDefaults?: readonly FilterCondition[];
|
|
13
|
+
/** Providers used to load values in the re-value popover. */
|
|
14
|
+
readonly providers: readonly FilterProvider[];
|
|
15
|
+
/** Active API types passed to async value loaders. */
|
|
16
|
+
readonly activeApiTypes?: readonly string[];
|
|
17
|
+
/** Called when the reader re-values a slot (field fixed; empty value = "*"). */
|
|
18
|
+
readonly onRevalue: (field: string, next: FilterCondition) => void;
|
|
19
|
+
/** Drops the reader's value so the author's takes over again. */
|
|
20
|
+
readonly onResetRevalue?: (field: string) => void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Dashboard-definition filter chips shown in view mode, rendered with the shared
|
|
24
|
+
* {@link FilterChip}. Locked filters render read-only with a padlock; re-valuable
|
|
25
|
+
* filters are clickable slots whose value the reader can change (field and
|
|
26
|
+
* operator are stated rather than offered). An empty value renders `label: Any`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function DashboardFilterChips({ lockedFilters, revaluableFilters, revaluableDefaults, providers, activeApiTypes, onRevalue, onResetRevalue, }: DashboardFilterChipsProps): import("react/jsx-runtime").JSX.Element | null;
|
|
29
|
+
//# sourceMappingURL=DashboardFilterChips.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DashboardFilterChips.d.ts","sourceRoot":"","sources":["../../src/dashboards/DashboardFilterChips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAKvD,MAAM,WAAW,yBAAyB;IACxC,2DAA2D;IAC3D,QAAQ,CAAC,aAAa,EAAE,SAAS,eAAe,EAAE,CAAC;IACnD,2EAA2E;IAC3E,QAAQ,CAAC,iBAAiB,EAAE,SAAS,eAAe,EAAE,CAAC;IACvD;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACzD,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IAC9C,sDAAsD;IACtD,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IACnE,iEAAiE;IACjE,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnD;AASD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,SAAS,EACT,cAAc,GACf,EAAE,yBAAyB,kDAmD3B"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FilterProvider } from '../filters/filter-provider';
|
|
2
|
+
import { FilterCondition } from '../types/domain';
|
|
3
|
+
export interface DashboardFilterValueFormProps {
|
|
4
|
+
/** The definition slot: its field and operator are the author's and stay. */
|
|
5
|
+
readonly condition: FilterCondition;
|
|
6
|
+
readonly provider?: FilterProvider;
|
|
7
|
+
readonly activeApiTypes?: readonly string[];
|
|
8
|
+
/**
|
|
9
|
+
* Puts the author's value back. Set only when the reader has moved away from
|
|
10
|
+
* it, so the control appears exactly when it has something to undo.
|
|
11
|
+
*/
|
|
12
|
+
readonly onReset?: () => void;
|
|
13
|
+
readonly onApply: (next: FilterCondition) => void;
|
|
14
|
+
readonly onCancel: () => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* What a reader gets when they open a re-valuable dashboard filter: one
|
|
18
|
+
* question, "which value?".
|
|
19
|
+
*
|
|
20
|
+
* Deliberately not the author's form with two thirds of it switched off. That
|
|
21
|
+
* shape showed a reader a field picker and an operator select they could never
|
|
22
|
+
* use, which communicates only that something is being withheld, and it made
|
|
23
|
+
* the guarantee a matter of disabled attributes: a greyed combobox is still
|
|
24
|
+
* focusable, and a wrapper that swallows input is a lie rather than a lock.
|
|
25
|
+
* Here the field and the operator are not controls at all, so there is nothing
|
|
26
|
+
* to grey, nothing to skip in the tab order, and no way to reach them.
|
|
27
|
+
*
|
|
28
|
+
* The value editor itself is shared with the author's form, so the half the two
|
|
29
|
+
* roles do have in common cannot drift.
|
|
30
|
+
*/
|
|
31
|
+
export declare function DashboardFilterValueForm({ condition, provider, activeApiTypes, onReset, onApply, onCancel, }: DashboardFilterValueFormProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
//# sourceMappingURL=DashboardFilterValueForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DashboardFilterValueForm.d.ts","sourceRoot":"","sources":["../../src/dashboards/DashboardFilterValueForm.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,4BAA4B,CAAC;AAIpF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,MAAM,WAAW,6BAA6B;IAC5C,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,SAAS,EACT,QAAQ,EACR,cAAc,EACd,OAAO,EACP,OAAO,EACP,QAAQ,GACT,EAAE,6BAA6B,2CAiF/B"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { FilterCondition } from '../types/domain';
|
|
2
|
+
/**
|
|
3
|
+
* How a filter with no value renders: every value passes, no query constraint.
|
|
4
|
+
* It is a slot the author leaves open so a reader finds the field ready to fill
|
|
5
|
+
* instead of having to build the chip themselves.
|
|
6
|
+
*
|
|
7
|
+
* A word rather than an asterisk. In a form, `*` is the established mark for a
|
|
8
|
+
* required field, so it read as the opposite of what this means.
|
|
9
|
+
*/
|
|
10
|
+
export declare const ALL_VALUES_LABEL = "Any";
|
|
11
|
+
/**
|
|
12
|
+
* A dashboard-definition filter is **locked** unless it explicitly opts into
|
|
13
|
+
* "allow value change" (`editable: true`). Defaulting a missing flag to locked
|
|
14
|
+
* is the safe direction: a scoping filter that silently became reader-editable
|
|
15
|
+
* would widen a scope its author fixed, while the reverse only costs a reader
|
|
16
|
+
* one control.
|
|
17
|
+
*
|
|
18
|
+
* A filter with no value is never locked, whatever the flag says. There is no
|
|
19
|
+
* value to fix, so locking one would produce a chip that constrains nothing and
|
|
20
|
+
* can never be filled: a dead slot. The rule lives here rather than only in the
|
|
21
|
+
* editor because a definition can also arrive from the JSON tab, a template or
|
|
22
|
+
* the backend, and none of those pass through the editor's toggle. Letting the
|
|
23
|
+
* reader value it cannot widen anything either, since the empty filter was
|
|
24
|
+
* imposing no constraint to begin with.
|
|
25
|
+
*/
|
|
26
|
+
export declare function isLocked(filter: FilterCondition): boolean;
|
|
27
|
+
export declare function isRevaluable(filter: FilterCondition): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* The flag to store for what the author expressed in the editor, kept next to
|
|
30
|
+
* {@link isLocked} so the two cannot drift apart on the empty-value rule.
|
|
31
|
+
*/
|
|
32
|
+
export declare function deriveEditable(allowValueChange: boolean, hasValue: boolean): boolean;
|
|
33
|
+
export interface ResolvedDashboardFilters {
|
|
34
|
+
/**
|
|
35
|
+
* Every field the dashboard governs, locked or re-valuable. Barrier 1: the
|
|
36
|
+
* page removes these from the reader's filter picker. Returned here rather
|
|
37
|
+
* than recomputed by the caller so all three barriers derive from one split.
|
|
38
|
+
*/
|
|
39
|
+
readonly governedFields: ReadonlySet<string>;
|
|
40
|
+
/** Locked filters: rendered read-only, always applied. */
|
|
41
|
+
readonly lockedChips: FilterCondition[];
|
|
42
|
+
/** Re-valuable filters, showing the reader's value if set, else the author's. */
|
|
43
|
+
readonly revaluableChips: FilterCondition[];
|
|
44
|
+
/**
|
|
45
|
+
* The author's own value for each re-valuable filter, aligned index by index
|
|
46
|
+
* with `revaluableChips`.
|
|
47
|
+
*
|
|
48
|
+
* Both halves already existed here; only the resolved one was published. A
|
|
49
|
+
* reader who changes a slot had no way to see they had diverged, and no way
|
|
50
|
+
* back: on a shared link the two are indistinguishable.
|
|
51
|
+
*/
|
|
52
|
+
readonly revaluableDefaults: FilterCondition[];
|
|
53
|
+
/** The reader's raw re-values (their URL filters on re-valuable fields), for preservation. */
|
|
54
|
+
readonly userRevalues: FilterCondition[];
|
|
55
|
+
/** The reader's own free filters (fields the dashboard does not govern). */
|
|
56
|
+
readonly userOwnFilters: FilterCondition[];
|
|
57
|
+
/** Filters actually applied to widgets (empty-value placeholders dropped at wire time). */
|
|
58
|
+
readonly effectiveFilters: FilterCondition[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Splits a dashboard's definition filters and the reader's URL filters into the
|
|
62
|
+
* chips to render and the effective filters to query.
|
|
63
|
+
*
|
|
64
|
+
* Locked filters are **non-circumventable** from the client. Three barriers,
|
|
65
|
+
* kept independent on purpose so no single one carries the guarantee alone:
|
|
66
|
+
*
|
|
67
|
+
* 1. the page removes every dashboard-governed field from the filter picker, so
|
|
68
|
+
* a competing chip cannot be built through the UI at all;
|
|
69
|
+
* 2. a URL filter on a locked field is discarded here. It lands in neither
|
|
70
|
+
* `userRevalues` nor `userOwnFilters`, so a hand-written query string is
|
|
71
|
+
* read and dropped rather than trusted;
|
|
72
|
+
* 3. the merge dedupes by field and takes the locked definitions last, so even
|
|
73
|
+
* a condition that reached this point some other way loses.
|
|
74
|
+
*
|
|
75
|
+
* A reader can only ever change the *value* of a re-valuable field. The flag
|
|
76
|
+
* itself is never encoded into the URL, so it cannot be granted by tampering.
|
|
77
|
+
*/
|
|
78
|
+
export declare function resolveDashboardFilters(dashboardFilters: readonly FilterCondition[], urlFilters: readonly FilterCondition[]): ResolvedDashboardFilters;
|
|
79
|
+
//# sourceMappingURL=dashboard-filters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-filters.d.ts","sourceRoot":"","sources":["../../src/dashboards/dashboard-filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,iBAAiB,CAAC;AAGvE;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AAEtC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAEzD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAE7D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,gBAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAEpF;AA4BD,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7C,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,eAAe,EAAE,CAAC;IACxC,iFAAiF;IACjF,QAAQ,CAAC,eAAe,EAAE,eAAe,EAAE,CAAC;IAC5C;;;;;;;OAOG;IACH,QAAQ,CAAC,kBAAkB,EAAE,eAAe,EAAE,CAAC;IAC/C,8FAA8F;IAC9F,QAAQ,CAAC,YAAY,EAAE,eAAe,EAAE,CAAC;IACzC,4EAA4E;IAC5E,QAAQ,CAAC,cAAc,EAAE,eAAe,EAAE,CAAC;IAC3C,2FAA2F;IAC3F,QAAQ,CAAC,gBAAgB,EAAE,eAAe,EAAE,CAAC;CAC9C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CACrC,gBAAgB,EAAE,SAAS,eAAe,EAAE,EAC5C,UAAU,EAAE,SAAS,eAAe,EAAE,GACrC,wBAAwB,CAiE1B"}
|
|
@@ -11,5 +11,13 @@
|
|
|
11
11
|
* belongs. The range still refreshes on demand, by re-picking it in the time
|
|
12
12
|
* range control.
|
|
13
13
|
*/
|
|
14
|
-
export
|
|
14
|
+
export interface DashboardEditorPageProps {
|
|
15
|
+
/**
|
|
16
|
+
* Context field carrying the host's module scope (e.g. `API_TYPE`), forwarded
|
|
17
|
+
* to the dashboard-filters editor so an author is only offered the fields and
|
|
18
|
+
* values their own module covers.
|
|
19
|
+
*/
|
|
20
|
+
readonly scopeFilterField?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function DashboardEditorPage({ scopeFilterField }: DashboardEditorPageProps): import("react/jsx-runtime").JSX.Element;
|
|
15
23
|
//# sourceMappingURL=DashboardEditorPage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardEditorPage.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/DashboardEditorPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DashboardEditorPage.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/DashboardEditorPage.tsx"],"names":[],"mappings":"AAkEA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,wBAAgB,mBAAmB,CAAC,EAAE,gBAAgB,EAAE,EAAE,wBAAwB,2CAYjF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { FilterCondition } from '../../types/domain';
|
|
2
|
+
export interface DashboardFiltersEditorProps {
|
|
3
|
+
readonly filters: readonly FilterCondition[];
|
|
4
|
+
/**
|
|
5
|
+
* Context field carrying the host's module scope (e.g. `API_TYPE`). It
|
|
6
|
+
* narrows what the author may *add*: which fields the picker offers and which
|
|
7
|
+
* values their loaders return. Without it an author scoped to LLM and MCP is
|
|
8
|
+
* shown every API the tenant owns and can build a filter pointing outside
|
|
9
|
+
* their own module.
|
|
10
|
+
*
|
|
11
|
+
* It deliberately does not narrow the filters already on the dashboard. Those
|
|
12
|
+
* stay editable and keep their catalog name whatever the scope says, so a
|
|
13
|
+
* definition written before the scope changed, or written by hand, never
|
|
14
|
+
* becomes a chip its author can only look at.
|
|
15
|
+
*/
|
|
16
|
+
readonly scopeFilterField?: string;
|
|
17
|
+
readonly onChange: (filters: FilterCondition[]) => void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Inline editor for a dashboard's definition filters. The author manipulates the
|
|
21
|
+
* exact chips the reader will see (WYSIWYG): each chip opens a popover to edit
|
|
22
|
+
* its value/operator and toggle "Allow value change" (locked vs re-valuable);
|
|
23
|
+
* "Add dashboard filter" appends one. An empty value renders `: Any`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function DashboardFiltersEditor({ filters, scopeFilterField, onChange }: DashboardFiltersEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
//# sourceMappingURL=DashboardFiltersEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DashboardFiltersEditor.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/DashboardFiltersEditor.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAa1D,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;CACzD;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,2BAA2B,2CAiD1G"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-editor-state.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/dashboard-editor-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGlH;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,uBAAuB,CAAA;CAAE,CAAC;AAEjE,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG,mBAAmB,CAE1E;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAEhE;AAMD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,oBAAoB,GAAG,mBAAmB,
|
|
1
|
+
{"version":3,"file":"dashboard-editor-state.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/dashboard-editor-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGlH;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,uBAAuB,CAAA;CAAE,CAAC;AAEjE,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG,mBAAmB,CAE1E;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAEhE;AAMD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,oBAAoB,GAAG,mBAAmB,CAgEnH;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAK5C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAE/D;AAED,6EAA6E;AAC7E,eAAO,MAAM,wBAAwB,YAAY,CAAC;AAClD,yEAAyE;AACzE,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAepC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAErE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAmDpG;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,IAAI,GAAG,MAAM,CAIvD;AAED,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,IAAiB,GAAG,SAAS,CAUtE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { FilterCondition, Widget } from '../../types/domain';
|
|
2
|
+
export interface LockedFilterConflict {
|
|
3
|
+
readonly widgetId: string;
|
|
4
|
+
/** Falls back to the id: a widget can be saved before it is named. */
|
|
5
|
+
readonly widgetTitle: string;
|
|
6
|
+
readonly field: string;
|
|
7
|
+
readonly label: string;
|
|
8
|
+
readonly dashboardValue: string[];
|
|
9
|
+
readonly dashboardValueLabels?: string[];
|
|
10
|
+
readonly widgetValue: string[];
|
|
11
|
+
readonly widgetValueLabels?: string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Widgets whose own filters override a locked dashboard filter.
|
|
15
|
+
*
|
|
16
|
+
* Widget filters are merged last, so on a shared field the widget's value is
|
|
17
|
+
* the one queried, whatever the padlock on the dashboard chip says. Within the
|
|
18
|
+
* host's module scope, which still clamps it either way. That is
|
|
19
|
+
* deliberate (see `ObservabilityDashboardPage`), which is exactly why the
|
|
20
|
+
* author has to be told: nothing downstream will. Most of these are written
|
|
21
|
+
* without anyone typing them, by `withAutoScope` stamping the `API_TYPE` a
|
|
22
|
+
* metric requires, so the contradiction can appear from picking a metric.
|
|
23
|
+
*
|
|
24
|
+
* A widget carrying the *same* value is not a conflict. It is what the AIM
|
|
25
|
+
* templates do today, pinning every widget to the API type the dashboard is
|
|
26
|
+
* about, and flagging it would cry wolf on the common case.
|
|
27
|
+
*/
|
|
28
|
+
export declare function findLockedFilterConflicts(dashboardFilters: readonly FilterCondition[], widgets: readonly Widget[]): LockedFilterConflict[];
|
|
29
|
+
//# sourceMappingURL=locked-filter-conflicts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locked-filter-conflicts.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/locked-filter-conflicts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGlE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CACvC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,gBAAgB,EAAE,SAAS,eAAe,EAAE,EAC5C,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,oBAAoB,EAAE,CAsBxB"}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { FilterCondition } from '../types/domain';
|
|
2
2
|
/**
|
|
3
|
-
* Union-merges multiple filter sources.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Union-merges multiple filter sources. Later sources take precedence when the
|
|
4
|
+
* same field is targeted, and the result keeps the first insertion position of
|
|
5
|
+
* each field.
|
|
6
|
+
*
|
|
7
|
+
* This is the mechanism, not the policy: it does not know which source is which
|
|
8
|
+
* and has no canonical order of its own. The host's scope is applied on top by
|
|
9
|
+
* `clampToScope`, which is what actually decides precedence and is the only
|
|
10
|
+
* place that describes the full chain.
|
|
11
|
+
*
|
|
12
|
+
* Note it keys on `field` alone, so two conditions on the same field with
|
|
13
|
+
* different operators can never coexist across sources: `latency gte 100` and
|
|
14
|
+
* `latency lte 500` collapse to one.
|
|
6
15
|
*/
|
|
7
16
|
export declare function mergeFilters(...sources: (readonly FilterCondition[] | undefined)[]): FilterCondition[];
|
|
8
17
|
//# sourceMappingURL=merge-filters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-filters.d.ts","sourceRoot":"","sources":["../../src/dashboards/merge-filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD
|
|
1
|
+
{"version":3,"file":"merge-filters.d.ts","sourceRoot":"","sources":["../../src/dashboards/merge-filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,GAAG,OAAO,EAAE,CAAC,SAAS,eAAe,EAAE,GAAG,SAAS,CAAC,EAAE,GAAG,eAAe,EAAE,CAWtG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CartesianWidgetRenderer.d.ts","sourceRoot":"","sources":["../../../src/dashboards/renderers/CartesianWidgetRenderer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CartesianWidgetRenderer.d.ts","sourceRoot":"","sources":["../../../src/dashboards/renderers/CartesianWidgetRenderer.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,oBAAoB,CAAC;AAO5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAGvE,wBAAgB,uBAAuB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,mBAAmB,CAAC,eAAe,CAAC,2CAkG3G"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { FilterCondition } from '../types/domain';
|
|
2
2
|
/**
|
|
3
3
|
* Resolves the effective filters for a widget renderer.
|
|
4
|
-
* Merge order: context → view → widget (widget wins on field conflict).
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* View filters then widget filters, the widget winning on a shared field, all
|
|
6
|
+
* of it then clamped by the host's context scope. The clamp is what changed:
|
|
7
|
+
* a widget filter used to replace a context filter outright, which let a widget
|
|
8
|
+
* render another module's data. It can now narrow inside the host's scope but
|
|
9
|
+
* not step outside it. See `clampToScope`.
|
|
10
|
+
*
|
|
11
|
+
* All widget renderers must use this hook so the contract is explicit and
|
|
12
|
+
* consistent, regardless of whether the downstream query hook also applies the
|
|
13
|
+
* scope itself.
|
|
9
14
|
*/
|
|
10
15
|
export declare function useMergedWidgetFilters(widgetFilters?: readonly FilterCondition[], viewFilters?: readonly FilterCondition[]): FilterCondition[];
|
|
11
16
|
//# sourceMappingURL=use-merged-widget-filters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-merged-widget-filters.d.ts","sourceRoot":"","sources":["../../src/dashboards/use-merged-widget-filters.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-merged-widget-filters.d.ts","sourceRoot":"","sources":["../../src/dashboards/use-merged-widget-filters.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,aAAa,CAAC,EAAE,SAAS,eAAe,EAAE,EAC1C,WAAW,CAAC,EAAE,SAAS,eAAe,EAAE,GACvC,eAAe,EAAE,CAGnB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Dashboard } from '../types/domain';
|
|
2
|
+
/**
|
|
3
|
+
* Failure returned by a server-backed dashboard persistence.
|
|
4
|
+
*
|
|
5
|
+
* The subclasses exist because the screens already tell these outcomes apart:
|
|
6
|
+
* a refused read degrades to the read-only template experience, a missing
|
|
7
|
+
* dashboard shows its own state, and a stale save asks the author what to do.
|
|
8
|
+
* Distinguishing them on a status code parsed from the message would put that
|
|
9
|
+
* decision in every caller instead of here.
|
|
10
|
+
*/
|
|
11
|
+
export declare class DashboardPersistenceError extends Error {
|
|
12
|
+
readonly status: number;
|
|
13
|
+
constructor(status: number, message: string);
|
|
14
|
+
}
|
|
15
|
+
/** The caller lacks the `ENVIRONMENT_DASHBOARD` ACL for this verb. */
|
|
16
|
+
export declare class DashboardForbiddenError extends DashboardPersistenceError {
|
|
17
|
+
constructor(message: string);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* No dashboard with this id exists in the current environment.
|
|
21
|
+
*
|
|
22
|
+
* The API answers 404 rather than 403 for an id belonging to another
|
|
23
|
+
* environment, so this also covers a dashboard the caller may not reach.
|
|
24
|
+
*/
|
|
25
|
+
export declare class DashboardNotFoundError extends DashboardPersistenceError {
|
|
26
|
+
readonly dashboardId: string;
|
|
27
|
+
constructor(dashboardId: string, message: string);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The dashboard was saved by someone else since it was read, so the update was
|
|
31
|
+
* refused and nothing on the server changed.
|
|
32
|
+
*
|
|
33
|
+
* Carries the server's current dashboard because the API returns it in the 412
|
|
34
|
+
* body: the author can be shown what they were about to overwrite, and can
|
|
35
|
+
* choose to reload, save a copy, or overwrite, without a second request.
|
|
36
|
+
*/
|
|
37
|
+
export declare class DashboardConflictError extends DashboardPersistenceError {
|
|
38
|
+
readonly currentVersion: number | undefined;
|
|
39
|
+
readonly currentDashboard: Dashboard;
|
|
40
|
+
constructor(message: string, currentDashboard: Dashboard, currentVersion?: number);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=dashboard-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-errors.d.ts","sourceRoot":"","sources":["../../src/data-sources/dashboard-errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;GAQG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK5C;AAED,sEAAsE;AACtE,qBAAa,uBAAwB,SAAQ,yBAAyB;gBACxD,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,qBAAa,sBAAuB,SAAQ,yBAAyB;IACnE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAKjD;AAED;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,yBAAyB;IACnE,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,gBAAgB,EAAE,SAAS,CAAC;gBAEzB,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM;CAMlF"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Dashboard, FilterCondition, TimeRange, Widget } from '../types/domain';
|
|
2
|
+
/**
|
|
3
|
+
* Wire shapes of the Gamma dashboards API and the mapping to the lib's domain
|
|
4
|
+
* model, in one module so the two directions cannot drift apart.
|
|
5
|
+
*
|
|
6
|
+
* The API is the authority on these shapes (`DashboardDto`, `DashboardFilterDto`,
|
|
7
|
+
* `DashboardTimeRangeDto`, `SaveDashboardRequestDto`). Every optional/nullable
|
|
8
|
+
* field below is declared that way because the server declares it that way, not
|
|
9
|
+
* defensively: the response types are what a `null` in the JSON actually looks
|
|
10
|
+
* like, and the mapping is the single place that decides what it becomes.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* One dashboard-definition filter as the API returns it. `operator` is
|
|
14
|
+
* UPPERCASE and `value` is always an array, even for single-value operators.
|
|
15
|
+
*/
|
|
16
|
+
export interface WireDashboardFilter {
|
|
17
|
+
name: string;
|
|
18
|
+
label?: string | null;
|
|
19
|
+
operator: string;
|
|
20
|
+
value?: string[] | null;
|
|
21
|
+
editable?: boolean | null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* `type` is lowercase on the wire — it was chosen to match this lib's
|
|
25
|
+
* discriminated union, so no translation is needed beyond the null handling.
|
|
26
|
+
*/
|
|
27
|
+
export interface WireTimeRange {
|
|
28
|
+
type: string;
|
|
29
|
+
period?: string | null;
|
|
30
|
+
from?: number | null;
|
|
31
|
+
to?: number | null;
|
|
32
|
+
}
|
|
33
|
+
export interface WireDashboard {
|
|
34
|
+
id: string;
|
|
35
|
+
title: string;
|
|
36
|
+
description?: string | null;
|
|
37
|
+
filters?: WireDashboardFilter[] | null;
|
|
38
|
+
timeRange?: WireTimeRange | null;
|
|
39
|
+
widgets?: unknown;
|
|
40
|
+
/** Revision counter, also handed out as the response `ETag`. Starts at 1. */
|
|
41
|
+
version?: number | null;
|
|
42
|
+
createdAt?: number | null;
|
|
43
|
+
updatedAt?: number | null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Body of `POST` and `PUT`. Server-owned fields (`version`, `createdAt`,
|
|
47
|
+
* `updatedAt`, `createdBy`) are absent by design — the API ignores them, and
|
|
48
|
+
* the revision a `PUT` is based on travels in `If-Match`, not in the body.
|
|
49
|
+
*/
|
|
50
|
+
export interface WireSaveDashboardRequest {
|
|
51
|
+
/** Client-supplied, and read on `POST` only: `PUT` takes the id from the path. */
|
|
52
|
+
id?: string;
|
|
53
|
+
title: string;
|
|
54
|
+
description?: string;
|
|
55
|
+
filters: WireDashboardFilter[];
|
|
56
|
+
timeRange: WireTimeRange;
|
|
57
|
+
widgets: readonly Widget[];
|
|
58
|
+
}
|
|
59
|
+
export interface WirePagination {
|
|
60
|
+
totalCount: number;
|
|
61
|
+
page: number;
|
|
62
|
+
perPage: number;
|
|
63
|
+
pageCount: number;
|
|
64
|
+
pageItemsCount: number;
|
|
65
|
+
}
|
|
66
|
+
export interface WireDashboardsPage {
|
|
67
|
+
data?: WireDashboard[] | null;
|
|
68
|
+
pagination?: WirePagination | null;
|
|
69
|
+
}
|
|
70
|
+
/** Body of the `412` refusing a stale save. Extends the standard error shape. */
|
|
71
|
+
export interface WireDashboardConflict {
|
|
72
|
+
message?: string;
|
|
73
|
+
http_status?: number;
|
|
74
|
+
currentVersion?: number | null;
|
|
75
|
+
dashboard?: WireDashboard | null;
|
|
76
|
+
}
|
|
77
|
+
export declare function toWireFilter(filter: FilterCondition): WireDashboardFilter;
|
|
78
|
+
export declare function fromWireFilter(wire: WireDashboardFilter): FilterCondition;
|
|
79
|
+
export declare function toWireTimeRange(timeRange: TimeRange): WireTimeRange;
|
|
80
|
+
export declare function fromWireTimeRange(wire: WireTimeRange | null | undefined): TimeRange;
|
|
81
|
+
export declare function fromWireDashboard(wire: WireDashboard): Dashboard;
|
|
82
|
+
export declare function toWireSaveRequest(dashboard: Dashboard, options: {
|
|
83
|
+
readonly includeId: boolean;
|
|
84
|
+
}): WireSaveDashboardRequest;
|
|
85
|
+
//# sourceMappingURL=dashboard-wire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-wire.d.ts","sourceRoot":"","sources":["../../src/data-sources/dashboard-wire.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAkC,SAAS,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAErH;;;;;;;;;GASG;AAEH;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,mBAAmB,EAAE,GAAG,IAAI,CAAC;IACvC,SAAS,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,kFAAkF;IAClF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,SAAS,EAAE,aAAa,CAAC;IACzB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAC9B,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CACpC;AAED,iFAAiF;AACjF,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CAClC;AAwBD,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,mBAAmB,CAYzE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,mBAAmB,GAAG,eAAe,CASzE;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,aAAa,CAInE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,CAcnF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,CAiBhE;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GACvC,wBAAwB,CAS1B"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { HttpOptions } from '../providers/http-provider';
|
|
2
|
+
import { Dashboard } from '../types/domain';
|
|
3
|
+
import { DashboardPersistence } from './dashboard-persistence';
|
|
4
|
+
export interface HttpDashboardPersistenceOptions extends HttpOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Path appended to `baseUrl` for the dashboards collection.
|
|
7
|
+
* @default '/observability/dashboards'
|
|
8
|
+
*/
|
|
9
|
+
readonly dashboardsPath?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface UpdateDashboardOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Applies the write over whatever revision is current (`If-Match: *`) instead
|
|
14
|
+
* of the revision this adapter last saw.
|
|
15
|
+
*
|
|
16
|
+
* This is the second step of the conflict flow, not a convenience: an author
|
|
17
|
+
* who was refused a save and chose "overwrite" applies their edit in one
|
|
18
|
+
* request, where re-reading and re-submitting could lose the same race again.
|
|
19
|
+
* It cannot be reached by accident — only by asking for it here. The
|
|
20
|
+
* dashboard must still exist, so an overwrite never resurrects a deleted one.
|
|
21
|
+
*/
|
|
22
|
+
readonly force?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A {@link DashboardPersistence} that can also be asked for a deliberate
|
|
26
|
+
* overwrite. The extra argument is optional, so this is the port plus a
|
|
27
|
+
* capability rather than a different shape: anything typed against the port
|
|
28
|
+
* keeps working, and callers holding this type can offer the overwrite.
|
|
29
|
+
*/
|
|
30
|
+
export interface HttpDashboardPersistence extends DashboardPersistence {
|
|
31
|
+
updateDashboard(dashboard: Dashboard, signal?: AbortSignal, options?: UpdateDashboardOptions): Promise<Dashboard>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* {@link DashboardPersistence} backed by the Gamma dashboards API
|
|
35
|
+
* (`{baseUrl}/observability/dashboards`).
|
|
36
|
+
*
|
|
37
|
+
* <h3>Revisions</h3>
|
|
38
|
+
* The API guards concurrent edits with `ETag` / `If-Match`, and its revision
|
|
39
|
+
* counter has no home in the lib's `Dashboard` — deliberately, so the port stays
|
|
40
|
+
* the same contract whatever backs it. This adapter therefore remembers, per
|
|
41
|
+
* dashboard id, the validator naming the revision the caller is working from,
|
|
42
|
+
* and quotes it back on the next save. `If-Match` is always sent, so the API's
|
|
43
|
+
* 428 is unreachable from here.
|
|
44
|
+
*
|
|
45
|
+
* A **write** always adopts the revision it just produced: after a save, that is
|
|
46
|
+
* what the caller holds. A **read** only fills a blank — it never moves a
|
|
47
|
+
* revision already remembered. The two differ because a read is not proof the
|
|
48
|
+
* caller took the content: an editor holds a draft seeded from an earlier read
|
|
49
|
+
* while TanStack Query refetches behind it, and adopting that refetch's revision
|
|
50
|
+
* would let the draft be saved with a validator naming a revision it was never
|
|
51
|
+
* based on — silently overwriting the edit that produced it, which is the one
|
|
52
|
+
* outcome the whole mechanism exists to prevent. The cost of the other direction
|
|
53
|
+
* is a save refused as a conflict while the author was in fact already looking
|
|
54
|
+
* at the current revision: they are shown it and can overwrite in one request.
|
|
55
|
+
* Visible and recoverable, where the reverse is neither.
|
|
56
|
+
*
|
|
57
|
+
* The `ETag` header is preferred and the body's `version` is the fallback: a
|
|
58
|
+
* cross-origin deployment that does not expose `ETag` still yields a usable
|
|
59
|
+
* validator instead of silently degrading every save to an overwrite.
|
|
60
|
+
*/
|
|
61
|
+
export declare function createHttpDashboardPersistence(baseUrl: string, options?: HttpDashboardPersistenceOptions): HttpDashboardPersistence;
|
|
62
|
+
//# sourceMappingURL=http-dashboard-persistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-dashboard-persistence.d.ts","sourceRoot":"","sources":["../../src/data-sources/http-dashboard-persistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAOjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAkBpE,MAAM,WAAW,+BAAgC,SAAQ,WAAW;IAClE;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;;;;;;OASG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,wBAAyB,SAAQ,oBAAoB;IACpE,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACnH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,+BAA+B,GACxC,wBAAwB,CAgN1B"}
|