@gravitee/gamma-lib-observability 3.1.1 → 3.2.0-amp-demo.da2facd
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/INTEGRATION.md +60 -0
- package/QUERYING.md +58 -7
- package/README.md +1 -0
- package/USAGE_GUIDE.md +83 -6
- package/dist/dashboards/DashboardView.d.ts +8 -1
- package/dist/dashboards/DashboardView.d.ts.map +1 -1
- package/dist/dashboards/WidgetGroup.d.ts +7 -1
- package/dist/dashboards/WidgetGroup.d.ts.map +1 -1
- package/dist/dashboards/WidgetInteractionContext.d.ts +31 -0
- package/dist/dashboards/WidgetInteractionContext.d.ts.map +1 -0
- package/dist/dashboards/WidgetItem.d.ts +7 -3
- package/dist/dashboards/WidgetItem.d.ts.map +1 -1
- package/dist/dashboards/analytics-table/AnalyticsTable.d.ts +54 -0
- package/dist/dashboards/analytics-table/AnalyticsTable.d.ts.map +1 -0
- package/dist/dashboards/analytics-table/analytics-table-model.d.ts +73 -0
- package/dist/dashboards/analytics-table/analytics-table-model.d.ts.map +1 -0
- package/dist/dashboards/analytics-table/format-table-value.d.ts +31 -0
- package/dist/dashboards/analytics-table/format-table-value.d.ts.map +1 -0
- package/dist/dashboards/analytics-table/index.d.ts +6 -0
- package/dist/dashboards/analytics-table/index.d.ts.map +1 -0
- package/dist/dashboards/analytics-table/plan-columns.d.ts +102 -0
- package/dist/dashboards/analytics-table/plan-columns.d.ts.map +1 -0
- package/dist/dashboards/analytics-table/row-color.d.ts +11 -0
- package/dist/dashboards/analytics-table/row-color.d.ts.map +1 -0
- package/dist/dashboards/analytics-table/use-analytics-table-query.d.ts +46 -0
- package/dist/dashboards/analytics-table/use-analytics-table-query.d.ts.map +1 -0
- package/dist/dashboards/editor/TableColumnsEditor.d.ts +26 -0
- package/dist/dashboards/editor/TableColumnsEditor.d.ts.map +1 -0
- package/dist/dashboards/editor/TableDisplayFields.d.ts +13 -0
- package/dist/dashboards/editor/TableDisplayFields.d.ts.map +1 -0
- package/dist/dashboards/editor/TableQueryFields.d.ts +15 -0
- package/dist/dashboards/editor/TableQueryFields.d.ts.map +1 -0
- package/dist/dashboards/editor/VisualizationTypePicker.d.ts.map +1 -1
- package/dist/dashboards/editor/WidgetConfigForm.d.ts.map +1 -1
- package/dist/dashboards/editor/WidgetEditorPanel.d.ts.map +1 -1
- package/dist/dashboards/editor/WidgetPreview.d.ts +5 -0
- package/dist/dashboards/editor/WidgetPreview.d.ts.map +1 -1
- package/dist/dashboards/editor/convert-widget-type.d.ts +0 -4
- package/dist/dashboards/editor/convert-widget-type.d.ts.map +1 -1
- package/dist/dashboards/editor/dashboard-editor-state.d.ts +8 -0
- package/dist/dashboards/editor/dashboard-editor-state.d.ts.map +1 -1
- package/dist/dashboards/editor/facet-display-cols.d.ts +2 -0
- package/dist/dashboards/editor/facet-display-cols.d.ts.map +1 -1
- package/dist/dashboards/editor/suggest-widget-title.d.ts.map +1 -1
- package/dist/dashboards/editor/widget-auto-scope.d.ts.map +1 -1
- package/dist/dashboards/index.d.ts +4 -1
- package/dist/dashboards/index.d.ts.map +1 -1
- package/dist/dashboards/register-default-renderers.d.ts +1 -1
- package/dist/dashboards/register-default-renderers.d.ts.map +1 -1
- package/dist/dashboards/renderers/TablePresentation.d.ts +20 -0
- package/dist/dashboards/renderers/TablePresentation.d.ts.map +1 -0
- package/dist/dashboards/renderers/TableWidgetRenderer.d.ts +4 -0
- package/dist/dashboards/renderers/TableWidgetRenderer.d.ts.map +1 -0
- package/dist/dashboards/renderers/index.d.ts +1 -0
- package/dist/dashboards/renderers/index.d.ts.map +1 -1
- package/dist/dashboards/widget-data.d.ts +29 -2
- package/dist/dashboards/widget-data.d.ts.map +1 -1
- package/dist/dashboards/widget-renderer-registry.d.ts +8 -0
- package/dist/dashboards/widget-renderer-registry.d.ts.map +1 -1
- package/dist/data-sources/http-data-source.d.ts.map +1 -1
- package/dist/hooks/query-keys.d.ts +14 -0
- package/dist/hooks/query-keys.d.ts.map +1 -1
- package/dist/hooks/use-facets-query.d.ts +7 -0
- package/dist/hooks/use-facets-query.d.ts.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6376 -3270
- package/dist/lib/use-element-size.d.ts +21 -0
- package/dist/lib/use-element-size.d.ts.map +1 -0
- package/dist/routing/ObservabilityDashboardPage.d.ts +16 -0
- package/dist/routing/ObservabilityDashboardPage.d.ts.map +1 -1
- package/dist/routing/ObservabilityRoutes.d.ts.map +1 -1
- package/dist/routing/detail-filter.d.ts +9 -4
- package/dist/routing/detail-filter.d.ts.map +1 -1
- package/dist/shared/ExplorerTable.d.ts +34 -2
- package/dist/shared/ExplorerTable.d.ts.map +1 -1
- package/dist/styles/observability.css +1 -1
- package/dist/targets/EvaluateNowButton.d.ts +19 -0
- package/dist/targets/EvaluateNowButton.d.ts.map +1 -0
- package/dist/targets/RuleTrend.d.ts +19 -0
- package/dist/targets/RuleTrend.d.ts.map +1 -0
- package/dist/targets/TargetCard.d.ts +18 -0
- package/dist/targets/TargetCard.d.ts.map +1 -0
- package/dist/targets/TargetForm.d.ts +19 -0
- package/dist/targets/TargetForm.d.ts.map +1 -0
- package/dist/targets/TargetHeatmap.d.ts +22 -0
- package/dist/targets/TargetHeatmap.d.ts.map +1 -0
- package/dist/targets/TargetStatusBadge.d.ts +18 -0
- package/dist/targets/TargetStatusBadge.d.ts.map +1 -0
- package/dist/targets/TargetsPanel.d.ts +15 -0
- package/dist/targets/TargetsPanel.d.ts.map +1 -0
- package/dist/targets/api-type-names.d.ts +5 -0
- package/dist/targets/api-type-names.d.ts.map +1 -0
- package/dist/targets/evaluation-summary.d.ts +34 -0
- package/dist/targets/evaluation-summary.d.ts.map +1 -0
- package/dist/targets/format.d.ts +26 -0
- package/dist/targets/format.d.ts.map +1 -0
- package/dist/targets/history-range.d.ts +14 -0
- package/dist/targets/history-range.d.ts.map +1 -0
- package/dist/targets/http-targets-source.d.ts +10 -0
- package/dist/targets/http-targets-source.d.ts.map +1 -0
- package/dist/targets/index.d.ts +15 -0
- package/dist/targets/index.d.ts.map +1 -0
- package/dist/targets/rule-filters.d.ts +7 -0
- package/dist/targets/rule-filters.d.ts.map +1 -0
- package/dist/targets/targets-provider.d.ts +27 -0
- package/dist/targets/targets-provider.d.ts.map +1 -0
- package/dist/targets/targets-source.d.ts +51 -0
- package/dist/targets/targets-source.d.ts.map +1 -0
- package/dist/targets/testing/in-memory-targets-source.d.ts +41 -0
- package/dist/targets/testing/in-memory-targets-source.d.ts.map +1 -0
- package/dist/targets/types.d.ts +130 -0
- package/dist/targets/types.d.ts.map +1 -0
- package/dist/targets/use-targets.d.ts +44 -0
- package/dist/targets/use-targets.d.ts.map +1 -0
- package/dist/{dashboard-access-provider.js → targets-source.js} +28 -1
- package/dist/testing/graphene-core-icons-mock.d.ts +8 -0
- package/dist/testing/graphene-core-icons-mock.d.ts.map +1 -1
- package/dist/testing/graphene-core-mock.d.ts +33 -7
- package/dist/testing/graphene-core-mock.d.ts.map +1 -1
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/mock-metrics-data-source.d.ts.map +1 -1
- package/dist/testing.js +379 -35
- package/dist/types/domain.d.ts +105 -1
- package/dist/types/domain.d.ts.map +1 -1
- package/dist/types/guards.d.ts +2 -1
- package/dist/types/guards.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/responses.d.ts +18 -0
- package/dist/types/responses.d.ts.map +1 -1
- package/dist/types-entry.d.ts +2 -0
- package/dist/types-entry.d.ts.map +1 -1
- package/package.json +1 -1
package/INTEGRATION.md
CHANGED
|
@@ -17,6 +17,7 @@ This guide walks through integrating the observability library into a Gamma modu
|
|
|
17
17
|
- [Feature: Logs](#feature-logs)
|
|
18
18
|
- [Feature: Widget Embedding](#feature-widget-embedding)
|
|
19
19
|
- [Feature: Traces (preview)](#feature-traces-preview)
|
|
20
|
+
- [Feature: Targets](#feature-targets)
|
|
20
21
|
- [Navigation & Breadcrumbs](#navigation--breadcrumbs)
|
|
21
22
|
- [Capabilities (RBAC)](#capabilities-rbac)
|
|
22
23
|
- [Advanced Topics](#advanced-topics)
|
|
@@ -803,6 +804,65 @@ When `tracesBaseUrl` is omitted, the lib falls back to `baseUrl`. Both now produ
|
|
|
803
804
|
|
|
804
805
|
---
|
|
805
806
|
|
|
807
|
+
## Feature: Targets
|
|
808
|
+
|
|
809
|
+
A **performance target** declares what "good" looks like for a subject — an API, an agent, anything the gateway reports telemetry for — as rules over the analytics vocabulary (`HTTP_GATEWAY_RESPONSE_TIME P95 ≤ 2000`, `HTTP_SERVER_ERROR_RATE PERCENTAGE ≤ 1`) evaluated on a rolling window. The Management API v2 stores the targets and evaluates them on a schedule (`/environments/{envId}/performance-targets`); this library ships the "Targets" tab and the list badge that read and write them.
|
|
810
|
+
|
|
811
|
+
The components know nothing about APIs versus agents. The host says what the subject is through three props, and the module that owns the subject keeps `apiIds` current (an API page passes its own id; an agent page passes the APIs its lineage resolved to):
|
|
812
|
+
|
|
813
|
+
| Prop | Value |
|
|
814
|
+
| ----------- | ---------------------------------------------------------------------------------------------------------- |
|
|
815
|
+
| `reference` | The lookup key the host will use to find these targets again — the API id, the agent's catalog id, … |
|
|
816
|
+
| `apiIds` | The API ids whose gateway telemetry is evaluated. May be empty while nothing is attributed yet. |
|
|
817
|
+
| `apiTypes` | The `ApiType` of those APIs (`PROXY`, `LLM_PROXY`, `MCP_PROXY`, `A2A_PROXY`, …); drives the metric picker. |
|
|
818
|
+
|
|
819
|
+
### Mounting the tab
|
|
820
|
+
|
|
821
|
+
Wrap the panel in a `TargetsProvider` whose `baseUrl` is the **Management API v2 environment root** (`{managementBaseURL}/v2/environments/{envId}`), where the targets and the analytics definition live. This is not the Gamma-scoped URL `observability.Routes` takes; a Gamma host builds it from the bootstrap's `managementBaseURL`. The provider reuses the nearest `HttpProvider` for `fetch`/headers/credentials, or takes an `http` prop of its own. `baseUrl` may be `undefined` while the host resolves it: badges then wait, and the panel should be mounted once it is known.
|
|
822
|
+
|
|
823
|
+
```tsx
|
|
824
|
+
import { TargetsPanel, TargetsProvider } from '@gravitee/gamma-lib-observability';
|
|
825
|
+
|
|
826
|
+
function ApiTargetsTab({ api }: { api: ApiDetailDto }) {
|
|
827
|
+
const { baseUrl } = useObservabilityBaseUrl();
|
|
828
|
+
return (
|
|
829
|
+
<TargetsProvider baseUrl={baseUrl} http={observabilityHttpOptions}>
|
|
830
|
+
<TargetsPanel
|
|
831
|
+
reference={api.id}
|
|
832
|
+
apiIds={[api.id]}
|
|
833
|
+
apiTypes={[api.type]}
|
|
834
|
+
readOnly={!canUpdateApi} // hides define / edit / delete / evaluate now
|
|
835
|
+
/>
|
|
836
|
+
</TargetsProvider>
|
|
837
|
+
);
|
|
838
|
+
}
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
The panel renders, in order: the empty state ("No targets declared", with the reason when `apiIds` is empty), one card per target with the latest verdict, a banner naming the missed rule and how long the miss has lasted, each rule's observed value against its threshold with deviation and sample count, the last windows as a strip, and "Evaluate now", which counts the server's rate limit down before offering again. `NOT_EVALUABLE` rules say why: no API attributed, no traffic in the window, or fewer samples than the target's minimum.
|
|
842
|
+
|
|
843
|
+
"Define targets" lists only the metrics the analytics definition serves for the subject's `apiTypes` (`GET /analytics/definition/apis/{apiName}/metrics`), shows the per-type scope only when the subject spans several types, and offers a filter only on metrics with a protocol dimension to scope by (MCP tool or method, LLM model, HTTP method or path, …). A server refusal that blames one rule (`parameters.ruleIndex`) lands under that rule.
|
|
844
|
+
|
|
845
|
+
### List badges
|
|
846
|
+
|
|
847
|
+
For a table, ask once for the whole page of rows and hand each row its answer; the hook batches by 500 references and never issues a request per row:
|
|
848
|
+
|
|
849
|
+
```tsx
|
|
850
|
+
import { TargetStatusBadge, useLatestTargetEvaluations } from '@gravitee/gamma-lib-observability';
|
|
851
|
+
|
|
852
|
+
function StatusColumn({ rows }: { rows: { id: string }[] }) {
|
|
853
|
+
const latest = useLatestTargetEvaluations(rows.map((row) => row.id));
|
|
854
|
+
return rows.map((row) => <TargetStatusBadge key={row.id} evaluation={latest.data?.[row.id]} />);
|
|
855
|
+
}
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
`evaluation` is `undefined` while loading, `null` when the reference has no target or no evaluation yet, and otherwise the latest evaluation (the worst one when several targets share the reference).
|
|
859
|
+
|
|
860
|
+
### Testing a host mount
|
|
861
|
+
|
|
862
|
+
`@gravitee/gamma-lib-observability/testing` exports `createInMemoryTargetsSource`, a `TargetsSource` over plain arrays with the server's refusals reproduced (400 with `ruleIndex`, 429 with `Retry-After`), and `SAMPLE_METRIC_SPECS`, a cut of the analytics definition. Pass it to `TargetsProvider` through the `source` prop.
|
|
863
|
+
|
|
864
|
+
---
|
|
865
|
+
|
|
806
866
|
## Navigation & Breadcrumbs
|
|
807
867
|
|
|
808
868
|
### Sidebar navigation
|
package/QUERYING.md
CHANGED
|
@@ -74,13 +74,14 @@ the same metric/range) dedupe.
|
|
|
74
74
|
|
|
75
75
|
## 4. Widget → request mapping
|
|
76
76
|
|
|
77
|
-
| Widget | Endpoint | Mapping
|
|
78
|
-
| -------------- | ----------- |
|
|
79
|
-
| `metric` | measures | `{ metric, measure }` → one `MetricRequest`. Widget `filters` → top-level filters.
|
|
80
|
-
| `metric-group` | measures | each `items[]` → one `MetricRequest` (`metric`, `measure`, per-item `filters`). Identical (metric+filters) items are deduped.
|
|
81
|
-
| `cartesian` | time-series | each `series[]` → one query. `metric`/`measure` → `metrics[0]`; `by` → `by[]`; `filters`/`sorts`/`ranges`/`limit` forwarded. Results are merged on the shared time bucket (`category`) before rendering.
|
|
82
|
-
| `doughnut` | facets | `by` → `by[]`; `metric`/`measure`/`sorts` → `metrics[0]`; `ranges`/`limit` forwarded.
|
|
83
|
-
| `bar` | facets | same as `doughnut`, plus `barLayout`.
|
|
77
|
+
| Widget | Endpoint | Mapping |
|
|
78
|
+
| -------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
79
|
+
| `metric` | measures | `{ metric, measure }` → one `MetricRequest`. Widget `filters` → top-level filters. |
|
|
80
|
+
| `metric-group` | measures | each `items[]` → one `MetricRequest` (`metric`, `measure`, per-item `filters`). Identical (metric+filters) items are deduped. |
|
|
81
|
+
| `cartesian` | time-series | each `series[]` → one query. `metric`/`measure` → `metrics[0]`; `by` → `by[]`; `filters`/`sorts`/`ranges`/`limit` forwarded. Results are merged on the shared time bucket (`category`) before rendering. |
|
|
82
|
+
| `doughnut` | facets | `by` → `by[]`; `metric`/`measure`/`sorts` → `metrics[0]`; `ranges`/`limit` forwarded. |
|
|
83
|
+
| `bar` | facets | same as `doughnut`, plus `barLayout`. |
|
|
84
|
+
| `table` | facets | `by` → `by[]`; `columns[]` grouped by distinct `metric` → one `metrics[]` entry each, measures de-duplicated; `sorts` goes on **exactly one** metric, the one owning the sort column; `ranges`/`limit` forwarded. With `showTotals` or a `share` column, one extra measures request with the same filters and range. |
|
|
84
85
|
|
|
85
86
|
**Presentation-only fields** (not sent to analytics; consumed by `CartesianPresentation` / graphene-charts):
|
|
86
87
|
|
|
@@ -109,6 +110,11 @@ chart total.
|
|
|
109
110
|
sent to the backend but flattened onto the first level.
|
|
110
111
|
- Distinct visual series for several measures of one metric are best expressed as one `series[]` entry
|
|
111
112
|
per measure (e.g. P90/P95/P99), which the renderer keys apart by measure.
|
|
113
|
+
- `table` rows come from the metric carrying `sorts`; the other metrics are joined on the bucket key.
|
|
114
|
+
The backend aggregates each metric separately, so a sort on anything but a count can leave a row
|
|
115
|
+
without a value for another column: the cell renders `—` and the widget reports how many rows are
|
|
116
|
+
incomplete. A single-column table issues exactly the request a top list on the same query issues, and
|
|
117
|
+
shares its cache entry.
|
|
112
118
|
|
|
113
119
|
---
|
|
114
120
|
|
|
@@ -224,6 +230,51 @@ series to keep a single left axis (backward compatible).
|
|
|
224
230
|
|
|
225
231
|
---
|
|
226
232
|
|
|
233
|
+
### 5.7 Multi-metric table (one facets request, sort on one metric)
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"type": "table",
|
|
238
|
+
"by": ["API"],
|
|
239
|
+
"columns": [
|
|
240
|
+
{ "metric": "HTTP_REQUESTS", "measure": "COUNT", "share": true },
|
|
241
|
+
{
|
|
242
|
+
"metric": "HTTP_ERROR_RATE",
|
|
243
|
+
"measure": "PERCENTAGE",
|
|
244
|
+
"thresholds": [{ "color": "red", "op": "gte", "value": 5 }]
|
|
245
|
+
},
|
|
246
|
+
{ "metric": "HTTP_GATEWAY_RESPONSE_TIME", "measure": "P95", "pinned": true }
|
|
247
|
+
],
|
|
248
|
+
"sort": { "columnId": "HTTP_GATEWAY_RESPONSE_TIME:P95", "order": "DESC" },
|
|
249
|
+
"limit": 10,
|
|
250
|
+
"showTotals": true
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Facets request (`sorts` on the P95 metric only, the others unordered):
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"by": ["API"],
|
|
259
|
+
"limit": 10,
|
|
260
|
+
"metrics": [
|
|
261
|
+
{ "name": "HTTP_REQUESTS", "measures": ["COUNT"] },
|
|
262
|
+
{ "name": "HTTP_ERROR_RATE", "measures": ["PERCENTAGE"] },
|
|
263
|
+
{ "name": "HTTP_GATEWAY_RESPONSE_TIME", "measures": ["P95"], "sorts": [{ "measure": "P95", "order": "DESC" }] }
|
|
264
|
+
]
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Plus, because `showTotals` is on, one measures request for the same three metrics under the same
|
|
269
|
+
filters and range. A column's id is `metric:measure` unless it declares an `id`; the sort refers to it.
|
|
270
|
+
A threshold is an alert tier: `{ color, op, value, basis? }` paints the cell `color` (`red`, `amber`
|
|
271
|
+
or `green`) when it crosses `value`, `op` being `gte` (at or above) or `lte` (at or below) and `basis`
|
|
272
|
+
what is compared: the cell's own value (default) or its share of the column total in percent
|
|
273
|
+
(`"basis": "share"`, which also triggers the measures request for the total). Thresholds are ordered rules: the first one a cell matches decides its colour, so the author's
|
|
274
|
+
order is the priority.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
227
278
|
## 6. Filter semantics
|
|
228
279
|
|
|
229
280
|
Filters merge in this order, later layers win on a field conflict:
|
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ This library provides a **contributor model**: it exports page components, route
|
|
|
11
11
|
- **Dashboards** — read-only preset dashboards with CSS Grid widget layout
|
|
12
12
|
- **Embeddable widgets** — `WidgetItem` and `WidgetGroup` for embedding KPIs/charts on any page, with auto (data-fetching) and manual (host-provided data) modes
|
|
13
13
|
- **Logs** — `LogsExplorerPage` with search, filters, pagination, and column visibility
|
|
14
|
+
- **Targets** — `TargetsPanel` and `TargetStatusBadge` for performance targets declared on any subject (API, agent), evaluated by the Management API against gateway telemetry
|
|
14
15
|
- **Filters & time range** — `<FilterBar>`, `<TimeRangePicker>`, URL state codec
|
|
15
16
|
- **DI providers** — DataSource ports (Metrics, Logs, Traces), Capability, Persistence
|
|
16
17
|
- **Routing** — `defineObservabilityFeatures` for zero-config route + nav integration
|
package/USAGE_GUIDE.md
CHANGED
|
@@ -492,6 +492,8 @@ import { MetricPresentation, BarPresentation } from '@gravitee/gamma-lib-observa
|
|
|
492
492
|
| Manual | `CartesianWidget` | `CartesianWidgetData` |
|
|
493
493
|
| Manual | `BarWidget` | `BarWidgetData` |
|
|
494
494
|
| Manual | `DoughnutWidget` | `DoughnutWidgetData` |
|
|
495
|
+
| Manual | `BreakdownWidget` | `BreakdownWidgetData` |
|
|
496
|
+
| Manual | `TableWidget` | `TableWidgetData` |
|
|
495
497
|
|
|
496
498
|
Shared props (available in all modes):
|
|
497
499
|
|
|
@@ -504,12 +506,46 @@ Shared props (available in all modes):
|
|
|
504
506
|
|
|
505
507
|
#### `WidgetGroupProps`
|
|
506
508
|
|
|
507
|
-
| Prop
|
|
508
|
-
|
|
|
509
|
-
| `timeRange`
|
|
510
|
-
| `filters`
|
|
511
|
-
| `align`
|
|
512
|
-
| `
|
|
509
|
+
| Prop | Type | Required | Default | Description |
|
|
510
|
+
| ------------- | ------------------------------- | -------- | ----------- | ---------------------------------------------------------- |
|
|
511
|
+
| `timeRange` | `TimeRange` | Yes | | Time range propagated to all nested `WidgetItem`s |
|
|
512
|
+
| `filters` | `readonly FilterCondition[]` | No | `[]` | Filters propagated to all nested `WidgetItem`s |
|
|
513
|
+
| `align` | `WidgetGroupAlign` | No | `'stretch'` | Cross-axis alignment: `stretch`, `center`, `start`, `end` |
|
|
514
|
+
| `interaction` | `WidgetInteractionContextValue` | No | | Receives what a reader acts on inside a widget (see below) |
|
|
515
|
+
| `children` | `ReactNode` | Yes | | `WidgetItem` children |
|
|
516
|
+
|
|
517
|
+
#### Widget interactions (row drill-down)
|
|
518
|
+
|
|
519
|
+
A widget can send a value the reader acted on back to the page — a table row, today — through a
|
|
520
|
+
`WidgetInteraction { kind, field, value, label? }`. `DashboardView` and `WidgetGroup` both take an
|
|
521
|
+
`interaction` prop; `ObservabilityDashboardPage` wires it for you (a row click adds a filter chip on
|
|
522
|
+
the widget's dimension, clicking the same row again clears it, a locked dashboard filter is never
|
|
523
|
+
overridden). When embedding widgets yourself:
|
|
524
|
+
|
|
525
|
+
```tsx
|
|
526
|
+
<WidgetGroup
|
|
527
|
+
timeRange={timeRange}
|
|
528
|
+
filters={filters}
|
|
529
|
+
interaction={{
|
|
530
|
+
onInteract: ({ kind, field, value }) => {
|
|
531
|
+
if (kind === 'filter') setFilters(upsertFilterCondition(filters, field, value));
|
|
532
|
+
},
|
|
533
|
+
// Optional: which kinds the page can act on, per field. Only `filter` is
|
|
534
|
+
// offered when omitted; `exclude` needs the field's provider to advertise
|
|
535
|
+
// `not_in`, `view-logs` / `view-traces` / `open-entity` need a route.
|
|
536
|
+
supports: (kind) => kind === 'filter',
|
|
537
|
+
}}
|
|
538
|
+
>
|
|
539
|
+
<WidgetItem widget={topApisTable} />
|
|
540
|
+
</WidgetGroup>
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
Widgets rendered without an `interaction` upstream show no row affordance at all rather than a dead
|
|
544
|
+
one. The built-in dashboard page offers **View logs** / **View traces** only for a sibling screen the
|
|
545
|
+
host enabled in `defineObservabilityFeatures` (and the reader may read), and **View traces** only on
|
|
546
|
+
the `API` dimension, since the tracing screen is per API (`tracing/:apiId`). A layout may declare `minCols` / `minRows`, which `DashboardView` forwards to the grid; no
|
|
547
|
+
widget type sets them by default. A table that gets too small degrades in steps instead: compact
|
|
548
|
+
numbers, collapsed columns, a top list, then an explicit "Enlarge the widget" state.
|
|
513
549
|
|
|
514
550
|
---
|
|
515
551
|
|
|
@@ -1206,4 +1242,45 @@ import { TracingScreen, SpanDetailPanel, TracingApiSelector } from '@gravitee/ga
|
|
|
1206
1242
|
|
|
1207
1243
|
---
|
|
1208
1244
|
|
|
1245
|
+
## Targets
|
|
1246
|
+
|
|
1247
|
+
Performance targets declared on a subject and evaluated by the Management API v2 (`/environments/{envId}/performance-targets`). Mounting and the subject props are covered in [`INTEGRATION.md`](./INTEGRATION.md#feature-targets); this is the API surface.
|
|
1248
|
+
|
|
1249
|
+
### Components
|
|
1250
|
+
|
|
1251
|
+
| Export | Description |
|
|
1252
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
1253
|
+
| `TargetsProvider` | Hands the components their `TargetsSource`: `baseUrl` (+ optional `http`, else the nearest `HttpProvider`) or a ready `source` for tests |
|
|
1254
|
+
| `TargetsPanel` | The "Targets" tab: `{ reference, apiIds, apiTypes, readOnly? }` — empty state, one card per target, the define/edit form, delete, evaluate |
|
|
1255
|
+
| `TargetStatusBadge` | List badge: `evaluation` is `undefined` (loading), `null` (no target) or the latest `TargetEvaluation` |
|
|
1256
|
+
| `TargetHeatmap` | The history as one status timeline per rule: runs of equal verdicts drawn as flat blocks (green met, red missed, grey not evaluable, blank where nothing was recorded or the rule did not exist yet), each window keeping its exact share of the strip; a cursor follows the pointer or the arrow keys one window at a time, and the card names the window and the run it sits in; `windows` pads the strip to the range the panel picked (2 h / 6 h / 24 h) |
|
|
1257
|
+
| `RuleTrend` | One rule's readings over the windows with the threshold as a dashed line, coloured per stretch by which side of the line it sat on; gaps where a window could not be evaluated |
|
|
1258
|
+
|
|
1259
|
+
### Hooks
|
|
1260
|
+
|
|
1261
|
+
All hooks read the source from `TargetsProvider` and key their queries under `observabilityQueryKeys.targets*`.
|
|
1262
|
+
|
|
1263
|
+
| Hook | Returns |
|
|
1264
|
+
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
|
|
1265
|
+
| `useTargetsByReference(reference)` | `PerformanceTarget[]` declared under the reference |
|
|
1266
|
+
| `useTargetHistory(targetId, perPage = 24)` | `{ data: TargetEvaluation[], totalCount }`, most recent first |
|
|
1267
|
+
| `useLatestTargetEvaluations(references)` | `Record<reference, TargetEvaluation \| null>`; batched by 500, one request per batch |
|
|
1268
|
+
| `useTargetMetricCatalog(apiTypes)` | `{ metrics, isLoading, error }` — the definition's metrics for those types, merged, `apis` covering every type |
|
|
1269
|
+
| `useTargetFilterSpecs(metricName)` | The definition's filters for one metric |
|
|
1270
|
+
| `useTargetMutations(reference)` | `{ create, update, remove, evaluateNow }` mutations that refresh the list, the history and the badges they touch |
|
|
1271
|
+
|
|
1272
|
+
### Errors
|
|
1273
|
+
|
|
1274
|
+
`TargetsApiError` carries the `status` and, on a 400 that blames one rule, `ruleIndex`; `TargetRateLimitedError` (429) carries `retryAfterSeconds`. Branch on `isTargetRateLimited(error)` and `targetErrorRuleIndex(error)` rather than `instanceof`, for the same reason as the dashboard errors.
|
|
1275
|
+
|
|
1276
|
+
### Vocabulary helpers
|
|
1277
|
+
|
|
1278
|
+
`analyticsApiName(apiType)` maps an `ApiType` to the analytics definition's API name (`PROXY` → `HTTP_PROXY`, `LLM_PROXY` → `LLM`, …). `describeRule(rule, { label, unit })` renders `p95 Gateway response time ≤ 2,000 ms`; `formatMetricValue`, `formatDeviation`, `statusLabel` (`Met` / `Missed` / `Not evaluable`) and `notEvaluableReason` produce the words the panel uses, so a host can quote a target consistently elsewhere.
|
|
1279
|
+
|
|
1280
|
+
### Testing
|
|
1281
|
+
|
|
1282
|
+
`@gravitee/gamma-lib-observability/testing` exports `createInMemoryTargetsSource(options)` — targets, evaluations, a metric catalog (`SAMPLE_METRIC_SPECS` by default), an `evaluate` function for "evaluate now", `rateLimitedForSeconds`, `latencyMs` and `failure` — to drive `TargetsPanel` through `TargetsProvider`'s `source` prop.
|
|
1283
|
+
|
|
1284
|
+
---
|
|
1285
|
+
|
|
1209
1286
|
_This guide will be expanded as new features are added (custom dashboards)._
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BreakpointCols } from '@gravitee/graphene-charts/dashboard-grid';
|
|
2
2
|
import { Dashboard, FilterCondition, TimeRange, Widget, WidgetLayout } from '../types/domain';
|
|
3
|
+
import { WidgetInteractionContextValue } from './WidgetInteractionContext';
|
|
3
4
|
export interface DashboardViewProps {
|
|
4
5
|
readonly dashboard: Dashboard;
|
|
5
6
|
readonly timeRange: TimeRange;
|
|
@@ -28,6 +29,12 @@ export interface DashboardViewProps {
|
|
|
28
29
|
* user knows the grid copy will be replaced on save.
|
|
29
30
|
*/
|
|
30
31
|
readonly highlightedWidgetId?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Receives what a reader acted on inside a widget — a table row, say — so the
|
|
34
|
+
* page can turn it into a dashboard filter or a navigation. Left out, widgets
|
|
35
|
+
* render without the affordance rather than with a dead one.
|
|
36
|
+
*/
|
|
37
|
+
readonly interaction?: WidgetInteractionContextValue;
|
|
31
38
|
}
|
|
32
|
-
export declare function DashboardView({ dashboard, timeRange, filters, editable, rowHeight, breakpointCols, onLayoutChange, widgetActions, highlightedWidgetId, }: DashboardViewProps): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
export declare function DashboardView({ dashboard, timeRange, filters, editable, rowHeight, breakpointCols, onLayoutChange, widgetActions, highlightedWidgetId, interaction, }: DashboardViewProps): import("react/jsx-runtime").JSX.Element;
|
|
33
40
|
//# sourceMappingURL=DashboardView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardView.d.ts","sourceRoot":"","sources":["../../src/dashboards/DashboardView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAwB,MAAM,0CAA0C,CAAC;AAIrG,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"DashboardView.d.ts","sourceRoot":"","sources":["../../src/dashboards/DashboardView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAwB,MAAM,0CAA0C,CAAC;AAIrG,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEnG,OAAO,EAA6B,KAAK,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AA+B3G,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,iIAAiI;IACjI,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,2DAA2D;IAC3D,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,KAAK,IAAI,CAAC;IAC/E;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC7D;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,6BAA6B,CAAC;CACtD;AAED,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,SAAS,EACT,OAAuB,EACvB,QAAgB,EAChB,SAAS,EACT,cAAwC,EACxC,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,WAAW,GACZ,EAAE,kBAAkB,2CAoFpB"}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { FilterCondition, TimeRange } from '../types/domain';
|
|
3
|
+
import { WidgetInteractionContextValue } from './WidgetInteractionContext';
|
|
3
4
|
export type WidgetGroupAlign = 'stretch' | 'center' | 'start' | 'end';
|
|
4
5
|
export interface WidgetGroupProps {
|
|
5
6
|
readonly timeRange: TimeRange;
|
|
6
7
|
readonly filters?: readonly FilterCondition[];
|
|
7
8
|
readonly align?: WidgetGroupAlign;
|
|
9
|
+
/**
|
|
10
|
+
* Receives what a reader acted on inside a widget. Same contract as on
|
|
11
|
+
* `DashboardView`, so an embedded group behaves like a dashboard does.
|
|
12
|
+
*/
|
|
13
|
+
readonly interaction?: WidgetInteractionContextValue;
|
|
8
14
|
readonly children: ReactNode;
|
|
9
15
|
}
|
|
10
16
|
/**
|
|
@@ -12,5 +18,5 @@ export interface WidgetGroupProps {
|
|
|
12
18
|
* `filters` context. Renders children in a responsive flex layout where
|
|
13
19
|
* each child takes equal width.
|
|
14
20
|
*/
|
|
15
|
-
export declare function WidgetGroup({ timeRange, filters, align, children }: WidgetGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export declare function WidgetGroup({ timeRange, filters, align, interaction, children, }: WidgetGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
16
22
|
//# sourceMappingURL=WidgetGroup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetGroup.d.ts","sourceRoot":"","sources":["../../src/dashboards/WidgetGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"WidgetGroup.d.ts","sourceRoot":"","sources":["../../src/dashboards/WidgetGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EAA6B,KAAK,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AAE3G,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,6BAA6B,CAAC;IACrD,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AASD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,OAAuB,EACvB,KAAiB,EACjB,WAAW,EACX,QAAQ,GACT,EAAE,gBAAgB,2CAYlB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a widget can ask the page to do with one of its values.
|
|
3
|
+
*
|
|
4
|
+
* `filter` and `exclude` are the drill-down proper. The three navigation kinds
|
|
5
|
+
* exist because the widget cannot build those links itself: the library
|
|
6
|
+
* contributes routes but never owns them, so only the page knows its base path
|
|
7
|
+
* and, for `open-entity`, what a value even points at. The widget offers the
|
|
8
|
+
* affordance; the page decides what it means.
|
|
9
|
+
*/
|
|
10
|
+
export type WidgetInteractionKind = 'filter' | 'exclude' | 'view-logs' | 'view-traces' | 'open-entity';
|
|
11
|
+
export interface WidgetInteraction {
|
|
12
|
+
readonly kind: WidgetInteractionKind;
|
|
13
|
+
/** Dimension the value belongs to, which is also its filter field. */
|
|
14
|
+
readonly field: string;
|
|
15
|
+
readonly value: string;
|
|
16
|
+
/** Human-readable form of `value`, when the data source resolved one. */
|
|
17
|
+
readonly label?: string;
|
|
18
|
+
}
|
|
19
|
+
export type WidgetInteractionHandler = (interaction: WidgetInteraction) => void;
|
|
20
|
+
export interface WidgetInteractionContextValue {
|
|
21
|
+
readonly onInteract: WidgetInteractionHandler;
|
|
22
|
+
/**
|
|
23
|
+
* Whether the page can act on a kind for a given field. A widget offers only
|
|
24
|
+
* what the page answers for: an entry that silently does nothing is worse
|
|
25
|
+
* than no entry at all. Everything is offered when this is omitted.
|
|
26
|
+
*/
|
|
27
|
+
readonly supports?: (kind: WidgetInteractionKind, field: string) => boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare const WidgetInteractionProvider: import('react').Provider<WidgetInteractionContextValue | null>;
|
|
30
|
+
export declare function useWidgetInteractionContext(): WidgetInteractionContextValue | null;
|
|
31
|
+
//# sourceMappingURL=WidgetInteractionContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetInteractionContext.d.ts","sourceRoot":"","sources":["../../src/dashboards/WidgetInteractionContext.tsx"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,GAAG,aAAa,CAAC;AAEvG,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,wBAAwB,GAAG,CAAC,WAAW,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAEhF,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;CAC7E;AAUD,eAAO,MAAM,yBAAyB,gEAAoC,CAAC;AAE3E,wBAAgB,2BAA2B,IAAI,6BAA6B,GAAG,IAAI,CAElF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BarWidget, BreakdownWidget, CartesianWidget, DoughnutWidget, FilterCondition, MetricGroupWidget, MetricWidget, TimeRange, Widget } from '../types/domain';
|
|
2
|
-
import { BarWidgetData, BreakdownWidgetData, CartesianWidgetData, DoughnutWidgetData, MetricGroupWidgetData, MetricWidgetData } from './widget-data';
|
|
1
|
+
import { BarWidget, BreakdownWidget, CartesianWidget, DoughnutWidget, FilterCondition, MetricGroupWidget, MetricWidget, TableWidget, TimeRange, Widget } from '../types/domain';
|
|
2
|
+
import { BarWidgetData, BreakdownWidgetData, CartesianWidgetData, DoughnutWidgetData, MetricGroupWidgetData, MetricWidgetData, TableWidgetData } from './widget-data';
|
|
3
3
|
interface WidgetItemBaseProps {
|
|
4
4
|
readonly timeRange?: TimeRange;
|
|
5
5
|
readonly filters?: readonly FilterCondition[];
|
|
@@ -32,11 +32,15 @@ interface WidgetItemManualBreakdownProps extends WidgetItemBaseProps {
|
|
|
32
32
|
readonly widget: BreakdownWidget;
|
|
33
33
|
readonly data: BreakdownWidgetData;
|
|
34
34
|
}
|
|
35
|
+
interface WidgetItemManualTableProps extends WidgetItemBaseProps {
|
|
36
|
+
readonly widget: TableWidget;
|
|
37
|
+
readonly data: TableWidgetData;
|
|
38
|
+
}
|
|
35
39
|
/**
|
|
36
40
|
* Props for `WidgetItem`. The union ensures that when `data` is provided,
|
|
37
41
|
* `data.type` is paired with the correct `widget` subtype at compile time.
|
|
38
42
|
*/
|
|
39
|
-
export type WidgetItemProps = WidgetItemAutoProps | WidgetItemManualMetricProps | WidgetItemManualMetricGroupProps | WidgetItemManualCartesianProps | WidgetItemManualBarProps | WidgetItemManualDoughnutProps | WidgetItemManualBreakdownProps;
|
|
43
|
+
export type WidgetItemProps = WidgetItemAutoProps | WidgetItemManualMetricProps | WidgetItemManualMetricGroupProps | WidgetItemManualCartesianProps | WidgetItemManualBarProps | WidgetItemManualDoughnutProps | WidgetItemManualBreakdownProps | WidgetItemManualTableProps;
|
|
40
44
|
/**
|
|
41
45
|
* Standalone widget that resolves a renderer from the widget registry.
|
|
42
46
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetItem.d.ts","sourceRoot":"","sources":["../../src/dashboards/WidgetItem.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,eAAe,EACf,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,SAAS,EACT,MAAM,EACP,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"WidgetItem.d.ts","sourceRoot":"","sources":["../../src/dashboards/WidgetItem.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,eAAe,EACf,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,SAAS,EACT,MAAM,EACP,MAAM,iBAAiB,CAAC;AAazB,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EAEhB,MAAM,eAAe,CAAC;AAKvB,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;CAC/C;AAED,UAAU,mBAAoB,SAAQ,mBAAmB;IACvD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;CAC3B;AAED,UAAU,2BAA4B,SAAQ,mBAAmB;IAC/D,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;CACjC;AAED,UAAU,gCAAiC,SAAQ,mBAAmB;IACpE,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;CACtC;AAED,UAAU,8BAA+B,SAAQ,mBAAmB;IAClE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;CACpC;AAED,UAAU,wBAAyB,SAAQ,mBAAmB;IAC5D,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;CAC9B;AAED,UAAU,6BAA8B,SAAQ,mBAAmB;IACjE,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;CACnC;AAED,UAAU,8BAA+B,SAAQ,mBAAmB;IAClE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;CACpC;AAED,UAAU,0BAA2B,SAAQ,mBAAmB;IAC9D,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GACvB,mBAAmB,GACnB,2BAA2B,GAC3B,gCAAgC,GAChC,8BAA8B,GAC9B,wBAAwB,GACxB,6BAA6B,GAC7B,8BAA8B,GAC9B,0BAA0B,CAAC;AAE/B;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAMhD"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ChartState } from '@gravitee/graphene-charts';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { TableRowMarker, TableSort } from '../../types/domain';
|
|
4
|
+
import { AnalyticsTableRow, ResolvedTableColumn } from './analytics-table-model';
|
|
5
|
+
import { RowColorResolver } from './row-color';
|
|
6
|
+
/** Key of the synthetic totals row. Never a real dimension value. */
|
|
7
|
+
export declare const TOTALS_ROW_KEY = "__totals__";
|
|
8
|
+
export declare function isTotalsRow(row: AnalyticsTableRow): boolean;
|
|
9
|
+
export interface AnalyticsTableProps {
|
|
10
|
+
readonly columns: readonly ResolvedTableColumn[];
|
|
11
|
+
readonly rows: readonly AnalyticsTableRow[];
|
|
12
|
+
/** Header of the label column, e.g. `API`. */
|
|
13
|
+
readonly dimensionLabel: string;
|
|
14
|
+
readonly state: ChartState;
|
|
15
|
+
/** Active sort when controlled; the initial sort otherwise. */
|
|
16
|
+
readonly sort: TableSort | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Makes the sort controlled. Left out — in manual mode, or in a story — the
|
|
19
|
+
* table sorts itself over the rows it was handed, which is the only thing it
|
|
20
|
+
* can do without a query to re-issue.
|
|
21
|
+
*/
|
|
22
|
+
readonly onSortChange?: (sort: TableSort) => void;
|
|
23
|
+
/** Overall metric totals, keyed by column id. Also the share denominator. */
|
|
24
|
+
readonly totals?: Readonly<Record<string, number>>;
|
|
25
|
+
readonly showTotals?: boolean;
|
|
26
|
+
/** How many rows the response could not fill completely. */
|
|
27
|
+
readonly partialRows?: number;
|
|
28
|
+
/** Ceiling on the rows shown per page; the height decides the rest. */
|
|
29
|
+
readonly pageSize?: number;
|
|
30
|
+
readonly rowMarker?: TableRowMarker;
|
|
31
|
+
/** Colour of a row's swatch when the dimension has semantic colours. */
|
|
32
|
+
readonly rowColorFor?: RowColorResolver;
|
|
33
|
+
readonly onRowSelect?: (row: AnalyticsTableRow) => void;
|
|
34
|
+
/** Extra entries for the per-row menu. The menu only exists when this is set. */
|
|
35
|
+
readonly renderRowMenuItems?: (row: AnalyticsTableRow) => ReactNode;
|
|
36
|
+
/**
|
|
37
|
+
* Ranked-list rendering used when the widget is too narrow for even one value
|
|
38
|
+
* column. Supplied by the caller so the fallback is the real top-list
|
|
39
|
+
* presentation rather than a second implementation of it.
|
|
40
|
+
*/
|
|
41
|
+
readonly renderTopList?: (sortColumn: ResolvedTableColumn) => ReactNode;
|
|
42
|
+
readonly emptyMessage?: ReactNode;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The table itself: sorting, paging, totals and degradation, over data someone
|
|
46
|
+
* else fetched.
|
|
47
|
+
*
|
|
48
|
+
* It measures its own body and adapts in discrete steps — compact numbers, then
|
|
49
|
+
* collapsed columns, then a top list, then an explicit "too small" state. It
|
|
50
|
+
* never scales and never scrolls: the widget lives in a box the grid clips, so
|
|
51
|
+
* anything that does not fit has to be decided about, not pushed out of view.
|
|
52
|
+
*/
|
|
53
|
+
export declare function AnalyticsTable({ columns, rows, dimensionLabel, state, sort, onSortChange, totals, showTotals, partialRows, pageSize, rowMarker, rowColorFor, onRowSelect, renderRowMenuItems, renderTopList, emptyMessage, }: AnalyticsTableProps): import("react/jsx-runtime").JSX.Element;
|
|
54
|
+
//# sourceMappingURL=AnalyticsTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnalyticsTable.d.ts","sourceRoot":"","sources":["../../../src/dashboards/analytics-table/AnalyticsTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAe5D,OAAO,EAAkC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvE,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACzB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,qEAAqE;AACrE,eAAO,MAAM,cAAc,eAAe,CAAC;AAM3C,wBAAgB,WAAW,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAE3D;AAyGD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACjD,QAAQ,CAAC,IAAI,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC5C,8CAA8C;IAC9C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAClD,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;IACpC,wEAAwE;IACxE,QAAQ,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC;IACxC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACxD,iFAAiF;IACjF,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,SAAS,CAAC;IACpE;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,SAAS,CAAC;IACxE,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,IAAI,EACJ,cAAc,EACd,KAAK,EACL,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,UAAkB,EAClB,WAAe,EACf,QAAQ,EACR,SAAS,EACT,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,YAAyC,GAC1C,EAAE,mBAAmB,2CAgPrB"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { SortOrder, TableColumn, TableColumnFormat, TableSort, TableThreshold } from '../../types/domain';
|
|
2
|
+
import { FacetBucket } from '../../types/responses';
|
|
3
|
+
/**
|
|
4
|
+
* A column with every default resolved: the identity used for sorting and for
|
|
5
|
+
* the collapse plan, the label and unit taken from the metric catalog when the
|
|
6
|
+
* author did not override them, and the flags turned into plain booleans.
|
|
7
|
+
*
|
|
8
|
+
* Resolution happens at render time, never at save time, so a table follows the
|
|
9
|
+
* catalog as it is corrected or extended instead of freezing a copy of it into
|
|
10
|
+
* the dashboard (see OBS-73 / OBS-81).
|
|
11
|
+
*/
|
|
12
|
+
export interface ResolvedTableColumn {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly metric: string;
|
|
15
|
+
readonly measure: string;
|
|
16
|
+
readonly label: string;
|
|
17
|
+
readonly unit?: string;
|
|
18
|
+
readonly format: TableColumnFormat;
|
|
19
|
+
readonly thresholds: readonly TableThreshold[];
|
|
20
|
+
readonly share: boolean;
|
|
21
|
+
readonly pinned: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface AnalyticsTableRow {
|
|
24
|
+
/** Bucket key — the value a row click filters on. */
|
|
25
|
+
readonly key: string;
|
|
26
|
+
readonly label: string;
|
|
27
|
+
/**
|
|
28
|
+
* Column id to value. A missing entry is a cell the response did not carry,
|
|
29
|
+
* which renders as "—" rather than as a zero: the two mean different things
|
|
30
|
+
* and reading "0 errors" where the backend said nothing is a lie.
|
|
31
|
+
*/
|
|
32
|
+
readonly values: Readonly<Record<string, number>>;
|
|
33
|
+
}
|
|
34
|
+
export interface AnalyticsTableModel {
|
|
35
|
+
readonly rows: readonly AnalyticsTableRow[];
|
|
36
|
+
/** Rows missing at least one column's value. */
|
|
37
|
+
readonly partialRows: number;
|
|
38
|
+
}
|
|
39
|
+
/** A column's identity is its metric/measure pair unless the author named it. */
|
|
40
|
+
export declare function tableColumnId(column: TableColumn): string;
|
|
41
|
+
export declare function resolveTableColumn(column: TableColumn): ResolvedTableColumn;
|
|
42
|
+
export declare function resolveTableColumns(columns: readonly TableColumn[]): ResolvedTableColumn[];
|
|
43
|
+
/**
|
|
44
|
+
* The sort the widget actually applies: the author's when it still names a
|
|
45
|
+
* column, otherwise the first column descending. A saved sort pointing at a
|
|
46
|
+
* column that has since been removed must not leave the table unordered.
|
|
47
|
+
*/
|
|
48
|
+
export declare function resolveTableSort(columns: readonly ResolvedTableColumn[], sort: TableSort | undefined): TableSort | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Joins the buckets of several metrics into one row per dimension value.
|
|
51
|
+
*
|
|
52
|
+
* The row list — and its order — comes from the metric that carries the sort,
|
|
53
|
+
* because that is the only aggregation the backend ordered. Every other metric
|
|
54
|
+
* is looked up by key, and a key it does not carry leaves a hole: with one
|
|
55
|
+
* `terms` aggregation per metric, a sort on something other than a count lets
|
|
56
|
+
* the other aggregations return a different top-N. Holes are counted so the
|
|
57
|
+
* widget can say how much of the table is incomplete rather than passing off a
|
|
58
|
+
* partial join as a full one.
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildTableModel(buckets: readonly FacetBucket[], columns: readonly ResolvedTableColumn[], sortMetric: string): AnalyticsTableModel;
|
|
61
|
+
/**
|
|
62
|
+
* Denominator for a share column: the metric's overall total when totals were
|
|
63
|
+
* fetched, otherwise the sum of what is on screen. The two answer different
|
|
64
|
+
* questions ("share of all traffic" vs "share of the top N"), so which one is
|
|
65
|
+
* in play has to reach the cell — hence the flag rather than a bare number.
|
|
66
|
+
*/
|
|
67
|
+
export declare function resolveShareBase(column: ResolvedTableColumn, rows: readonly AnalyticsTableRow[], totals: Readonly<Record<string, number>> | undefined): {
|
|
68
|
+
readonly base: number;
|
|
69
|
+
readonly ofTotal: boolean;
|
|
70
|
+
};
|
|
71
|
+
/** Client-side ordering over the top-N the backend returned. */
|
|
72
|
+
export declare function sortTableRows(rows: readonly AnalyticsTableRow[], columnId: string, order: SortOrder): AnalyticsTableRow[];
|
|
73
|
+
//# sourceMappingURL=analytics-table-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-table-model.d.ts","sourceRoot":"","sources":["../../../src/dashboards/analytics-table/analytics-table-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,iBAAiB,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC/G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIzD;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC5C,gDAAgD;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAEzD;AAaD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,mBAAmB,CAc3E;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,mBAAmB,EAAE,CAE1F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,mBAAmB,EAAE,EACvC,IAAI,EAAE,SAAS,GAAG,SAAS,GAC1B,SAAS,GAAG,SAAS,CAKvB;AAYD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,SAAS,WAAW,EAAE,EAC/B,OAAO,EAAE,SAAS,mBAAmB,EAAE,EACvC,UAAU,EAAE,MAAM,GACjB,mBAAmB,CAmCrB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE,SAAS,iBAAiB,EAAE,EAClC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,GACnD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAKtD;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,iBAAiB,EAAE,EAClC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,SAAS,GACf,iBAAiB,EAAE,CAWrB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { TableColumnFormat, TableThreshold, TableTierColor } from '../../types/domain';
|
|
2
|
+
import { ResolvedTableColumn } from './analytics-table-model';
|
|
3
|
+
import { TableDensity } from './plan-columns';
|
|
4
|
+
/** What an absent cell reads as. Never a zero — see `AnalyticsTableRow.values`. */
|
|
5
|
+
export declare const MISSING_CELL = "\u2014";
|
|
6
|
+
export interface FormatTableValueOptions {
|
|
7
|
+
readonly format: TableColumnFormat;
|
|
8
|
+
readonly unit?: string;
|
|
9
|
+
/** Compact density switches plain numbers to `1.28M`. @default 'comfortable' */
|
|
10
|
+
readonly density?: TableDensity;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Formats one cell. The unit suffix is only appended to plain numbers: a
|
|
14
|
+
* percentage, a duration and a byte size all carry their own, and repeating it
|
|
15
|
+
* gives "2.3% %".
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatTableValue(value: number, options: FormatTableValueOptions): string;
|
|
18
|
+
/** Formats a cell of a resolved column, or the placeholder when it has no value. */
|
|
19
|
+
export declare function formatColumnValue(value: number | undefined, column: ResolvedTableColumn, density: TableDensity): string;
|
|
20
|
+
/**
|
|
21
|
+
* The colour a cell takes, or none. Thresholds are ordered rules and **the
|
|
22
|
+
* first one that matches wins**, the way conditional formatting works in
|
|
23
|
+
* Datadog, Metabase or a spreadsheet: the author's order is the priority, and
|
|
24
|
+
* a later rule never overrides an earlier one. Each rule is checked against
|
|
25
|
+
* what it asks for: the cell's value, or its share of the column total (a
|
|
26
|
+
* ratio here, a percentage in the rule).
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveThresholdColor(value: number | undefined, share: number | undefined, thresholds: readonly TableThreshold[]): TableTierColor | undefined;
|
|
29
|
+
/** Design-system tokens, so both themes are covered without a theme branch. */
|
|
30
|
+
export declare const THRESHOLD_TEXT_CLASS: Record<TableTierColor, string>;
|
|
31
|
+
//# sourceMappingURL=format-table-value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-table-value.d.ts","sourceRoot":"","sources":["../../../src/dashboards/analytics-table/format-table-value.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC5F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAKnD,mFAAmF;AACnF,eAAO,MAAM,YAAY,WAAM,CAAC;AAuBhC,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,gFAAgF;IAChF,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;CACjC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAkBxF;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,YAAY,GACpB,MAAM,CAOR;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,UAAU,EAAE,SAAS,cAAc,EAAE,GACpC,cAAc,GAAG,SAAS,CAU5B;AAED,+EAA+E;AAC/E,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAI/D,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { AnalyticsTable, TOTALS_ROW_KEY, isTotalsRow, type AnalyticsTableProps } from './AnalyticsTable';
|
|
2
|
+
export { buildTableModel, resolveShareBase, resolveTableColumn, resolveTableColumns, resolveTableSort, sortTableRows, tableColumnId, type AnalyticsTableModel, type AnalyticsTableRow, type ResolvedTableColumn, } from './analytics-table-model';
|
|
3
|
+
export { MISSING_CELL, formatColumnValue, formatTableValue, resolveThresholdColor, type FormatTableValueOptions, } from './format-table-value';
|
|
4
|
+
export { planColumns, resolveRowsPerPage, type ColumnPlan, type PageSizePlan, type PlanColumnsOptions, type TableDensity, type TableLayoutMode, } from './plan-columns';
|
|
5
|
+
export { buildTableMetrics, useAnalyticsTableQuery, type AnalyticsTableQueryResult, type UseAnalyticsTableQueryParams, } from './use-analytics-table-query';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dashboards/analytics-table/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACzG,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,GAClC,MAAM,6BAA6B,CAAC"}
|