@gravitee/gamma-lib-observability 5.2.0 → 6.0.0

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.
Files changed (39) hide show
  1. package/INTEGRATION.md +11 -0
  2. package/QUERYING.md +46 -20
  3. package/USAGE_GUIDE.md +14 -1
  4. package/dist/dashboard-access-provider.js +68 -54
  5. package/dist/dashboards/editor/DashboardEditorPage.d.ts.map +1 -1
  6. package/dist/dashboards/editor/WidgetConfigForm.d.ts +7 -2
  7. package/dist/dashboards/editor/WidgetConfigForm.d.ts.map +1 -1
  8. package/dist/dashboards/editor/WidgetPreview.d.ts +1 -1
  9. package/dist/dashboards/editor/dashboard-json.d.ts.map +1 -1
  10. package/dist/dashboards/editor/locked-filter-conflicts.d.ts +29 -12
  11. package/dist/dashboards/editor/locked-filter-conflicts.d.ts.map +1 -1
  12. package/dist/dashboards/editor/widget-auto-scope.d.ts +7 -2
  13. package/dist/dashboards/editor/widget-auto-scope.d.ts.map +1 -1
  14. package/dist/dashboards/merge-filters.d.ts +8 -5
  15. package/dist/dashboards/merge-filters.d.ts.map +1 -1
  16. package/dist/dashboards/metric-group-requests.d.ts +35 -0
  17. package/dist/dashboards/metric-group-requests.d.ts.map +1 -0
  18. package/dist/dashboards/renderers/CartesianWidgetRenderer.d.ts.map +1 -1
  19. package/dist/dashboards/renderers/MetricGroupWidgetRenderer.d.ts.map +1 -1
  20. package/dist/dashboards/use-merged-widget-filters.d.ts +8 -6
  21. package/dist/dashboards/use-merged-widget-filters.d.ts.map +1 -1
  22. package/dist/data-sources/http-data-source.d.ts.map +1 -1
  23. package/dist/filters/index.d.ts +1 -1
  24. package/dist/filters/index.d.ts.map +1 -1
  25. package/dist/filters/scope-ceiling.d.ts +27 -1
  26. package/dist/filters/scope-ceiling.d.ts.map +1 -1
  27. package/dist/hooks/query-keys.d.ts.map +1 -1
  28. package/dist/index.js +2860 -2752
  29. package/dist/providers/clamped-data-sources.d.ts +8 -5
  30. package/dist/providers/clamped-data-sources.d.ts.map +1 -1
  31. package/dist/testing/mock-metrics-data-source.d.ts.map +1 -1
  32. package/dist/testing.js +7 -7
  33. package/dist/types/domain.d.ts +9 -5
  34. package/dist/types/domain.d.ts.map +1 -1
  35. package/dist/types/requests.d.ts +8 -0
  36. package/dist/types/requests.d.ts.map +1 -1
  37. package/dist/types/responses.d.ts +6 -0
  38. package/dist/types/responses.d.ts.map +1 -1
  39. package/package.json +1 -1
package/INTEGRATION.md CHANGED
@@ -1332,6 +1332,17 @@ interface MetricsDataSource {
1332
1332
  }
1333
1333
  ```
1334
1334
 
1335
+ The request contract a custom source must honour:
1336
+
1337
+ - `filters[]` can name the **same field several times** (a dashboard filter and a widget's own
1338
+ filter on `HTTP_STATUS`, plus the host scope). Every condition must be ANDed: a source that keeps
1339
+ only one per field lets a widget ignore the dashboard, or step outside the host's scope.
1340
+ - A metric-group `fetchMeasures` names each metric with an `id` (all or none), and can name the same
1341
+ metric twice with different `metrics[].filters`. Echo each `id` on its `MetricResult`; results
1342
+ without ids are read by metric name, and two tiles on one metric then show the same value.
1343
+
1344
+ See [`QUERYING.md` §6](./QUERYING.md#6-filter-semantics).
1345
+
1335
1346
  ### Custom filter providers
1336
1347
 
1337
1348
  Override the async-loaded filter definitions:
package/QUERYING.md CHANGED
@@ -47,7 +47,8 @@ Which request fields each endpoint accepts (✅ supported, — not applicable):
47
47
  | `ranges` | `NumericRange[]` | `{ from: number; to: number }[]` — inclusive `from`, exclusive `to`. |
48
48
  | `metrics[].name` | `string` | Metric name, e.g. `HTTP_REQUESTS`, `HTTP_GATEWAY_RESPONSE_TIME`, `LLM_PROMPT_TOTAL_TOKEN`. |
49
49
  | `metrics[].measures` | `string[]` | `AVG`, `MIN`, `MAX`, `P50`, `P90`, `P95`, `P99`, `COUNT`, `PERCENTAGE`. |
50
- | `metrics[].filters` | `FilterCondition[]` | Per-metric filters (same shape as top-level filters). |
50
+ | `metrics[].id` | `string` | **measures only.** The caller's name for the metric, echoed on its result. All metrics of a request or none (§5.5). |
51
+ | `metrics[].filters` | `FilterCondition[]` | Per-metric filters (same shape as top-level filters), ANDed with them. **measures only.** |
51
52
  | `metrics[].sorts` | `MeasureSort[]` | `{ measure, order: 'ASC' \| 'DESC' }[]` (facets & grouped time-series only). |
52
53
  | filter `operator` | `eq` / `in` / `gte` / `lte` | Mapped to wire `EQ` / `IN` / `GTE` / `LTE`. Other lib operators throw at serialization time. |
53
54
 
@@ -203,7 +204,15 @@ Each example shows the widget config and the resulting request payload.
203
204
  }
204
205
  ```
205
206
 
206
- → `{ metrics: [ { name: 'HTTP_REQUESTS', measures: ['COUNT'] }, { name: 'HTTP_ERRORS', measures: ['COUNT'], filters: [{ name: 'HTTP_STATUS_CODE_GROUP', operator: 'EQ', value: '5xx' }] } ], timeRange }`
207
+ → `{ metrics: [ { id: 'HTTP_REQUESTS::', name: 'HTTP_REQUESTS', measures: ['COUNT'] }, { id: 'HTTP_ERRORS::[…]', name: 'HTTP_ERRORS', measures: ['COUNT'], filters: [{ name: 'HTTP_STATUS_CODE_GROUP', operator: 'EQ', value: '5xx' }] } ], timeRange }`
208
+
209
+ Every metric of a metric-group request carries an `id`: its metric and its own conditions. Tiles
210
+ sharing both share an entry, and two tiles on **the same metric** with different filters (`Requests`
211
+ and `5xx requests` on `HTTP_REQUESTS`) each get their own value. The response echoes each `id`, and
212
+ tiles are read by it, the previous-period request included. A source whose results carry no `id` is
213
+ read by metric name, and two tiles on one metric then show the same value. A metric group can use at
214
+ most 10 distinct sets of tile filters (tiles without filters do not count): the JSON tab refuses more.
215
+ A Management API older than OBS-132 ignores the ids and does not apply tile filters.
207
216
 
208
217
  ### 5.6 Dual-axis combo chart (mixed bar + line)
209
218
 
@@ -288,37 +297,54 @@ order is the priority.
288
297
 
289
298
  ## 6. Filter semantics
290
299
 
291
- Filters merge in this order, later layers win on a field conflict:
300
+ A widget's request carries two layers, **appended, never merged into each other**:
292
301
 
293
302
  ```
294
- dashboard definition (re-valuable default) → reader URL filters → dashboard definition (locked) → widget (widget.filters) → series/item (series[].filters / items[].filters)
303
+ dashboard layer: definition (re-valuable default) → reader URL filters → definition (locked)
304
+ then: widget (widget.filters) → series (series[].filters)
295
305
  ```
296
306
 
297
- **The host's context scope sits above all of it as a ceiling, not as a layer.** A module mounted with
298
- `scopeApiTypes` (or explicit `contextFilters`) always carries that scope, and any condition on a
299
- scoped field is intersected with it: a later layer can narrow inside the scope, never step outside
300
- it. An intersection that comes out empty falls back to the host's own values rather than to no
301
- condition at all, because a value-less condition is dropped before the request and would leave the
302
- query unscoped. Only ceilings whose operator is `eq` or `in` are enforced this way. See
303
- `clampToScope` in `src/filters/scope-ceiling.ts`.
307
+ Inside the **dashboard layer**, a later source replaces an earlier one on the same field: a reader
308
+ value replaces the default, a locked definition filter holds. A dashboard keeps one filter per field.
309
+ See `resolveDashboardFilters` for how a reader's URL filters are reconciled with it.
310
+
311
+ The widget's and the series' own filters are then **appended** to that list, never replacing it.
312
+ The same field can appear several times in `filters[]`, and the analytics API ANDs every top-level
313
+ condition (OBS-132). A widget filter therefore **combines** with the dashboard's, like Kibana,
314
+ Datadog, Grafana and New Relic do: a "5xx" widget under a dashboard filtered on `HTTP_STATUS = 200`
315
+ answers 0 rather than ignoring the dashboard. The editor flags a widget, series or tile value that can
316
+ never overlap a **locked** dashboard value ("These widgets will be empty under the dashboard filters").
317
+
318
+ Metric-group tile filters (`items[].filters`) stay on their metric (`metrics[].filters`, measures
319
+ only), where the API ANDs them with the request's `filters[]`; see §5.5. Facets and time-series never
320
+ carry per-metric filters.
321
+
322
+ > **Requires a Management API with OBS-132.** An older one refuses a repeated top-level field
323
+ > (`observability.filter.repeated`, HTTP 400) and does not apply tile filters.
324
+
325
+ **The host's context scope sits above all of it as a ceiling.** A module mounted with
326
+ `scopeApiTypes` (or explicit `contextFilters`) always sends that scope, and every other condition is
327
+ sent beside it: the API ANDs them, so a request can never leave the scope. A widget pinned entirely
328
+ outside it answers 0, and a `contains`, `gte` or `lte` on a scoped field narrows inside it. A
329
+ condition identical to one already listed (same field, operator and values, in any order) is sent
330
+ once. See `clampAnalyticsToScope` in `src/filters/scope-ceiling.ts`.
331
+
332
+ **Logs keep the older clamp** (`clampToScope`): the logs search refuses a repeated field, so a
333
+ condition on a scoped field is intersected with the scope, and an empty intersection falls back to
334
+ the host's own values.
304
335
 
305
336
  The clamp happens at the data source, not at each call site. `useMetricsDataSource`,
306
337
  `useLogsDataSource` and their `useOptional*` variants return a source that clamps the top-level
307
338
  `filters` of every request against the context filters before delegating to the one the host
308
- mounted, so a component that queries the source directly, or merges a filter after its own clamp,
339
+ mounted, so a component that queries the source directly, or appends a filter after its own clamp,
309
340
  still cannot step outside the scope. The query hooks clamp as well, because their cache keys are
310
341
  derived from the filters actually sent; clamping twice changes nothing. Per-metric `filters` are
311
- not clamped (the server ANDs them under the top-level ones), and neither is the `apiId` passed to
342
+ not clamped (the API ANDs them with the top-level ones), and neither is the `apiId` passed to
312
343
  `getById`. See `src/providers/clamped-data-sources.ts`.
313
344
 
314
- Within a dashboard, a definition filter is locked or re-valuable (`editable`); see
315
- `resolveDashboardFilters` for how a reader's URL filters are reconciled with it.
345
+ A custom `MetricsDataSource` must AND repeated fields in `filters[]`, and should echo each metric's
346
+ `id` on its result.
316
347
 
317
- - The merged top-level filters are sent as the request `filters[]`. Item filters (`items[].filters`)
318
- are sent as per-metric `filters[]`; series filters are merged into the top-level `filters[]` of
319
- that series' own request, since each series is one request. The Gamma analytics endpoints validate
320
- per-metric filters but do not apply them yet: they come back in that metric's `ignoredFilters`, so
321
- the widget says so instead of showing an unfiltered number as filtered.
322
348
  - Operators are mapped to the v2 wire format: `eq → EQ`, `in → IN`, `gte → GTE`, `lte → LTE`.
323
349
  `eq`/`gte`/`lte` take a single value; `in` takes an array. Unsupported operators throw with a clear
324
350
  error rather than silently dropping the filter.
package/USAGE_GUIDE.md CHANGED
@@ -187,6 +187,17 @@ export const myMetricsDataSource: MetricsDataSource = {
187
187
 
188
188
  Pass it as the `dataSource` prop on `<observability.Routes>` to override the built-in adapter.
189
189
 
190
+ The request contract a custom source must honour:
191
+
192
+ - `filters[]` can name the **same field several times** (a dashboard filter and a widget's own
193
+ filter on `HTTP_STATUS`, plus the host scope). Every condition must be ANDed: a source that keeps
194
+ only one per field lets a widget ignore the dashboard, or step outside the host's scope.
195
+ - A metric-group `fetchMeasures` names each metric with an `id` (all or none), and can name the same
196
+ metric twice with different `metrics[].filters`. Echo each `id` on its `MetricResult`; results
197
+ without ids are read by metric name, and two tiles on one metric then show the same value.
198
+
199
+ See [`QUERYING.md` §6](./QUERYING.md#6-filter-semantics).
200
+
190
201
  ### Custom LogsDataSource
191
202
 
192
203
  ```ts
@@ -244,7 +255,7 @@ When no `CapabilityProvider` is present, all capabilities default to `false` (se
244
255
  - `TimeSeriesPoint` — `{ timestamp, value }`
245
256
  - `TimeSeriesGroup` — `{ key, label, points, ignoredFilters? }`
246
257
  - `FacetBucket` — `{ value, label, count, metric?, unit?, measures?, ignoredFilters? }`
247
- - `MetricResult` — `{ name, unit?, measures, ignoredFilters? }`. `ignoredFilters` names the filters the backend could not apply to the metric; see [`QUERYING.md`](./QUERYING.md#filters-a-metric-could-not-apply)
258
+ - `MetricResult` — `{ id?, name, unit?, measures, ignoredFilters? }`. `id` echoes the request metric's `id` when the request named its metrics by id (metric groups). `ignoredFilters` names the filters the backend could not apply to the metric; see [`QUERYING.md`](./QUERYING.md#filters-a-metric-could-not-apply)
248
259
  - `MeasureValue` — `{ key, label, value, unit?, previousValue? }`
249
260
  - `TraceSummary` — trace list entry (traceId, rootOperationName, rootServiceName, startTime, duration, spanCount, status)
250
261
  - `TraceDetail` — full trace with span tree (extends summary with `spans: Span[]`)
@@ -362,6 +373,8 @@ import { DashboardWidget } from '@gravitee/graphene-charts/dashboard-grid';
362
373
 
363
374
  `WidgetGroup` filters are passed to renderers via the `filters` prop. If a page-level `ContextFiltersProvider` is also present, renderers will merge both sources — group filters **compose with** page filters, they do not replace them.
364
375
 
376
+ A widget's own `filters` (and a series' or a metric-group tile's) compose the same way: they are sent **beside** the group filters, never in their place, and the analytics API ANDs them, the same field included. A widget filtered on `HTTP_STATUS = 500` inside a group filtered on `HTTP_STATUS = 200` shows nothing. A custom renderer registered with `registerWidgetRenderer` gets this from `useMergedWidgetFilters(widget.filters, filters)`, and appends anything of its own below the widget to the list it returns. See [`QUERYING.md` §6](./QUERYING.md#6-filter-semantics).
377
+
365
378
  ### Level 3 — `WidgetItem` standalone (isolated widget)
366
379
 
367
380
  Use when embedding a single widget in a sidebar, card, or other context.
@@ -36,8 +36,8 @@ function d(e) {
36
36
  }
37
37
  //#endregion
38
38
  //#region src/dashboards/grid.ts
39
- var f = 24, p = 2, m = 12, h = 24 / m;
40
- function ee(e) {
39
+ var ee = 24, f = 2, p = 12, m = 24 / p;
40
+ function te(e) {
41
41
  if (typeof e != "object" || !e) return "unreadable";
42
42
  let t = typeof e.version == "number" ? e.version : void 0;
43
43
  if (t !== void 0 && t >= 2) return "current";
@@ -47,18 +47,18 @@ function ee(e) {
47
47
  r,
48
48
  i,
49
49
  a
50
- ].every((e) => Number.isFinite(e)) ? t === void 0 && n + i > m ? "current-unmarked" : "legacy" : "unreadable";
50
+ ].every((e) => Number.isFinite(e)) ? t === void 0 && n + i > p ? "current-unmarked" : "legacy" : "unreadable";
51
51
  }
52
- function te(e) {
53
- switch (ee(e)) {
52
+ function h(e) {
53
+ switch (te(e)) {
54
54
  case "legacy": return {
55
- x: e.x * h,
56
- y: e.y * h,
57
- cols: e.cols * h,
58
- rows: e.rows * h,
55
+ x: e.x * m,
56
+ y: e.y * m,
57
+ cols: e.cols * m,
58
+ rows: e.rows * m,
59
59
  version: 2,
60
- ...e.minCols !== void 0 && { minCols: e.minCols * h },
61
- ...e.minRows !== void 0 && { minRows: e.minRows * h }
60
+ ...e.minCols !== void 0 && { minCols: e.minCols * m },
61
+ ...e.minRows !== void 0 && { minRows: e.minRows * m }
62
62
  };
63
63
  case "current-unmarked": return {
64
64
  ...e,
@@ -71,7 +71,7 @@ function te(e) {
71
71
  function g(e) {
72
72
  if (!e || !Array.isArray(e.widgets)) return e;
73
73
  let t = !1, n = e.widgets.map((e) => {
74
- let n = te(e.layout);
74
+ let n = h(e.layout);
75
75
  return n === e.layout ? e : (t = !0, {
76
76
  ...e,
77
77
  layout: n
@@ -214,11 +214,25 @@ function L(e, t) {
214
214
  return n.flatMap((e) => {
215
215
  let t = r.get(e.field);
216
216
  if (!t || e === t) return [e];
217
- let n = R(e, t);
217
+ let n = B(e, t);
218
218
  return n === t ? i.has(e.field) ? [] : (i.add(e.field), [t]) : [n];
219
219
  });
220
220
  }
221
221
  function R(e, t) {
222
+ let n = /* @__PURE__ */ new Set();
223
+ return [...e, ...t ?? []].filter((e) => {
224
+ let t = z(e);
225
+ return n.has(t) ? !1 : (n.add(t), !0);
226
+ });
227
+ }
228
+ function z(e) {
229
+ return JSON.stringify([
230
+ e.field,
231
+ e.operator,
232
+ [...e.value].sort()
233
+ ]);
234
+ }
235
+ function B(e, t) {
222
236
  if (!I.has(e.operator)) return t;
223
237
  let n = new Set(t.value), r = e.value.map((e, t) => n.has(e) ? t : -1).filter((e) => e >= 0);
224
238
  return r.length === 0 ? t : r.length === e.value.length ? e : {
@@ -229,23 +243,23 @@ function R(e, t) {
229
243
  }
230
244
  //#endregion
231
245
  //#region src/providers/clamped-data-sources.ts
232
- function z(e, t) {
246
+ function V(e, t) {
233
247
  return {
234
248
  fetchTimeSeries: (n) => e.fetchTimeSeries({
235
249
  ...n,
236
- filters: L(t, n.filters)
250
+ filters: R(t, n.filters)
237
251
  }),
238
252
  fetchFacets: (n) => e.fetchFacets({
239
253
  ...n,
240
- filters: L(t, n.filters)
254
+ filters: R(t, n.filters)
241
255
  }),
242
256
  fetchMeasures: (n) => e.fetchMeasures({
243
257
  ...n,
244
- filters: L(t, n.filters)
258
+ filters: R(t, n.filters)
245
259
  })
246
260
  };
247
261
  }
248
- function B(e, t) {
262
+ function H(e, t) {
249
263
  let n = e.getById;
250
264
  return {
251
265
  fetchLogs: (n) => e.fetchLogs({
@@ -257,78 +271,78 @@ function B(e, t) {
257
271
  }
258
272
  //#endregion
259
273
  //#region src/providers/logs-data-source-provider.tsx
260
- var V = e(null);
261
- function H({ dataSource: e, children: t }) {
262
- return /* @__PURE__ */ a(V.Provider, {
274
+ var U = e(null);
275
+ function W({ dataSource: e, children: t }) {
276
+ return /* @__PURE__ */ a(U.Provider, {
263
277
  value: e,
264
278
  children: t
265
279
  });
266
280
  }
267
- function U() {
268
- let e = W();
281
+ function ae() {
282
+ let e = G();
269
283
  if (!e) throw Error("[gamma-lib-observability] useLogsDataSource must be used within a <LogsDataSourceProvider>. Wrap your component tree with <LogsDataSourceProvider dataSource={yourImpl}>.");
270
284
  return e;
271
285
  }
272
- function W() {
273
- let e = n(V), t = A();
274
- return r(() => e ? B(e, t) : null, [e, t]);
286
+ function G() {
287
+ let e = n(U), t = A();
288
+ return r(() => e ? H(e, t) : null, [e, t]);
275
289
  }
276
290
  //#endregion
277
291
  //#region src/providers/metrics-data-source-provider.tsx
278
- var G = e(null);
279
- function K({ dataSource: e, children: t }) {
280
- return /* @__PURE__ */ a(G.Provider, {
292
+ var K = e(null);
293
+ function q({ dataSource: e, children: t }) {
294
+ return /* @__PURE__ */ a(K.Provider, {
281
295
  value: e,
282
296
  children: t
283
297
  });
284
298
  }
285
- function q() {
286
- let e = J();
299
+ function J() {
300
+ let e = Y();
287
301
  if (!e) throw Error("[gamma-lib-observability] useMetricsDataSource must be used within a <MetricsDataSourceProvider>. Wrap your component tree with <MetricsDataSourceProvider dataSource={yourImpl}>.");
288
302
  return e;
289
303
  }
290
- function J() {
291
- let e = n(G), t = A();
292
- return r(() => e ? z(e, t) : null, [e, t]);
304
+ function Y() {
305
+ let e = n(K), t = A();
306
+ return r(() => e ? V(e, t) : null, [e, t]);
293
307
  }
294
308
  //#endregion
295
309
  //#region src/providers/traces-data-source-provider.tsx
296
- var Y = e(null);
297
- function ae({ dataSource: e, children: t }) {
298
- return /* @__PURE__ */ a(Y.Provider, {
310
+ var X = e(null);
311
+ function oe({ dataSource: e, children: t }) {
312
+ return /* @__PURE__ */ a(X.Provider, {
299
313
  value: e,
300
314
  children: t
301
315
  });
302
316
  }
303
- function oe() {
304
- let e = n(Y);
317
+ function se() {
318
+ let e = n(X);
305
319
  if (!e) throw Error("[gamma-lib-observability] useTracesDataSource must be used within a <TracesDataSourceProvider>. Wrap your component tree with <TracesDataSourceProvider dataSource={yourImpl}>.");
306
320
  return e;
307
321
  }
308
- function se() {
309
- return n(Y);
322
+ function ce() {
323
+ return n(X);
310
324
  }
311
325
  //#endregion
312
326
  //#region src/filters/filter-providers-context.tsx
313
- var X = e(null);
314
- function ce({ providers: e, children: t }) {
327
+ var Z = e(null);
328
+ function le({ providers: e, children: t }) {
315
329
  let n = r(() => e, [e]);
316
- return /* @__PURE__ */ a(X.Provider, {
330
+ return /* @__PURE__ */ a(Z.Provider, {
317
331
  value: n,
318
332
  children: t
319
333
  });
320
334
  }
321
- function Z() {
322
- let e = n(X);
335
+ function Q() {
336
+ let e = n(Z);
323
337
  if (!e) throw Error("[gamma-lib-observability] useFilterProviders must be used within a <FilterProvidersProvider>. Wrap your component tree with <FilterProvidersProvider providers={[...]}>.");
324
338
  return e;
325
339
  }
326
- function le() {
327
- return n(X) ?? ue;
340
+ function ue() {
341
+ return n(Z) ?? de;
328
342
  }
329
- var ue = Object.freeze([]);
330
- function Q(e) {
331
- let t = Z();
343
+ var de = Object.freeze([]);
344
+ function fe(e) {
345
+ let t = Q();
332
346
  if (e) return t.find((t) => t.field === e);
333
347
  }
334
348
  //#endregion
@@ -339,7 +353,7 @@ var $ = e({
339
353
  reportRefused: () => {},
340
354
  reportGranted: () => {}
341
355
  });
342
- function de({ children: e }) {
356
+ function pe({ children: e }) {
343
357
  let [n, o] = i({
344
358
  read: !1,
345
359
  write: !1
@@ -369,8 +383,8 @@ function de({ children: e }) {
369
383
  children: e
370
384
  });
371
385
  }
372
- function fe() {
386
+ function me() {
373
387
  return n($);
374
388
  }
375
389
  //#endregion
376
- export { f as A, re as C, _ as D, y as E, d as F, s as I, o as L, g as M, l as N, S as O, u as P, ie as S, v as T, M as _, Z as a, A as b, se as c, q as d, J as f, L as g, W as h, Q as i, p as j, x as k, oe as l, U as m, fe as n, le as o, H as p, ce as r, ae as s, de as t, K as u, N as v, b as w, ne as x, k as y };
390
+ export { x as A, ie as C, y as D, v as E, u as F, d as I, s as L, f as M, g as N, _ as O, l as P, o as R, ne as S, b as T, L as _, Q as a, k as b, ce as c, J as d, Y as f, R as g, G as h, fe as i, ee as j, S as k, se as l, ae as m, me as n, ue as o, W as p, le as r, oe as s, pe as t, q as u, M as v, re as w, A as x, N as y };
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardEditorPage.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/DashboardEditorPage.tsx"],"names":[],"mappings":"AAgFA;;;;;;;;;;;;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"}
1
+ {"version":3,"file":"DashboardEditorPage.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/DashboardEditorPage.tsx"],"names":[],"mappings":"AAiFA;;;;;;;;;;;;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"}
@@ -1,7 +1,12 @@
1
- import { Widget } from '../../types/domain';
1
+ import { FilterCondition, Widget } from '../../types/domain';
2
2
  export interface WidgetConfigFormProps {
3
3
  readonly widget: Widget;
4
4
  readonly onChange: (widget: Widget) => void;
5
+ /**
6
+ * The dashboard's own filters. Its locked ones, like the host's scope, decide
7
+ * whether a scoped metric still needs its `API_TYPE` stamped on the widget.
8
+ */
9
+ readonly dashboardFilters?: readonly FilterCondition[];
5
10
  }
6
11
  /**
7
12
  * Controlled configuration form for a single widget. Every change is emitted
@@ -13,5 +18,5 @@ export interface WidgetConfigFormProps {
13
18
  * The visualization picker stays above the tabs: it decides which tabs exist,
14
19
  * so it cannot live inside one of them.
15
20
  */
16
- export declare function WidgetConfigForm({ widget, onChange }: WidgetConfigFormProps): import("react/jsx-runtime").JSX.Element;
21
+ export declare function WidgetConfigForm({ widget, onChange, dashboardFilters }: WidgetConfigFormProps): import("react/jsx-runtime").JSX.Element;
17
22
  //# sourceMappingURL=WidgetConfigForm.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WidgetConfigForm.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/WidgetConfigForm.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAKV,MAAM,EAEP,MAAM,oBAAoB,CAAC;AAkB5B,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAYD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,qBAAqB,2CAsE3E"}
1
+ {"version":3,"file":"WidgetConfigForm.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/WidgetConfigForm.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAEV,eAAe,EAGf,MAAM,EAEP,MAAM,oBAAoB,CAAC;AAkB5B,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;CACxD;AAYD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,EAAE,qBAAqB,2CA4E7F"}
@@ -8,7 +8,7 @@ export interface WidgetPreviewProps {
8
8
  /**
9
9
  * Live preview of the widget under edition. The configuration is debounced so
10
10
  * typing does not fire an analytics query per keystroke; widget-level filters
11
- * are merged by the renderer itself (widget wins over dashboard filters).
11
+ * are added by the renderer itself, beside the dashboard's.
12
12
  *
13
13
  * The preview takes the panel's full width, the way Grafana's and Datadog's
14
14
  * editors do, rather than reproducing the widget's grid width: the author is
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-json.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/dashboard-json.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,SAAS,EAKf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAGL,KAAK,qBAAqB,EAE1B,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAoB,KAAK,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAY1F,MAAM,MAAM,wBAAwB,GAChC;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAE/D,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAC;CAC1C;AAKD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAO/D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,EAAE,OAAY,EAAE,GAAE,yBAA8B,GAC/C,wBAAwB,CAqC1B;AAiGD,6GAA6G;AAC7G,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,CAI3E"}
1
+ {"version":3,"file":"dashboard-json.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/dashboard-json.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,SAAS,EAKf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAGL,KAAK,qBAAqB,EAE1B,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAoB,KAAK,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAY1F,MAAM,MAAM,wBAAwB,GAChC;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAE/D,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAC;CAC1C;AAKD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAO/D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,EAAE,OAAY,EAAE,GAAE,yBAA8B,GAC/C,wBAAwB,CAqC1B;AAmGD,6GAA6G;AAC7G,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,CAI3E"}
@@ -9,26 +9,43 @@ export interface LockedFilterConflict {
9
9
  readonly widgetId: string;
10
10
  /** Falls back to the id: a widget can be saved before it is named. */
11
11
  readonly widgetTitle: string;
12
+ /**
13
+ * The chart series or metric tile whose own filter empties it, by its label.
14
+ * Absent when the widget's own filters already do.
15
+ */
16
+ readonly part?: string;
12
17
  readonly field: string;
13
18
  readonly label: string;
14
19
  readonly dashboard: ConflictingCondition;
15
- /** Every condition the widget sets on the field: two for a range. */
20
+ /** Every condition the widget (and the part) sets on the field: two for a range. */
16
21
  readonly widget: readonly ConflictingCondition[];
17
22
  }
18
23
  /**
19
- * Widgets whose own filters override a locked dashboard filter.
24
+ * Widgets that will show nothing under a locked dashboard filter.
20
25
  *
21
- * Widget filters are merged last, so on a shared field the widget's value is
22
- * the one queried, whatever the padlock on the dashboard chip says. Within the
23
- * host's module scope, which still clamps it either way. That is
24
- * deliberate (see `ObservabilityDashboardPage`), which is exactly why the
25
- * author has to be told: nothing downstream will. Most of these are written
26
- * without anyone typing them, by `withAutoScope` stamping the `API_TYPE` a
27
- * metric requires, so the contradiction can appear from picking a metric.
26
+ * A widget's, series' or tile's own filters are sent alongside the dashboard's
27
+ * and the analytics API ANDs them, the same field included. So a widget value
28
+ * that can never overlap a locked dashboard value empties the widget, and the
29
+ * author has to be told: the reader only sees a 0. Most widget filters are
30
+ * written by `withAutoScope` rather than typed, so the contradiction can appear
31
+ * just from picking a metric.
28
32
  *
29
- * A widget carrying the *same* value is not a conflict. It is what the AIM
30
- * templates do today, pinning every widget to the API type the dashboard is
31
- * about, and flagging it would cry wolf on the common case.
33
+ * Only locked filters are checked: a reader can change a default, and the
34
+ * widget then fills again. Only what can be decided is flagged (see
35
+ * `canOverlap`), so a warning is never a false alarm.
32
36
  */
33
37
  export declare function findLockedFilterConflicts(dashboardFilters: readonly FilterCondition[], widgets: readonly Widget[]): LockedFilterConflict[];
38
+ /**
39
+ * Whether conditions on one field, ANDed, can still match a value. Only what
40
+ * can be decided answers `false`:
41
+ *
42
+ * - value sets (`eq`, `in`) with no common value;
43
+ * - a value set whose every value is excluded (`neq`, `not_in`);
44
+ * - bounds that cross (`gte` above `lte`), or that leave out every listed
45
+ * numeric value.
46
+ *
47
+ * Anything else may match: `contains`, a value without a value set, or a
48
+ * non-numeric value against a bound.
49
+ */
50
+ export declare function canOverlap(conditions: readonly FilterCondition[]): boolean;
34
51
  //# sourceMappingURL=locked-filter-conflicts.d.ts.map
@@ -1 +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,cAAc,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGlF,yEAAyE;AACzE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,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,SAAS,EAAE,oBAAoB,CAAC;IACzC,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,SAAS,oBAAoB,EAAE,CAAC;CAClD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,gBAAgB,EAAE,SAAS,eAAe,EAAE,EAC5C,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,oBAAoB,EAAE,CA2BxB"}
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,cAAc,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAIlF,yEAAyE;AACzE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,oBAAoB,CAAC;IACzC,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,SAAS,oBAAoB,EAAE,CAAC;CAClD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,gBAAgB,EAAE,SAAS,eAAe,EAAE,EAC5C,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,oBAAoB,EAAE,CA4BxB;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,GAAG,OAAO,CA+B1E"}
@@ -1,14 +1,19 @@
1
- import { Widget } from '../../types/domain';
1
+ import { FilterCondition, Widget } from '../../types/domain';
2
2
  /**
3
3
  * Ensures widgets whose metrics belong to a specific API type always carry the
4
4
  * owning `API_TYPE` filter, because querying a scoped metric without it fails
5
5
  * server-side (GMA-414). The filter is applied as a regular, visible widget
6
6
  * filter so the user can still broaden it deliberately.
7
7
  *
8
+ * Not when `upstream` (the dashboard's locked filters and the host's scope)
9
+ * already constrains `API_TYPE`: the query then carries one anyway, and a
10
+ * widget filter is ANDed with it, so a stamped type the dashboard does not
11
+ * allow would only empty the widget.
12
+ *
8
13
  * It is applied only when the edit actually changes which metrics or
9
14
  * dimensions are referenced. Re-deriving it on every edit would make the chip
10
15
  * impossible to remove: dropping it and then toggling any unrelated control
11
16
  * would silently bring it back.
12
17
  */
13
- export declare function withAutoScope(previous: Widget, next: Widget): Widget;
18
+ export declare function withAutoScope(previous: Widget, next: Widget, upstream?: readonly FilterCondition[]): Widget;
14
19
  //# sourceMappingURL=widget-auto-scope.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"widget-auto-scope.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/widget-auto-scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AA2BjD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKpE"}
1
+ {"version":3,"file":"widget-auto-scope.d.ts","sourceRoot":"","sources":["../../../src/dashboards/editor/widget-auto-scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAqClE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,SAAS,eAAe,EAAO,GAAG,MAAM,CAK/G"}
@@ -7,16 +7,19 @@ export declare function isRangeBound(filter: FilterCondition): boolean;
7
7
  * each field.
8
8
  *
9
9
  * This is the mechanism, not the policy: it does not know which source is which
10
- * and has no canonical order of its own. The host's scope is applied on top by
11
- * `clampToScope`, which is what actually decides precedence and is the only
12
- * place that describes the full chain.
10
+ * and has no canonical order of its own. It resolves the **dashboard layer**
11
+ * (definition default, reader value, locked definition filter) into one
12
+ * condition per field. A widget's and a series' own filters are not merged
13
+ * with it: they are appended after it and the analytics API ANDs them (see
14
+ * `useMergedWidgetFilters`). The host's scope sits above both
15
+ * (`clampAnalyticsToScope`, `clampToScope` for logs).
13
16
  *
14
17
  * Within one source, a field keeps its last condition, with one exception: a
15
18
  * field whose conditions are all `gte` / `lte` keeps one of each, so
16
19
  * `latency gte 100` and `latency lte 500` stay a range the server ANDs. A
17
20
  * repeated bound still replaces the earlier one. Between sources, a later one
18
- * replaces the whole field, range included, so a widget's range overrides the
19
- * dashboard's rather than mixing a bound from each.
21
+ * replaces the whole field, range included, so a reader's range replaces the
22
+ * dashboard default rather than mixing a bound from each.
20
23
  */
21
24
  export declare function mergeFilters(...sources: (readonly FilterCondition[] | undefined)[]): FilterCondition[];
22
25
  //# 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,EAAkB,MAAM,iBAAiB,CAAC;AAKvE,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAE7D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,GAAG,OAAO,EAAE,CAAC,SAAS,eAAe,EAAE,GAAG,SAAS,CAAC,EAAE,GAAG,eAAe,EAAE,CAWtG"}
1
+ {"version":3,"file":"merge-filters.d.ts","sourceRoot":"","sources":["../../src/dashboards/merge-filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,iBAAiB,CAAC;AAKvE,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAE7D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAAC,GAAG,OAAO,EAAE,CAAC,SAAS,eAAe,EAAE,GAAG,SAAS,CAAC,EAAE,GAAG,eAAe,EAAE,CAWtG"}
@@ -0,0 +1,35 @@
1
+ import { FilterCondition, MetricGroupItemDefinition } from '../types/domain';
2
+ import { MetricRequest } from '../types/requests';
3
+ import { MetricResult } from '../types/responses';
4
+ /**
5
+ * Most distinct sets of tile filters one metric group may carry: the analytics
6
+ * API runs one query per set and refuses a request with more (OBS-132). Tiles
7
+ * without filters of their own do not count.
8
+ */
9
+ export declare const MAX_ITEM_FILTER_SETS = 10;
10
+ type ItemQuery = Pick<MetricGroupItemDefinition, 'metric' | 'filters'>;
11
+ /**
12
+ * The id of the request entry a tile reads: its metric and its own conditions.
13
+ * Tiles sharing both share an entry, and the id is the same in the current and
14
+ * the previous-period requests.
15
+ */
16
+ export declare function metricGroupItemId(item: ItemQuery): string;
17
+ /**
18
+ * The measures request of a metric group: one entry per distinct metric and
19
+ * tile conditions, every entry named by its id. The tile's conditions stay on
20
+ * the entry (`metrics[].filters`), where the API ANDs them with the request's
21
+ * own, so two tiles on one metric with different filters each get their value.
22
+ */
23
+ export declare function buildMetricGroupRequests(items: readonly MetricGroupItemDefinition[]): MetricRequest[];
24
+ /**
25
+ * Finds the entry a tile reads: by id when the source echoed the ids, by metric
26
+ * name when no entry carries one (a custom data source, or a backend older than
27
+ * OBS-132). Read by name, two tiles on one metric show the same value.
28
+ */
29
+ export declare function readMetricGroupResult(results: readonly MetricResult[] | undefined): (item: ItemQuery) => MetricResult | undefined;
30
+ /** How many distinct, non-empty sets of filters the tiles carry, the number `MAX_ITEM_FILTER_SETS` caps. */
31
+ export declare function countItemFilterSets(items: readonly {
32
+ readonly filters?: readonly FilterCondition[];
33
+ }[]): number;
34
+ export {};
35
+ //# sourceMappingURL=metric-group-requests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metric-group-requests.d.ts","sourceRoot":"","sources":["../../src/dashboards/metric-group-requests.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,KAAK,SAAS,GAAG,IAAI,CAAC,yBAAyB,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC;AAYvE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,yBAAyB,EAAE,GAAG,aAAa,EAAE,CAerG;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,SAAS,GAC3C,CAAC,IAAI,EAAE,SAAS,KAAK,YAAY,GAAG,SAAS,CAQ/C;AAED,4GAA4G;AAC5G,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,EAAE,GAAG,MAAM,CAE/G"}
@@ -1 +1 @@
1
- {"version":3,"file":"CartesianWidgetRenderer.d.ts","sourceRoot":"","sources":["../../../src/dashboards/renderers/CartesianWidgetRenderer.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,oBAAoB,CAAC;AAQ5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAGvE,wBAAgB,uBAAuB,CAAC,EACtC,MAAM,EACN,SAAS,EACT,OAAO,EACP,eAAe,GAChB,EAAE,mBAAmB,CAAC,eAAe,CAAC,2CA0HtC"}
1
+ {"version":3,"file":"CartesianWidgetRenderer.d.ts","sourceRoot":"","sources":["../../../src/dashboards/renderers/CartesianWidgetRenderer.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,oBAAoB,CAAC;AAO5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAGvE,wBAAgB,uBAAuB,CAAC,EACtC,MAAM,EACN,SAAS,EACT,OAAO,EACP,eAAe,GAChB,EAAE,mBAAmB,CAAC,eAAe,CAAC,2CAyHtC"}
@@ -1 +1 @@
1
- {"version":3,"file":"MetricGroupWidgetRenderer.d.ts","sourceRoot":"","sources":["../../../src/dashboards/renderers/MetricGroupWidgetRenderer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAA8C,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAQxG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AA6CvE,wBAAgB,yBAAyB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,mBAAmB,CAAC,iBAAiB,CAAC,2CA8G/G"}
1
+ {"version":3,"file":"MetricGroupWidgetRenderer.d.ts","sourceRoot":"","sources":["../../../src/dashboards/renderers/MetricGroupWidgetRenderer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAA6B,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AASvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAGvE,wBAAgB,yBAAyB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,mBAAmB,CAAC,iBAAiB,CAAC,2CA2G/G"}