@meshmakers/octo-meshboard 3.5.500 → 3.5.520

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.
@@ -7,7 +7,7 @@ import { SortDto, FieldFilterDto, QueryModeDto, ResolveSeriesQueryInputDto, CkRo
7
7
  export { RuntimeEntityDialogDataSource, RuntimeEntityItem, RuntimeEntitySelectDataSource, TENANT_ID_PROVIDER, TenantIdProvider } from '@meshmakers/octo-services';
8
8
  import { ControlValueAccessor } from '@angular/forms';
9
9
  import * as i1 from '@meshmakers/shared-ui';
10
- import { EntitySelectDialogDataSource, ColumnDefinition, DialogFetchOptions, DialogFetchResult, EntitySelectInputComponent, TimeRange, FetchDataOptions, FetchResultTyped, TableColumn as TableColumn$1, ListViewMessages, HasUnsavedChanges, TimeRangePickerLabels, TimeRangeSelection as TimeRangeSelection$1 } from '@meshmakers/shared-ui';
10
+ import { EntitySelectDialogDataSource, ColumnDefinition, DialogFetchOptions, DialogFetchResult, EntitySelectInputComponent, TimeRange, FetchDataOptions, FetchResultTyped, TableColumn as TableColumn$1, ListViewMessages, EntitySelectInputMessages, HasUnsavedChanges, TimeRangePickerLabels, TimeRangeSelection as TimeRangeSelection$1 } from '@meshmakers/shared-ui';
11
11
  import { EntitySelectDataSource, EntitySelectResult } from '@meshmakers/shared-services';
12
12
  import * as Apollo from 'apollo-angular';
13
13
  import { CkTypeSelectorInputComponent, AttributeValueTypeDto, FieldFilterItem, FilterVariable, PropertyGridItem, PropertyGridConfig, OctoGraphQlDataSource, FieldFilterEditorComponent } from '@meshmakers/octo-ui';
@@ -281,7 +281,7 @@ interface PersistentQueryDataSource extends WidgetDataSource {
281
281
  /**
282
282
  * Asset-scope binding: the `id` of an entity selector whose selection scopes
283
283
  * this widget's stream-data query. The selector resolves its picked entity to
284
- * a set of source rtIds (via its `childScope` one-hop, or the picked entity
284
+ * a set of source rtIds (via its `childScope` hop or path, or the picked entity
285
285
  * itself when no childScope is configured); those rtIds are passed as the
286
286
  * query's `streamDataArgs.rtIds`, replacing the persisted RtIds at execution
287
287
  * time. Absent ⇒ the query runs with its persisted scope. Ignored for runtime
@@ -577,9 +577,29 @@ interface TableColumnStatusIconMapping {
577
577
  tooltip: string;
578
578
  color?: string;
579
579
  }
580
+ /**
581
+ * Display label of one raw cell value of a table column (AB#7655), e.g. `{ label: 'L2' }` for `2`.
582
+ */
583
+ interface TableColumnValueLabel {
584
+ /**
585
+ * Text shown instead of the raw value: one string for every language, or a text per culture
586
+ * code (`{ "de-AT": "gut", "en-GB": "good" }`) that follows the host language
587
+ * (`MESHBOARD_LANGUAGE`; exact culture, then language part). Without a match the raw value shows.
588
+ */
589
+ label: string | Record<string, string>;
590
+ /** Optional CSS text colour (e.g. `var(--kendo-color-success)`); without it the theme text colour applies. */
591
+ color?: string;
592
+ }
580
593
  interface TableColumn {
581
594
  field: string;
595
+ /** Header text; the fallback when `titles` has no text for the host language. */
582
596
  title: string;
597
+ /**
598
+ * Header text per culture code (AB#7655), e.g. `{ "de-AT": "Datenqualität", "en-GB": "Data quality" }`.
599
+ * Picked for the host language (`MESHBOARD_LANGUAGE` / `provideMeshBoard({ language })`): exact
600
+ * culture, then a key equal to the language part (`de`), then `title`. No host language = `title`.
601
+ */
602
+ titles?: Record<string, string>;
583
603
  width?: number;
584
604
  dataType?: string;
585
605
  /**
@@ -589,6 +609,15 @@ interface TableColumn {
589
609
  */
590
610
  format?: string;
591
611
  statusMapping?: Record<string, TableColumnStatusIconMapping>;
612
+ /**
613
+ * Labels for raw cell values (AB#7655), keyed by the value as string (`"1"`, `"2"`, `"3"`); a
614
+ * number `2` and a string `"2"` both match `"2"`. The cell shows the label as plain text (with the
615
+ * optional colour); a value without a label keeps the column's `dataType` / `format` rendering,
616
+ * `null` / missing is an empty cell. When no label applies for the current language the column
617
+ * renders as without `valueLabels`. Wins over `MESHBOARD_LABEL_RESOLVER`. Not supported together
618
+ * with `statusMapping` (the labels are shown, a console warning is logged).
619
+ */
620
+ valueLabels?: Record<string, TableColumnValueLabel>;
592
621
  }
593
622
  /**
594
623
  * Gauge types available
@@ -639,6 +668,17 @@ interface GaugeWidgetConfig extends WidgetConfig {
639
668
  queryCategoryValue?: string;
640
669
  /** Field filters for data source */
641
670
  filters?: WidgetFilterConfig[];
671
+ /**
672
+ * How the value is obtained, as on the KPI (AB#7950). `'formula'` computes it from
673
+ * {@link formula} over MeshBoard variables (the data source stays `{ type: 'static' }`);
674
+ * `'value'` or absent uses the data source.
675
+ */
676
+ valueMode?: KpiValueMode;
677
+ /**
678
+ * Formula over MeshBoard variables, e.g. `max(0, min(100, (1 - ${import} / ${consumption}) * 100))`.
679
+ * Used when `valueMode` is `'formula'`; the result must be a number.
680
+ */
681
+ formula?: string;
642
682
  }
643
683
  /**
644
684
  * Pie Chart types available
@@ -832,9 +872,21 @@ type HeatmapColorScheme = 'green' | 'redGreen' | 'blue' | 'heat';
832
872
  */
833
873
  type HeatmapColorMode = 'gradient' | 'threshold';
834
874
  /**
835
- * Client-side aggregation function for simple queries
875
+ * Client-side aggregation function for simple queries.
876
+ * `weightedAvg` (AB#7956): cell = Σ valueField / Σ weightField, for rollup archives that store a
877
+ * mean as a sum column plus a count column; a cell without rows is empty, not 0.
878
+ */
879
+ type HeatmapAggregation = 'count' | 'sum' | 'avg' | 'weightedAvg';
880
+ /**
881
+ * Widget-level relative time window of a heatmap (AB#7956), e.g. the last 30 days.
882
+ * Overrides the board time filter for this widget's stream-data query.
836
883
  */
837
- type HeatmapAggregation = 'count' | 'sum' | 'avg';
884
+ interface HeatmapTimeWindow {
885
+ /** Number of units, a positive integer */
886
+ value: number;
887
+ /** Unit of the window */
888
+ unit: RelativeTimeUnit;
889
+ }
838
890
  /**
839
891
  * Heatmap Widget - displays data availability or density as a heatmap
840
892
  * X-axis: Date (day), Y-axis: Time slot (hour or 15-min interval), Color: aggregated value
@@ -851,10 +903,25 @@ interface HeatmapWidgetConfig extends WidgetConfig {
851
903
  /** Optional end-of-interval field (e.g. timeRange.to). When set, the interval width is auto-detected
852
904
  * and sub-hour columns are shown (e.g. 00-15, 15-30, 30-45, 45-60 for 15-min data). */
853
905
  dateEndField?: string;
854
- /** Field containing the numeric value to aggregate (for sum/avg) */
906
+ /** Field containing the numeric value to aggregate (for sum/avg; the sum column for weightedAvg) */
855
907
  valueField?: string;
856
908
  /** Client-side aggregation function for simple queries */
857
909
  aggregation: HeatmapAggregation;
910
+ /** `weightedAvg` only: the weight (count) column; cell = Σ valueField / Σ weightField (AB#7956) */
911
+ weightField?: string;
912
+ /**
913
+ * The date field marks the END of a bucket (rollup archives) (AB#7956). Each row is shifted back by
914
+ * {@link bucketWidthMinutes} to its bucket start before hour/day bucketing, so the last bucket of an
915
+ * hour stays in that hour. Ignored when {@link dateEndField} is set.
916
+ */
917
+ timestampIsBucketEnd?: boolean;
918
+ /** Bucket width in minutes for {@link timestampIsBucketEnd} (e.g. 5 for a 5-min rollup) */
919
+ bucketWidthMinutes?: number;
920
+ /**
921
+ * Own relative time window (AB#7956). When set, it overrides the board time filter for this
922
+ * widget's stream-data query, and the widget shows the window in a badge. Unset = board filter.
923
+ */
924
+ timeWindow?: HeatmapTimeWindow;
858
925
  /** Color scheme for the heatmap (used in `gradient` color mode) */
859
926
  colorScheme: HeatmapColorScheme;
860
927
  /** Coloring mode — relative `gradient` (default) or absolute `threshold` bands */
@@ -1374,21 +1441,44 @@ interface EntitySelectorAttributeMapping {
1374
1441
  attributeValueType?: string;
1375
1442
  }
1376
1443
  /**
1377
- * One-hop association traversal that turns a selected entity into the set of
1378
- * source rtIds a stream-data widget should be scoped to.
1444
+ * One association hop of a multi-hop child scope (AB#7723): from the entities
1445
+ * reached so far (the picked entity for the first hop) over `roleId` in
1446
+ * `direction` to the entities of `targetCkTypeId`.
1447
+ */
1448
+ interface EntitySelectorScopeHop {
1449
+ /** Association role of this hop (e.g. "System/ParentChild"). */
1450
+ roleId: string;
1451
+ /** Traversal direction; defaults to `'in'` (see {@link EntitySelectorChildScope.direction}). */
1452
+ direction?: 'in' | 'out';
1453
+ /** CK type of the entities this hop reaches; the source type of the next hop. */
1454
+ targetCkTypeId: string;
1455
+ }
1456
+ /**
1457
+ * Association traversal that turns a selected entity into the set of source
1458
+ * rtIds a stream-data widget should be scoped to.
1379
1459
  *
1380
1460
  * Use case: the user picks a `MeteringPoint`, but the stream-data archive is
1381
1461
  * keyed by its child `EnergyMeasurement` rtIds. The childScope describes that
1382
- * single hop (target type + association role + direction); the selected
1383
- * entity's children of `targetCkTypeId` reached via `roleId` become the scope
1384
- * rtIds. When a selector has no childScope, the picked entity's own rtId is the
1385
- * scope (direct keying).
1462
+ * hop (target type + association role + direction); the selected entity's
1463
+ * children of `targetCkTypeId` reached via `roleId` become the scope rtIds.
1464
+ * When a selector has no childScope, the picked entity's own rtId is the scope
1465
+ * (direct keying).
1466
+ *
1467
+ * Two forms (AB#7723):
1468
+ * - **One hop** — the top-level `targetCkTypeId` / `roleId` / `direction`. This
1469
+ * is the original form; the editor keeps writing one-hop scopes this way, so
1470
+ * older library versions keep reading them.
1471
+ * - **Path** — `path`, an ordered list of 2 to {@link MAX_SCOPE_HOPS} hops
1472
+ * (A → B → C). The source type of hop n is the target type of hop n-1; the
1473
+ * scope is the distinct rtIds reached by the last hop. When `path` is present
1474
+ * (non-empty) it wins and the top-level fields are ignored; the editor then
1475
+ * omits them.
1386
1476
  */
1387
1477
  interface EntitySelectorChildScope {
1388
- /** CK type of the child entities that key the stream-data archive (e.g. EnergyMeasurement). */
1389
- targetCkTypeId: string;
1390
- /** Association role linking the selected entity to the children (e.g. "System/ParentChild"). */
1391
- roleId: string;
1478
+ /** CK type of the child entities that key the stream-data archive (e.g. EnergyMeasurement). One-hop form. */
1479
+ targetCkTypeId?: string;
1480
+ /** Association role linking the selected entity to the children (e.g. "System/ParentChild"). One-hop form. */
1481
+ roleId?: string;
1392
1482
  /**
1393
1483
  * Traversal direction from the selected (parent) entity to its children.
1394
1484
  * For `System/ParentChild` the child owns the association to its parent, so
@@ -1396,6 +1486,35 @@ interface EntitySelectorChildScope {
1396
1486
  * `'out'` only for custom roles modelled parent → child.
1397
1487
  */
1398
1488
  direction?: 'in' | 'out';
1489
+ /**
1490
+ * Ordered multi-hop path (AB#7723). Wins over the top-level fields when
1491
+ * non-empty. At most {@link MAX_SCOPE_HOPS} hops; a longer path, or a hop
1492
+ * without role or target type, makes the scope fail (no data plus notice).
1493
+ */
1494
+ path?: EntitySelectorScopeHop[];
1495
+ }
1496
+ /** Maximum number of hops of a child-scope path, enforced by editor and runtime (AB#7723). */
1497
+ declare const MAX_SCOPE_HOPS = 5;
1498
+ /**
1499
+ * Scope source of a dependent selector (AB#7915): the selector's picker lists
1500
+ * only the entities reached from the leader's current pick through `path`.
1501
+ *
1502
+ * - `selectorId` — the leader: another selector of the same board that is
1503
+ * neither a follower (`followsSelectorId`) nor itself dependent. One level
1504
+ * only, like AB#7722 followers.
1505
+ * - `path` — 1 to {@link MAX_SCOPE_HOPS} hops (the AB#7723 hop shape) from the
1506
+ * leader's CK type to this selector's CK type. Always a path, also for a
1507
+ * single hop (no one-hop shorthand).
1508
+ *
1509
+ * The picker sends the distinct rtIds at the end of the path as GraphQL field
1510
+ * filter `rtId IN (…)`, AND-combined with the picker filter (AB#7724) and the
1511
+ * text search. See `utils/entity-selector-scope-source.ts`.
1512
+ */
1513
+ interface EntitySelectorScopeSource {
1514
+ /** Id of the leader selector. */
1515
+ selectorId: string;
1516
+ /** Hops from the leader's CK type to this selector's CK type (1–{@link MAX_SCOPE_HOPS}). */
1517
+ path: EntitySelectorScopeHop[];
1399
1518
  }
1400
1519
  /**
1401
1520
  * Configuration for a single entity selector in the MeshBoard toolbar.
@@ -1415,8 +1534,8 @@ interface EntitySelectorConfig {
1415
1534
  /** Optional pre-selected entity rtId */
1416
1535
  defaultRtId?: string;
1417
1536
  /**
1418
- * Optional one-hop traversal that resolves the picked entity to the child
1419
- * source rtIds a stream-data widget scopes by. Absent ⇒ the picked entity's
1537
+ * Optional traversal (one hop, or a multi-hop `path` — AB#7723) that resolves
1538
+ * the picked entity to the source rtIds a stream-data widget scopes by. Absent ⇒ the picked entity's
1420
1539
  * own rtId is the scope. See {@link EntitySelectorChildScope}.
1421
1540
  */
1422
1541
  childScope?: EntitySelectorChildScope;
@@ -1431,6 +1550,32 @@ interface EntitySelectorConfig {
1431
1550
  * See `utils/entity-selector-follow.ts`.
1432
1551
  */
1433
1552
  followsSelectorId?: string;
1553
+ /**
1554
+ * Optional picker filter (AB#7724): attribute filter rows on `ckTypeId`,
1555
+ * combined with AND, the same type and variable substitution as widget
1556
+ * filters (`MeshBoardVariableService.convertToFieldFilterDto`). The toolbar
1557
+ * dropdown, its search dialog and the editor's default-entity picker send
1558
+ * the rows as GraphQL `fieldFilter` (server side); the picker's text search
1559
+ * is one more AND row. Absent or empty ⇒ the picker lists every entity of
1560
+ * `ckTypeId`, as before.
1561
+ *
1562
+ * The filter affects the listing only: a `defaultRtId` or a URL pick that
1563
+ * does not match is still applied (the editor warns about a non-matching
1564
+ * `defaultRtId`). Followers have no picker; the editor writes no filter for
1565
+ * them and a follower's filter is ignored at runtime.
1566
+ * See `utils/entity-selector-filter.ts`.
1567
+ */
1568
+ filters?: WidgetFilterConfig[];
1569
+ /**
1570
+ * Optional scope source (AB#7915): makes this selector *dependent* on a
1571
+ * leader selector. While the leader has a pick, the toolbar dropdown and its
1572
+ * search dialog list only the entities reached from that pick through
1573
+ * `path` (server side, `rtId IN`). Without a leader pick the picker lists as
1574
+ * if no scope source were set. A failed or invalid scope lists nothing — it
1575
+ * never falls back to the full list. Followers ignore it.
1576
+ * See {@link EntitySelectorScopeSource}.
1577
+ */
1578
+ scopeSource?: EntitySelectorScopeSource;
1434
1579
  /** Current selection (transient, not persisted) */
1435
1580
  selectedRtId?: string;
1436
1581
  /** Display name of the currently selected entity */
@@ -1848,6 +1993,20 @@ interface QueryExecutionOptions {
1848
1993
  fieldFilter?: FieldFilterDto[] | null;
1849
1994
  /** Stream-data-only: time-range, interval, limit, queryMode. Ignored for runtime queries. */
1850
1995
  streamDataArgs?: StreamDataExecutionArgs | null;
1996
+ /**
1997
+ * Entity-selector scope (AB#7725): the source rtIds a widget bound to an entity
1998
+ * selector is restricted to. Applied on the server for both families:
1999
+ * - runtime queries (SimpleRtQuery, AggregationRtQuery, GroupingAggregationRtQuery):
2000
+ * adds the field filter `rtId IN (scopeRtIds)`, AND-combined with
2001
+ * {@link fieldFilter} and the persisted query's own filters — a grouping or
2002
+ * aggregation query aggregates over the scoped entities only;
2003
+ * - stream-data queries: sent as `arg.rtIds` unless `streamDataArgs.rtIds` is set.
2004
+ *
2005
+ * `null`/`undefined` or an empty array means "no scope" (the query runs as saved).
2006
+ * An empty scope must never reach the executor: callers skip the query instead
2007
+ * (`StreamDataScope.kind === 'empty'`, AB#7721).
2008
+ */
2009
+ scopeRtIds?: string[] | null;
1851
2010
  /** Force a network round-trip instead of using the Apollo cache. */
1852
2011
  forceRefresh?: boolean;
1853
2012
  }
@@ -1989,6 +2148,16 @@ declare class QueryExecutorService {
1989
2148
  * {@link ENTITY_GROUP_FETCH_CAP}; a truncated read is logged (never silently capped).
1990
2149
  */
1991
2150
  fetchEntityGroups(ckTypeId: string, groupField: string, restrictRtIds?: string[]): Promise<Map<string, string[]>>;
2151
+ /**
2152
+ * Runtime entity-selector scope (AB#7725): appends `rtId IN (scopeRtIds)` to the
2153
+ * caller's field filters. The backend AND-combines all runtime field filters with
2154
+ * the persisted query's filters before the database query, so simple rows as well
2155
+ * as aggregation / grouping results cover the scoped entities only. Returns the
2156
+ * caller's filters unchanged (or `undefined`) when there is no scope.
2157
+ */
2158
+ static withRtIdScope(fieldFilter: FieldFilterDto[] | null | undefined, scopeRtIds: string[] | null | undefined): FieldFilterDto[] | undefined;
2159
+ /** Stream-data entity-selector scope: `scopeRtIds` fill `rtIds` unless the caller set them. */
2160
+ private static withStreamDataScope;
1992
2161
  private buildStreamDataArg;
1993
2162
  private mapColumns;
1994
2163
  private mapRuntimeRows;
@@ -2003,9 +2172,13 @@ declare class QueryExecutorService {
2003
2172
  * transiently by `MeshBoardStateService`, written by the view while a pick is
2004
2173
  * resolved to its source rtIds.
2005
2174
  *
2006
- * - `pending`: the pick is being resolved (one-hop childScope traversal).
2175
+ * - `pending`: the pick is being resolved (childScope traversal, one hop or a path).
2007
2176
  * - `resolved`: the pick resolved to `rtIds` — possibly none.
2008
2177
  * - `failed`: the resolution threw (e.g. the association fetch failed).
2178
+ * - `needsPick` (AB#7916): a dependent selector (`scopeSource`) — or a follower
2179
+ * of one — has no pick while its leader has one. Bound widgets show no data
2180
+ * and the view asks for a pick; the persisted scope would show entities
2181
+ * outside the leader's pick. Only used for widget scopes, never for picker scopes.
2009
2182
  *
2010
2183
  * A selector without an entry has no active pick: bound widgets keep the
2011
2184
  * query's persisted scope.
@@ -2017,19 +2190,30 @@ type EntitySelectorScopeState = {
2017
2190
  rtIds: string[];
2018
2191
  } | {
2019
2192
  status: 'failed';
2193
+ } | {
2194
+ status: 'needsPick';
2020
2195
  };
2021
2196
  /**
2022
- * What a widget bound to an entity selector does with its stream-data query
2023
- * (AB#7721). Returned by `MeshBoardStateService.resolveStreamDataScope`.
2197
+ * What a widget bound to an entity selector does with its persistent query —
2198
+ * stream data (AB#7721) and runtime queries (AB#7725). Returned by
2199
+ * `MeshBoardStateService.resolveEntitySelectorScope`.
2024
2200
  *
2025
- * - `unscoped`: no binding, a runtime query, or no active pick — query with the
2026
- * persisted scope (unchanged behaviour).
2201
+ * - `unscoped`: no binding or no active pick — query with the persisted scope
2202
+ * (unchanged behaviour).
2027
2203
  * - `pending`: the scope is still resolving — show the loading state and send
2028
2204
  * NO query; the view triggers a refresh once the scope is known.
2029
- * - `scoped`: query with `rtIds` as `streamDataArgs.rtIds`.
2205
+ * - `scoped`: query restricted to `rtIds` on the server — stream data via
2206
+ * `streamDataArgs.rtIds`, runtime queries (simple, aggregation, grouping) via
2207
+ * the field filter `rtId IN (rtIds)` (`QueryExecutionOptions.scopeRtIds`).
2030
2208
  * - `empty`: the pick has nothing in scope (`noTargets`) or the lookup failed
2031
2209
  * (`failed`) — show the no-data state and send NO query. Never fall back to
2032
2210
  * the persisted scope: that would show rows of other entities.
2211
+ * `noPick` (AB#7916): a dependent selector has no pick while its leader has
2212
+ * one — the view shows "Pick a <label> to see this data.".
2213
+ * `invalidTimeRange` (AB#7582): the embedding host set a `timeRange` that is
2214
+ * unparseable or empty (`from >= to`) — every stream-data query bound to the
2215
+ * time filter is skipped, whatever its selector binding; a widget with
2216
+ * `ignoreTimeFilter` is not affected.
2033
2217
  */
2034
2218
  type StreamDataScope = {
2035
2219
  kind: 'unscoped';
@@ -2040,7 +2224,7 @@ type StreamDataScope = {
2040
2224
  rtIds: string[];
2041
2225
  } | {
2042
2226
  kind: 'empty';
2043
- reason: 'noTargets' | 'failed';
2227
+ reason: 'noTargets' | 'failed' | 'noPick' | 'invalidTimeRange';
2044
2228
  };
2045
2229
  /**
2046
2230
  * The result a widget renders instead of executing its query when its scope is
@@ -2282,6 +2466,83 @@ declare class WidgetNotConfiguredComponent {
2282
2466
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<WidgetNotConfiguredComponent, "mm-widget-not-configured", never, {}, {}, never, never, true, never>;
2283
2467
  }
2284
2468
 
2469
+ interface FormulaValidationResult {
2470
+ valid: boolean;
2471
+ /** Syntax error or other reason the formula is invalid */
2472
+ error?: string;
2473
+ /** Referenced variables that do not exist (bare identifiers are reported as well) */
2474
+ unknownVariables: string[];
2475
+ }
2476
+ /**
2477
+ * Outcome of evaluating a formula:
2478
+ * - `ok`: a value;
2479
+ * - `pending`: empty formula or a referenced variable has no value yet → the widget shows `-`, no error;
2480
+ * - `nonFinite`: the result is `Infinity`/`NaN` (e.g. division by zero, PV = 0 at night) → the widget
2481
+ * shows `-` and the `reason` as tooltip, no error state (AB#7950);
2482
+ * - `error`: syntax or evaluation error → the widget error state with the message.
2483
+ */
2484
+ type FormulaEvaluationResult = {
2485
+ status: 'pending';
2486
+ } | {
2487
+ status: 'ok';
2488
+ value: number | string | boolean;
2489
+ } | {
2490
+ status: 'nonFinite';
2491
+ reason: string;
2492
+ } | {
2493
+ status: 'error';
2494
+ error: string;
2495
+ };
2496
+
2497
+ /**
2498
+ * Formula field shared by the widget config dialogs (KPI, gauge; AB#7950): the formula input,
2499
+ * the syntax hint, the validation message, the live preview and the list of insertable variables.
2500
+ *
2501
+ * Validation is `validateFormulaField` of `utils/meshboard-formula.ts` — the dialogs call the same
2502
+ * function to decide whether Save is enabled, so there is exactly one validation rule.
2503
+ *
2504
+ * Usage:
2505
+ * ```html
2506
+ * <mm-meshboard-formula-field
2507
+ * [(formula)]="form.formula"
2508
+ * [variables]="formulaVariables"
2509
+ * [declaredNames]="declaredVariableNames">
2510
+ * </mm-meshboard-formula-field>
2511
+ * ```
2512
+ */
2513
+ declare class FormulaFieldComponent {
2514
+ private readonly evaluator;
2515
+ /** The formula text (two-way: `[(formula)]`) */
2516
+ readonly formula: _angular_core.ModelSignal<string>;
2517
+ /** Variables the formula can reference; their current values drive the preview */
2518
+ readonly variables: _angular_core.InputSignal<readonly MeshBoardVariable[]>;
2519
+ /** Names that exist by configuration but carry no value yet (count as known, preview pending) */
2520
+ readonly declaredNames: _angular_core.InputSignal<readonly string[]>;
2521
+ /** The result must be a number (gauge): a string/boolean preview shows "Result is not a number" */
2522
+ readonly numericOnly: _angular_core.InputSignal<boolean>;
2523
+ /** Show the clamp pattern in the hint (widgets with a scale) */
2524
+ readonly clampHint: _angular_core.InputSignal<boolean>;
2525
+ readonly label: _angular_core.InputSignal<string>;
2526
+ readonly placeholder: _angular_core.InputSignal<string>;
2527
+ readonly variableSyntaxHint = "${variableName}";
2528
+ readonly clampExample = "max(0, min(100, \u2026))";
2529
+ private readonly id;
2530
+ readonly inputId: string;
2531
+ readonly hintId: string;
2532
+ readonly messageId: string;
2533
+ readonly variablesLabelId: string;
2534
+ /** Validation of the current formula (the same rule the dialogs use for Save) */
2535
+ readonly validation: _angular_core.Signal<FormulaValidationResult>;
2536
+ /** Evaluation of the current formula over the current variable values */
2537
+ readonly evaluation: _angular_core.Signal<FormulaEvaluationResult>;
2538
+ readonly preview: _angular_core.Signal<string>;
2539
+ readonly inputAttributes: _angular_core.Signal<Record<string, string>>;
2540
+ /** Appends a `${name}` reference to the formula */
2541
+ insertVariable(name: string): void;
2542
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormulaFieldComponent, never>;
2543
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FormulaFieldComponent, "mm-meshboard-formula-field", never, { "formula": { "alias": "formula"; "required": false; "isSignal": true; }; "variables": { "alias": "variables"; "required": false; "isSignal": true; }; "declaredNames": { "alias": "declaredNames"; "required": false; "isSignal": true; }; "numericOnly": { "alias": "numericOnly"; "required": false; "isSignal": true; }; "clampHint": { "alias": "clampHint"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; }, { "formula": "formulaChange"; }, never, never, true, never>;
2544
+ }
2545
+
2285
2546
  /**
2286
2547
  * Defines how parent associations should be handled when mapping widget input
2287
2548
  */
@@ -2425,6 +2686,20 @@ declare class MeshBoardPersistenceService {
2425
2686
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<MeshBoardPersistenceService>;
2426
2687
  }
2427
2688
 
2689
+ /**
2690
+ * The period an embedding host sets on the board (AB#7582): two exact instants
2691
+ * (half-open `[from, to)`), or `invalid` (with the reason) when the host passed an
2692
+ * unparseable or empty range. Produced by `parseHostTimeRange`, held transiently by
2693
+ * {@link MeshBoardStateService.setHostTimeRange}.
2694
+ */
2695
+ type HostTimeRangeState = {
2696
+ status: 'valid';
2697
+ from: Date;
2698
+ to: Date;
2699
+ } | {
2700
+ status: 'invalid';
2701
+ reason: string;
2702
+ };
2428
2703
  /**
2429
2704
  * Service that manages MeshBoard state and persistence.
2430
2705
  * Coordinates loading, saving, and switching between MeshBoards.
@@ -2445,12 +2720,28 @@ declare class MeshBoardStateService {
2445
2720
  /**
2446
2721
  * Transient scope state of each entity selector's current selection (keyed
2447
2722
  * by selector id): `pending` while the view resolves the pick, `resolved`
2448
- * with the source rtIds (one-hop childScope traversal, or the picked entity's
2723
+ * with the source rtIds (childScope hop or path, or the picked entity's
2449
2724
  * own rtId; possibly none), or `failed`. No entry = no active pick. Not
2450
2725
  * persisted — derived fresh from each selection, cleared on board switch
2451
2726
  * (AB#7721).
2452
2727
  */
2453
2728
  private readonly _entitySelectorScopes;
2729
+ /**
2730
+ * Transient picker scope of each dependent selector (AB#7915, keyed by the
2731
+ * dependent's id): `pending` while the leader's pick resolves along
2732
+ * `scopeSource.path`, `resolved` with the rtIds the picker may list
2733
+ * (possibly none), or `failed`. No entry = the leader has no pick, the picker
2734
+ * lists unscoped. Not persisted, cleared on board switch.
2735
+ */
2736
+ private readonly _pickerScopes;
2737
+ /** Picker scopes of the dependent selectors (AB#7915), for the toolbar. */
2738
+ readonly pickerScopes: _angular_core.Signal<Record<string, EntitySelectorScopeState>>;
2739
+ /**
2740
+ * Period set by the page that embeds the board (`MeshBoardViewComponent.timeRange`, AB#7582):
2741
+ * exact instants, or `invalid` when the host passed an unusable range. `null` = the board's own
2742
+ * selection applies. Transient — never persisted, never written into the board config.
2743
+ */
2744
+ private readonly _hostTimeRange;
2454
2745
  /**
2455
2746
  * Transient variables published by widgets (KPI output variables, AB#5364).
2456
2747
  * Kept apart from `_meshBoardConfig` so publishing triggers no persistence and
@@ -2702,6 +2993,11 @@ declare class MeshBoardStateService {
2702
2993
  * Boundaries are resolved on the board's {@link timeZoneMode} basis (local by
2703
2994
  * default, or UTC), the same basis widgets format their datetime display on —
2704
2995
  * so the selected range and the displayed timestamps stay consistent.
2996
+ *
2997
+ * While an embedding host has set a period ({@link setHostTimeRange}, AB#7582)
2998
+ * and the board's time filter is enabled, the host's instants are returned
2999
+ * unchanged (no day snapping, no zone conversion) and the stored selection is
3000
+ * ignored; an invalid host period resolves to `null`.
2705
3001
  */
2706
3002
  resolveCurrentTimeRange(): TimeRange | null;
2707
3003
  /**
@@ -2742,7 +3038,7 @@ declare class MeshBoardStateService {
2742
3038
  /**
2743
3039
  * Stores the source rtIds resolved from an entity selector's current
2744
3040
  * selection. Called by the view component after a selection resolves (the
2745
- * one-hop childScope traversal, or the picked entity's own rtId when the
3041
+ * childScope traversal (one hop or a path), or the picked entity's own rtId when the
2746
3042
  * selector has no childScope). An empty array is a resolved EMPTY scope:
2747
3043
  * bound widgets show no data and send no query (AB#7721). Transient — not
2748
3044
  * persisted.
@@ -2755,6 +3051,13 @@ declare class MeshBoardStateService {
2755
3051
  * (AB#7721).
2756
3052
  */
2757
3053
  setEntitySelectorScopeFailed(selectorId: string): void;
3054
+ /**
3055
+ * Marks a selector as "needs a pick" (AB#7916): a dependent selector — or a
3056
+ * follower of one — has no pick while its leader has one. Bound widgets show
3057
+ * no data and send no query (never the persisted scope, which would show
3058
+ * entities outside the leader's pick); the view asks for a pick.
3059
+ */
3060
+ setEntitySelectorScopeNeedsPick(selectorId: string): void;
2758
3061
  /**
2759
3062
  * Clears the scope state for an entity selector (its selection was cleared).
2760
3063
  * Bound widgets then query with the persisted scope again.
@@ -2768,19 +3071,39 @@ declare class MeshBoardStateService {
2768
3071
  */
2769
3072
  readonly failedEntitySelectorScopeIds: _angular_core.Signal<string[]>;
2770
3073
  /**
2771
- * Decides how a widget bound to an entity selector runs its stream-data query
2772
- * (AB#7721):
3074
+ * Ids of the selectors that need a pick (AB#7916), for the view's
3075
+ * "Pick a <label> to see this data." notice.
3076
+ */
3077
+ readonly needsPickEntitySelectorIds: _angular_core.Signal<string[]>;
3078
+ /**
3079
+ * Decides how a widget runs its persistent query — the entry point every
3080
+ * built-in widget calls with its binding, query family and time-filter opt-out:
2773
3081
  *
2774
- * - `unscoped` — no binding, a runtime query (`family === 'runtime'`, the
2775
- * binding is ignored there), or no active pick: keep the persisted scope.
3082
+ * 1. Host gate (AB#7582): while the embedding host's period is invalid, every
3083
+ * stream-data query bound to the time filter is `empty` (`invalidTimeRange`),
3084
+ * whatever its selector binding; pass the widget's `ignoreTimeFilter` so an
3085
+ * opted-out widget, whose data does not depend on the period, keeps querying.
3086
+ * Runtime queries have no time window and are not gated. A legacy config
3087
+ * without `queryFamily` is treated as stream data here.
3088
+ * 2. Entity-selector scope ({@link resolveEntitySelectorScope}, AB#7721) — since
3089
+ * AB#7725 for runtime queries too: `unscoped` / `pending` / `scoped` / `empty`.
3090
+ */
3091
+ resolveStreamDataScope(entitySelectorId?: string, family?: QueryFamily, ignoreTimeFilter?: boolean): StreamDataScope;
3092
+ /**
3093
+ * The entity-selector part of {@link resolveStreamDataScope}, without the host
3094
+ * gate — stream data (AB#7721) and runtime queries alike (AB#7725):
3095
+ *
3096
+ * - `unscoped` — no binding, or no active pick: keep the query as saved.
2776
3097
  * - `pending` — the pick is still resolving: show loading, send no query.
2777
- * - `scoped` — query with the resolved source rtIds.
3098
+ * - `scoped` — query restricted to the resolved rtIds: stream data via
3099
+ * `streamDataArgs.rtIds`, runtime queries via the `rtId IN` field filter
3100
+ * (`QueryExecutionOptions.scopeRtIds`).
2778
3101
  * - `empty` — the pick has nothing in scope or the lookup failed: show the
2779
3102
  * no-data state and send no query. Never fall back to the persisted scope.
2780
- *
2781
- * A legacy config without `queryFamily` is treated as stream data.
3103
+ * Also a dependent selector without pick while its leader has one
3104
+ * (`noPick`, AB#7916).
2782
3105
  */
2783
- resolveStreamDataScope(entitySelectorId?: string, family?: QueryFamily): StreamDataScope;
3106
+ resolveEntitySelectorScope(entitySelectorId?: string): StreamDataScope;
2784
3107
  /**
2785
3108
  * Resolves the stream-data `rtIds` for a persistent-query widget bound to an
2786
3109
  * entity selector: the resolved source rtIds when the scope is `scoped`,
@@ -2791,7 +3114,43 @@ declare class MeshBoardStateService {
2791
3114
  * skip the query for `pending` / `empty` (AB#7721).
2792
3115
  */
2793
3116
  resolveStreamDataRtIds(entitySelectorId?: string): string[] | undefined;
3117
+ /** Marks a dependent selector's picker scope as resolving (AB#7915): the picker lists nothing yet. */
3118
+ setPickerScopePending(selectorId: string): void;
3119
+ /** Stores the rtIds a dependent selector's picker may list (AB#7915); `[]` = nothing in the leader's pick. */
3120
+ setPickerScopeRtIds(selectorId: string, rtIds: string[]): void;
3121
+ /** Marks a dependent selector's picker scope as failed (AB#7915): the picker lists nothing. */
3122
+ setPickerScopeFailed(selectorId: string): void;
3123
+ /** Clears a dependent selector's picker scope (its leader has no pick): the picker lists unscoped. */
3124
+ clearPickerScope(selectorId: string): void;
3125
+ /** The picker scope of a dependent selector, or `undefined` when its leader has no pick. */
3126
+ getPickerScopeState(selectorId: string): EntitySelectorScopeState | undefined;
3127
+ private setPickerScope;
2794
3128
  private setEntitySelectorScope;
3129
+ /**
3130
+ * Sets (or with `null` clears) the period of the page embedding the board
3131
+ * (AB#7582). Called by `MeshBoardViewComponent` for its `timeRange` input; a
3132
+ * host normally sets the input instead of calling this. Transient: not
3133
+ * persisted, not written into the board config, so it never causes unsaved
3134
+ * changes. Only takes effect while the board's time filter is enabled.
3135
+ */
3136
+ setHostTimeRange(state: HostTimeRangeState | null, owner?: object): void;
3137
+ /**
3138
+ * Clears the host period only if `owner` set it (AB#7582). The service is
3139
+ * root-provided, so a view that is destroyed (or drops its `timeRange`) must not
3140
+ * clear a period another view set in the meantime.
3141
+ */
3142
+ clearHostTimeRange(owner: object): void;
3143
+ /** The view (or other caller) that set the current host period, if it said so. */
3144
+ private hostTimeRangeOwner;
3145
+ /** The period set by the embedding host, or `null` when the board's own selection applies. */
3146
+ readonly hostTimeRange: _angular_core.Signal<HostTimeRangeState | null>;
3147
+ /**
3148
+ * True when an invalid host period blocks a stream-data query that is bound to
3149
+ * the time filter (AB#7582): the period is invalid, the board's time filter is
3150
+ * enabled and the caller did not opt out with `ignoreTimeFilter`. Such a query
3151
+ * must not be sent — without a window it would read the whole archive.
3152
+ */
3153
+ isStreamDataBlockedByHostTimeRange(ignoreTimeFilter?: boolean): boolean;
2795
3154
  /**
2796
3155
  * Updates the time filter configuration.
2797
3156
  */
@@ -2893,12 +3252,17 @@ interface RepeaterDataItem {
2893
3252
  /** All attributes as a Map for easy access */
2894
3253
  attributes: Map<string, unknown>;
2895
3254
  }
3255
+ /** Source rtIds per request of one batched association hop (AB#7723). */
3256
+ declare const ASSOCIATION_HOP_SOURCE_BATCH = 100;
3257
+ /** Targets read per source entity in one association hop (AB#7723). */
3258
+ declare const ASSOCIATION_HOP_TARGETS_PER_SOURCE = 1000;
2896
3259
  declare class MeshBoardDataService {
2897
3260
  private readonly getDashboardEntityGQL;
2898
3261
  private readonly getCkModelsWithStateGQL;
2899
3262
  private readonly getEntitiesByCkTypeGQL;
2900
3263
  private readonly queryExecutor;
2901
3264
  private readonly getAssociationTargetsGQL;
3265
+ private readonly getAssociationTargetRtIdsGQL;
2902
3266
  private readonly secretSafeNames;
2903
3267
  private readonly getCkTypeAttributesGQL;
2904
3268
  private readonly apollo;
@@ -2981,6 +3345,20 @@ declare class MeshBoardDataService {
2981
3345
  * Uses the associations.targets() GraphQL endpoint.
2982
3346
  */
2983
3347
  fetchAssociationTargets(sourceRtId: string, sourceCkTypeId: string, targetCkTypeId: string, roleId: string, direction: 'in' | 'out', attributeNames?: string[], first?: number): Observable<TargetEntityWithAttributes[]>;
3348
+ /**
3349
+ * One association hop for MANY source entities (AB#7723, multi-hop child
3350
+ * scope): the rtIds of the `targetCkTypeId` entities reached from each of
3351
+ * `sourceRtIds` (all of `sourceCkTypeId`) over `roleId` in `direction`.
3352
+ *
3353
+ * Query cost: the sources go out in batches of
3354
+ * {@link ASSOCIATION_HOP_SOURCE_BATCH} rtIds per request (`runtimeEntities(rtIds:)`
3355
+ * with the association targets nested), the batches of one hop in parallel —
3356
+ * never one request per entity. Only rtIds are selected. Per source at most
3357
+ * {@link ASSOCIATION_HOP_TARGETS_PER_SOURCE} targets are read; a truncated
3358
+ * source is logged as a warning. Duplicates are not removed here.
3359
+ * Errors propagate (the caller turns them into a failed scope).
3360
+ */
3361
+ fetchAssociationTargetRtIds(sourceRtIds: readonly string[], sourceCkTypeId: string, targetCkTypeId: string, roleId: string, direction: 'in' | 'out'): Observable<string[]>;
2984
3362
  /**
2985
3363
  * Fetches CK type attribute definitions (name + type) for config dialog.
2986
3364
  */
@@ -3599,6 +3977,11 @@ declare class KpiWidgetComponent implements DashboardWidget<KpiWidgetConfig, Run
3599
3977
  private readonly formulaResult;
3600
3978
  /** Error message of the formula (syntax, evaluation or circular reference). */
3601
3979
  readonly formulaError: _angular_core.Signal<string | null>;
3980
+ /**
3981
+ * Tooltip of the value: the reason a formula result is shown as `-` although every
3982
+ * variable has a value (non-finite result, e.g. division by zero; AB#7950), else `null`.
3983
+ */
3984
+ readonly valueTooltip: _angular_core.Signal<string | null>;
3602
3985
  /**
3603
3986
  * Unformatted value: the formula result, or the value taken from the loaded data
3604
3987
  * (query values already scaled by `valueMultiplier`).
@@ -3652,14 +4035,6 @@ declare class KpiWidgetComponent implements DashboardWidget<KpiWidgetConfig, Run
3652
4035
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<KpiWidgetComponent, "mm-kpi-widget", never, { "config": { "alias": "config"; "required": false; }; }, {}, never, never, true, never>;
3653
4036
  }
3654
4037
 
3655
- interface FormulaValidationResult {
3656
- valid: boolean;
3657
- /** Syntax error or other reason the formula is invalid */
3658
- error?: string;
3659
- /** Referenced variables that do not exist (bare identifiers are reported as well) */
3660
- unknownVariables: string[];
3661
- }
3662
-
3663
4038
  /**
3664
4039
  * Data source type for KPI. `'formula'` computes the value from a formula over
3665
4040
  * MeshBoard variables (stored as static data source with `valueMode: 'formula'`).
@@ -3799,15 +4174,13 @@ declare class KpiConfigDialogComponent implements OnInit {
3799
4174
  * outputs declared by other KPIs (e.g. still loading or in error) and the variables an
3800
4175
  * entity selector exposes once an entity is picked.
3801
4176
  */
3802
- private get declaredVariableNames();
4177
+ get declaredVariableNames(): string[];
3803
4178
  /**
3804
4179
  * Validation of the current formula (memoized per formula text and available variable names).
3805
4180
  * Declared names count as known, so a reference to an output without a value yet can be saved;
3806
4181
  * the preview keeps evaluating the live values and shows it as pending.
3807
4182
  */
3808
4183
  get formulaValidation(): FormulaValidationResult;
3809
- /** Result of the current formula over the current variable values */
3810
- get formulaPreview(): string;
3811
4184
  /** Validation message for the output variable name, or `null` when valid or empty */
3812
4185
  get outputVariableError(): string | null;
3813
4186
  /** Circular reference introduced by the pending formula / output name, or `null` */
@@ -3835,8 +4208,6 @@ declare class KpiConfigDialogComponent implements OnInit {
3835
4208
  private displayFields;
3836
4209
  onCancel(): void;
3837
4210
  onDataSourceTypeChange(type: KpiDataSourceType): void;
3838
- /** Appends a `${name}` reference to the formula */
3839
- insertVariable(name: string): void;
3840
4211
  onQuerySelected(query: PersistentQueryItem | null): Promise<void>;
3841
4212
  onQueryModeChange(mode: KpiQueryMode): Promise<void>;
3842
4213
  private loadQueryColumnsAndValues;
@@ -4131,17 +4502,34 @@ declare class TableWidgetComponent implements DashboardWidget<TableWidgetConfig,
4131
4502
  dataSource?: TableWidgetDataSourceDirective;
4132
4503
  private readonly stateService;
4133
4504
  /** Host texts (`MESHBOARD_MESSAGES`, AB#5622): list texts (empty state, pager, toolbar) and the placeholder. */
4134
- protected readonly texts: _angular_core.Signal<_meshmakers_octo_meshboard.MeshBoardMessages & Required<Omit<_meshmakers_octo_meshboard.MeshBoardMessages, "tableList">>>;
4505
+ protected readonly texts: Signal<_meshmakers_octo_meshboard.MeshBoardMessages & Required<Omit<_meshmakers_octo_meshboard.MeshBoardMessages, "tableList">>>;
4135
4506
  /** Host translation of enum cell values (`MESHBOARD_LABEL_RESOLVER`, AB#5622); absent = raw text. */
4136
4507
  private readonly labelResolver;
4137
4508
  /** CK value type per derived column field (persistent queries), for the label resolver. */
4138
4509
  private readonly _queryColumnValueTypes;
4510
+ /** Host UI language (`MESHBOARD_LANGUAGE`, AB#7655) for column `titles` / `valueLabels`; `null` = `title` / raw texts. */
4511
+ private readonly language;
4512
+ /**
4513
+ * Problems already warned about (`<widget id or instance>|<field>|<problem hash>`), so a bad config
4514
+ * logs once, not on every language change, while a new problem after a config edit is reported again.
4515
+ */
4516
+ private readonly warnedColumns;
4517
+ /** Fallback warning key of a widget without an id. */
4518
+ private readonly instanceKey;
4519
+ /** App locale for the `number` / `date` rendering of unlabelled values in value-label columns. */
4520
+ private readonly locale;
4521
+ /**
4522
+ * Bumped on every `config` change: `config` is a plain `@Input`, so the computeds that read it
4523
+ * depend on this signal to pick up a new config on the same widget instance (AB#7655).
4524
+ */
4525
+ private readonly _configVersion;
4526
+ constructor();
4139
4527
  private readonly _isLoading;
4140
4528
  private readonly _data;
4141
4529
  private readonly _error;
4142
- readonly isLoading: _angular_core.Signal<boolean>;
4143
- readonly data: _angular_core.Signal<Record<string, unknown>[]>;
4144
- readonly error: _angular_core.Signal<string | null>;
4530
+ readonly isLoading: Signal<boolean>;
4531
+ readonly data: Signal<Record<string, unknown>[]>;
4532
+ readonly error: Signal<string | null>;
4145
4533
  /** Signal to track query columns from data source (for persistent queries) */
4146
4534
  private readonly _queryColumnsForView;
4147
4535
  /**
@@ -4153,7 +4541,7 @@ declare class TableWidgetComponent implements DashboardWidget<TableWidgetConfig,
4153
4541
  * Converts TableWidgetConfig columns to ListViewComponent TableColumn format.
4154
4542
  * For persistent queries, uses dynamically derived columns from the query response.
4155
4543
  */
4156
- readonly listViewColumns: _angular_core.Signal<TableColumn$1[]>;
4544
+ readonly listViewColumns: Signal<TableColumn$1[]>;
4157
4545
  /**
4158
4546
  * Checks if the widget has a valid configuration.
4159
4547
  * Supports both runtimeEntity and persistentQuery data sources.
@@ -4164,7 +4552,15 @@ declare class TableWidgetComponent implements DashboardWidget<TableWidgetConfig,
4164
4552
  * For persistent queries, columns are derived from the query response.
4165
4553
  * Returns true once columns are available.
4166
4554
  */
4167
- readonly columnsReady: _angular_core.Signal<boolean>;
4555
+ readonly columnsReady: Signal<boolean>;
4556
+ /**
4557
+ * Logs one console warning per widget, column and set of problems for ignored `titles` /
4558
+ * `valueLabels` entries (unknown culture keys, malformed titles or value labels, `valueLabels`
4559
+ * together with `statusMapping`, AB#7655). The table still renders. The key carries a hash of the
4560
+ * problem list, so a different problem after a config edit is reported again; widgets without an
4561
+ * id use a per-instance key.
4562
+ */
4563
+ private warnOnce;
4168
4564
  private formatColumnTitle;
4169
4565
  ngOnChanges(changes: SimpleChanges): void;
4170
4566
  refresh(): void;
@@ -4208,6 +4604,10 @@ declare class TableConfigDialogComponent implements OnInit {
4208
4604
  private readonly getCkTypeAvailableQueryColumnsGQL;
4209
4605
  private readonly stateService;
4210
4606
  private readonly windowRef;
4607
+ private readonly getRuntimeQueryColumnsGQL;
4608
+ private readonly queryExecutor;
4609
+ /** Fields the saved query returns now, loaded once per query rtId (AB#7655, kept explicit columns). */
4610
+ private queryFieldsLoad?;
4211
4611
  ckTypeSelectorInput?: CkTypeSelectorInputComponent;
4212
4612
  filterEditor?: FieldFilterEditorComponent;
4213
4613
  querySelector?: QuerySelectorComponent;
@@ -4265,7 +4665,13 @@ declare class TableConfigDialogComponent implements OnInit {
4265
4665
  onFiltersChange(filters: FieldFilterItem[]): void;
4266
4666
  getColumnsSummary(): string;
4267
4667
  getSortingSummary(): string;
4268
- onSave(): void;
4668
+ /**
4669
+ * The fields a persistent query returns now (`null` when unknown or the lookup failed). Runtime
4670
+ * queries use the metadata-only column resolver; stream-data queries execute with `first: 1`
4671
+ * (no column-introspection endpoint), like the chart dialogs.
4672
+ */
4673
+ private loadQueryFields;
4674
+ onSave(): Promise<void>;
4269
4675
  private formatColumnTitle;
4270
4676
  onCancel(): void;
4271
4677
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableConfigDialogComponent, never>;
@@ -4282,10 +4688,23 @@ declare class GaugeWidgetComponent implements DashboardWidget<GaugeWidgetConfig,
4282
4688
  private static readonly SUPPORTED_ROW_TYPES;
4283
4689
  private readonly stateService;
4284
4690
  private readonly variableService;
4691
+ private readonly expressionEvaluator;
4285
4692
  config: GaugeWidgetConfig;
4693
+ /**
4694
+ * Signal mirror of the `config` input, so the formula computeds re-run when the config
4695
+ * changes (the input itself is a plain property). Falls back to the input before the
4696
+ * first lifecycle hook.
4697
+ */
4698
+ private readonly _config;
4699
+ private currentConfig;
4286
4700
  private readonly _isLoading;
4287
4701
  private readonly _data;
4288
4702
  private readonly _error;
4703
+ /**
4704
+ * Incremented on every load; a request that resolves after a newer load started (e.g. the
4705
+ * config switched to formula mode meanwhile) must not overwrite the newer state.
4706
+ */
4707
+ private loadGeneration;
4289
4708
  readonly isLoading: _angular_core.Signal<boolean>;
4290
4709
  readonly data: _angular_core.Signal<RuntimeEntityData | null>;
4291
4710
  readonly error: _angular_core.Signal<string | null>;
@@ -4294,7 +4713,31 @@ declare class GaugeWidgetComponent implements DashboardWidget<GaugeWidgetConfig,
4294
4713
  * This is a method (not computed) to ensure it re-evaluates when config changes via @Input.
4295
4714
  */
4296
4715
  isNotConfigured(): boolean;
4716
+ /** True when the value is computed from a formula over MeshBoard variables (AB#7950). */
4717
+ isFormulaMode(): boolean;
4718
+ /**
4719
+ * Formula evaluation result, live over the MeshBoard variables (AB#7950); `null` outside
4720
+ * formula mode. Same engine and rules as the KPI, but the result must be a number.
4721
+ * A gauge publishes no output variable, so it can never be part of a variable cycle.
4722
+ */
4723
+ private readonly formulaResult;
4724
+ /** Error message of the formula (syntax, evaluation, non-numeric result). */
4725
+ readonly formulaError: _angular_core.Signal<string | null>;
4726
+ /**
4727
+ * Tooltip of the value label: the reason a formula result is shown as `-` although every
4728
+ * variable has a value (non-finite result, e.g. division by zero), else `null`.
4729
+ */
4730
+ readonly valueTooltip: _angular_core.Signal<string | null>;
4731
+ /** True when there is a value to show (data loaded, or a formula result). */
4732
+ readonly hasValue: _angular_core.Signal<boolean>;
4733
+ /** The real value, shown in the label (may lie outside the scale). */
4297
4734
  readonly numericValue: _angular_core.Signal<number>;
4735
+ /**
4736
+ * Value of the pointer: the real value clamped to the scale, so the pointer stops at the
4737
+ * scale end while the label shows the real value (AB#7950). Without a value it rests at
4738
+ * the scale start.
4739
+ */
4740
+ readonly pointerValue: _angular_core.Signal<number>;
4298
4741
  readonly formattedValue: _angular_core.Signal<string>;
4299
4742
  readonly label: _angular_core.Signal<string>;
4300
4743
  ngOnInit(): void;
@@ -4316,9 +4759,10 @@ declare class GaugeWidgetComponent implements DashboardWidget<GaugeWidgetConfig,
4316
4759
  }
4317
4760
 
4318
4761
  /**
4319
- * Data source type for Gauge
4762
+ * Data source type for Gauge. `'formula'` computes the value from a formula over MeshBoard
4763
+ * variables (stored as static data source with `valueMode: 'formula'`, AB#7950).
4320
4764
  */
4321
- type GaugeDataSourceType = 'runtimeEntity' | 'persistentQuery';
4765
+ type GaugeDataSourceType = 'runtimeEntity' | 'persistentQuery' | 'formula';
4322
4766
  /**
4323
4767
  * Configuration result from the Gauge dialog
4324
4768
  */
@@ -4338,6 +4782,7 @@ interface GaugeConfigResult extends WidgetConfigResult {
4338
4782
  queryValueField?: string;
4339
4783
  queryCategoryField?: string;
4340
4784
  queryCategoryValue?: string;
4785
+ formula?: string;
4341
4786
  gaugeType: GaugeType;
4342
4787
  min?: number;
4343
4788
  max?: number;
@@ -4371,6 +4816,7 @@ declare class GaugeConfigDialogComponent implements OnInit {
4371
4816
  private static readonly INTROSPECTION_ROW_TYPES;
4372
4817
  private readonly meshBoardStateService;
4373
4818
  private readonly windowRef;
4819
+ private readonly expressionEvaluator;
4374
4820
  ckTypeSelectorInput?: CkTypeSelectorInputComponent;
4375
4821
  entitySelectorInput?: EntitySelectInputComponent;
4376
4822
  querySelector?: QuerySelectorComponent;
@@ -4397,6 +4843,9 @@ declare class GaugeConfigDialogComponent implements OnInit {
4397
4843
  initialQueryCategoryField?: string;
4398
4844
  initialQueryCategoryValue?: string;
4399
4845
  initialFilters?: WidgetFilterConfig[];
4846
+ /** Id of the edited widget (excluded from the declared output names) */
4847
+ initialWidgetId?: string;
4848
+ initialFormula?: string;
4400
4849
  dataSourceType: GaugeDataSourceType;
4401
4850
  selectedCkType: CkTypeSelectorItem | null;
4402
4851
  selectedEntity: RuntimeEntityItem | null;
@@ -4436,7 +4885,18 @@ declare class GaugeConfigDialogComponent implements OnInit {
4436
4885
  queryValueField: string;
4437
4886
  queryCategoryField: string;
4438
4887
  queryCategoryValue: string;
4888
+ formula: string;
4439
4889
  };
4890
+ /**
4891
+ * Variables a formula can reference: MeshBoard variables plus the KPIs' published outputs.
4892
+ * Read live, so outputs published while the dialog is open become available immediately.
4893
+ */
4894
+ get formulaVariables(): MeshBoardVariable[];
4895
+ /** Names that exist by configuration but carry no value yet (declared KPI outputs, selector variables) */
4896
+ get declaredVariableNames(): string[];
4897
+ private formulaValidationCache?;
4898
+ /** Validation of the current formula — the same rule the shared formula field shows */
4899
+ get formulaValidation(): FormulaValidationResult;
4440
4900
  gaugeTypeOptions: GaugeTypeOption[];
4441
4901
  queryModeOptions: {
4442
4902
  value: KpiQueryMode;
@@ -4456,6 +4916,8 @@ declare class GaugeConfigDialogComponent implements OnInit {
4456
4916
  addRange(): void;
4457
4917
  removeRange(index: number): void;
4458
4918
  onSave(): void;
4919
+ /** Gauge options shared by every data source */
4920
+ private gaugeOptionsResult;
4459
4921
  onCancel(): void;
4460
4922
  onDataSourceTypeChange(type: GaugeDataSourceType): void;
4461
4923
  onQuerySelected(query: PersistentQueryItem | null): Promise<void>;
@@ -4472,7 +4934,7 @@ declare class GaugeConfigDialogComponent implements OnInit {
4472
4934
  private loadCategoryValuesForField;
4473
4935
  onFiltersChange(updatedFilters: FieldFilterItem[]): void;
4474
4936
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<GaugeConfigDialogComponent, never>;
4475
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<GaugeConfigDialogComponent, "mm-gauge-config-dialog", never, { "initialCkTypeId": { "alias": "initialCkTypeId"; "required": false; }; "initialRtId": { "alias": "initialRtId"; "required": false; }; "initialGaugeType": { "alias": "initialGaugeType"; "required": false; }; "initialValueAttribute": { "alias": "initialValueAttribute"; "required": false; }; "initialLabelAttribute": { "alias": "initialLabelAttribute"; "required": false; }; "initialMin": { "alias": "initialMin"; "required": false; }; "initialMax": { "alias": "initialMax"; "required": false; }; "initialRanges": { "alias": "initialRanges"; "required": false; }; "initialShowLabel": { "alias": "initialShowLabel"; "required": false; }; "initialPrefix": { "alias": "initialPrefix"; "required": false; }; "initialSuffix": { "alias": "initialSuffix"; "required": false; }; "initialReverse": { "alias": "initialReverse"; "required": false; }; "initialDataSourceType": { "alias": "initialDataSourceType"; "required": false; }; "initialQueryRtId": { "alias": "initialQueryRtId"; "required": false; }; "initialQueryName": { "alias": "initialQueryName"; "required": false; }; "initialQueryFamily": { "alias": "initialQueryFamily"; "required": false; }; "initialIgnoreTimeFilter": { "alias": "initialIgnoreTimeFilter"; "required": false; }; "initialEntitySelectorId": { "alias": "initialEntitySelectorId"; "required": false; }; "initialQueryMode": { "alias": "initialQueryMode"; "required": false; }; "initialQueryValueField": { "alias": "initialQueryValueField"; "required": false; }; "initialQueryCategoryField": { "alias": "initialQueryCategoryField"; "required": false; }; "initialQueryCategoryValue": { "alias": "initialQueryCategoryValue"; "required": false; }; "initialFilters": { "alias": "initialFilters"; "required": false; }; }, {}, never, never, true, never>;
4937
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<GaugeConfigDialogComponent, "mm-gauge-config-dialog", never, { "initialCkTypeId": { "alias": "initialCkTypeId"; "required": false; }; "initialRtId": { "alias": "initialRtId"; "required": false; }; "initialGaugeType": { "alias": "initialGaugeType"; "required": false; }; "initialValueAttribute": { "alias": "initialValueAttribute"; "required": false; }; "initialLabelAttribute": { "alias": "initialLabelAttribute"; "required": false; }; "initialMin": { "alias": "initialMin"; "required": false; }; "initialMax": { "alias": "initialMax"; "required": false; }; "initialRanges": { "alias": "initialRanges"; "required": false; }; "initialShowLabel": { "alias": "initialShowLabel"; "required": false; }; "initialPrefix": { "alias": "initialPrefix"; "required": false; }; "initialSuffix": { "alias": "initialSuffix"; "required": false; }; "initialReverse": { "alias": "initialReverse"; "required": false; }; "initialDataSourceType": { "alias": "initialDataSourceType"; "required": false; }; "initialQueryRtId": { "alias": "initialQueryRtId"; "required": false; }; "initialQueryName": { "alias": "initialQueryName"; "required": false; }; "initialQueryFamily": { "alias": "initialQueryFamily"; "required": false; }; "initialIgnoreTimeFilter": { "alias": "initialIgnoreTimeFilter"; "required": false; }; "initialEntitySelectorId": { "alias": "initialEntitySelectorId"; "required": false; }; "initialQueryMode": { "alias": "initialQueryMode"; "required": false; }; "initialQueryValueField": { "alias": "initialQueryValueField"; "required": false; }; "initialQueryCategoryField": { "alias": "initialQueryCategoryField"; "required": false; }; "initialQueryCategoryValue": { "alias": "initialQueryCategoryValue"; "required": false; }; "initialFilters": { "alias": "initialFilters"; "required": false; }; "initialWidgetId": { "alias": "initialWidgetId"; "required": false; }; "initialFormula": { "alias": "initialFormula"; "required": false; }; }, {}, never, never, true, never>;
4476
4938
  }
4477
4939
 
4478
4940
  /**
@@ -5256,8 +5718,8 @@ interface HeatmapDataItem {
5256
5718
  date: string;
5257
5719
  /** Y-axis: hour label (e.g. '08:00') */
5258
5720
  hour: string;
5259
- /** Color intensity value */
5260
- value: number;
5721
+ /** Color intensity value; `null` = empty cell (`weightedAvg` without rows, AB#7956) */
5722
+ value: number | null;
5261
5723
  /** Per-cell color (transparent for no-data) */
5262
5724
  color: string;
5263
5725
  }
@@ -5281,10 +5743,10 @@ declare class HeatmapWidgetComponent implements DashboardWidget<HeatmapWidgetCon
5281
5743
  readonly error: _angular_core.Signal<string | null>;
5282
5744
  readonly data: _angular_core.Signal<HeatmapDataItem[]>;
5283
5745
  /**
5284
- * Returns the color for a given value based on the color scheme ranges.
5285
- * Returns 'transparent' for zero/no-data values.
5746
+ * Returns the gradient color for a filled cell based on the color scheme ranges.
5747
+ * Empty cells are made transparent by the caller ({@link isEmptyCell}).
5286
5748
  */
5287
- private getColorForValue;
5749
+ private rangeColor;
5288
5750
  isNotConfigured(): boolean;
5289
5751
  ngOnInit(): void;
5290
5752
  ngOnChanges(changes: SimpleChanges): void;
@@ -5297,8 +5759,18 @@ declare class HeatmapWidgetComponent implements DashboardWidget<HeatmapWidgetCon
5297
5759
  */
5298
5760
  private formatSI;
5299
5761
  cellLabelContent: (e: {
5300
- value: number;
5762
+ value: number | null;
5301
5763
  }) => string;
5764
+ /**
5765
+ * An empty cell shows no label and no colour: `null` always; 0 too, except for `weightedAvg`,
5766
+ * where 0 is a real mean and an empty cell is `null` (AB#7956).
5767
+ */
5768
+ isEmptyCell(value: number | null | undefined): boolean;
5769
+ /**
5770
+ * Badge text of the widget's own time window (AB#7956), e.g. `Last 30 days`; `null` when the
5771
+ * widget follows the board time filter or queries runtime data (the window binds stream data only).
5772
+ */
5773
+ timeWindowLabel(): string | null;
5302
5774
  xLabelContent: (e: {
5303
5775
  value: string;
5304
5776
  }) => string;
@@ -5310,17 +5782,23 @@ declare class HeatmapWidgetComponent implements DashboardWidget<HeatmapWidgetCon
5310
5782
  * Otherwise aggregates into hourly buckets.
5311
5783
  */
5312
5784
  private processHeatmapData;
5785
+ /**
5786
+ * True when `dateField` refers to the top-level timestamp of a stream-data row.
5787
+ * Runtime rows are excluded so their date keeps coming only from the cells.
5788
+ */
5789
+ private static isRowTimestampField;
5313
5790
  /**
5314
5791
  * Detects the interval width in minutes from the first row with from+to.
5315
5792
  */
5316
5793
  private detectIntervalMinutes;
5317
5794
  /**
5318
- * Processes data into hourly buckets (original behavior).
5795
+ * Processes data into hourly buckets. Hour and day follow the board time zone; a DST
5796
+ * fall-back day keeps its repeated hour as its own row (`02:00 (2)`, AB#7956).
5319
5797
  */
5320
5798
  private processHourlyData;
5321
5799
  /**
5322
5800
  * Processes data into sub-hour interval buckets.
5323
- * Y-axis: hours (00:00..23:00), X-axis: interval labels (e.g. "00-15", "15-30", ...).
5801
+ * Y-axis: hours (00:00..23:00, plus a repeated DST hour), X-axis: interval labels (e.g. "00-15", "15-30", ...).
5324
5802
  * For multi-day data, X-axis labels are prefixed with the date.
5325
5803
  */
5326
5804
  private processSubHourData;
@@ -5342,7 +5820,6 @@ declare class HeatmapWidgetComponent implements DashboardWidget<HeatmapWidgetCon
5342
5820
  * → amber, above → red.
5343
5821
  */
5344
5822
  private getThresholdColor;
5345
- private aggregate;
5346
5823
  /** Delegates to {@link toInstant} so naive wire timestamps are pinned to UTC (AB#4818). */
5347
5824
  private parseDate;
5348
5825
  private convertFiltersToDto;
@@ -5364,6 +5841,13 @@ interface HeatmapConfigResult extends WidgetConfigResult {
5364
5841
  dateEndField?: string;
5365
5842
  valueField?: string;
5366
5843
  aggregation: HeatmapAggregation;
5844
+ /** `weightedAvg` only: the weight (count) column (AB#7956) */
5845
+ weightField?: string;
5846
+ /** The date field marks the bucket end; shift rows by {@link bucketWidthMinutes} (AB#7956) */
5847
+ timestampIsBucketEnd?: boolean;
5848
+ bucketWidthMinutes?: number;
5849
+ /** Own relative time window that overrides the board time filter (AB#7956) */
5850
+ timeWindow?: HeatmapTimeWindow;
5367
5851
  colorScheme: HeatmapColorScheme;
5368
5852
  colorMode?: HeatmapColorMode;
5369
5853
  thresholdTarget?: number;
@@ -5389,6 +5873,10 @@ declare class HeatmapConfigDialogComponent implements OnInit {
5389
5873
  initialDateEndField?: string;
5390
5874
  initialValueField?: string;
5391
5875
  initialAggregation?: HeatmapAggregation;
5876
+ initialWeightField?: string;
5877
+ initialTimestampIsBucketEnd?: boolean;
5878
+ initialBucketWidthMinutes?: number;
5879
+ initialTimeWindow?: HeatmapTimeWindow;
5392
5880
  initialColorScheme?: HeatmapColorScheme;
5393
5881
  initialColorMode?: HeatmapColorMode;
5394
5882
  initialThresholdTarget?: number;
@@ -5412,6 +5900,10 @@ declare class HeatmapConfigDialogComponent implements OnInit {
5412
5900
  value: string;
5413
5901
  label: string;
5414
5902
  }[];
5903
+ timeWindowUnitOptions: {
5904
+ value: RelativeTimeUnit;
5905
+ label: string;
5906
+ }[];
5415
5907
  colorModeOptions: {
5416
5908
  value: HeatmapColorMode;
5417
5909
  label: string;
@@ -5434,6 +5926,12 @@ declare class HeatmapConfigDialogComponent implements OnInit {
5434
5926
  dateEndField: string | undefined;
5435
5927
  valueField: string | undefined;
5436
5928
  aggregation: HeatmapAggregation;
5929
+ weightField: string | undefined;
5930
+ timestampIsBucketEnd: boolean;
5931
+ bucketWidthMinutes: number | undefined;
5932
+ useTimeWindow: boolean;
5933
+ timeWindowValue: number | undefined;
5934
+ timeWindowUnit: RelativeTimeUnit;
5437
5935
  colorScheme: HeatmapColorScheme;
5438
5936
  colorMode: HeatmapColorMode;
5439
5937
  thresholdTarget: number | undefined;
@@ -5444,6 +5942,8 @@ declare class HeatmapConfigDialogComponent implements OnInit {
5444
5942
  valueMultiplier: number;
5445
5943
  };
5446
5944
  get isValid(): boolean;
5945
+ /** Why the AB#7956 options block saving, or `null`. */
5946
+ get optionsError(): string | null;
5447
5947
  /** Entity selectors available on the current MeshBoard (for the scope picker). */
5448
5948
  get availableEntitySelectors(): EntitySelectorConfig[];
5449
5949
  get selectedQueryFamily(): QueryFamily | null;
@@ -5460,7 +5960,7 @@ declare class HeatmapConfigDialogComponent implements OnInit {
5460
5960
  onSave(): void;
5461
5961
  onCancel(): void;
5462
5962
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HeatmapConfigDialogComponent, never>;
5463
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<HeatmapConfigDialogComponent, "mm-heatmap-config-dialog", never, { "initialQueryRtId": { "alias": "initialQueryRtId"; "required": false; }; "initialQueryName": { "alias": "initialQueryName"; "required": false; }; "initialQueryFamily": { "alias": "initialQueryFamily"; "required": false; }; "initialIgnoreTimeFilter": { "alias": "initialIgnoreTimeFilter"; "required": false; }; "initialEntitySelectorId": { "alias": "initialEntitySelectorId"; "required": false; }; "initialDateField": { "alias": "initialDateField"; "required": false; }; "initialDateEndField": { "alias": "initialDateEndField"; "required": false; }; "initialValueField": { "alias": "initialValueField"; "required": false; }; "initialAggregation": { "alias": "initialAggregation"; "required": false; }; "initialColorScheme": { "alias": "initialColorScheme"; "required": false; }; "initialColorMode": { "alias": "initialColorMode"; "required": false; }; "initialThresholdTarget": { "alias": "initialThresholdTarget"; "required": false; }; "initialShowLegend": { "alias": "initialShowLegend"; "required": false; }; "initialLegendPosition": { "alias": "initialLegendPosition"; "required": false; }; "initialDecimalPlaces": { "alias": "initialDecimalPlaces"; "required": false; }; "initialCompactNumbers": { "alias": "initialCompactNumbers"; "required": false; }; "initialValueMultiplier": { "alias": "initialValueMultiplier"; "required": false; }; "initialFilters": { "alias": "initialFilters"; "required": false; }; }, {}, never, never, true, never>;
5963
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<HeatmapConfigDialogComponent, "mm-heatmap-config-dialog", never, { "initialQueryRtId": { "alias": "initialQueryRtId"; "required": false; }; "initialQueryName": { "alias": "initialQueryName"; "required": false; }; "initialQueryFamily": { "alias": "initialQueryFamily"; "required": false; }; "initialIgnoreTimeFilter": { "alias": "initialIgnoreTimeFilter"; "required": false; }; "initialEntitySelectorId": { "alias": "initialEntitySelectorId"; "required": false; }; "initialDateField": { "alias": "initialDateField"; "required": false; }; "initialDateEndField": { "alias": "initialDateEndField"; "required": false; }; "initialValueField": { "alias": "initialValueField"; "required": false; }; "initialAggregation": { "alias": "initialAggregation"; "required": false; }; "initialWeightField": { "alias": "initialWeightField"; "required": false; }; "initialTimestampIsBucketEnd": { "alias": "initialTimestampIsBucketEnd"; "required": false; }; "initialBucketWidthMinutes": { "alias": "initialBucketWidthMinutes"; "required": false; }; "initialTimeWindow": { "alias": "initialTimeWindow"; "required": false; }; "initialColorScheme": { "alias": "initialColorScheme"; "required": false; }; "initialColorMode": { "alias": "initialColorMode"; "required": false; }; "initialThresholdTarget": { "alias": "initialThresholdTarget"; "required": false; }; "initialShowLegend": { "alias": "initialShowLegend"; "required": false; }; "initialLegendPosition": { "alias": "initialLegendPosition"; "required": false; }; "initialDecimalPlaces": { "alias": "initialDecimalPlaces"; "required": false; }; "initialCompactNumbers": { "alias": "initialCompactNumbers"; "required": false; }; "initialValueMultiplier": { "alias": "initialValueMultiplier"; "required": false; }; "initialFilters": { "alias": "initialFilters"; "required": false; }; }, {}, never, never, true, never>;
5464
5964
  }
5465
5965
 
5466
5966
  interface StatValue {
@@ -6391,6 +6891,12 @@ interface MeshBoardMessages {
6391
6891
  * 'Could not resolve the scope of "{label}" - widgets bound to it show no data.'
6392
6892
  */
6393
6893
  scopeResolutionFailed?: string;
6894
+ /**
6895
+ * Board notice for a dependent entity selector without pick while its leader has one (AB#7916):
6896
+ * widgets bound to it show no data until a pick is made. `{label}` is replaced by the selector
6897
+ * label. Default: 'Pick a {label} to see this data.'
6898
+ */
6899
+ scopePickRequired?: string;
6394
6900
  }
6395
6901
  /** Default texts of {@link MeshBoardMessages} (the list texts default inside `mm-list-view`). */
6396
6902
  declare const DEFAULT_MESHBOARD_MESSAGES: Required<Omit<MeshBoardMessages, 'tableList'>>;
@@ -6412,6 +6918,36 @@ declare const MESHBOARD_MESSAGES: InjectionToken<MeshBoardMessagesSource>;
6412
6918
  /** The resolved MeshBoard texts: defaults with the host layer on top (missing / null members keep the default). */
6413
6919
  declare function resolveMeshBoardMessages(messages: MeshBoardMessages | null | undefined): MeshBoardMessages & typeof DEFAULT_MESHBOARD_MESSAGES;
6414
6920
 
6921
+ /**
6922
+ * What a host provides on {@link MESHBOARD_LANGUAGE} (AB#7655): the current UI language as a culture
6923
+ * code (`de-AT`, `en-GB`, `de`), fixed or as a signal for apps that switch the language at runtime
6924
+ * (the widgets follow it without reloading data). `null` / `undefined` / `''` = no language.
6925
+ */
6926
+ type MeshBoardLanguageSource = string | Signal<string | null | undefined>;
6927
+ /**
6928
+ * Optional: the host's current UI language. MeshBoard does not derive it from `LOCALE_ID` (that is
6929
+ * static in many apps); a host that wants per-language texts in board configurations (table column
6930
+ * `titles`, `valueLabels`) hands its language over once, via `provideMeshBoard({ language })`,
6931
+ * `provideMeshBoardLanguage(language)` or this token directly. Not provided = the configured default
6932
+ * texts (e.g. the column `title`).
6933
+ *
6934
+ * ```ts
6935
+ * providers: [provideMeshBoard({ language: languageService.currentLanguage })] // Signal<string>
6936
+ * ```
6937
+ */
6938
+ declare const MESHBOARD_LANGUAGE: InjectionToken<MeshBoardLanguageSource>;
6939
+ /**
6940
+ * Picks the text for `language` from a per-language map (AB#7655). Lookup order:
6941
+ * 1. the exact culture or language (`de-AT`, `de`; case-insensitive);
6942
+ * 2. a culture (`de-AT`) without an exact key: a key equal to its language part (`de`). A culture
6943
+ * never picks a sibling culture (`de-DE` does not take `de-AT`);
6944
+ * 3. a bare language (`de`) without an exact key: the first authored key of that language
6945
+ * (`de-AT` in `{ 'en-GB': …, 'de-AT': …, 'de-DE': … }`), in the map's key order.
6946
+ * Returns `undefined` when there is no language, no map or no match, so the caller applies its own
6947
+ * fallback (e.g. the column `title`).
6948
+ */
6949
+ declare function pickLocalizedText(texts: Readonly<Record<string, string>> | null | undefined, language: string | null | undefined): string | undefined;
6950
+
6415
6951
  declare function registerDefaultWidgets(registry: WidgetRegistryService): void;
6416
6952
  /**
6417
6953
  * Provides the widget registry with all built-in widgets registered.
@@ -6445,6 +6981,13 @@ interface MeshBoardOptions {
6445
6981
  * table widget's list texts. Fixed object or signal. Absent = English.
6446
6982
  */
6447
6983
  messages?: MeshBoardMessagesSource;
6984
+ /**
6985
+ * The host's current UI language (AB#7655), provided as `MESHBOARD_LANGUAGE`: a culture code
6986
+ * (`de-AT`) or a signal of it for apps that switch the language at runtime. Board configurations
6987
+ * use it to pick per-language texts (table column `titles`, `valueLabels`). Absent = the default
6988
+ * texts (column `title`); MeshBoard never falls back to `LOCALE_ID`.
6989
+ */
6990
+ language?: MeshBoardLanguageSource;
6448
6991
  }
6449
6992
  /**
6450
6993
  * Injection token for MeshBoard options
@@ -6479,6 +7022,11 @@ declare function provideMeshBoard(options?: MeshBoardOptions): EnvironmentProvid
6479
7022
  * without `provideMeshBoard()` — for apps that register the widgets lazily.
6480
7023
  */
6481
7024
  declare function provideMeshBoardMessages(messages: MeshBoardMessagesSource): EnvironmentProviders;
7025
+ /**
7026
+ * Provides the host's UI language (`MESHBOARD_LANGUAGE`, AB#7655) without `provideMeshBoard()` —
7027
+ * for apps that register the widgets lazily. A string or a signal (the widgets follow it).
7028
+ */
7029
+ declare function provideMeshBoardLanguage(language: MeshBoardLanguageSource): EnvironmentProviders;
6482
7030
  /**
6483
7031
  * Provider function for registering custom widgets.
6484
7032
  * Use this to add your own widget types to MeshBoard.
@@ -6560,9 +7108,17 @@ declare class EntitySelectorEditorComponent {
6560
7108
  private readonly variableService;
6561
7109
  private readonly getEntitiesByCkTypeGQL;
6562
7110
  private readonly confirmationService;
7111
+ private readonly cdr;
7112
+ private readonly destroyRef;
7113
+ private readonly injector;
6563
7114
  entitySelectors: EntitySelectorConfig[];
6564
7115
  /** Existing variable names from other sources (static variables, other selectors) for duplicate detection */
6565
7116
  existingVariableNames: string[];
7117
+ /**
7118
+ * The board's static variables (AB#7724): offered in the picker filter and
7119
+ * substituted when the editor lists default entities and checks the default.
7120
+ */
7121
+ variables: MeshBoardVariable[];
6566
7122
  entitySelectorsChange: EventEmitter<EntitySelectorConfig[]>;
6567
7123
  /** Emits true when entering edit mode, false when leaving — allows parent to hide its own buttons */
6568
7124
  editingStateChange: EventEmitter<boolean>;
@@ -6578,15 +7134,25 @@ declare class EntitySelectorEditorComponent {
6578
7134
  protected editMappings: EntitySelectorAttributeMapping[];
6579
7135
  protected editShowInToolbar: boolean;
6580
7136
  protected editDefaultRtId: string;
6581
- protected editChildScopeTargetCkTypeId: string;
6582
- protected editChildScopeTargetCkTypeItem: CkTypeSelectorItem | null;
6583
- protected editChildScopeRoleId: string;
6584
- protected editChildScopeDirection: 'in' | 'out';
7137
+ protected editScopeHops: EntitySelectorScopeHop[];
6585
7138
  protected editFollowsSelectorId: string;
6586
7139
  /** Why choosing the leader changed the form (CK type fixed, mappings/default cleared). */
6587
7140
  protected followNotice: string;
7141
+ protected editFilters: FieldFilterItem[];
7142
+ /** Filter rows a follower carries from hand-editing; ignored and dropped on save. */
7143
+ protected followerFilterCount: number;
7144
+ /** Result of the server check whether the default entity matches the filter. */
7145
+ protected defaultFilterCheck: DefaultFilterCheck;
7146
+ private readonly defaultCheckRequests;
7147
+ protected editScopeSourceSelectorId: string;
7148
+ /** Hops from the leader's CK type to this selector's CK type; the last target is fixed. */
7149
+ protected editScopeSourceHops: EntitySelectorScopeHop[];
7150
+ /** Result of the check whether the default entity is inside the leader's default pick. */
7151
+ protected defaultScopeCheck: DefaultScopeCheck;
7152
+ private readonly scopeCheckRequests;
6588
7153
  protected defaultEntityDataSource: RuntimeEntitySelectDataSource | null;
6589
7154
  protected defaultEntityDialogDataSource: RuntimeEntityDialogDataSource | null;
7155
+ constructor();
6590
7156
  /**
6591
7157
  * Starts adding a new entity selector.
6592
7158
  */
@@ -6609,6 +7175,45 @@ declare class EntitySelectorEditorComponent {
6609
7175
  get followedByLabels(): string;
6610
7176
  /** Validation message of the "Follows" choice, or '' when it is valid. */
6611
7177
  get followError(): string;
7178
+ /** Selectors that list only entities inside the edited selector (AB#7917). */
7179
+ get dependents(): EntitySelectorConfig[];
7180
+ /** "A and B" of the selectors depending on the edited one. */
7181
+ get dependentsLabels(): string;
7182
+ /** True when the Follows choice is locked: the selector is followed or has dependents and follows nobody. */
7183
+ get isFollowsLocked(): boolean;
7184
+ /** Selectors the edited one may list "inside": not followers, not dependent, not itself. */
7185
+ get scopeSourceLeaderOptions(): EntitySelectorConfig[];
7186
+ /** True when the stored leader is not among the selectable leaders (deleted, follower, dependent). */
7187
+ get isScopeSourceLeaderUnavailable(): boolean;
7188
+ /** The leader selector of the scope source, if it exists. */
7189
+ get scopeSourceLeader(): EntitySelectorConfig | undefined;
7190
+ /** Label of the scope source leader (label, else id). */
7191
+ get scopeSourceLeaderLabel(): string;
7192
+ /** Source type of hop 1: the leader's CK type. */
7193
+ get scopeSourceLeaderCkTypeId(): string;
7194
+ /** "Room" — the edited selector in texts. */
7195
+ get editName(): string;
7196
+ /** True when the "Inside the pick of" choice is locked: other selectors depend on this one (one level). */
7197
+ get isScopeSourceLocked(): boolean;
7198
+ /** Validation message of the scope source, or '' when it can be saved (or is dropped on save). */
7199
+ get scopeSourceError(): string;
7200
+ /**
7201
+ * The scope source error as the section shows it: hop errors are already
7202
+ * shown by the path editor next to the hop, so they are not repeated here.
7203
+ */
7204
+ get scopeSourceDisplayError(): string;
7205
+ /** Maximum hop count of a path (getter: relative imports must not initialise fields). */
7206
+ get maxScopeHops(): number;
7207
+ /** Handles a change of the "Inside the pick of" choice. */
7208
+ onScopeSourceChanged(leaderId: string): void;
7209
+ /** Takes the hop list of the scope source path editor. */
7210
+ onScopeSourceHopsChanged(hops: EntitySelectorScopeHop[]): void;
7211
+ /** "Inside: Site (3 hops)" chip of a selector in the list, or ''. */
7212
+ getScopeSourceSummary(selector: EntitySelectorConfig): string;
7213
+ /** True when a selector's scope source cannot be used (list chip shown as an error). */
7214
+ isInvalidScopeSource(selector: EntitySelectorConfig): boolean;
7215
+ /** The edited selector as far as the scope source validation needs it. */
7216
+ private formSelectorForValidation;
6612
7217
  /** True while the edited selector follows another one. */
6613
7218
  get isFollower(): boolean;
6614
7219
  /**
@@ -6633,14 +7238,10 @@ declare class EntitySelectorEditorComponent {
6633
7238
  * Opens the attribute selector dialog to pick attributes for variable mappings.
6634
7239
  */
6635
7240
  selectAttributes(): Promise<void>;
6636
- /**
6637
- * Handles child-scope target CK type selection.
6638
- */
6639
- onChildScopeCkTypeSelected(ckType: CkTypeSelectorItem): void;
6640
- /**
6641
- * Handles child-scope target CK type cleared.
6642
- */
6643
- onChildScopeCkTypeCleared(): void;
7241
+ /** Takes the hop list of the child-scope editor (AB#7723). */
7242
+ onScopeHopsChanged(hops: EntitySelectorScopeHop[]): void;
7243
+ /** Validation message of the hop list, or '' when it can be saved. */
7244
+ get scopeHopsError(): string;
6644
7245
  /**
6645
7246
  * Handles default entity selection from the entity picker.
6646
7247
  */
@@ -6649,6 +7250,20 @@ declare class EntitySelectorEditorComponent {
6649
7250
  * Handles default entity cleared.
6650
7251
  */
6651
7252
  onDefaultEntityCleared(): void;
7253
+ /** Takes the rows of the picker filter editor (AB#7724). */
7254
+ onFiltersChange(filters: FieldFilterItem[]): void;
7255
+ /**
7256
+ * Variables offered in filter values: the board's static variables and the
7257
+ * variables other selectors map. The edited selector's own mappings are
7258
+ * left out — they are filled from its own pick.
7259
+ */
7260
+ get filterVariables(): FilterVariable[];
7261
+ /** "2 filters" chip of a selector in the list, or '' without filter. */
7262
+ getFilterSummary(selector: EntitySelectorConfig): string;
7263
+ /** "$a, $b" of the variables the default-entity check cannot substitute. */
7264
+ get uncheckedVariablesText(): string;
7265
+ /** Label of the leader the edited follower takes its pick from. */
7266
+ get leaderLabel(): string;
6652
7267
  /**
6653
7268
  * Saves the current entity selector being edited.
6654
7269
  */
@@ -6688,9 +7303,193 @@ declare class EntitySelectorEditorComponent {
6688
7303
  getVariableNameError(mapping: EntitySelectorAttributeMapping): string;
6689
7304
  private generateSelectorId;
6690
7305
  private updateDefaultEntityDataSources;
7306
+ private toFilterConfigs;
7307
+ /**
7308
+ * The filter rows that apply in the editor, with the board's static
7309
+ * variables substituted. Rows whose value still names a variable without a
7310
+ * value (e.g. one a selector pick fills at view time) are left out and
7311
+ * reported in `unresolved`; the editor cannot know their value.
7312
+ */
7313
+ private resolvedEditorFilters;
7314
+ /** Queues the (debounced) check whether the default entity matches the filter. */
7315
+ private requestDefaultCheck;
7316
+ /** Asks the server whether the entity is among the filtered ones (rtId + filter, first 1). */
7317
+ private checkDefaultEntity;
7318
+ /**
7319
+ * Queues the (debounced) check whether the default entity lies inside the
7320
+ * leader's default pick (AB#7917). Only for a valid scope source and when
7321
+ * both selectors have a default; otherwise clears the result.
7322
+ */
7323
+ private requestScopeCheck;
7324
+ /** Resolves the leader's default pick through the path and looks for the default entity. */
7325
+ private checkDefaultInScope;
6691
7326
  private emitChange;
6692
7327
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntitySelectorEditorComponent, never>;
6693
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntitySelectorEditorComponent, "mm-entity-selector-editor", never, { "entitySelectors": { "alias": "entitySelectors"; "required": false; }; "existingVariableNames": { "alias": "existingVariableNames"; "required": false; }; }, { "entitySelectorsChange": "entitySelectorsChange"; "editingStateChange": "editingStateChange"; }, never, never, true, never>;
7328
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntitySelectorEditorComponent, "mm-entity-selector-editor", never, { "entitySelectors": { "alias": "entitySelectors"; "required": false; }; "existingVariableNames": { "alias": "existingVariableNames"; "required": false; }; "variables": { "alias": "variables"; "required": false; }; }, { "entitySelectorsChange": "entitySelectorsChange"; "editingStateChange": "editingStateChange"; }, never, never, true, never>;
7329
+ }
7330
+ /**
7331
+ * Outcome of the check whether a dependent selector's default entity lies
7332
+ * inside its leader's default pick (AB#7917). Never blocks saving: `outside`
7333
+ * warns, `error` says the check failed.
7334
+ */
7335
+ type DefaultScopeCheck = {
7336
+ state: 'none';
7337
+ } | {
7338
+ state: 'inside';
7339
+ } | {
7340
+ state: 'outside';
7341
+ } | {
7342
+ state: 'error';
7343
+ };
7344
+ /**
7345
+ * Outcome of the default-entity filter check (AB#7724). Never blocks saving:
7346
+ * `mismatch` warns, `error` says the check failed, `unchecked` names the
7347
+ * variables the editor cannot substitute.
7348
+ */
7349
+ type DefaultFilterCheck = {
7350
+ state: 'none';
7351
+ } | {
7352
+ state: 'match';
7353
+ } | {
7354
+ state: 'mismatch';
7355
+ } | {
7356
+ state: 'error';
7357
+ } | {
7358
+ state: 'unchecked';
7359
+ variables: string[];
7360
+ };
7361
+
7362
+ /** One association of a CK type as the "Association" dropdown offers it. */
7363
+ interface ScopeAssociationOption {
7364
+ /** `<direction>|<roleId>|<baseTargetCkTypeId>`, or {@link OTHER_ASSOCIATION}. */
7365
+ key: string;
7366
+ roleId: string;
7367
+ direction: 'in' | 'out';
7368
+ /** Target type of the association in the CK metadata (base type for the target-type picker). */
7369
+ baseTargetCkTypeId: string;
7370
+ label: string;
7371
+ }
7372
+ /** Editor row of one hop. */
7373
+ interface HopRow {
7374
+ roleId: string;
7375
+ direction: 'in' | 'out';
7376
+ targetCkTypeId: string;
7377
+ targetItem: CkTypeSelectorItem | null;
7378
+ /** Key of the chosen association, or {@link OTHER_ASSOCIATION} for free text. */
7379
+ associationKey: string;
7380
+ }
7381
+ /**
7382
+ * Hop list of an entity selector's child scope (AB#7723; wireframe agreed by
7383
+ * Freya, AB#7723 comment 6625315). Each hop picks an association of its source
7384
+ * type from the CK metadata (role + direction + base target in one entry, or
7385
+ * "Other role…" for free text) and a target type restricted to types derived
7386
+ * from the association's target. The source type of hop 1 is the selector's
7387
+ * CK type, of every later hop the previous hop's target type. Hops can be
7388
+ * added (at most {@link MAX_SCOPE_HOPS}), removed and moved up/down.
7389
+ *
7390
+ * Two-way bindable; emits the hops as configured (validation is the host's,
7391
+ * see `scopeHopsValidationError`):
7392
+ * ```html
7393
+ * <mm-entity-selector-scope-path-editor
7394
+ * [sourceCkTypeId]="ckTypeId"
7395
+ * [(hops)]="hops">
7396
+ * </mm-entity-selector-scope-path-editor>
7397
+ * ```
7398
+ */
7399
+ declare class EntitySelectorScopePathEditorComponent {
7400
+ private readonly rolesGQL;
7401
+ private readonly cdr;
7402
+ hopsChange: EventEmitter<EntitySelectorScopeHop[]>;
7403
+ private hopCards?;
7404
+ protected rows: HopRow[];
7405
+ protected readonly plusIcon: _progress_kendo_svg_icons.SVGIcon;
7406
+ protected readonly arrowUpIcon: _progress_kendo_svg_icons.SVGIcon;
7407
+ protected readonly arrowDownIcon: _progress_kendo_svg_icons.SVGIcon;
7408
+ protected readonly trashIcon: _progress_kendo_svg_icons.SVGIcon;
7409
+ /**
7410
+ * Intro text above the hop list. Unset = the child-scope text (AB#7723);
7411
+ * the scope-source section of the selector editor passes its own (AB#7917).
7412
+ */
7413
+ description: string | null;
7414
+ /** What the source of hop 1 is, shown after its type ("picked entity"). */
7415
+ sourceDescription: string;
7416
+ /** Text shown while there is no hop. Unset = the child-scope text. */
7417
+ emptyText: string | null;
7418
+ private _sourceCkTypeId;
7419
+ private _lockedTargetCkTypeId;
7420
+ private lastEmitted;
7421
+ private readonly associations;
7422
+ /** CK type of the picked entity — the source type of hop 1. */
7423
+ set sourceCkTypeId(value: string | null | undefined);
7424
+ get sourceCkTypeId(): string;
7425
+ /**
7426
+ * When set, the last hop's target type is fixed to this type (AB#7917: the
7427
+ * scope source path always ends at the dependent selector's CK type). The
7428
+ * last hop then shows the type read-only, new hops are inserted before it,
7429
+ * and it cannot be moved; removing it makes the previous hop the fixed one.
7430
+ */
7431
+ set lockedTargetCkTypeId(value: string | null | undefined);
7432
+ get lockedTargetCkTypeId(): string;
7433
+ /** The configured hops (one-hop form = one hop). */
7434
+ set hops(value: EntitySelectorScopeHop[] | null | undefined);
7435
+ /** True when the last hop's target type is fixed ({@link lockedTargetCkTypeId}). */
7436
+ get isLocked(): boolean;
7437
+ /** True when hop `index` is the last hop and its target type is fixed. */
7438
+ isLockedHop(index: number): boolean;
7439
+ /** True when hop `index` offers "move up" (a fixed last hop stays last). */
7440
+ canMoveUp(index: number): boolean;
7441
+ /** True when hop `index` offers "move down" (nothing moves below a fixed last hop). */
7442
+ canMoveDown(index: number): boolean;
7443
+ /** Maximum hop count (getter: relative imports must not initialise fields, see CLAUDE.md). */
7444
+ get maxHops(): number;
7445
+ get canAddHop(): boolean;
7446
+ /** "Test/Site → Test/System → Test/Device". */
7447
+ get pathLabel(): string;
7448
+ /** True when the association metadata of any shown source type could not be loaded. */
7449
+ get metadataFailed(): boolean;
7450
+ /** Source type of hop `index`. */
7451
+ sourceTypeOf(index: number): string;
7452
+ /** Dropdown entries of hop `index`: the source type's associations plus "Other role…". */
7453
+ associationOptions(index: number): ScopeAssociationOption[];
7454
+ /** True when hop `index` offers the association dropdown (metadata loaded with ≥1 association). */
7455
+ hasAssociationList(index: number): boolean;
7456
+ /** True when hop `index` shows the free-text role and direction fields. */
7457
+ isFreeText(index: number): boolean;
7458
+ /** Base type the target-type picker of hop `index` is restricted to (undefined = any type). */
7459
+ baseTargetOf(index: number): string | undefined;
7460
+ /**
7461
+ * Warning of hop `index` when its role is not an association of its (new)
7462
+ * source type — after a reorder, a removal or a changed earlier target. The
7463
+ * values are kept; it does not block saving.
7464
+ */
7465
+ associationWarning(index: number): string;
7466
+ /** Validation message of hop `index`: an incomplete hop blocks saving (see `scopeHopsValidationError`). */
7467
+ hopError(index: number): string;
7468
+ isRoleInvalid(index: number): boolean;
7469
+ isTargetInvalid(index: number): boolean;
7470
+ addHop(): void;
7471
+ removeHop(index: number): void;
7472
+ moveHop(index: number, delta: -1 | 1): void;
7473
+ onAssociationChanged(index: number, key: string): void;
7474
+ onRoleChanged(index: number, roleId: string): void;
7475
+ onDirectionChanged(index: number, direction: 'in' | 'out'): void;
7476
+ onTargetSelected(index: number, ckType: CkTypeSelectorItem): void;
7477
+ onTargetCleared(index: number): void;
7478
+ /** Sets the last hop's target type to the fixed type (no-op without a lock). */
7479
+ private applyLock;
7480
+ private emit;
7481
+ private loadOf;
7482
+ /**
7483
+ * Matches every hop's role/direction to an entry of its source type's
7484
+ * associations (loading missing metadata); a hop whose association is not
7485
+ * listed switches to "Other role…" with its values kept.
7486
+ */
7487
+ private syncAssociationKeys;
7488
+ private loadAssociations;
7489
+ /** Keeps the keyboard focus on a moved hop (wireframe change 4). */
7490
+ private focusHop;
7491
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntitySelectorScopePathEditorComponent, never>;
7492
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntitySelectorScopePathEditorComponent, "mm-entity-selector-scope-path-editor", never, { "description": { "alias": "description"; "required": false; }; "sourceDescription": { "alias": "sourceDescription"; "required": false; }; "emptyText": { "alias": "emptyText"; "required": false; }; "sourceCkTypeId": { "alias": "sourceCkTypeId"; "required": false; }; "lockedTargetCkTypeId": { "alias": "lockedTargetCkTypeId"; "required": false; }; "hops": { "alias": "hops"; "required": false; }; }, { "hopsChange": "hopsChange"; }, never, never, true, never>;
6694
7493
  }
6695
7494
 
6696
7495
  /**
@@ -6708,18 +7507,38 @@ interface EntitySelectorClearEvent {
6708
7507
  }
6709
7508
  /**
6710
7509
  * Toolbar component that renders entity select inputs for each configured entity selector.
6711
- * Creates data sources per CK type and emits selection/clear events.
7510
+ * Creates data sources per CK type, picker filter (AB#7724) and picker scope (AB#7915) and emits
7511
+ * selection/clear events.
6712
7512
  */
6713
- declare class EntitySelectorToolbarComponent implements OnChanges {
7513
+ declare class EntitySelectorToolbarComponent implements OnChanges, OnDestroy {
6714
7514
  private readonly getEntitiesByCkTypeGQL;
7515
+ private readonly variableService;
6715
7516
  entitySelectors: EntitySelectorConfig[];
7517
+ /**
7518
+ * Board variables substituted into the selectors' picker filters (AB#7724),
7519
+ * the same substitution widget filters get.
7520
+ */
7521
+ variables: MeshBoardVariable[];
7522
+ /**
7523
+ * Picker scopes of dependent selectors (AB#7915), keyed by selector id
7524
+ * (`MeshBoardStateService.pickerScopes`). No entry = the leader has no pick.
7525
+ */
7526
+ pickerScopes: Record<string, EntitySelectorScopeState>;
6716
7527
  entitySelected: EventEmitter<EntitySelectorEvent>;
6717
7528
  entityCleared: EventEmitter<EntitySelectorClearEvent>;
6718
7529
  private dataSourceCache;
6719
7530
  private dialogDataSourceCache;
6720
7531
  protected selectorDataSources: Map<string, RuntimeEntitySelectDataSource>;
6721
7532
  protected selectorDialogDataSources: Map<string, RuntimeEntityDialogDataSource>;
7533
+ protected selectorMessages: Map<string, Partial<EntitySelectInputMessages>>;
7534
+ private filteredSelectorIds;
7535
+ private readonly settledPickers$;
6722
7536
  ngOnChanges(changes: SimpleChanges): void;
7537
+ ngOnDestroy(): void;
7538
+ /** Texts of the selector's picker: a filtered picker explains its empty list (AB#7724). */
7539
+ getMessages(selector: EntitySelectorConfig): Partial<EntitySelectInputMessages>;
7540
+ /** Title of the selector's search dialog; marks a filtered picker (AB#7724). */
7541
+ getDialogTitle(selector: EntitySelectorConfig): string;
6723
7542
  /**
6724
7543
  * True when the selector renders a picker. Hidden selectors and followers
6725
7544
  * (AB#7722) never do; a follower's pick is derived from its leader.
@@ -6742,11 +7561,33 @@ declare class EntitySelectorToolbarComponent implements OnChanges {
6742
7561
  */
6743
7562
  onEntityCleared(selectorId: string): void;
6744
7563
  /**
6745
- * Creates or retrieves cached data sources for each selector.
7564
+ * Creates or retrieves cached data sources for each selector. Selectors of
7565
+ * the same CK type, the same resolved filter and the same picker scope share
7566
+ * their data sources; a selector without filter and scope source uses the
7567
+ * plain query, exactly as before AB#7724. The cache key changes with the
7568
+ * picker scope (AB#7915), so a leader change gives the dependent fresh data
7569
+ * sources. Entries no selector uses any more are dropped, so the caches never
7570
+ * outgrow the current selectors.
6746
7571
  */
6747
7572
  private updateDataSources;
7573
+ /**
7574
+ * The query service of a picker: filter rows (AB#7724) plus, for a dependent
7575
+ * selector, the picker scope `rtId IN (…)` (AB#7915). Empty and failed scopes
7576
+ * list nothing without a request; a pending scope waits until it settled.
7577
+ */
7578
+ private pickerQuery;
7579
+ /** The query of `selectorId` once its picker scope is no longer pending (`null` = list nothing). */
7580
+ private settledPicker;
7581
+ /**
7582
+ * Picker texts (wording agreed with the Studio PO): a dependent picker with
7583
+ * nothing in scope or a failed scope says so right away (also before the
7584
+ * user types); a filtered picker explains an empty search result (AB#7724).
7585
+ */
7586
+ private pickerMessages;
7587
+ /** Number of cached data source pairs (for tests). */
7588
+ get cachedDataSourceCount(): number;
6748
7589
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntitySelectorToolbarComponent, never>;
6749
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntitySelectorToolbarComponent, "mm-entity-selector-toolbar", never, { "entitySelectors": { "alias": "entitySelectors"; "required": false; }; }, { "entitySelected": "entitySelected"; "entityCleared": "entityCleared"; }, never, never, true, never>;
7590
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntitySelectorToolbarComponent, "mm-entity-selector-toolbar", never, { "entitySelectors": { "alias": "entitySelectors"; "required": false; }; "variables": { "alias": "variables"; "required": false; }; "pickerScopes": { "alias": "pickerScopes"; "required": false; }; }, { "entitySelected": "entitySelected"; "entityCleared": "entityCleared"; }, never, never, true, never>;
6750
7591
  }
6751
7592
 
6752
7593
  /**
@@ -6770,6 +7611,28 @@ interface WidgetPlacement {
6770
7611
  rowSpan: number;
6771
7612
  }
6772
7613
 
7614
+ /**
7615
+ * The period a host page sets on an embedded MeshBoard (`mm-meshboard-view [timeRange]`, AB#7582):
7616
+ * two exact instants, half-open `[from, to)`. A string must be an RFC 3339 date-time with an
7617
+ * explicit offset - see {@link parseHostTimeRange}.
7618
+ */
7619
+ interface MeshBoardHostTimeRange {
7620
+ from: Date | string;
7621
+ to: Date | string;
7622
+ }
7623
+ /**
7624
+ * Who controls the board's period: `board` (default) shows the board's own time-range picker;
7625
+ * `host` hides the picker and its reset button because the host page owns the period.
7626
+ */
7627
+ type MeshBoardTimeFilterControl = 'board' | 'host';
7628
+ /**
7629
+ * Parses the host's `timeRange` input. `undefined`/`null` = the host sets no period.
7630
+ * Never snaps or converts: the instants are taken as given. `Date` objects are accepted as they
7631
+ * are; strings must be RFC 3339 with an offset, e.g. `2026-03-28T05:00:00Z` or
7632
+ * `2026-03-28T06:00:00+01:00` (see {@link RFC3339}).
7633
+ */
7634
+ declare function parseHostTimeRange(value: MeshBoardHostTimeRange | null | undefined): HostTimeRangeState | undefined;
7635
+
6773
7636
  interface WidgetPositionUpdate {
6774
7637
  id: string;
6775
7638
  title: string;
@@ -6878,6 +7741,41 @@ declare class MeshBoardViewComponent implements OnInit, OnDestroy, HasUnsavedCha
6878
7741
  readonly chrome: _angular_core.InputSignal<MeshBoardChrome | undefined>;
6879
7742
  private readonly routeChrome;
6880
7743
  protected readonly effectiveChrome: _angular_core.Signal<MeshBoardChrome>;
7744
+ /**
7745
+ * The period set by the host page (AB#7582): two exact instants, half-open `[from, to)`, as
7746
+ * `Date` objects or ISO 8601 strings with a zone designator. While set (and the board's time
7747
+ * filter is enabled) the view publishes exactly these instants as `$timeRangeFrom` /
7748
+ * `$timeRangeTo` and as the stream-data window - no day snapping, no zone conversion - and
7749
+ * ignores the `tf_*` query parameters and the stored/default selection. It writes no `tf_*`
7750
+ * parameters and causes no unsaved changes. A change reloads the widgets once; `undefined`
7751
+ * returns the board to its own selection. Day rules (e.g. a 06:00 gas day) belong to the host.
7752
+ * An invalid range (unparseable, or `from >= to`) sends no stream-data query and logs one
7753
+ * console error. A board with the time filter disabled ignores the input.
7754
+ */
7755
+ readonly timeRange: _angular_core.InputSignal<MeshBoardHostTimeRange | undefined>;
7756
+ /**
7757
+ * Who controls the period: `board` (default, unchanged behaviour) shows the board's time-range
7758
+ * picker; `host` hides the picker and its reset button - entity selectors and actions stay.
7759
+ * While `timeRange` is set the picker is hidden and its events are ignored either way.
7760
+ */
7761
+ readonly timeFilterControl: _angular_core.InputSignal<MeshBoardTimeFilterControl>;
7762
+ /** The parsed `timeRange` input; `undefined` = the host sets no period. */
7763
+ protected readonly parsedHostTimeRange: _angular_core.Signal<HostTimeRangeState | undefined>;
7764
+ /** True while the host owns the period (a valid or an invalid `timeRange` is set). */
7765
+ protected readonly isHostTimeRangeActive: _angular_core.Signal<boolean>;
7766
+ /** Whether the board's own time-range picker (and its reset button) is rendered. */
7767
+ protected readonly showTimeRangePicker: _angular_core.Signal<boolean>;
7768
+ /** The host range last applied to the state service (to reload only on a real change). */
7769
+ private appliedHostTimeRange;
7770
+ /** The invalid host range already reported, so a board switch does not log it again. */
7771
+ private reportedInvalidHostTimeRange;
7772
+ /**
7773
+ * Set once the host has owned the period: the `tf_*` parameters of the URL this view was opened
7774
+ * with are stale from then on and are not applied again when `timeRange` goes back to undefined.
7775
+ */
7776
+ private hostHasOwnedPeriod;
7777
+ /** Set in ngOnDestroy; the async initial load stops touching shared state after it (AB#7582). */
7778
+ private destroyed;
6881
7779
  protected readonly meshBoardPageLink: _angular_core.Signal<string>;
6882
7780
  protected readonly hasWidgets: _angular_core.Signal<boolean>;
6883
7781
  /** Widgets shown: outside edit mode those that reported "nothing for this viewer" are collapsed (AB#5558). */
@@ -6900,6 +7798,10 @@ declare class MeshBoardViewComponent implements OnInit, OnDestroy, HasUnsavedCha
6900
7798
  private readonly _urlTimeSelection;
6901
7799
  protected readonly initialTimeSelection: _angular_core.Signal<TimeRangeSelection$1 | undefined>;
6902
7800
  protected readonly entitySelectorsConfig: _angular_core.Signal<EntitySelectorConfig[]>;
7801
+ /** Picker scopes of dependent selectors (AB#7915). */
7802
+ protected readonly pickerScopes: _angular_core.Signal<Record<string, EntitySelectorScopeState>>;
7803
+ /** Board variables substituted into the selectors' picker filters (AB#7724). */
7804
+ protected readonly boardVariables: _angular_core.Signal<_meshmakers_octo_meshboard.MeshBoardVariable[]>;
6903
7805
  protected readonly hasEntitySelectors: _angular_core.Signal<boolean>;
6904
7806
  protected readonly unselectedToolbarSelectors: _angular_core.Signal<EntitySelectorConfig[]>;
6905
7807
  /**
@@ -6922,7 +7824,12 @@ declare class MeshBoardViewComponent implements OnInit, OnDestroy, HasUnsavedCha
6922
7824
  * fail with a NavigationError (AB#4457).
6923
7825
  */
6924
7826
  private updateUrlWithRtId;
6925
- /** The active time-filter selection to mirror into the URL, or null when the filter is off. */
7827
+ /**
7828
+ * The active time-filter selection to mirror into the URL, or null when the filter is off or
7829
+ * the host owns the period or controls the filter (AB#7582: the view then writes no tf_*
7830
+ * parameters; with `timeFilterControl='host'` and no `timeRange` the board selection still
7831
+ * applies, but the URL is the host's).
7832
+ */
6926
7833
  private activeTimeFilterSelection;
6927
7834
  ngOnInit(): Promise<void>;
6928
7835
  /**
@@ -6946,8 +7853,22 @@ declare class MeshBoardViewComponent implements OnInit, OnDestroy, HasUnsavedCha
6946
7853
  /**
6947
7854
  * Initializes time filter variables based on URL query params or stored selection.
6948
7855
  * URL params take precedence over stored selection to support page reload.
7856
+ * A period set by the host (`timeRange`, AB#7582) takes precedence over both.
6949
7857
  */
6950
7858
  private initializeTimeFilterVariables;
7859
+ /**
7860
+ * Hands the host period to the state service and publishes `$timeRangeFrom` / `$timeRangeTo`
7861
+ * as exactly its instants (AB#7582). Returns true while the host owns the period, so the
7862
+ * caller skips the board's own selection. With the time filter disabled the period is only
7863
+ * stored (the state service ignores it then) and nothing is logged.
7864
+ */
7865
+ private applyHostTimeRange;
7866
+ /**
7867
+ * Applies a change of the `timeRange` input after the initial load (AB#7582): the host period,
7868
+ * or the board's own selection again when the input went back to `undefined`. Reloads the
7869
+ * widgets once; an equal period (same instants) changes nothing.
7870
+ */
7871
+ private onHostTimeRangeChanged;
6951
7872
  /**
6952
7873
  * Recomputes the active time-filter range from the current selection on the
6953
7874
  * board's (possibly just-changed) timezone mode and republishes the
@@ -7007,17 +7928,80 @@ declare class MeshBoardViewComponent implements OnInit, OnDestroy, HasUnsavedCha
7007
7928
  * Programmatically sets an entity selector value from outside the component.
7008
7929
  * Use this when the host application controls entity selection (e.g., with meshBoardHideEntitySelectors).
7009
7930
  * Resolves entity attributes, sets variables, and refreshes widgets.
7931
+ *
7932
+ * Dependent selectors (AB#7916): an rtId outside the dependent's picker scope
7933
+ * (the leader's pick) is rejected with a console warning and nothing
7934
+ * re-queries. On a leader the leader-change rules apply: each dependent keeps
7935
+ * its pick if it is in the new scope, else its default if that is, else it
7936
+ * has no pick; widgets refresh once for the whole change.
7010
7937
  */
7011
7938
  setEntitySelector(selectorId: string, rtId: string, displayName?: string): Promise<void>;
7012
7939
  /**
7013
7940
  * Programmatically clears an entity selector value from outside the component.
7941
+ * Clearing a leader keeps its dependents' picks (AB#7916); clearing a
7942
+ * dependent while its leader has a pick leaves its widgets without data
7943
+ * until a new pick is made.
7014
7944
  */
7015
7945
  clearEntitySelector(selectorId: string): void;
7016
7946
  /**
7017
7947
  * Clears one selector's pick, variables and scope state. Without a pick bound
7018
- * widgets fall back to the persisted scope (AB#7721).
7948
+ * widgets fall back to the persisted scope (AB#7721) — except a dependent
7949
+ * selector (or a follower of one without pick) while the leader has a pick:
7950
+ * its widgets show no data and the view asks for a pick (AB#7916).
7019
7951
  */
7020
7952
  private clearSelectorPick;
7953
+ /**
7954
+ * True when the selector — having no pick — must show no data instead of
7955
+ * the persisted scope (AB#7916): it is a valid dependent whose leader has a
7956
+ * pick (the dependent has a picker scope), or a follower of such a dependent
7957
+ * while the dependent has no pick either.
7958
+ */
7959
+ private needsPickWithoutOwnPick;
7960
+ /** True when the selector has a usable scope source (AB#7915). */
7961
+ private isDependent;
7962
+ /**
7963
+ * A dependent may only be picked inside its picker scope (AB#7916). While the
7964
+ * scope resolves the check waits for it; a scope overtaken meanwhile is read
7965
+ * again.
7966
+ */
7967
+ private acceptsDependentPick;
7968
+ /** Starts a new change of `selectorId`'s pick and returns its number (AB#7916). */
7969
+ private beginLeaderChange;
7970
+ /** True while no newer change of `selectorId`'s pick has started. */
7971
+ private isCurrentLeaderChange;
7972
+ /**
7973
+ * Picks `rtId` on a selector that may lead dependents (AB#7915/AB#7916). In
7974
+ * one synchronous step it marks the selector and its followers pending and
7975
+ * starts the dependents' picker scopes and pick decisions
7976
+ * ({@link settleDependentsOf}); then resolves the selector's own variables
7977
+ * and scope. `displayName` settles with the picked entity's display name,
7978
+ * `dependents` once every dependent's pick is decided, with the ids of the
7979
+ * dependents whose pick changed. `initialPicks` (board load) replaces the
7980
+ * dependents' current picks.
7981
+ */
7982
+ private pickWithDependents;
7983
+ /**
7984
+ * The leader `leaderId` was picked (`leaderRtId`): decides each dependent's
7985
+ * pick (AB#7916). Synchronously, each dependent's picker scope becomes
7986
+ * pending; a dependent with a current pick or a default is also marked
7987
+ * pending together with its followers, so bound widgets show loading and
7988
+ * never the old pick's data. Once the picker scope resolved, the pick is
7989
+ * {@link nextDependentPick}: kept if in scope, else the default if in scope,
7990
+ * else none. Without pick the dependent's widgets show no data with a
7991
+ * "pick" notice — a failed picker scope shows the scope-failed notice
7992
+ * instead. A decision overtaken by a newer leader change or a leader clear
7993
+ * is dropped. Resolves with the ids of the dependents whose pick changed.
7994
+ */
7995
+ private settleDependentsOf;
7996
+ /**
7997
+ * The leader `leaderId` loses its pick (`clear` clears it, which also drops
7998
+ * the dependents' picker scopes): dependents keep their picks (AB#7916). A
7999
+ * dependent without pick goes back to the persisted scope (AB#7721), and so
8000
+ * do its followers that needed a pick; a dependent whose pick was still being
8001
+ * decided resolves its current pick again. Returns a promise for those
8002
+ * resolutions, or `null` when there are none.
8003
+ */
8004
+ private releaseDependentsOf;
7021
8005
  /**
7022
8006
  * The leader `leaderId` has no pick any more: each of its followers resolves
7023
8007
  * its own `defaultRtId`, or — without one — has no pick and no scope
@@ -7037,11 +8021,36 @@ declare class MeshBoardViewComponent implements OnInit, OnDestroy, HasUnsavedCha
7037
8021
  selectorId: string;
7038
8022
  message: string;
7039
8023
  }[]>;
8024
+ /**
8025
+ * One notice per dependent selector without pick while its leader has one
8026
+ * (AB#7916): "Pick a <label> to see this data.". Followers of such a
8027
+ * dependent show no data too, but the notice names the selector to pick.
8028
+ */
8029
+ protected readonly scopePickRequiredNotices: _angular_core.Signal<{
8030
+ selectorId: string;
8031
+ message: string;
8032
+ }[]>;
7040
8033
  /**
7041
8034
  * Per-selector sequence number of the latest scope resolution, so a slower
7042
8035
  * resolution of an earlier pick never overwrites the scope of a newer pick.
7043
8036
  */
7044
8037
  private readonly scopeRequestSeq;
8038
+ /**
8039
+ * Per-dependent sequence number of the latest picker-scope resolution
8040
+ * (AB#7915): a late resolution of an earlier leader pick is discarded.
8041
+ */
8042
+ private readonly pickerScopeSeq;
8043
+ /** The latest picker-scope resolution of each dependent (AB#7916), awaited by a host pick. */
8044
+ private readonly pickerScopeResolutions;
8045
+ /**
8046
+ * Per-selector number of the latest pick change (AB#7916): the widget
8047
+ * refresh and URL write of a change overtaken by a newer one are skipped.
8048
+ */
8049
+ private readonly leaderChangeSeq;
8050
+ /** Dependents whose pick is being decided after a leader change (AB#7916). */
8051
+ private readonly decidingDependents;
8052
+ /** Set when the board load dropped an out-of-scope dependent pick from the URL or route data (AB#7916). */
8053
+ private entitySelectorUrlNeedsRewrite;
7045
8054
  /**
7046
8055
  * Handles time range change from the time range picker.
7047
8056
  * No-op: refresh is triggered by onTimeSelectionChange to ensure variables are updated first.
@@ -7151,17 +8160,34 @@ declare class MeshBoardViewComponent implements OnInit, OnDestroy, HasUnsavedCha
7151
8160
  /**
7152
8161
  * Handles entity selection from the entity selector toolbar.
7153
8162
  * Fetches entity attributes, sets variables, syncs to URL, and refreshes widgets.
8163
+ * On a leader the dependents' picks are decided first (AB#7916) and the
8164
+ * widgets refresh once for the whole change; a dependent only accepts an
8165
+ * rtId inside its picker scope.
7154
8166
  */
7155
8167
  onEntitySelectorSelected(event: EntitySelectorEvent): Promise<void>;
7156
8168
  /**
7157
8169
  * Handles entity cleared from the entity selector toolbar.
7158
- * Clears variables, syncs URL, and refreshes widgets.
8170
+ * Clears variables, syncs URL, and refreshes widgets. Clearing a leader keeps
8171
+ * its dependents' picks (AB#7916).
7159
8172
  */
7160
8173
  onEntitySelectorCleared(event: EntitySelectorClearEvent): Promise<void>;
7161
8174
  /**
7162
8175
  * Initializes entity selectors from URL params, route data, or defaults.
8176
+ *
8177
+ * Leaders resolve first (AB#7916): a dependent whose leader has a pick gets
8178
+ * its pick decided against the picker scope — an initial pick outside it is
8179
+ * dropped (default if in scope, else no pick); one dropped from the URL or
8180
+ * route data is logged once and the URL is rewritten. Widgets refresh once,
8181
+ * after every pick is decided.
7163
8182
  */
7164
8183
  private initializeEntitySelectors;
8184
+ /**
8185
+ * Logs (once per board load) each dependent whose URL or route-data pick was
8186
+ * dropped because it is outside the leader's pick, and marks the URL for a
8187
+ * rewrite (AB#7916). A dropped `defaultRtId` is not reported: it never was
8188
+ * in the URL.
8189
+ */
8190
+ private reportDroppedInitialPicks;
7165
8191
  /**
7166
8192
  * The initial pick of each entity selector. Priority: route data > URL
7167
8193
  * params > defaultRtId. Selectors without a pick are left out.
@@ -7181,6 +8207,24 @@ declare class MeshBoardViewComponent implements OnInit, OnDestroy, HasUnsavedCha
7181
8207
  * Selectors without a pick stay without scope state (persisted scope).
7182
8208
  */
7183
8209
  private primeEntitySelectorScopes;
8210
+ /**
8211
+ * Picker scopes of dependent selectors right after a board loaded (AB#7915):
8212
+ * a dependent whose leader has an initial pick is pending (its picker lists
8213
+ * nothing until the scope resolved); an invalid scope source is failed and
8214
+ * logs one warning per board load (the state is cleared on board switch, so
8215
+ * the guard on an existing state makes this idempotent).
8216
+ */
8217
+ private primePickerScopes;
8218
+ /**
8219
+ * Resolves the picker scope of `dependent` from its leader's pick `rtId`
8220
+ * (AB#7915): marks it pending synchronously, then walks `scopeSource.path`
8221
+ * with `resolveScopePath` (one batched request per hop) and stores the
8222
+ * distinct rtIds of the last hop — `[]` when the pick reaches nothing. A
8223
+ * failing hop is a failed picker scope (logged once). Resolves with the
8224
+ * stored state, or `null` when a newer leader pick (or a clear) overtook it.
8225
+ * Never rejects.
8226
+ */
8227
+ private resolvePickerScope;
7184
8228
  /**
7185
8229
  * Resolves variables for an entity selector by fetching entity attributes,
7186
8230
  * then its stream-data scope.
@@ -7201,10 +8245,16 @@ declare class MeshBoardViewComponent implements OnInit, OnDestroy, HasUnsavedCha
7201
8245
  * Resolves the set of source rtIds that a stream-data widget bound to this
7202
8246
  * selector should be scoped to, and caches them on the state service.
7203
8247
  *
7204
- * When the selector defines a {@link EntitySelectorChildScope}, the picked
7205
- * entity's children of `targetCkTypeId` reached via `roleId`/`direction`
7206
- * become the scope (e.g. MeteringPoint → its EnergyMeasurement rtIds). With
7207
- * no childScope, the picked entity's own rtId is the scope (direct keying).
8248
+ * - No {@link EntitySelectorChildScope}: the picked entity's own rtId is the
8249
+ * scope (direct keying).
8250
+ * - One-hop form (top-level fields): the picked entity's targets of
8251
+ * `targetCkTypeId` reached via `roleId`/`direction` (e.g. MeteringPoint →
8252
+ * its EnergyMeasurement rtIds) — exactly as before AB#7723.
8253
+ * - `path` (AB#7723): hop by hop, each hop one batched request over all
8254
+ * entities the previous hop reached; the scope is the distinct rtIds of the
8255
+ * last hop. An empty hop ends the resolution with an empty scope; a failed
8256
+ * hop, or an invalid path (more than 5 hops, a hop without role or target
8257
+ * type), is a failed scope (AB#7721).
7208
8258
  */
7209
8259
  private resolveEntitySelectorScopeRtIds;
7210
8260
  /**
@@ -7219,6 +8269,8 @@ declare class MeshBoardViewComponent implements OnInit, OnDestroy, HasUnsavedCha
7219
8269
  * Format: es_<selectorId>=<rtId>
7220
8270
  */
7221
8271
  private writeEntitySelectorsToUrl;
8272
+ /** The `es_<selectorId>` query parameters of the current picks (`null` = remove). */
8273
+ private entitySelectorUrlParams;
7222
8274
  /**
7223
8275
  * Reads entity selector selections from URL query parameters.
7224
8276
  * Returns a map of selectorId -> rtId.
@@ -7235,7 +8287,7 @@ declare class MeshBoardViewComponent implements OnInit, OnDestroy, HasUnsavedCha
7235
8287
  */
7236
8288
  saveChanges(): Promise<boolean>;
7237
8289
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MeshBoardViewComponent, never>;
7238
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MeshBoardViewComponent, "mm-meshboard-view", never, { "headerMode": { "alias": "headerMode"; "required": false; "isSignal": true; }; "chrome": { "alias": "chrome"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.UnsavedChangesDirective; inputs: {}; outputs: {}; }]>;
8290
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MeshBoardViewComponent, "mm-meshboard-view", never, { "headerMode": { "alias": "headerMode"; "required": false; "isSignal": true; }; "chrome": { "alias": "chrome"; "required": false; "isSignal": true; }; "timeRange": { "alias": "timeRange"; "required": false; "isSignal": true; }; "timeFilterControl": { "alias": "timeFilterControl"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.UnsavedChangesDirective; inputs: {}; outputs: {}; }]>;
7239
8291
  }
7240
8292
 
7241
8293
  /**
@@ -9097,5 +10149,5 @@ declare function pipelineExecutionInputs(children: (unknown | null)[] | null | u
9097
10149
  */
9098
10150
  declare function countPipelineExecutions(pipelines: PipelineExecutionInput[], now?: number): PipelineExecutionCounts;
9099
10151
 
9100
- export { ADAPTER_OFFLINE_GRACE_MS, ATTENTION_SEVERITY_ORDER, AdaptersAttentionProvider, AddWidgetDialogComponent, AiInsightsConfigDialogComponent, AiInsightsService, AiInsightsWidgetComponent, AlertBannerConfigDialogComponent, AlertBannerWidgetComponent, AlertListConfigDialogComponent, AlertListWidgetComponent, AssociationsConfigDialogComponent, AttentionListConfigDialogComponent, AttentionListWidgetComponent, AutoRefreshTimerService, BUILT_IN_ATTENTION_PROVIDERS, BarChartConfigDialogComponent, BarChartWidgetComponent, BlueprintUpdatesAttentionProvider, COCKPIT_ADAPTER_LIMIT, COCKPIT_ATTENTION_PROVIDERS, COCKPIT_BLUEPRINT_CATALOG_LIMIT, COCKPIT_CHILD_TENANT_IDS, COCKPIT_DATA_FLOW_LIMIT, COCKPIT_EXPLAIN_HANDLER, COCKPIT_FAILED_EXECUTIONS_OPTIONS, COCKPIT_KPI_GATES, COCKPIT_KPI_SLOW_LOADING_MS, COCKPIT_LINK_RESOLVER, COCKPIT_RECENT_ITEMS, COCKPIT_ROLES, COCKPIT_SERVICE_NAMES, COCKPIT_VERSION_SOURCE, COCKPIT_VIEWER_ACCESS, COCKPIT_WIDGET_MESSAGES, COCKPIT_WIDGET_TYPES, CkModelsResolveFailedAttentionProvider, CockpitAdapterStatesService, CockpitAttentionService, CockpitBlueprintStatusService, CockpitChildTenantsService, CockpitCkModelStatesService, CockpitContextService, CockpitDataFlowExecutionsService, CockpitKpiConfigDialogComponent, CockpitKpiService, CockpitKpiWidgetComponent, CockpitServiceHealthService, DAY_MS, DEFAULT_ATTENTION_MAX_ITEMS, DEFAULT_COCKPIT_WIDGET_MESSAGES, DEFAULT_FAILED_EXECUTIONS_OPTIONS, DEFAULT_MESHBOARD_MESSAGES, DEFAULT_RECENT_ITEMS_MAX, DEFAULT_TIME_ZONE_MODE, DashboardDataService, DashboardGridService, EditModeStateService, EditWidgetDialogComponent, EntityAssociationsWidgetComponent, EntityCardConfigDialogComponent, EntityCardWidgetComponent, EntityDetailDialogComponent, EntitySelectorEditorComponent, EntitySelectorToolbarComponent, FALLBACK_SERIES_COLORS, FailedExecutionsAttentionProvider, FeaturesNotInstalledAttentionProvider, GaugeConfigDialogComponent, GaugeWidgetComponent, HISTOGRAM_HOURS, HOUR_MS, HeatmapConfigDialogComponent, HeatmapWidgetComponent, KPI_ERROR_TEXT, KpiConfigDialogComponent, KpiWidgetComponent, LazyMarkdownComponent, LineChartConfigDialogComponent, LineChartWidgetComponent, MAX_RECENT_ITEMS, MESHBOARD_CHROME_ROUTE_DATA, MESHBOARD_DESCRIPTION_MARKER, MESHBOARD_EDIT_QUERY_PARAM, MESHBOARD_HEADER_MODE_ROUTE_DATA, MESHBOARD_LABEL_RESOLVER, MESHBOARD_MESSAGES, MESHBOARD_OPTIONS, MESHBOARD_TENANT_ID_PROVIDER, MarkdownConfigDialogComponent, MarkdownWidgetComponent, MeshBoardDataService, MeshBoardGridService, MeshBoardManagerDialogComponent, MeshBoardPersistenceService, MeshBoardSettingsDialogComponent, MeshBoardSettingsResult, MeshBoardStateService, MeshBoardViewComponent, NOT_AVAILABLE_TEXT, PieChartConfigDialogComponent, PieChartWidgetComponent, QueryExecutorService, QuerySelectorComponent, RecentItemsConfigDialogComponent, RecentItemsWidgetComponent, RuntimeEntitySelectorComponent, SERVICE_MANAGED_BLUEPRINT_PREFIX, STATE_STATUS_BY_KEY, ServiceHealthConfigDialogComponent, ServiceHealthWidgetComponent, ServicesHealthAttentionProvider, StatsGridConfigDialogComponent, StatsGridWidgetComponent, StatusIndicatorConfigDialogComponent, StatusIndicatorWidgetComponent, StatusListConfigDialogComponent, StatusListWidgetComponent, SummaryCardConfigDialogComponent, SummaryCardWidgetComponent, TableConfigDialogComponent, TableWidgetComponent, TableWidgetDataSourceDirective, UnregisteredPoolsAttentionProvider, WidgetFactoryService, WidgetGroupComponent, WidgetGroupConfigDialogComponent, WidgetNotConfiguredComponent, WidgetRegistryService, adapterKpi, adaptersInError, adaptersOffline, blueprintUpdatesKpi, buildHourlyHistogram, categoryStatus, chartSeriesColors, ckModelKpi, classifyQuery, compareBlueprintVersions, compareMeshBoardNavigation, countFlowExecutions, countLabel, countPipelineExecutions, emptyQueryExecutionResult, enabledButNotInstalled, executionKpi, failedExecutionsSeverity, formatCockpitMessage, formatCount, humanizeCategory, isAdapterAtRest, isAdapterExpectedToRun, isAdapterOnline, isCockpitWidgetType, isMeshBoardChrome, isMeshBoardHeaderMode, isServiceConfigured, joinEncodedDescription, kpiKindOf, latestStatisticsUpdate, legacyCockpitLinkTarget, loadNgxMarkdown, nameList, newMeshBoardConfig, normalizeNavigation, observeThemeChanges, pipelineExecutionInputs, plural, provideCockpitWidgetHost, provideCockpitWidgets, provideDefaultWidgets, provideMeshBoard, provideMeshBoardMessages, provideProcessWidget, provideWidgetRegistrations, queryFamily, readMeshBoardNavigation, recentRelativeTime, registerCockpitWidgets, registerDefaultWidgets, registerProcessWidget, resolveChartColor, resolveCockpitWidgetMessages, resolveMeshBoardChrome, resolveMeshBoardHeaderMode, resolveMeshBoardLabel, resolveMeshBoardMessages, selectProviders, serviceStateText, servicesHealthKpi, sortAttentionFindings, sparklineGeometry, splitBlueprintId, splitEncodedDescription, statusColor, summarizeAdapterOnline, tenantCountKpi, toBlueprintStatus, toServiceHealthStatus, truncationNote, versionKpi, withMeshBoardNavigation };
9101
- export type { AdapterOnlineFields, AdapterOnlineSummary, AdapterStatusWidgetConfig, AggregationDataSource, AggregationQuery, AggregationType, AiInsightsConfigResult, AiInsightsWidgetConfig, AlertBannerConfigResult, AlertBannerWidgetConfig, AlertListConfigResult, AlertListWidgetConfig, AnyWidgetConfig, AssociationsConfigResult, AttentionContext, AttentionFinding, AttentionLink, AttentionListConfigResult, AttentionListWidgetConfig, AttentionProvider, AttentionProviderInfo, AttentionSeverity, AttentionState, BarChartColorThreshold, BarChartConfigResult, BarChartSeries, BarChartType, BarChartWidgetConfig, BaseWidgetConfig, BlueprintUpdatesWidgetConfig, CategoryStatus, CategoryValueItem, ChartReferenceLine, CkModelStateWidgetConfig, CkQueryResult, CkQueryTarget, CkTypeAttributeInfo, CockpitAdapterState, CockpitAdapterStates, CockpitBlueprintStatus, CockpitBlueprintUpdate, CockpitChildTenants, CockpitCkModelCounts, CockpitDataFlowExecutions, CockpitDataFlowRow, CockpitExecutionCounts, CockpitExplainHandler, CockpitExplainTarget, CockpitKpi, CockpitKpiConfigResult, CockpitKpiKind, CockpitKpiResult, CockpitKpiStatus, CockpitKpiWidgetConfig, CockpitKpiWidgetOptions, CockpitLinkQueryParams, CockpitLinkResolver, CockpitLinkTarget, CockpitRecentItem, CockpitRecentItemKind, CockpitRecentItemsSource, CockpitResolvedLink, CockpitRouteLinkTarget, CockpitServiceHealth, CockpitServiceHealthStatus, CockpitServiceKey, CockpitVersionEntry, CockpitVersionSource, CockpitViewerAccess, CockpitWidgetHost, CockpitWidgetMessages, CockpitWidgetMessagesSource, CockpitWidgetType, ConfigDialogResult, ConfigResultApplier, ConstructionKitQueryDataSource, DashboardConfig, DashboardWidget, DataSource, DataSourceType, DiagramPropertyMapping, EncodedDescription, EntityAssociation, EntityAttribute, EntityCardConfigResult, EntityCardWidgetConfig, EntityListWidget, EntitySelectorAttributeMapping, EntitySelectorChildScope, EntitySelectorClearEvent, EntitySelectorConfig, EntitySelectorEvent, EntitySelectorScopeState, EntityWidget, EntityWithAssociationsWidgetConfig, FailedExecutionsAttentionOptions, GaugeConfigResult, GaugeRange, GaugeType, GaugeWidgetConfig, GridCell, GridPosition, GroupChildWidgetType, GroupedDataItem, HeatmapAggregation, HeatmapColorMode, HeatmapColorScheme, HeatmapConfigResult, HeatmapWidgetConfig, HourlyExecutionBucket, HourlyHistogramOptions, KpiConfigResult, KpiDataSourceType, KpiQueryMode, KpiValueMode, KpiWidgetConfig, LatestExecutionInput, LineChartConfigResult, LineChartType, LineChartWidgetConfig, MarkdownConfigResult, MarkdownTextAlign, MarkdownWidgetConfig, MeshBoardChrome, MeshBoardConfig, MeshBoardHeaderMode, MeshBoardLabelKind, MeshBoardLabelRequest, MeshBoardLabelResolver, MeshBoardMessages, MeshBoardMessagesSource, MeshBoardNavigationConfig, MeshBoardOptions, MeshBoardTimeFilterConfig, MeshBoardTimeZoneMode, MeshBoardVariable, MeshBoardVariableSource, MeshBoardVariableType, ParentAssociationMode, PersistedDashboard, PersistedMeshBoard, PersistedWidget, PersistedWidgetData, PersistentQueryCellMode, PersistentQueryCellSource, PersistentQueryDataSource, PersistentQueryItem, PieChartConfigResult, PieChartLabelPosition, PieChartType, PieChartWidgetConfig, PipelineExecutionCounts, PipelineExecutionInput, PipelineExecutionsWidgetConfig, PipelineStatisticsInput, ProcessWidgetConfig, Quarter, QueryCell, QueryClassification, QueryColumn, QueryColumnInfo, QueryColumnItem, QueryExecutionOptions, QueryExecutionResult, QueryFamily, QueryKind, QueryResultRow, RawHourBucket, RecentItemsConfigResult, RecentItemsWidgetConfig, RelativeTimeUnit, RepeaterDataItem, RepeaterQueryDataSource, RuntimeEntityData, RuntimeEntityDataSource, RuntimeEntitySelectorValue, SeriesAggregationFunction, SeriesResolutionResult, ServiceCallDataSource, ServiceCallType, ServiceHealthConfigResult, ServiceHealthWidgetConfig, ServicesHealthWidgetConfig, SparklineGeometry, StatColor, StatItem, StaticDataSource, StatsGridConfigResult, StatsGridWidgetConfig, StatusIndicatorConfigResult, StatusIndicatorWidgetConfig, StatusListConfigResult, StatusListWidgetConfig, StreamDataExecutionArgs, StreamDataScope, SummaryCardConfigResult, SummaryCardTile, SummaryCardWidgetConfig, TableColumn, TableColumnStatusIconMapping, TableConfigResult, TableFilterConfig, TableSortConfig, TableWidgetConfig, TargetEntityWithAttributes, TenantCountWidgetConfig, TimeRangePickerConfig, TimeRangeSelection, TimeRangeType, UpdateDashboardResult, VariableResolutionError, VersionInfoWidgetConfig, WidgetConfig, WidgetConfigDialog, WidgetConfigDialogSize, WidgetConfigResult, WidgetCreationOptions, WidgetDataSource, WidgetFilterConfig, WidgetGroupAttributeMappings, WidgetGroupChildTemplate, WidgetGroupConfig, WidgetGroupConfigResult, WidgetGroupLayout, WidgetPersistenceData, WidgetPositionUpdate, WidgetRegistration, WidgetType, WidgetZone };
10152
+ export { ADAPTER_OFFLINE_GRACE_MS, ASSOCIATION_HOP_SOURCE_BATCH, ASSOCIATION_HOP_TARGETS_PER_SOURCE, ATTENTION_SEVERITY_ORDER, AdaptersAttentionProvider, AddWidgetDialogComponent, AiInsightsConfigDialogComponent, AiInsightsService, AiInsightsWidgetComponent, AlertBannerConfigDialogComponent, AlertBannerWidgetComponent, AlertListConfigDialogComponent, AlertListWidgetComponent, AssociationsConfigDialogComponent, AttentionListConfigDialogComponent, AttentionListWidgetComponent, AutoRefreshTimerService, BUILT_IN_ATTENTION_PROVIDERS, BarChartConfigDialogComponent, BarChartWidgetComponent, BlueprintUpdatesAttentionProvider, COCKPIT_ADAPTER_LIMIT, COCKPIT_ATTENTION_PROVIDERS, COCKPIT_BLUEPRINT_CATALOG_LIMIT, COCKPIT_CHILD_TENANT_IDS, COCKPIT_DATA_FLOW_LIMIT, COCKPIT_EXPLAIN_HANDLER, COCKPIT_FAILED_EXECUTIONS_OPTIONS, COCKPIT_KPI_GATES, COCKPIT_KPI_SLOW_LOADING_MS, COCKPIT_LINK_RESOLVER, COCKPIT_RECENT_ITEMS, COCKPIT_ROLES, COCKPIT_SERVICE_NAMES, COCKPIT_VERSION_SOURCE, COCKPIT_VIEWER_ACCESS, COCKPIT_WIDGET_MESSAGES, COCKPIT_WIDGET_TYPES, CkModelsResolveFailedAttentionProvider, CockpitAdapterStatesService, CockpitAttentionService, CockpitBlueprintStatusService, CockpitChildTenantsService, CockpitCkModelStatesService, CockpitContextService, CockpitDataFlowExecutionsService, CockpitKpiConfigDialogComponent, CockpitKpiService, CockpitKpiWidgetComponent, CockpitServiceHealthService, DAY_MS, DEFAULT_ATTENTION_MAX_ITEMS, DEFAULT_COCKPIT_WIDGET_MESSAGES, DEFAULT_FAILED_EXECUTIONS_OPTIONS, DEFAULT_MESHBOARD_MESSAGES, DEFAULT_RECENT_ITEMS_MAX, DEFAULT_TIME_ZONE_MODE, DashboardDataService, DashboardGridService, EditModeStateService, EditWidgetDialogComponent, EntityAssociationsWidgetComponent, EntityCardConfigDialogComponent, EntityCardWidgetComponent, EntityDetailDialogComponent, EntitySelectorEditorComponent, EntitySelectorScopePathEditorComponent, EntitySelectorToolbarComponent, FALLBACK_SERIES_COLORS, FailedExecutionsAttentionProvider, FeaturesNotInstalledAttentionProvider, FormulaFieldComponent, GaugeConfigDialogComponent, GaugeWidgetComponent, HISTOGRAM_HOURS, HOUR_MS, HeatmapConfigDialogComponent, HeatmapWidgetComponent, KPI_ERROR_TEXT, KpiConfigDialogComponent, KpiWidgetComponent, LazyMarkdownComponent, LineChartConfigDialogComponent, LineChartWidgetComponent, MAX_RECENT_ITEMS, MAX_SCOPE_HOPS, MESHBOARD_CHROME_ROUTE_DATA, MESHBOARD_DESCRIPTION_MARKER, MESHBOARD_EDIT_QUERY_PARAM, MESHBOARD_HEADER_MODE_ROUTE_DATA, MESHBOARD_LABEL_RESOLVER, MESHBOARD_LANGUAGE, MESHBOARD_MESSAGES, MESHBOARD_OPTIONS, MESHBOARD_TENANT_ID_PROVIDER, MarkdownConfigDialogComponent, MarkdownWidgetComponent, MeshBoardDataService, MeshBoardGridService, MeshBoardManagerDialogComponent, MeshBoardPersistenceService, MeshBoardSettingsDialogComponent, MeshBoardSettingsResult, MeshBoardStateService, MeshBoardViewComponent, NOT_AVAILABLE_TEXT, PieChartConfigDialogComponent, PieChartWidgetComponent, QueryExecutorService, QuerySelectorComponent, RecentItemsConfigDialogComponent, RecentItemsWidgetComponent, RuntimeEntitySelectorComponent, SERVICE_MANAGED_BLUEPRINT_PREFIX, STATE_STATUS_BY_KEY, ServiceHealthConfigDialogComponent, ServiceHealthWidgetComponent, ServicesHealthAttentionProvider, StatsGridConfigDialogComponent, StatsGridWidgetComponent, StatusIndicatorConfigDialogComponent, StatusIndicatorWidgetComponent, StatusListConfigDialogComponent, StatusListWidgetComponent, SummaryCardConfigDialogComponent, SummaryCardWidgetComponent, TableConfigDialogComponent, TableWidgetComponent, TableWidgetDataSourceDirective, UnregisteredPoolsAttentionProvider, WidgetFactoryService, WidgetGroupComponent, WidgetGroupConfigDialogComponent, WidgetNotConfiguredComponent, WidgetRegistryService, adapterKpi, adaptersInError, adaptersOffline, blueprintUpdatesKpi, buildHourlyHistogram, categoryStatus, chartSeriesColors, ckModelKpi, classifyQuery, compareBlueprintVersions, compareMeshBoardNavigation, countFlowExecutions, countLabel, countPipelineExecutions, emptyQueryExecutionResult, enabledButNotInstalled, executionKpi, failedExecutionsSeverity, formatCockpitMessage, formatCount, humanizeCategory, isAdapterAtRest, isAdapterExpectedToRun, isAdapterOnline, isCockpitWidgetType, isMeshBoardChrome, isMeshBoardHeaderMode, isServiceConfigured, joinEncodedDescription, kpiKindOf, latestStatisticsUpdate, legacyCockpitLinkTarget, loadNgxMarkdown, nameList, newMeshBoardConfig, normalizeNavigation, observeThemeChanges, parseHostTimeRange, pickLocalizedText, pipelineExecutionInputs, plural, provideCockpitWidgetHost, provideCockpitWidgets, provideDefaultWidgets, provideMeshBoard, provideMeshBoardLanguage, provideMeshBoardMessages, provideProcessWidget, provideWidgetRegistrations, queryFamily, readMeshBoardNavigation, recentRelativeTime, registerCockpitWidgets, registerDefaultWidgets, registerProcessWidget, resolveChartColor, resolveCockpitWidgetMessages, resolveMeshBoardChrome, resolveMeshBoardHeaderMode, resolveMeshBoardLabel, resolveMeshBoardMessages, selectProviders, serviceStateText, servicesHealthKpi, sortAttentionFindings, sparklineGeometry, splitBlueprintId, splitEncodedDescription, statusColor, summarizeAdapterOnline, tenantCountKpi, toBlueprintStatus, toServiceHealthStatus, truncationNote, versionKpi, withMeshBoardNavigation };
10153
+ export type { AdapterOnlineFields, AdapterOnlineSummary, AdapterStatusWidgetConfig, AggregationDataSource, AggregationQuery, AggregationType, AiInsightsConfigResult, AiInsightsWidgetConfig, AlertBannerConfigResult, AlertBannerWidgetConfig, AlertListConfigResult, AlertListWidgetConfig, AnyWidgetConfig, AssociationsConfigResult, AttentionContext, AttentionFinding, AttentionLink, AttentionListConfigResult, AttentionListWidgetConfig, AttentionProvider, AttentionProviderInfo, AttentionSeverity, AttentionState, BarChartColorThreshold, BarChartConfigResult, BarChartSeries, BarChartType, BarChartWidgetConfig, BaseWidgetConfig, BlueprintUpdatesWidgetConfig, CategoryStatus, CategoryValueItem, ChartReferenceLine, CkModelStateWidgetConfig, CkQueryResult, CkQueryTarget, CkTypeAttributeInfo, CockpitAdapterState, CockpitAdapterStates, CockpitBlueprintStatus, CockpitBlueprintUpdate, CockpitChildTenants, CockpitCkModelCounts, CockpitDataFlowExecutions, CockpitDataFlowRow, CockpitExecutionCounts, CockpitExplainHandler, CockpitExplainTarget, CockpitKpi, CockpitKpiConfigResult, CockpitKpiKind, CockpitKpiResult, CockpitKpiStatus, CockpitKpiWidgetConfig, CockpitKpiWidgetOptions, CockpitLinkQueryParams, CockpitLinkResolver, CockpitLinkTarget, CockpitRecentItem, CockpitRecentItemKind, CockpitRecentItemsSource, CockpitResolvedLink, CockpitRouteLinkTarget, CockpitServiceHealth, CockpitServiceHealthStatus, CockpitServiceKey, CockpitVersionEntry, CockpitVersionSource, CockpitViewerAccess, CockpitWidgetHost, CockpitWidgetMessages, CockpitWidgetMessagesSource, CockpitWidgetType, ConfigDialogResult, ConfigResultApplier, ConstructionKitQueryDataSource, DashboardConfig, DashboardWidget, DataSource, DataSourceType, DiagramPropertyMapping, EncodedDescription, EntityAssociation, EntityAttribute, EntityCardConfigResult, EntityCardWidgetConfig, EntityListWidget, EntitySelectorAttributeMapping, EntitySelectorChildScope, EntitySelectorClearEvent, EntitySelectorConfig, EntitySelectorEvent, EntitySelectorScopeHop, EntitySelectorScopeSource, EntitySelectorScopeState, EntityWidget, EntityWithAssociationsWidgetConfig, FailedExecutionsAttentionOptions, GaugeConfigResult, GaugeRange, GaugeType, GaugeWidgetConfig, GridCell, GridPosition, GroupChildWidgetType, GroupedDataItem, HeatmapAggregation, HeatmapColorMode, HeatmapColorScheme, HeatmapConfigResult, HeatmapTimeWindow, HeatmapWidgetConfig, HostTimeRangeState, HourlyExecutionBucket, HourlyHistogramOptions, KpiConfigResult, KpiDataSourceType, KpiQueryMode, KpiValueMode, KpiWidgetConfig, LatestExecutionInput, LineChartConfigResult, LineChartType, LineChartWidgetConfig, MarkdownConfigResult, MarkdownTextAlign, MarkdownWidgetConfig, MeshBoardChrome, MeshBoardConfig, MeshBoardHeaderMode, MeshBoardHostTimeRange, MeshBoardLabelKind, MeshBoardLabelRequest, MeshBoardLabelResolver, MeshBoardLanguageSource, MeshBoardMessages, MeshBoardMessagesSource, MeshBoardNavigationConfig, MeshBoardOptions, MeshBoardTimeFilterConfig, MeshBoardTimeFilterControl, MeshBoardTimeZoneMode, MeshBoardVariable, MeshBoardVariableSource, MeshBoardVariableType, ParentAssociationMode, PersistedDashboard, PersistedMeshBoard, PersistedWidget, PersistedWidgetData, PersistentQueryCellMode, PersistentQueryCellSource, PersistentQueryDataSource, PersistentQueryItem, PieChartConfigResult, PieChartLabelPosition, PieChartType, PieChartWidgetConfig, PipelineExecutionCounts, PipelineExecutionInput, PipelineExecutionsWidgetConfig, PipelineStatisticsInput, ProcessWidgetConfig, Quarter, QueryCell, QueryClassification, QueryColumn, QueryColumnInfo, QueryColumnItem, QueryExecutionOptions, QueryExecutionResult, QueryFamily, QueryKind, QueryResultRow, RawHourBucket, RecentItemsConfigResult, RecentItemsWidgetConfig, RelativeTimeUnit, RepeaterDataItem, RepeaterQueryDataSource, RuntimeEntityData, RuntimeEntityDataSource, RuntimeEntitySelectorValue, SeriesAggregationFunction, SeriesResolutionResult, ServiceCallDataSource, ServiceCallType, ServiceHealthConfigResult, ServiceHealthWidgetConfig, ServicesHealthWidgetConfig, SparklineGeometry, StatColor, StatItem, StaticDataSource, StatsGridConfigResult, StatsGridWidgetConfig, StatusIndicatorConfigResult, StatusIndicatorWidgetConfig, StatusListConfigResult, StatusListWidgetConfig, StreamDataExecutionArgs, StreamDataScope, SummaryCardConfigResult, SummaryCardTile, SummaryCardWidgetConfig, TableColumn, TableColumnStatusIconMapping, TableColumnValueLabel, TableConfigResult, TableFilterConfig, TableSortConfig, TableWidgetConfig, TargetEntityWithAttributes, TenantCountWidgetConfig, TimeRangePickerConfig, TimeRangeSelection, TimeRangeType, UpdateDashboardResult, VariableResolutionError, VersionInfoWidgetConfig, WidgetConfig, WidgetConfigDialog, WidgetConfigDialogSize, WidgetConfigResult, WidgetCreationOptions, WidgetDataSource, WidgetFilterConfig, WidgetGroupAttributeMappings, WidgetGroupChildTemplate, WidgetGroupConfig, WidgetGroupConfigResult, WidgetGroupLayout, WidgetPersistenceData, WidgetPositionUpdate, WidgetRegistration, WidgetType, WidgetZone };