@meshmakers/octo-meshboard 3.4.190 → 3.4.210
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FieldFilterOperatorsDto, CkTypeSelectorService, RuntimeEntitySelectDataSource as RuntimeEntitySelectDataSource$2, RuntimeEntityDialogDataSource as RuntimeEntityDialogDataSource$2, DeleteStrategiesDto, AssociationModOptionsDto, CkModelService, QueryModeDto, GraphDirectionDto, AttributeSelectorService, GraphQL, GetCkTypeAvailableQueryColumnsDtoGQL, SortOrdersDto, HealthService, TENANT_ID_PROVIDER, AssetRepoService, JobManagementService } from '@meshmakers/octo-services';
|
|
2
2
|
export { RuntimeEntityDialogDataSource, RuntimeEntitySelectDataSource, TENANT_ID_PROVIDER } from '@meshmakers/octo-services';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { Injectable, inject, EventEmitter, forwardRef, Output, Input, ViewChild, ChangeDetectionStrategy, Component, Injector, EnvironmentInjector, ApplicationRef, signal, computed, Directive, makeEnvironmentProviders, provideAppInitializer, InjectionToken, effect } from '@angular/core';
|
|
4
|
+
import { Injectable, inject, EventEmitter, forwardRef, Output, Input, ViewChild, ChangeDetectionStrategy, Component, Injector, EnvironmentInjector, ApplicationRef, signal, computed, Directive, ElementRef, NgZone, makeEnvironmentProviders, provideAppInitializer, InjectionToken, effect } from '@angular/core';
|
|
5
5
|
import * as i1$1 from '@angular/forms';
|
|
6
6
|
import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
|
|
7
7
|
import { firstValueFrom, from, map, Observable, of, catchError, interval, filter } from 'rxjs';
|
|
@@ -1761,7 +1761,8 @@ class MeshBoardPersistenceService {
|
|
|
1761
1761
|
ckTypeId: es.ckTypeId,
|
|
1762
1762
|
attributeMappings: es.attributeMappings,
|
|
1763
1763
|
showInToolbar: es.showInToolbar,
|
|
1764
|
-
defaultRtId: es.defaultRtId
|
|
1764
|
+
defaultRtId: es.defaultRtId,
|
|
1765
|
+
childScope: es.childScope
|
|
1765
1766
|
}));
|
|
1766
1767
|
}
|
|
1767
1768
|
const dataJson = JSON.stringify(data);
|
|
@@ -2001,6 +2002,14 @@ class MeshBoardStateService {
|
|
|
2001
2002
|
...(ngDevMode ? [{ debugName: "_isModelAvailable" }] : /* istanbul ignore next */ []));
|
|
2002
2003
|
_variableResolutionErrors = signal([], /* @ts-ignore */
|
|
2003
2004
|
...(ngDevMode ? [{ debugName: "_variableResolutionErrors" }] : /* istanbul ignore next */ []));
|
|
2005
|
+
/**
|
|
2006
|
+
* Transient cache of the source rtIds resolved from each entity selector's
|
|
2007
|
+
* current selection (keyed by selector id). Populated by the view component
|
|
2008
|
+
* when a selection resolves (one-hop childScope traversal, or the picked
|
|
2009
|
+
* entity's own rtId). Not persisted — derived fresh from each selection.
|
|
2010
|
+
*/
|
|
2011
|
+
_entitySelectorRtIds = signal({}, /* @ts-ignore */
|
|
2012
|
+
...(ngDevMode ? [{ debugName: "_entitySelectorRtIds" }] : /* istanbul ignore next */ []));
|
|
2004
2013
|
// Public computed signals
|
|
2005
2014
|
meshBoardConfig = computed(() => this._meshBoardConfig(), /* @ts-ignore */
|
|
2006
2015
|
...(ngDevMode ? [{ debugName: "meshBoardConfig" }] : /* istanbul ignore next */ []));
|
|
@@ -2504,6 +2513,42 @@ class MeshBoardStateService {
|
|
|
2504
2513
|
}
|
|
2505
2514
|
return { from: range.from, to: range.to };
|
|
2506
2515
|
}
|
|
2516
|
+
/**
|
|
2517
|
+
* Stores the source rtIds resolved from an entity selector's current
|
|
2518
|
+
* selection. Called by the view component after a selection resolves (the
|
|
2519
|
+
* one-hop childScope traversal, or the picked entity's own rtId when the
|
|
2520
|
+
* selector has no childScope). Transient — not persisted.
|
|
2521
|
+
*/
|
|
2522
|
+
setEntitySelectorRtIds(selectorId, rtIds) {
|
|
2523
|
+
this._entitySelectorRtIds.update(map => ({ ...map, [selectorId]: rtIds }));
|
|
2524
|
+
}
|
|
2525
|
+
/**
|
|
2526
|
+
* Clears the cached source rtIds for an entity selector (e.g. when its
|
|
2527
|
+
* selection is cleared).
|
|
2528
|
+
*/
|
|
2529
|
+
clearEntitySelectorRtIds(selectorId) {
|
|
2530
|
+
this._entitySelectorRtIds.update(map => {
|
|
2531
|
+
if (!(selectorId in map)) {
|
|
2532
|
+
return map;
|
|
2533
|
+
}
|
|
2534
|
+
const next = { ...map };
|
|
2535
|
+
delete next[selectorId];
|
|
2536
|
+
return next;
|
|
2537
|
+
});
|
|
2538
|
+
}
|
|
2539
|
+
/**
|
|
2540
|
+
* Resolves the stream-data `rtIds` scope for a persistent-query widget bound
|
|
2541
|
+
* to an entity selector. Returns the source rtIds cached from the selector's
|
|
2542
|
+
* current selection, or `undefined` when the selector id is absent, unknown,
|
|
2543
|
+
* or has no active selection (so the query keeps its persisted scope).
|
|
2544
|
+
*/
|
|
2545
|
+
resolveStreamDataRtIds(entitySelectorId) {
|
|
2546
|
+
if (!entitySelectorId) {
|
|
2547
|
+
return undefined;
|
|
2548
|
+
}
|
|
2549
|
+
const rtIds = this._entitySelectorRtIds()[entitySelectorId];
|
|
2550
|
+
return rtIds && rtIds.length > 0 ? rtIds : undefined;
|
|
2551
|
+
}
|
|
2507
2552
|
/**
|
|
2508
2553
|
* Updates the time filter configuration.
|
|
2509
2554
|
*/
|
|
@@ -2945,7 +2990,8 @@ class QueryExecutorService {
|
|
|
2945
2990
|
// Skip the entire `arg` field when the caller has nothing to override —
|
|
2946
2991
|
// the persisted query then runs with its intrinsic from/to/limit and the
|
|
2947
2992
|
// GraphQL request stays minimal.
|
|
2948
|
-
const
|
|
2993
|
+
const hasRtIds = args.rtIds != null && args.rtIds.length > 0;
|
|
2994
|
+
const hasOverride = args.from != null || args.to != null || args.interval != null || args.limit != null || args.queryMode != null || hasRtIds;
|
|
2949
2995
|
if (!hasOverride) {
|
|
2950
2996
|
return undefined;
|
|
2951
2997
|
}
|
|
@@ -2957,6 +3003,7 @@ class QueryExecutorService {
|
|
|
2957
3003
|
to: args.to ?? undefined,
|
|
2958
3004
|
interval: args.interval ?? undefined,
|
|
2959
3005
|
limit: args.limit ?? undefined,
|
|
3006
|
+
rtIds: hasRtIds ? args.rtIds : undefined,
|
|
2960
3007
|
queryMode: args.queryMode ?? QueryModeDto.DefaultDto
|
|
2961
3008
|
};
|
|
2962
3009
|
}
|
|
@@ -3633,7 +3680,10 @@ class MeshBoardDataService {
|
|
|
3633
3680
|
roleId,
|
|
3634
3681
|
direction: graphDirection,
|
|
3635
3682
|
first: first ?? 100,
|
|
3636
|
-
|
|
3683
|
+
// The server's `attributes` resolver rejects a null attributeNames argument
|
|
3684
|
+
// (ARGUMENT_NULL); send an empty list when the caller doesn't need attributes
|
|
3685
|
+
// (e.g. childScope rtId resolution, which only reads rtId).
|
|
3686
|
+
attributeNames: attributeNames ?? []
|
|
3637
3687
|
}
|
|
3638
3688
|
}).pipe(map(result => {
|
|
3639
3689
|
const entity = result.data?.runtime?.runtimeEntities?.items?.[0];
|
|
@@ -5082,7 +5132,12 @@ class KpiWidgetComponent {
|
|
|
5082
5132
|
}
|
|
5083
5133
|
buildStreamDataArgs() {
|
|
5084
5134
|
const ds = this.config.dataSource;
|
|
5085
|
-
|
|
5135
|
+
const timeArgs = this.stateService.resolveStreamDataTimeArgs(ds.ignoreTimeFilter);
|
|
5136
|
+
const rtIds = this.stateService.resolveStreamDataRtIds(ds.entitySelectorId);
|
|
5137
|
+
if (!timeArgs && !rtIds) {
|
|
5138
|
+
return undefined;
|
|
5139
|
+
}
|
|
5140
|
+
return { ...timeArgs, rtIds };
|
|
5086
5141
|
}
|
|
5087
5142
|
extractAggregationValue(queryResult) {
|
|
5088
5143
|
const firstRow = queryResult.rows.find(row => KpiWidgetComponent.SUPPORTED_ROW_TYPES.has(row.__typename ?? ''));
|
|
@@ -5273,6 +5328,111 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
5273
5328
|
type: Output
|
|
5274
5329
|
}] } });
|
|
5275
5330
|
|
|
5331
|
+
/**
|
|
5332
|
+
* Per-widget asset-scope binding for stream-data persistent-query widgets.
|
|
5333
|
+
*
|
|
5334
|
+
* Stream-data archives are keyed by their source rtIds, so a widget is scoped
|
|
5335
|
+
* to a picked asset by passing those source rtIds as `streamDataArgs.rtIds`
|
|
5336
|
+
* (see `MeshBoardStateService.resolveStreamDataRtIds` and the backend
|
|
5337
|
+
* `StreamDataArguments.rtIds` override). This control lets the designer bind a
|
|
5338
|
+
* single widget to one of the MeshBoard's entity selectors: when the selector's
|
|
5339
|
+
* entity is picked, its resolved source rtIds (the selector's `childScope`
|
|
5340
|
+
* one-hop, or the picked entity itself) scope this widget's query.
|
|
5341
|
+
*
|
|
5342
|
+
* The control renders only when the selected query is a stream-data query
|
|
5343
|
+
* (`family === 'streamData'`); for runtime queries the binding has no effect and
|
|
5344
|
+
* the picker stays hidden (mirrors `SdTimeFilterToggleComponent`).
|
|
5345
|
+
*
|
|
5346
|
+
* Two-way bindable:
|
|
5347
|
+
* ```html
|
|
5348
|
+
* <mm-entity-selector-scope-picker
|
|
5349
|
+
* [family]="selectedQueryFamily"
|
|
5350
|
+
* [selectors]="availableEntitySelectors"
|
|
5351
|
+
* [(entitySelectorId)]="entitySelectorId">
|
|
5352
|
+
* </mm-entity-selector-scope-picker>
|
|
5353
|
+
* ```
|
|
5354
|
+
*/
|
|
5355
|
+
class EntitySelectorScopePickerComponent {
|
|
5356
|
+
/** Family of the currently selected query. Picker is shown only for 'streamData'. */
|
|
5357
|
+
family;
|
|
5358
|
+
/** Currently bound entity selector id (`undefined` ⇒ no binding). */
|
|
5359
|
+
entitySelectorId;
|
|
5360
|
+
/** Available entity selectors to choose from. */
|
|
5361
|
+
set selectors(value) {
|
|
5362
|
+
this._selectors = value ?? [];
|
|
5363
|
+
}
|
|
5364
|
+
get selectors() {
|
|
5365
|
+
return this._selectors;
|
|
5366
|
+
}
|
|
5367
|
+
_selectors = [];
|
|
5368
|
+
/** Emits on change (enables `[(entitySelectorId)]` two-way binding). */
|
|
5369
|
+
entitySelectorIdChange = new EventEmitter();
|
|
5370
|
+
get visible() {
|
|
5371
|
+
return this.family === 'streamData';
|
|
5372
|
+
}
|
|
5373
|
+
/** "None" row first, then one row per available selector. */
|
|
5374
|
+
get options() {
|
|
5375
|
+
return [
|
|
5376
|
+
{ label: '— None —', value: undefined },
|
|
5377
|
+
...this._selectors.map(s => ({ label: s.label || s.id, value: s.id }))
|
|
5378
|
+
];
|
|
5379
|
+
}
|
|
5380
|
+
onSelect(value) {
|
|
5381
|
+
this.entitySelectorId = value ?? undefined;
|
|
5382
|
+
this.entitySelectorIdChange.emit(this.entitySelectorId);
|
|
5383
|
+
}
|
|
5384
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: EntitySelectorScopePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5385
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: EntitySelectorScopePickerComponent, isStandalone: true, selector: "mm-entity-selector-scope-picker", inputs: { family: "family", entitySelectorId: "entitySelectorId", selectors: "selectors" }, outputs: { entitySelectorIdChange: "entitySelectorIdChange" }, ngImport: i0, template: `
|
|
5386
|
+
@if (visible) {
|
|
5387
|
+
<div class="form-field entity-selector-scope-picker">
|
|
5388
|
+
<label>Scope to entity selector</label>
|
|
5389
|
+
<kendo-dropdownlist
|
|
5390
|
+
[data]="options"
|
|
5391
|
+
textField="label"
|
|
5392
|
+
valueField="value"
|
|
5393
|
+
[valuePrimitive]="true"
|
|
5394
|
+
[ngModel]="entitySelectorId ?? null"
|
|
5395
|
+
(valueChange)="onSelect($event)">
|
|
5396
|
+
</kendo-dropdownlist>
|
|
5397
|
+
<p class="field-hint">
|
|
5398
|
+
Scopes this widget's stream-data query to the rtIds resolved from the
|
|
5399
|
+
selected asset. Leave unset to use the saved query's own scope.
|
|
5400
|
+
</p>
|
|
5401
|
+
</div>
|
|
5402
|
+
}
|
|
5403
|
+
`, isInline: true, styles: [".entity-selector-scope-picker .field-hint{font-size:.85em;margin-top:4px;opacity:.7}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
5404
|
+
}
|
|
5405
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: EntitySelectorScopePickerComponent, decorators: [{
|
|
5406
|
+
type: Component,
|
|
5407
|
+
args: [{ selector: 'mm-entity-selector-scope-picker', standalone: true, imports: [FormsModule, DropDownsModule], changeDetection: ChangeDetectionStrategy.Eager, template: `
|
|
5408
|
+
@if (visible) {
|
|
5409
|
+
<div class="form-field entity-selector-scope-picker">
|
|
5410
|
+
<label>Scope to entity selector</label>
|
|
5411
|
+
<kendo-dropdownlist
|
|
5412
|
+
[data]="options"
|
|
5413
|
+
textField="label"
|
|
5414
|
+
valueField="value"
|
|
5415
|
+
[valuePrimitive]="true"
|
|
5416
|
+
[ngModel]="entitySelectorId ?? null"
|
|
5417
|
+
(valueChange)="onSelect($event)">
|
|
5418
|
+
</kendo-dropdownlist>
|
|
5419
|
+
<p class="field-hint">
|
|
5420
|
+
Scopes this widget's stream-data query to the rtIds resolved from the
|
|
5421
|
+
selected asset. Leave unset to use the saved query's own scope.
|
|
5422
|
+
</p>
|
|
5423
|
+
</div>
|
|
5424
|
+
}
|
|
5425
|
+
`, styles: [".entity-selector-scope-picker .field-hint{font-size:.85em;margin-top:4px;opacity:.7}\n"] }]
|
|
5426
|
+
}], propDecorators: { family: [{
|
|
5427
|
+
type: Input
|
|
5428
|
+
}], entitySelectorId: [{
|
|
5429
|
+
type: Input
|
|
5430
|
+
}], selectors: [{
|
|
5431
|
+
type: Input
|
|
5432
|
+
}], entitySelectorIdChange: [{
|
|
5433
|
+
type: Output
|
|
5434
|
+
}] } });
|
|
5435
|
+
|
|
5276
5436
|
/**
|
|
5277
5437
|
* Configuration dialog for KPI widgets.
|
|
5278
5438
|
* Allows selecting data source, value attribute, and display options.
|
|
@@ -5313,6 +5473,7 @@ class KpiConfigDialogComponent {
|
|
|
5313
5473
|
initialQueryName;
|
|
5314
5474
|
initialQueryFamily;
|
|
5315
5475
|
initialIgnoreTimeFilter;
|
|
5476
|
+
initialEntitySelectorId;
|
|
5316
5477
|
initialQueryMode;
|
|
5317
5478
|
initialQueryValueField;
|
|
5318
5479
|
initialQueryCategoryField;
|
|
@@ -5334,6 +5495,7 @@ class KpiConfigDialogComponent {
|
|
|
5334
5495
|
selectedPersistentQuery = null;
|
|
5335
5496
|
/** Stream-data opt-out: when true the MeshBoard time filter is not bound to the query. */
|
|
5336
5497
|
ignoreTimeFilter = false;
|
|
5498
|
+
entitySelectorId;
|
|
5337
5499
|
queryColumns = [];
|
|
5338
5500
|
categoryValues = [];
|
|
5339
5501
|
queryMode = 'simpleCount';
|
|
@@ -5341,6 +5503,10 @@ class KpiConfigDialogComponent {
|
|
|
5341
5503
|
get selectedQueryFamily() {
|
|
5342
5504
|
return queryFamily(this.selectedPersistentQuery?.ckTypeId) ?? this.initialQueryFamily ?? null;
|
|
5343
5505
|
}
|
|
5506
|
+
/** Entity selectors available on the current MeshBoard (for the scope picker). */
|
|
5507
|
+
get availableEntitySelectors() {
|
|
5508
|
+
return this.meshBoardStateService.getEntitySelectors();
|
|
5509
|
+
}
|
|
5344
5510
|
isLoadingQueryColumns = false;
|
|
5345
5511
|
isLoadingCategoryValues = false;
|
|
5346
5512
|
// Attribute selection
|
|
@@ -5437,6 +5603,7 @@ class KpiConfigDialogComponent {
|
|
|
5437
5603
|
this.dataSourceType = this.initialDataSourceType || 'runtimeEntity';
|
|
5438
5604
|
this.queryMode = this.initialQueryMode || 'simpleCount';
|
|
5439
5605
|
this.ignoreTimeFilter = this.initialIgnoreTimeFilter ?? false;
|
|
5606
|
+
this.entitySelectorId = this.initialEntitySelectorId;
|
|
5440
5607
|
// Check if this is count mode (for runtime entity)
|
|
5441
5608
|
this.isCountMode = this.initialValueAttribute === '_count';
|
|
5442
5609
|
if (this.dataSourceType === 'persistentQuery' && this.initialQueryRtId) {
|
|
@@ -5607,6 +5774,7 @@ class KpiConfigDialogComponent {
|
|
|
5607
5774
|
queryName: this.selectedPersistentQuery.name,
|
|
5608
5775
|
queryFamily: family,
|
|
5609
5776
|
ignoreTimeFilter: this.ignoreTimeFilter,
|
|
5777
|
+
entitySelectorId: this.entitySelectorId,
|
|
5610
5778
|
queryMode: this.queryMode,
|
|
5611
5779
|
queryValueField: this.form.queryValueField || undefined,
|
|
5612
5780
|
queryCategoryField: this.form.queryCategoryField || undefined,
|
|
@@ -5771,7 +5939,7 @@ class KpiConfigDialogComponent {
|
|
|
5771
5939
|
this.filters = updatedFilters;
|
|
5772
5940
|
}
|
|
5773
5941
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: KpiConfigDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5774
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: KpiConfigDialogComponent, isStandalone: true, selector: "mm-kpi-config-dialog", inputs: { initialCkTypeId: "initialCkTypeId", initialRtId: "initialRtId", initialValueAttribute: "initialValueAttribute", initialLabelAttribute: "initialLabelAttribute", initialPrefix: "initialPrefix", initialSuffix: "initialSuffix", initialTrend: "initialTrend", initialComparisonText: "initialComparisonText", initialDataSourceType: "initialDataSourceType", initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialQueryMode: "initialQueryMode", initialQueryValueField: "initialQueryValueField", initialQueryCategoryField: "initialQueryCategoryField", initialQueryCategoryValue: "initialQueryCategoryValue", initialStaticValue: "initialStaticValue", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "ckTypeSelectorInput", first: true, predicate: ["ckTypeSelector"], descendants: true }, { propertyName: "entitySelectorInput", first: true, predicate: ["entitySelector"], descendants: true }, { propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
5942
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: KpiConfigDialogComponent, isStandalone: true, selector: "mm-kpi-config-dialog", inputs: { initialCkTypeId: "initialCkTypeId", initialRtId: "initialRtId", initialValueAttribute: "initialValueAttribute", initialLabelAttribute: "initialLabelAttribute", initialPrefix: "initialPrefix", initialSuffix: "initialSuffix", initialTrend: "initialTrend", initialComparisonText: "initialComparisonText", initialDataSourceType: "initialDataSourceType", initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialQueryMode: "initialQueryMode", initialQueryValueField: "initialQueryValueField", initialQueryCategoryField: "initialQueryCategoryField", initialQueryCategoryValue: "initialQueryCategoryValue", initialStaticValue: "initialStaticValue", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "ckTypeSelectorInput", first: true, predicate: ["ckTypeSelector"], descendants: true }, { propertyName: "entitySelectorInput", first: true, predicate: ["entitySelector"], descendants: true }, { propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
5775
5943
|
<div class="config-container">
|
|
5776
5944
|
|
|
5777
5945
|
<div class="config-form" [class.loading]="isLoadingInitial">
|
|
@@ -5952,6 +6120,12 @@ class KpiConfigDialogComponent {
|
|
|
5952
6120
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
5953
6121
|
</mm-sd-time-filter-toggle>
|
|
5954
6122
|
|
|
6123
|
+
<mm-entity-selector-scope-picker
|
|
6124
|
+
[family]="selectedQueryFamily"
|
|
6125
|
+
[selectors]="availableEntitySelectors"
|
|
6126
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
6127
|
+
</mm-entity-selector-scope-picker>
|
|
6128
|
+
|
|
5955
6129
|
<!-- Query Mode Selection -->
|
|
5956
6130
|
<div class="form-field">
|
|
5957
6131
|
<label>Query Mode</label>
|
|
@@ -6147,7 +6321,7 @@ class KpiConfigDialogComponent {
|
|
|
6147
6321
|
</button>
|
|
6148
6322
|
</div>
|
|
6149
6323
|
</div>
|
|
6150
|
-
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.form-field{display:flex;flex-direction:column;gap:6px}.form-field.disabled{opacity:.6}.form-field.flex-1{flex:1}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.form-section h4{margin:0 0 16px;font-size:.95rem;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-row{display:flex;gap:16px}.mode-toggle{display:flex;gap:8px}.mode-toggle button{flex:1}.attribute-item{display:flex;justify-content:space-between;align-items:center;gap:8px;width:100%}.attribute-path{flex:1}.attribute-type{font-size:.75rem;color:var(--kendo-color-subtle, #6c757d);background:var(--kendo-color-surface-alt, #f8f9fa);padding:2px 6px;border-radius:3px}.required{color:var(--kendo-color-error, #dc3545)}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "messages", "dialogMessages", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: EntitySelectInputComponent, selector: "mm-entity-select-input", inputs: ["dataSource", "placeholder", "minSearchLength", "maxResults", "debounceMs", "prefix", "initialDisplayValue", "dialogDataSource", "dialogTitle", "multiSelect", "advancedSearchLabel", "dialogMessages", "messages", "disabled", "required"], outputs: ["entitySelected", "entityCleared", "entitiesSelected"] }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
6324
|
+
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.form-field{display:flex;flex-direction:column;gap:6px}.form-field.disabled{opacity:.6}.form-field.flex-1{flex:1}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.form-section h4{margin:0 0 16px;font-size:.95rem;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-row{display:flex;gap:16px}.mode-toggle{display:flex;gap:8px}.mode-toggle button{flex:1}.attribute-item{display:flex;justify-content:space-between;align-items:center;gap:8px;width:100%}.attribute-path{flex:1}.attribute-type{font-size:.75rem;color:var(--kendo-color-subtle, #6c757d);background:var(--kendo-color-surface-alt, #f8f9fa);padding:2px 6px;border-radius:3px}.required{color:var(--kendo-color-error, #dc3545)}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "messages", "dialogMessages", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: EntitySelectInputComponent, selector: "mm-entity-select-input", inputs: ["dataSource", "placeholder", "minSearchLength", "maxResults", "debounceMs", "prefix", "initialDisplayValue", "dialogDataSource", "dialogTitle", "multiSelect", "advancedSearchLabel", "dialogMessages", "messages", "disabled", "required"], outputs: ["entitySelected", "entityCleared", "entitiesSelected"] }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
6151
6325
|
}
|
|
6152
6326
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: KpiConfigDialogComponent, decorators: [{
|
|
6153
6327
|
type: Component,
|
|
@@ -6162,6 +6336,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
6162
6336
|
FieldFilterEditorComponent,
|
|
6163
6337
|
QuerySelectorComponent,
|
|
6164
6338
|
SdTimeFilterToggleComponent,
|
|
6339
|
+
EntitySelectorScopePickerComponent,
|
|
6165
6340
|
LoadingOverlayComponent
|
|
6166
6341
|
], template: `
|
|
6167
6342
|
<div class="config-container">
|
|
@@ -6344,6 +6519,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
6344
6519
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
6345
6520
|
</mm-sd-time-filter-toggle>
|
|
6346
6521
|
|
|
6522
|
+
<mm-entity-selector-scope-picker
|
|
6523
|
+
[family]="selectedQueryFamily"
|
|
6524
|
+
[selectors]="availableEntitySelectors"
|
|
6525
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
6526
|
+
</mm-entity-selector-scope-picker>
|
|
6527
|
+
|
|
6347
6528
|
<!-- Query Mode Selection -->
|
|
6348
6529
|
<div class="form-field">
|
|
6349
6530
|
<label>Query Mode</label>
|
|
@@ -6575,6 +6756,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
6575
6756
|
type: Input
|
|
6576
6757
|
}], initialIgnoreTimeFilter: [{
|
|
6577
6758
|
type: Input
|
|
6759
|
+
}], initialEntitySelectorId: [{
|
|
6760
|
+
type: Input
|
|
6578
6761
|
}], initialQueryMode: [{
|
|
6579
6762
|
type: Input
|
|
6580
6763
|
}], initialQueryValueField: [{
|
|
@@ -8279,8 +8462,13 @@ class TableWidgetDataSourceDirective extends OctoGraphQlDataSource {
|
|
|
8279
8462
|
*/
|
|
8280
8463
|
buildStreamDataArgs() {
|
|
8281
8464
|
const ds = this._config?.dataSource;
|
|
8282
|
-
const
|
|
8283
|
-
|
|
8465
|
+
const isPersistentQuery = ds?.type === 'persistentQuery';
|
|
8466
|
+
const timeArgs = this.stateService.resolveStreamDataTimeArgs(isPersistentQuery ? ds.ignoreTimeFilter : undefined);
|
|
8467
|
+
const rtIds = this.stateService.resolveStreamDataRtIds(isPersistentQuery ? ds.entitySelectorId : undefined);
|
|
8468
|
+
if (!timeArgs && !rtIds) {
|
|
8469
|
+
return undefined;
|
|
8470
|
+
}
|
|
8471
|
+
return { ...timeArgs, rtIds };
|
|
8284
8472
|
}
|
|
8285
8473
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: TableWidgetDataSourceDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
8286
8474
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.2", type: TableWidgetDataSourceDirective, isStandalone: true, selector: "[mmTableWidgetDataSource]", inputs: { config: "config" }, outputs: { queryColumnsLoaded: "queryColumnsLoaded" }, providers: [
|
|
@@ -8525,6 +8713,7 @@ class TableConfigDialogComponent {
|
|
|
8525
8713
|
initialQueryName;
|
|
8526
8714
|
initialQueryFamily;
|
|
8527
8715
|
initialIgnoreTimeFilter;
|
|
8716
|
+
initialEntitySelectorId;
|
|
8528
8717
|
columnsIcon = columnsIcon;
|
|
8529
8718
|
sortIcon = sortAscIcon;
|
|
8530
8719
|
filterIcon = filterIcon;
|
|
@@ -8545,8 +8734,13 @@ class TableConfigDialogComponent {
|
|
|
8545
8734
|
// Query configuration
|
|
8546
8735
|
selectedPersistentQuery = null;
|
|
8547
8736
|
ignoreTimeFilter = false;
|
|
8737
|
+
entitySelectorId;
|
|
8548
8738
|
// Variables for filter editor
|
|
8549
8739
|
filterVariables = [];
|
|
8740
|
+
/** Entity selectors available on the current MeshBoard (for the scope picker). */
|
|
8741
|
+
get availableEntitySelectors() {
|
|
8742
|
+
return this.stateService.getEntitySelectors();
|
|
8743
|
+
}
|
|
8550
8744
|
form = {
|
|
8551
8745
|
pageSize: 10,
|
|
8552
8746
|
sortable: true
|
|
@@ -8576,6 +8770,7 @@ class TableConfigDialogComponent {
|
|
|
8576
8770
|
this.form.pageSize = this.initialPageSize ?? 10;
|
|
8577
8771
|
this.form.sortable = this.initialSortable ?? true;
|
|
8578
8772
|
this.ignoreTimeFilter = this.initialIgnoreTimeFilter ?? false;
|
|
8773
|
+
this.entitySelectorId = this.initialEntitySelectorId;
|
|
8579
8774
|
// Convert initial sorting from string-based format to SortDto
|
|
8580
8775
|
if (this.initialSorting) {
|
|
8581
8776
|
this.sorting = this.initialSorting.map(s => ({
|
|
@@ -8764,6 +8959,7 @@ class TableConfigDialogComponent {
|
|
|
8764
8959
|
queryName: this.selectedPersistentQuery.name,
|
|
8765
8960
|
queryFamily: family,
|
|
8766
8961
|
ignoreTimeFilter: this.ignoreTimeFilter,
|
|
8962
|
+
entitySelectorId: this.entitySelectorId,
|
|
8767
8963
|
pageSize: this.form.pageSize,
|
|
8768
8964
|
sortable: this.form.sortable
|
|
8769
8965
|
});
|
|
@@ -8780,7 +8976,7 @@ class TableConfigDialogComponent {
|
|
|
8780
8976
|
this.windowRef.close();
|
|
8781
8977
|
}
|
|
8782
8978
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: TableConfigDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8783
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: TableConfigDialogComponent, isStandalone: true, selector: "mm-table-config-dialog", inputs: { initialDataSourceType: "initialDataSourceType", initialCkTypeId: "initialCkTypeId", initialColumns: "initialColumns", initialSorting: "initialSorting", initialFilters: "initialFilters", initialPageSize: "initialPageSize", initialSortable: "initialSortable", initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter" }, providers: [
|
|
8979
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: TableConfigDialogComponent, isStandalone: true, selector: "mm-table-config-dialog", inputs: { initialDataSourceType: "initialDataSourceType", initialCkTypeId: "initialCkTypeId", initialColumns: "initialColumns", initialSorting: "initialSorting", initialFilters: "initialFilters", initialPageSize: "initialPageSize", initialSortable: "initialSortable", initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId" }, providers: [
|
|
8784
8980
|
AttributeSelectorDialogService,
|
|
8785
8981
|
AttributeSortSelectorDialogService
|
|
8786
8982
|
], viewQueries: [{ propertyName: "ckTypeSelectorInput", first: true, predicate: ["ckTypeSelector"], descendants: true }, { propertyName: "filterEditor", first: true, predicate: ["filterEditor"], descendants: true }, { propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
@@ -8905,6 +9101,12 @@ class TableConfigDialogComponent {
|
|
|
8905
9101
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
8906
9102
|
</mm-sd-time-filter-toggle>
|
|
8907
9103
|
|
|
9104
|
+
<mm-entity-selector-scope-picker
|
|
9105
|
+
[family]="selectedQueryFamily"
|
|
9106
|
+
[selectors]="availableEntitySelectors"
|
|
9107
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
9108
|
+
</mm-entity-selector-scope-picker>
|
|
9109
|
+
|
|
8908
9110
|
@if (selectedPersistentQuery) {
|
|
8909
9111
|
<div class="config-card">
|
|
8910
9112
|
<div class="card-header">
|
|
@@ -8988,7 +9190,7 @@ class TableConfigDialogComponent {
|
|
|
8988
9190
|
</button>
|
|
8989
9191
|
</div>
|
|
8990
9192
|
</div>
|
|
8991
|
-
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:16px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.form-field{display:flex;flex-direction:column;gap:6px}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.config-card{padding:12px 16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.card-header{display:flex;align-items:center;gap:8px;margin-bottom:8px}.card-header kendo-svgicon{color:var(--kendo-color-primary, #0d6efd)}.card-title{font-weight:600;font-size:.95rem;color:var(--kendo-color-primary, #0d6efd)}.card-count{color:var(--kendo-color-subtle, #6c757d);font-size:.85rem}.card-content{display:flex;align-items:center;justify-content:space-between;gap:16px}.config-summary{margin:0;font-size:.85rem;color:var(--kendo-color-on-app-surface, #212529);flex:1}.filters-card .card-content{flex-direction:column;align-items:stretch}.filter-content{width:100%}.options-card .options-content{display:flex;gap:24px;align-items:flex-end}.checkbox-field{flex-direction:row;align-items:center}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;color:var(--kendo-color-on-app-surface, #212529)}.data-source-type .radio-group{display:flex;gap:24px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400;color:var(--kendo-color-on-app-surface, #212529)}.radio-label span{color:var(--kendo-color-on-app-surface, #212529)}.query-info{flex-direction:column;align-items:stretch;gap:8px}.info-row{display:flex;gap:8px}.info-label{font-weight:600;min-width:100px;color:var(--kendo-color-subtle, #6c757d)}.info-value{flex:1;color:var(--kendo-color-on-app-surface, #212529)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { kind: "ngmodule", type: NumericTextBoxModule }, { kind: "ngmodule", type: DropDownsModule }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: i1$4.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "messages", "dialogMessages", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
9193
|
+
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:16px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.form-field{display:flex;flex-direction:column;gap:6px}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.config-card{padding:12px 16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.card-header{display:flex;align-items:center;gap:8px;margin-bottom:8px}.card-header kendo-svgicon{color:var(--kendo-color-primary, #0d6efd)}.card-title{font-weight:600;font-size:.95rem;color:var(--kendo-color-primary, #0d6efd)}.card-count{color:var(--kendo-color-subtle, #6c757d);font-size:.85rem}.card-content{display:flex;align-items:center;justify-content:space-between;gap:16px}.config-summary{margin:0;font-size:.85rem;color:var(--kendo-color-on-app-surface, #212529);flex:1}.filters-card .card-content{flex-direction:column;align-items:stretch}.filter-content{width:100%}.options-card .options-content{display:flex;gap:24px;align-items:flex-end}.checkbox-field{flex-direction:row;align-items:center}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;color:var(--kendo-color-on-app-surface, #212529)}.data-source-type .radio-group{display:flex;gap:24px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400;color:var(--kendo-color-on-app-surface, #212529)}.radio-label span{color:var(--kendo-color-on-app-surface, #212529)}.query-info{flex-direction:column;align-items:stretch;gap:8px}.info-row{display:flex;gap:8px}.info-label{font-weight:600;min-width:100px;color:var(--kendo-color-subtle, #6c757d)}.info-value{flex:1;color:var(--kendo-color-on-app-surface, #212529)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { kind: "ngmodule", type: NumericTextBoxModule }, { kind: "ngmodule", type: DropDownsModule }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: i1$4.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "messages", "dialogMessages", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
8992
9194
|
}
|
|
8993
9195
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: TableConfigDialogComponent, decorators: [{
|
|
8994
9196
|
type: Component,
|
|
@@ -9004,6 +9206,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
9004
9206
|
FieldFilterEditorComponent,
|
|
9005
9207
|
QuerySelectorComponent,
|
|
9006
9208
|
SdTimeFilterToggleComponent,
|
|
9209
|
+
EntitySelectorScopePickerComponent,
|
|
9007
9210
|
LoadingOverlayComponent
|
|
9008
9211
|
], providers: [
|
|
9009
9212
|
AttributeSelectorDialogService,
|
|
@@ -9130,6 +9333,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
9130
9333
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
9131
9334
|
</mm-sd-time-filter-toggle>
|
|
9132
9335
|
|
|
9336
|
+
<mm-entity-selector-scope-picker
|
|
9337
|
+
[family]="selectedQueryFamily"
|
|
9338
|
+
[selectors]="availableEntitySelectors"
|
|
9339
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
9340
|
+
</mm-entity-selector-scope-picker>
|
|
9341
|
+
|
|
9133
9342
|
@if (selectedPersistentQuery) {
|
|
9134
9343
|
<div class="config-card">
|
|
9135
9344
|
<div class="card-header">
|
|
@@ -9245,6 +9454,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
9245
9454
|
type: Input
|
|
9246
9455
|
}], initialIgnoreTimeFilter: [{
|
|
9247
9456
|
type: Input
|
|
9457
|
+
}], initialEntitySelectorId: [{
|
|
9458
|
+
type: Input
|
|
9248
9459
|
}] } });
|
|
9249
9460
|
|
|
9250
9461
|
class GaugeWidgetComponent {
|
|
@@ -9427,7 +9638,12 @@ class GaugeWidgetComponent {
|
|
|
9427
9638
|
}
|
|
9428
9639
|
buildStreamDataArgs() {
|
|
9429
9640
|
const ds = this.config.dataSource;
|
|
9430
|
-
|
|
9641
|
+
const timeArgs = this.stateService.resolveStreamDataTimeArgs(ds.ignoreTimeFilter);
|
|
9642
|
+
const rtIds = this.stateService.resolveStreamDataRtIds(ds.entitySelectorId);
|
|
9643
|
+
if (!timeArgs && !rtIds) {
|
|
9644
|
+
return undefined;
|
|
9645
|
+
}
|
|
9646
|
+
return { ...timeArgs, rtIds };
|
|
9431
9647
|
}
|
|
9432
9648
|
extractAggregationValue(queryResult) {
|
|
9433
9649
|
const firstRow = queryResult.rows.find(row => GaugeWidgetComponent.SUPPORTED_ROW_TYPES.has(row.__typename ?? ''));
|
|
@@ -9877,6 +10093,7 @@ class GaugeConfigDialogComponent {
|
|
|
9877
10093
|
initialQueryName;
|
|
9878
10094
|
initialQueryFamily;
|
|
9879
10095
|
initialIgnoreTimeFilter;
|
|
10096
|
+
initialEntitySelectorId;
|
|
9880
10097
|
initialQueryMode;
|
|
9881
10098
|
initialQueryValueField;
|
|
9882
10099
|
initialQueryCategoryField;
|
|
@@ -9895,6 +10112,7 @@ class GaugeConfigDialogComponent {
|
|
|
9895
10112
|
selectedPersistentQuery = null;
|
|
9896
10113
|
/** Stream-data opt-out: when true the MeshBoard time filter is not bound to the query. */
|
|
9897
10114
|
ignoreTimeFilter = false;
|
|
10115
|
+
entitySelectorId;
|
|
9898
10116
|
queryColumns = [];
|
|
9899
10117
|
categoryValues = [];
|
|
9900
10118
|
queryMode = 'simpleCount';
|
|
@@ -9902,6 +10120,10 @@ class GaugeConfigDialogComponent {
|
|
|
9902
10120
|
get selectedQueryFamily() {
|
|
9903
10121
|
return queryFamily(this.selectedPersistentQuery?.ckTypeId) ?? this.initialQueryFamily ?? null;
|
|
9904
10122
|
}
|
|
10123
|
+
/** Entity selectors available on the current MeshBoard (for the scope picker). */
|
|
10124
|
+
get availableEntitySelectors() {
|
|
10125
|
+
return this.meshBoardStateService.getEntitySelectors();
|
|
10126
|
+
}
|
|
9905
10127
|
isLoadingQueryColumns = false;
|
|
9906
10128
|
isLoadingCategoryValues = false;
|
|
9907
10129
|
// Attribute selection
|
|
@@ -9996,6 +10218,7 @@ class GaugeConfigDialogComponent {
|
|
|
9996
10218
|
this.dataSourceType = this.initialDataSourceType || 'runtimeEntity';
|
|
9997
10219
|
this.queryMode = this.initialQueryMode || 'simpleCount';
|
|
9998
10220
|
this.ignoreTimeFilter = this.initialIgnoreTimeFilter ?? false;
|
|
10221
|
+
this.entitySelectorId = this.initialEntitySelectorId;
|
|
9999
10222
|
if (this.dataSourceType === 'persistentQuery' && this.initialQueryRtId) {
|
|
10000
10223
|
this.isLoadingInitial = true;
|
|
10001
10224
|
setTimeout(async () => {
|
|
@@ -10145,6 +10368,7 @@ class GaugeConfigDialogComponent {
|
|
|
10145
10368
|
queryName: this.selectedPersistentQuery.name,
|
|
10146
10369
|
queryFamily: family,
|
|
10147
10370
|
ignoreTimeFilter: this.ignoreTimeFilter,
|
|
10371
|
+
entitySelectorId: this.entitySelectorId,
|
|
10148
10372
|
queryMode: this.queryMode,
|
|
10149
10373
|
queryValueField: this.form.queryValueField || undefined,
|
|
10150
10374
|
queryCategoryField: this.form.queryCategoryField || undefined,
|
|
@@ -10308,7 +10532,7 @@ class GaugeConfigDialogComponent {
|
|
|
10308
10532
|
this.filters = updatedFilters;
|
|
10309
10533
|
}
|
|
10310
10534
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GaugeConfigDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10311
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: GaugeConfigDialogComponent, isStandalone: true, selector: "mm-gauge-config-dialog", inputs: { initialCkTypeId: "initialCkTypeId", initialRtId: "initialRtId", initialGaugeType: "initialGaugeType", initialValueAttribute: "initialValueAttribute", initialLabelAttribute: "initialLabelAttribute", initialMin: "initialMin", initialMax: "initialMax", initialRanges: "initialRanges", initialShowLabel: "initialShowLabel", initialPrefix: "initialPrefix", initialSuffix: "initialSuffix", initialReverse: "initialReverse", initialDataSourceType: "initialDataSourceType", initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialQueryMode: "initialQueryMode", initialQueryValueField: "initialQueryValueField", initialQueryCategoryField: "initialQueryCategoryField", initialQueryCategoryValue: "initialQueryCategoryValue", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "ckTypeSelectorInput", first: true, predicate: ["ckTypeSelector"], descendants: true }, { propertyName: "entitySelectorInput", first: true, predicate: ["entitySelector"], descendants: true }, { propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
10535
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: GaugeConfigDialogComponent, isStandalone: true, selector: "mm-gauge-config-dialog", inputs: { initialCkTypeId: "initialCkTypeId", initialRtId: "initialRtId", initialGaugeType: "initialGaugeType", initialValueAttribute: "initialValueAttribute", initialLabelAttribute: "initialLabelAttribute", initialMin: "initialMin", initialMax: "initialMax", initialRanges: "initialRanges", initialShowLabel: "initialShowLabel", initialPrefix: "initialPrefix", initialSuffix: "initialSuffix", initialReverse: "initialReverse", initialDataSourceType: "initialDataSourceType", initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialQueryMode: "initialQueryMode", initialQueryValueField: "initialQueryValueField", initialQueryCategoryField: "initialQueryCategoryField", initialQueryCategoryValue: "initialQueryCategoryValue", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "ckTypeSelectorInput", first: true, predicate: ["ckTypeSelector"], descendants: true }, { propertyName: "entitySelectorInput", first: true, predicate: ["entitySelector"], descendants: true }, { propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
10312
10536
|
<div class="config-container">
|
|
10313
10537
|
|
|
10314
10538
|
<div class="config-form" [class.loading]="isLoadingInitial">
|
|
@@ -10428,6 +10652,12 @@ class GaugeConfigDialogComponent {
|
|
|
10428
10652
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
10429
10653
|
</mm-sd-time-filter-toggle>
|
|
10430
10654
|
|
|
10655
|
+
<mm-entity-selector-scope-picker
|
|
10656
|
+
[family]="selectedQueryFamily"
|
|
10657
|
+
[selectors]="availableEntitySelectors"
|
|
10658
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
10659
|
+
</mm-entity-selector-scope-picker>
|
|
10660
|
+
|
|
10431
10661
|
<!-- Query Mode Selection -->
|
|
10432
10662
|
<div class="form-field">
|
|
10433
10663
|
<label>Query Mode</label>
|
|
@@ -10712,7 +10942,7 @@ class GaugeConfigDialogComponent {
|
|
|
10712
10942
|
</button>
|
|
10713
10943
|
</div>
|
|
10714
10944
|
</div>
|
|
10715
|
-
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:20px;padding:16px;position:relative;flex:1;overflow-y:auto}.config-form.loading{pointer-events:none}.form-field{display:flex;flex-direction:column;gap:6px}.form-field.disabled{opacity:.6}.form-field.flex-1{flex:1}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.form-section h4{margin:0 0 16px;font-size:.95rem;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-row{display:flex;gap:16px}.checkbox-label{margin-left:8px;font-weight:400}.gauge-type-item{display:flex;flex-direction:column;gap:2px}.gauge-type-label{font-weight:500}.gauge-type-desc{font-size:.75rem;color:var(--kendo-color-subtle, #6c757d)}.attribute-item{display:flex;justify-content:space-between;align-items:center;gap:8px;width:100%}.attribute-path{flex:1}.attribute-type{font-size:.75rem;color:var(--kendo-color-subtle, #6c757d);background:var(--kendo-color-surface-alt, #f8f9fa);padding:2px 6px;border-radius:3px}.range-row{display:flex;align-items:center;gap:8px;margin-bottom:8px}.range-input{width:80px}.range-separator{color:var(--kendo-color-subtle, #6c757d)}.color-picker{width:40px;height:32px;padding:2px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;cursor:pointer}.mode-toggle{display:flex;gap:8px}.mode-toggle button{flex:1}.required{color:var(--kendo-color-error, #dc3545)}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "messages", "dialogMessages", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: EntitySelectInputComponent, selector: "mm-entity-select-input", inputs: ["dataSource", "placeholder", "minSearchLength", "maxResults", "debounceMs", "prefix", "initialDisplayValue", "dialogDataSource", "dialogTitle", "multiSelect", "advancedSearchLabel", "dialogMessages", "messages", "disabled", "required"], outputs: ["entitySelected", "entityCleared", "entitiesSelected"] }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
10945
|
+
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:20px;padding:16px;position:relative;flex:1;overflow-y:auto}.config-form.loading{pointer-events:none}.form-field{display:flex;flex-direction:column;gap:6px}.form-field.disabled{opacity:.6}.form-field.flex-1{flex:1}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.form-section h4{margin:0 0 16px;font-size:.95rem;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-row{display:flex;gap:16px}.checkbox-label{margin-left:8px;font-weight:400}.gauge-type-item{display:flex;flex-direction:column;gap:2px}.gauge-type-label{font-weight:500}.gauge-type-desc{font-size:.75rem;color:var(--kendo-color-subtle, #6c757d)}.attribute-item{display:flex;justify-content:space-between;align-items:center;gap:8px;width:100%}.attribute-path{flex:1}.attribute-type{font-size:.75rem;color:var(--kendo-color-subtle, #6c757d);background:var(--kendo-color-surface-alt, #f8f9fa);padding:2px 6px;border-radius:3px}.range-row{display:flex;align-items:center;gap:8px;margin-bottom:8px}.range-input{width:80px}.range-separator{color:var(--kendo-color-subtle, #6c757d)}.color-picker{width:40px;height:32px;padding:2px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;cursor:pointer}.mode-toggle{display:flex;gap:8px}.mode-toggle button{flex:1}.required{color:var(--kendo-color-error, #dc3545)}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "messages", "dialogMessages", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: EntitySelectInputComponent, selector: "mm-entity-select-input", inputs: ["dataSource", "placeholder", "minSearchLength", "maxResults", "debounceMs", "prefix", "initialDisplayValue", "dialogDataSource", "dialogTitle", "multiSelect", "advancedSearchLabel", "dialogMessages", "messages", "disabled", "required"], outputs: ["entitySelected", "entityCleared", "entitiesSelected"] }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
10716
10946
|
}
|
|
10717
10947
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GaugeConfigDialogComponent, decorators: [{
|
|
10718
10948
|
type: Component,
|
|
@@ -10727,6 +10957,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
10727
10957
|
FieldFilterEditorComponent,
|
|
10728
10958
|
QuerySelectorComponent,
|
|
10729
10959
|
SdTimeFilterToggleComponent,
|
|
10960
|
+
EntitySelectorScopePickerComponent,
|
|
10730
10961
|
LoadingOverlayComponent
|
|
10731
10962
|
], template: `
|
|
10732
10963
|
<div class="config-container">
|
|
@@ -10848,6 +11079,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
10848
11079
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
10849
11080
|
</mm-sd-time-filter-toggle>
|
|
10850
11081
|
|
|
11082
|
+
<mm-entity-selector-scope-picker
|
|
11083
|
+
[family]="selectedQueryFamily"
|
|
11084
|
+
[selectors]="availableEntitySelectors"
|
|
11085
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
11086
|
+
</mm-entity-selector-scope-picker>
|
|
11087
|
+
|
|
10851
11088
|
<!-- Query Mode Selection -->
|
|
10852
11089
|
<div class="form-field">
|
|
10853
11090
|
<label>Query Mode</label>
|
|
@@ -11176,6 +11413,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
11176
11413
|
type: Input
|
|
11177
11414
|
}], initialIgnoreTimeFilter: [{
|
|
11178
11415
|
type: Input
|
|
11416
|
+
}], initialEntitySelectorId: [{
|
|
11417
|
+
type: Input
|
|
11179
11418
|
}], initialQueryMode: [{
|
|
11180
11419
|
type: Input
|
|
11181
11420
|
}], initialQueryValueField: [{
|
|
@@ -11370,7 +11609,12 @@ class PieChartWidgetComponent {
|
|
|
11370
11609
|
}
|
|
11371
11610
|
buildStreamDataArgs() {
|
|
11372
11611
|
const ds = this.config.dataSource;
|
|
11373
|
-
|
|
11612
|
+
const timeArgs = this.stateService.resolveStreamDataTimeArgs(ds.ignoreTimeFilter);
|
|
11613
|
+
const rtIds = this.stateService.resolveStreamDataRtIds(ds.entitySelectorId);
|
|
11614
|
+
if (!timeArgs && !rtIds) {
|
|
11615
|
+
return undefined;
|
|
11616
|
+
}
|
|
11617
|
+
return { ...timeArgs, rtIds };
|
|
11374
11618
|
}
|
|
11375
11619
|
/**
|
|
11376
11620
|
* Converts widget filter configuration to GraphQL FieldFilterDto format.
|
|
@@ -11485,6 +11729,7 @@ class PieChartConfigDialogComponent {
|
|
|
11485
11729
|
initialQueryName;
|
|
11486
11730
|
initialQueryFamily;
|
|
11487
11731
|
initialIgnoreTimeFilter;
|
|
11732
|
+
initialEntitySelectorId;
|
|
11488
11733
|
initialChartType;
|
|
11489
11734
|
initialCategoryField;
|
|
11490
11735
|
initialValueField;
|
|
@@ -11519,6 +11764,7 @@ class PieChartConfigDialogComponent {
|
|
|
11519
11764
|
selectedPersistentQuery = null;
|
|
11520
11765
|
/** Stream-data opt-out: when true the MeshBoard time filter is not bound to the query. */
|
|
11521
11766
|
ignoreTimeFilter = false;
|
|
11767
|
+
entitySelectorId;
|
|
11522
11768
|
queryColumns = [];
|
|
11523
11769
|
// Filter state
|
|
11524
11770
|
filters = [];
|
|
@@ -11557,6 +11803,10 @@ class PieChartConfigDialogComponent {
|
|
|
11557
11803
|
get selectedQueryFamily() {
|
|
11558
11804
|
return queryFamily(this.selectedPersistentQuery?.ckTypeId) ?? this.initialQueryFamily ?? null;
|
|
11559
11805
|
}
|
|
11806
|
+
/** Entity selectors available on the current MeshBoard (for the scope picker). */
|
|
11807
|
+
get availableEntitySelectors() {
|
|
11808
|
+
return this.stateService.getEntitySelectors();
|
|
11809
|
+
}
|
|
11560
11810
|
async ngOnInit() {
|
|
11561
11811
|
// Initialize filter variables from MeshBoard state
|
|
11562
11812
|
this.filterVariables = this.stateService.getVariables().map(v => ({
|
|
@@ -11574,6 +11824,7 @@ class PieChartConfigDialogComponent {
|
|
|
11574
11824
|
this.form.ckQueryTarget = this.initialCkQueryTarget ?? 'models';
|
|
11575
11825
|
this.form.ckGroupBy = this.initialCkGroupBy ?? 'modelState';
|
|
11576
11826
|
this.ignoreTimeFilter = this.initialIgnoreTimeFilter ?? false;
|
|
11827
|
+
this.entitySelectorId = this.initialEntitySelectorId;
|
|
11577
11828
|
// Initialize filters
|
|
11578
11829
|
if (this.initialFilters && this.initialFilters.length > 0) {
|
|
11579
11830
|
this.filters = this.initialFilters.map((f, index) => ({
|
|
@@ -11736,6 +11987,7 @@ class PieChartConfigDialogComponent {
|
|
|
11736
11987
|
result.queryName = this.selectedPersistentQuery.name;
|
|
11737
11988
|
result.queryFamily = queryFamily(this.selectedPersistentQuery.ckTypeId) ?? this.initialQueryFamily ?? undefined;
|
|
11738
11989
|
result.ignoreTimeFilter = this.ignoreTimeFilter;
|
|
11990
|
+
result.entitySelectorId = this.entitySelectorId;
|
|
11739
11991
|
}
|
|
11740
11992
|
else if (this.form.dataSourceType === 'constructionKitQuery') {
|
|
11741
11993
|
result.ckQueryTarget = this.form.ckQueryTarget;
|
|
@@ -11747,7 +11999,7 @@ class PieChartConfigDialogComponent {
|
|
|
11747
11999
|
this.windowRef.close();
|
|
11748
12000
|
}
|
|
11749
12001
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: PieChartConfigDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11750
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: PieChartConfigDialogComponent, isStandalone: true, selector: "mm-pie-chart-config-dialog", inputs: { initialDataSourceType: "initialDataSourceType", initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialValueField: "initialValueField", initialShowLabels: "initialShowLabels", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialCkQueryTarget: "initialCkQueryTarget", initialCkGroupBy: "initialCkGroupBy", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
12002
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: PieChartConfigDialogComponent, isStandalone: true, selector: "mm-pie-chart-config-dialog", inputs: { initialDataSourceType: "initialDataSourceType", initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialValueField: "initialValueField", initialShowLabels: "initialShowLabels", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialCkQueryTarget: "initialCkQueryTarget", initialCkGroupBy: "initialCkGroupBy", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
11751
12003
|
<div class="config-container">
|
|
11752
12004
|
|
|
11753
12005
|
<div class="config-form" [class.loading]="isLoadingInitial">
|
|
@@ -11787,6 +12039,12 @@ class PieChartConfigDialogComponent {
|
|
|
11787
12039
|
[family]="selectedQueryFamily"
|
|
11788
12040
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
11789
12041
|
</mm-sd-time-filter-toggle>
|
|
12042
|
+
|
|
12043
|
+
<mm-entity-selector-scope-picker
|
|
12044
|
+
[family]="selectedQueryFamily"
|
|
12045
|
+
[selectors]="availableEntitySelectors"
|
|
12046
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
12047
|
+
</mm-entity-selector-scope-picker>
|
|
11790
12048
|
}
|
|
11791
12049
|
|
|
11792
12050
|
<!-- Construction Kit Query Options -->
|
|
@@ -11951,7 +12209,7 @@ class PieChartConfigDialogComponent {
|
|
|
11951
12209
|
</button>
|
|
11952
12210
|
</div>
|
|
11953
12211
|
</div>
|
|
11954
|
-
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;flex:1;overflow-y:auto;gap:20px;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.radio-group{display:flex;gap:24px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
12212
|
+
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;flex:1;overflow-y:auto;gap:20px;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.radio-group{display:flex;gap:24px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
11955
12213
|
}
|
|
11956
12214
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: PieChartConfigDialogComponent, decorators: [{
|
|
11957
12215
|
type: Component,
|
|
@@ -11965,6 +12223,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
11965
12223
|
FieldFilterEditorComponent,
|
|
11966
12224
|
QuerySelectorComponent,
|
|
11967
12225
|
SdTimeFilterToggleComponent,
|
|
12226
|
+
EntitySelectorScopePickerComponent,
|
|
11968
12227
|
LoadingOverlayComponent
|
|
11969
12228
|
], template: `
|
|
11970
12229
|
<div class="config-container">
|
|
@@ -12006,6 +12265,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
12006
12265
|
[family]="selectedQueryFamily"
|
|
12007
12266
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
12008
12267
|
</mm-sd-time-filter-toggle>
|
|
12268
|
+
|
|
12269
|
+
<mm-entity-selector-scope-picker
|
|
12270
|
+
[family]="selectedQueryFamily"
|
|
12271
|
+
[selectors]="availableEntitySelectors"
|
|
12272
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
12273
|
+
</mm-entity-selector-scope-picker>
|
|
12009
12274
|
}
|
|
12010
12275
|
|
|
12011
12276
|
<!-- Construction Kit Query Options -->
|
|
@@ -12184,6 +12449,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
12184
12449
|
type: Input
|
|
12185
12450
|
}], initialIgnoreTimeFilter: [{
|
|
12186
12451
|
type: Input
|
|
12452
|
+
}], initialEntitySelectorId: [{
|
|
12453
|
+
type: Input
|
|
12187
12454
|
}], initialChartType: [{
|
|
12188
12455
|
type: Input
|
|
12189
12456
|
}], initialCategoryField: [{
|
|
@@ -12366,7 +12633,12 @@ class BarChartWidgetComponent {
|
|
|
12366
12633
|
}
|
|
12367
12634
|
buildStreamDataArgs() {
|
|
12368
12635
|
const ds = this.config.dataSource;
|
|
12369
|
-
|
|
12636
|
+
const timeArgs = this.stateService.resolveStreamDataTimeArgs(ds.ignoreTimeFilter);
|
|
12637
|
+
const rtIds = this.stateService.resolveStreamDataRtIds(ds.entitySelectorId);
|
|
12638
|
+
if (!timeArgs && !rtIds) {
|
|
12639
|
+
return undefined;
|
|
12640
|
+
}
|
|
12641
|
+
return { ...timeArgs, rtIds };
|
|
12370
12642
|
}
|
|
12371
12643
|
/**
|
|
12372
12644
|
* Processes data in Static Series Mode.
|
|
@@ -12703,6 +12975,7 @@ class BarChartConfigDialogComponent {
|
|
|
12703
12975
|
initialQueryName;
|
|
12704
12976
|
initialQueryFamily;
|
|
12705
12977
|
initialIgnoreTimeFilter;
|
|
12978
|
+
initialEntitySelectorId;
|
|
12706
12979
|
initialChartType;
|
|
12707
12980
|
initialCategoryField;
|
|
12708
12981
|
initialSeries;
|
|
@@ -12723,6 +12996,12 @@ class BarChartConfigDialogComponent {
|
|
|
12723
12996
|
numericColumns = [];
|
|
12724
12997
|
/** Per-widget opt-out of the MeshBoard time-filter → stream-data binding. */
|
|
12725
12998
|
ignoreTimeFilter = false;
|
|
12999
|
+
/** Asset-scope binding: id of the entity selector whose selection scopes the stream-data query. */
|
|
13000
|
+
entitySelectorId;
|
|
13001
|
+
/** Entity selectors available on the current MeshBoard (for the scope picker). */
|
|
13002
|
+
get availableEntitySelectors() {
|
|
13003
|
+
return this.stateService.getEntitySelectors();
|
|
13004
|
+
}
|
|
12726
13005
|
/** Family of the currently selected query — gates the time-filter opt-out toggle. */
|
|
12727
13006
|
get selectedQueryFamily() {
|
|
12728
13007
|
return queryFamily(this.selectedPersistentQuery?.ckTypeId) ?? this.initialQueryFamily ?? null;
|
|
@@ -12779,6 +13058,7 @@ class BarChartConfigDialogComponent {
|
|
|
12779
13058
|
}));
|
|
12780
13059
|
// Initialize form with initial values
|
|
12781
13060
|
this.ignoreTimeFilter = this.initialIgnoreTimeFilter ?? false;
|
|
13061
|
+
this.entitySelectorId = this.initialEntitySelectorId;
|
|
12782
13062
|
this.form.chartType = this.initialChartType ?? 'column';
|
|
12783
13063
|
this.form.categoryField = this.initialCategoryField ?? '';
|
|
12784
13064
|
this.form.showLegend = this.initialShowLegend ?? true;
|
|
@@ -12937,6 +13217,7 @@ class BarChartConfigDialogComponent {
|
|
|
12937
13217
|
queryName: this.selectedPersistentQuery.name,
|
|
12938
13218
|
queryFamily: family,
|
|
12939
13219
|
ignoreTimeFilter: this.ignoreTimeFilter,
|
|
13220
|
+
entitySelectorId: this.entitySelectorId,
|
|
12940
13221
|
chartType: this.form.chartType,
|
|
12941
13222
|
categoryField: this.form.categoryField,
|
|
12942
13223
|
series,
|
|
@@ -12964,7 +13245,7 @@ class BarChartConfigDialogComponent {
|
|
|
12964
13245
|
this.windowRef.close();
|
|
12965
13246
|
}
|
|
12966
13247
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BarChartConfigDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
12967
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BarChartConfigDialogComponent, isStandalone: true, selector: "mm-bar-chart-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialSeries: "initialSeries", initialSeriesGroupField: "initialSeriesGroupField", initialValueField: "initialValueField", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialShowDataLabels: "initialShowDataLabels", initialColorThresholds: "initialColorThresholds", initialDefaultBarColor: "initialDefaultBarColor", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
13248
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BarChartConfigDialogComponent, isStandalone: true, selector: "mm-bar-chart-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialSeries: "initialSeries", initialSeriesGroupField: "initialSeriesGroupField", initialValueField: "initialValueField", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialShowDataLabels: "initialShowDataLabels", initialColorThresholds: "initialColorThresholds", initialDefaultBarColor: "initialDefaultBarColor", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
12968
13249
|
<div class="config-container">
|
|
12969
13250
|
|
|
12970
13251
|
<div class="config-form" [class.loading]="isLoadingInitial">
|
|
@@ -12989,6 +13270,12 @@ class BarChartConfigDialogComponent {
|
|
|
12989
13270
|
[family]="selectedQueryFamily"
|
|
12990
13271
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
12991
13272
|
</mm-sd-time-filter-toggle>
|
|
13273
|
+
|
|
13274
|
+
<mm-entity-selector-scope-picker
|
|
13275
|
+
[family]="selectedQueryFamily"
|
|
13276
|
+
[selectors]="availableEntitySelectors"
|
|
13277
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
13278
|
+
</mm-entity-selector-scope-picker>
|
|
12992
13279
|
</div>
|
|
12993
13280
|
|
|
12994
13281
|
<!-- Field Mapping Section -->
|
|
@@ -13230,7 +13517,7 @@ class BarChartConfigDialogComponent {
|
|
|
13230
13517
|
</button>
|
|
13231
13518
|
</div>
|
|
13232
13519
|
</div>
|
|
13233
|
-
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.chart-type-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.form-row{display:flex;gap:24px}.checkbox-field{flex-direction:row;align-items:center}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{margin-top:8px}.form-section h4{margin:0 0 4px;font-size:.95rem;font-weight:600}.threshold-row{display:flex;gap:8px;align-items:center;margin-bottom:8px}.threshold-row label{font-size:.85rem;min-width:70px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "component", type: i4.MultiSelectComponent, selector: "kendo-multiselect", inputs: ["showStickyHeader", "focusableId", "autoClose", "loading", "data", "value", "valueField", "textField", "tabindex", "tabIndex", "size", "rounded", "fillMode", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "disabled", "itemDisabled", "checkboxes", "readonly", "filterable", "virtual", "popupSettings", "listHeight", "valuePrimitive", "clearButton", "tagMapper", "allowCustom", "valueNormalizer", "inputAttributes"], outputs: ["filterChange", "valueChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "removeTag"], exportAs: ["kendoMultiSelect"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
13520
|
+
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.chart-type-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.form-row{display:flex;gap:24px}.checkbox-field{flex-direction:row;align-items:center}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.query-item{display:flex;flex-direction:column;gap:2px}.query-name{font-weight:500}.query-description{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{margin-top:8px}.form-section h4{margin:0 0 4px;font-size:.95rem;font-weight:600}.threshold-row{display:flex;gap:8px;align-items:center;margin-bottom:8px}.threshold-row label{font-size:.85rem;min-width:70px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "component", type: i4.MultiSelectComponent, selector: "kendo-multiselect", inputs: ["showStickyHeader", "focusableId", "autoClose", "loading", "data", "value", "valueField", "textField", "tabindex", "tabIndex", "size", "rounded", "fillMode", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "disabled", "itemDisabled", "checkboxes", "readonly", "filterable", "virtual", "popupSettings", "listHeight", "valuePrimitive", "clearButton", "tagMapper", "allowCustom", "valueNormalizer", "inputAttributes"], outputs: ["filterChange", "valueChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "removeTag"], exportAs: ["kendoMultiSelect"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
13234
13521
|
}
|
|
13235
13522
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BarChartConfigDialogComponent, decorators: [{
|
|
13236
13523
|
type: Component,
|
|
@@ -13244,6 +13531,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
13244
13531
|
FieldFilterEditorComponent,
|
|
13245
13532
|
QuerySelectorComponent,
|
|
13246
13533
|
SdTimeFilterToggleComponent,
|
|
13534
|
+
EntitySelectorScopePickerComponent,
|
|
13247
13535
|
LoadingOverlayComponent
|
|
13248
13536
|
], template: `
|
|
13249
13537
|
<div class="config-container">
|
|
@@ -13270,6 +13558,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
13270
13558
|
[family]="selectedQueryFamily"
|
|
13271
13559
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
13272
13560
|
</mm-sd-time-filter-toggle>
|
|
13561
|
+
|
|
13562
|
+
<mm-entity-selector-scope-picker
|
|
13563
|
+
[family]="selectedQueryFamily"
|
|
13564
|
+
[selectors]="availableEntitySelectors"
|
|
13565
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
13566
|
+
</mm-entity-selector-scope-picker>
|
|
13273
13567
|
</div>
|
|
13274
13568
|
|
|
13275
13569
|
<!-- Field Mapping Section -->
|
|
@@ -13523,6 +13817,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
13523
13817
|
type: Input
|
|
13524
13818
|
}], initialIgnoreTimeFilter: [{
|
|
13525
13819
|
type: Input
|
|
13820
|
+
}], initialEntitySelectorId: [{
|
|
13821
|
+
type: Input
|
|
13526
13822
|
}], initialChartType: [{
|
|
13527
13823
|
type: Input
|
|
13528
13824
|
}], initialCategoryField: [{
|
|
@@ -13547,8 +13843,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
13547
13843
|
type: Input
|
|
13548
13844
|
}] } });
|
|
13549
13845
|
|
|
13846
|
+
/** Series colours so a series' min/max band and its avg line share one hue. */
|
|
13847
|
+
const SERIES_PALETTE = ['#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6', '#ec4899', '#14b8a6', '#f97316'];
|
|
13550
13848
|
class LineChartWidgetComponent {
|
|
13551
13849
|
queryExecutor = inject(QueryExecutorService);
|
|
13850
|
+
elementRef = inject(ElementRef);
|
|
13851
|
+
ngZone = inject(NgZone);
|
|
13852
|
+
// FE-2 resize handling: re-query at a new resolution when the chart is resized materially.
|
|
13853
|
+
resizeObserver;
|
|
13854
|
+
resizeTimer;
|
|
13855
|
+
/** The downsampling `limit` used by the last load; 0 when the last load wasn't downsampled. */
|
|
13856
|
+
lastLimit = 0;
|
|
13552
13857
|
static SUPPORTED_ROW_TYPES = new Set([
|
|
13553
13858
|
'RtSimpleQueryRow',
|
|
13554
13859
|
'RtAggregationQueryRow',
|
|
@@ -13571,11 +13876,17 @@ class LineChartWidgetComponent {
|
|
|
13571
13876
|
...(ngDevMode ? [{ debugName: "_error" }] : /* istanbul ignore next */ []));
|
|
13572
13877
|
_seriesUnitMap = signal(new Map(), /* @ts-ignore */
|
|
13573
13878
|
...(ngDevMode ? [{ debugName: "_seriesUnitMap" }] : /* istanbul ignore next */ []));
|
|
13879
|
+
// Debug aid: how many rows came back vs. how many distinct category points
|
|
13880
|
+
// actually plotted. A large `rows` with tiny `points` flags a data collapse
|
|
13881
|
+
// (e.g. all rows sharing one category/timestamp).
|
|
13882
|
+
_dataInfo = signal(null, /* @ts-ignore */
|
|
13883
|
+
...(ngDevMode ? [{ debugName: "_dataInfo" }] : /* istanbul ignore next */ []));
|
|
13574
13884
|
isLoading = this._isLoading.asReadonly();
|
|
13575
13885
|
categories = this._categories.asReadonly();
|
|
13576
13886
|
seriesData = this._seriesData.asReadonly();
|
|
13577
13887
|
valueAxes = this._valueAxes.asReadonly();
|
|
13578
13888
|
error = this._error.asReadonly();
|
|
13889
|
+
dataInfo = this._dataInfo.asReadonly();
|
|
13579
13890
|
data = computed(() => this._seriesData(), /* @ts-ignore */
|
|
13580
13891
|
...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
13581
13892
|
plotBands = computed(() => {
|
|
@@ -13639,8 +13950,37 @@ class LineChartWidgetComponent {
|
|
|
13639
13950
|
const maxLen = 18;
|
|
13640
13951
|
return e.value.length > maxLen ? e.value.substring(0, maxLen) + '...' : e.value;
|
|
13641
13952
|
};
|
|
13642
|
-
|
|
13953
|
+
ngAfterViewInit() {
|
|
13954
|
+
// Defer the initial load to after view init so the host has a measured width — the
|
|
13955
|
+
// downsampling bucket count (FE-1) is derived from the rendered pixel width.
|
|
13643
13956
|
this.loadData();
|
|
13957
|
+
this.setupResizeObserver();
|
|
13958
|
+
}
|
|
13959
|
+
ngOnDestroy() {
|
|
13960
|
+
this.resizeObserver?.disconnect();
|
|
13961
|
+
if (this.resizeTimer)
|
|
13962
|
+
clearTimeout(this.resizeTimer);
|
|
13963
|
+
}
|
|
13964
|
+
/**
|
|
13965
|
+
* FE-2: when the chart is resized so the pixel-derived bucket count would change materially
|
|
13966
|
+
* (>15%), re-query at the new resolution after a 300 ms debounce. Only relevant while
|
|
13967
|
+
* downsampling is active (lastLimit > 0); raw charts don't depend on width.
|
|
13968
|
+
*/
|
|
13969
|
+
setupResizeObserver() {
|
|
13970
|
+
if (typeof ResizeObserver === 'undefined')
|
|
13971
|
+
return;
|
|
13972
|
+
this.resizeObserver = new ResizeObserver(() => this.onResize());
|
|
13973
|
+
this.resizeObserver.observe(this.elementRef.nativeElement);
|
|
13974
|
+
}
|
|
13975
|
+
onResize() {
|
|
13976
|
+
if (this.lastLimit <= 0)
|
|
13977
|
+
return; // last load wasn't downsampled (or hasn't completed yet)
|
|
13978
|
+
const newLimit = this.computeDownsampleLimit();
|
|
13979
|
+
if (Math.abs(newLimit - this.lastLimit) / this.lastLimit < 0.15)
|
|
13980
|
+
return;
|
|
13981
|
+
if (this.resizeTimer)
|
|
13982
|
+
clearTimeout(this.resizeTimer);
|
|
13983
|
+
this.resizeTimer = setTimeout(() => this.ngZone.run(() => this.loadData()), 300);
|
|
13644
13984
|
}
|
|
13645
13985
|
ngOnChanges(changes) {
|
|
13646
13986
|
if (changes['config'] && !changes['config'].firstChange) {
|
|
@@ -13681,6 +14021,8 @@ class LineChartWidgetComponent {
|
|
|
13681
14021
|
// falls back to a one-time lookup by rtId. streamDataArgs is sent
|
|
13682
14022
|
// unconditionally because the runtime path ignores it.
|
|
13683
14023
|
const streamDataArgs = this.buildStreamDataArgs();
|
|
14024
|
+
// Remember the resolution used so a later resize can decide whether to re-query (FE-2).
|
|
14025
|
+
this.lastLimit = streamDataArgs?.limit ?? 0;
|
|
13684
14026
|
const result = await firstValueFrom(this.queryExecutor.execute(queryDataSource.queryFamily, queryDataSource.queryRtId, {
|
|
13685
14027
|
fieldFilter: fieldFilter ?? undefined,
|
|
13686
14028
|
streamDataArgs
|
|
@@ -13689,52 +14031,94 @@ class LineChartWidgetComponent {
|
|
|
13689
14031
|
throw err;
|
|
13690
14032
|
})));
|
|
13691
14033
|
const filteredRows = result.rows.filter(row => LineChartWidgetComponent.SUPPORTED_ROW_TYPES.has(row.__typename ?? ''));
|
|
13692
|
-
|
|
14034
|
+
const downsampled = streamDataArgs?.queryMode === QueryModeDto.DownsamplingDto;
|
|
14035
|
+
this.processData(filteredRows, downsampled);
|
|
14036
|
+
this._dataInfo.set({ rows: filteredRows.length, points: this._categories().length, total: result.totalCount });
|
|
13693
14037
|
this._isLoading.set(false);
|
|
13694
14038
|
}
|
|
13695
14039
|
catch (err) {
|
|
13696
14040
|
console.error('Error loading Line Chart data:', err);
|
|
13697
14041
|
this._error.set('Failed to load data');
|
|
14042
|
+
this._dataInfo.set(null);
|
|
13698
14043
|
this._isLoading.set(false);
|
|
13699
14044
|
}
|
|
13700
14045
|
}
|
|
13701
14046
|
buildStreamDataArgs() {
|
|
13702
14047
|
const ds = this.config.dataSource;
|
|
13703
|
-
|
|
14048
|
+
const timeArgs = this.stateService.resolveStreamDataTimeArgs(ds.ignoreTimeFilter);
|
|
14049
|
+
const rtIds = this.stateService.resolveStreamDataRtIds(ds.entitySelectorId);
|
|
14050
|
+
if (!timeArgs && !rtIds) {
|
|
14051
|
+
return undefined;
|
|
14052
|
+
}
|
|
14053
|
+
// Auto-downsampling (FE-1): for stream-data queries with a resolved time range, ask the
|
|
14054
|
+
// backend to reduce to ~one bucket per 2 px of chart width instead of streaming every row.
|
|
14055
|
+
// Without a time range the backend can't downsample (needs from/to/limit) → raw fallback.
|
|
14056
|
+
if (ds.queryFamily === 'streamData' && timeArgs?.from && timeArgs?.to) {
|
|
14057
|
+
return { ...timeArgs, rtIds, limit: this.computeDownsampleLimit(), queryMode: QueryModeDto.DownsamplingDto };
|
|
14058
|
+
}
|
|
14059
|
+
return { ...timeArgs, rtIds };
|
|
14060
|
+
}
|
|
14061
|
+
/**
|
|
14062
|
+
* Bucket count for backend downsampling, sized to the rendered width (~1 bucket / 2 px),
|
|
14063
|
+
* clamped to [50, 4000]. Falls back to 1500 before the host has a measured width.
|
|
14064
|
+
*/
|
|
14065
|
+
computeDownsampleLimit() {
|
|
14066
|
+
const width = this.elementRef.nativeElement?.offsetWidth ?? 0;
|
|
14067
|
+
const effective = width > 50 ? width : 1500;
|
|
14068
|
+
return Math.min(4000, Math.max(50, Math.round(effective / 2)));
|
|
13704
14069
|
}
|
|
13705
14070
|
/**
|
|
13706
14071
|
* Processes query rows into line chart data.
|
|
13707
14072
|
* Groups by seriesGroupField, orders by categoryField (date), supports multi-axis by unitField.
|
|
13708
14073
|
*/
|
|
13709
|
-
processData(filteredRows) {
|
|
14074
|
+
processData(filteredRows, downsample = false) {
|
|
13710
14075
|
const categoryField = this.config.categoryField;
|
|
13711
14076
|
const seriesGroupField = this.config.seriesGroupField;
|
|
13712
14077
|
const valueField = this.config.valueField;
|
|
13713
14078
|
const unitField = this.config.unitField;
|
|
13714
|
-
// Collect data: category -> seriesGroup -> value
|
|
14079
|
+
// Collect data: category -> seriesGroup -> value (and, for downsampling, the min/max band)
|
|
13715
14080
|
const dataMap = new Map();
|
|
14081
|
+
const bandMap = new Map();
|
|
13716
14082
|
const allCategories = new Map(); // label -> parsed date for sorting
|
|
13717
14083
|
const allSeriesGroups = new Set();
|
|
13718
14084
|
const seriesUnitMap = new Map(); // seriesGroup -> unit
|
|
13719
14085
|
for (const row of filteredRows) {
|
|
13720
|
-
|
|
14086
|
+
// In downsampling mode the x-axis is the bucket timestamp (the persisted category column
|
|
14087
|
+
// comes back reduced, e.g. `window_start_max`); use the row's bin timestamp instead.
|
|
14088
|
+
let categoryValue = downsample && row.timestamp ? String(row.timestamp) : '';
|
|
13721
14089
|
let seriesGroupValue = '';
|
|
13722
|
-
let
|
|
14090
|
+
let lineValue = downsample ? null : 0;
|
|
14091
|
+
let minValue = null;
|
|
14092
|
+
let maxValue = null;
|
|
13723
14093
|
let unitValue = '';
|
|
13724
14094
|
for (const cell of row.cells) {
|
|
13725
|
-
|
|
14095
|
+
const path = cell.attributePath;
|
|
14096
|
+
if (!downsample && matchesAttributePath(path, categoryField)) {
|
|
13726
14097
|
categoryValue = String(cell.value ?? '');
|
|
13727
14098
|
}
|
|
13728
|
-
else if (matchesAttributePath(
|
|
14099
|
+
else if (matchesAttributePath(path, seriesGroupField)) {
|
|
13729
14100
|
seriesGroupValue = String(cell.value ?? '');
|
|
13730
14101
|
}
|
|
13731
|
-
else if (matchesAttributePath(
|
|
13732
|
-
|
|
13733
|
-
|
|
13734
|
-
|
|
13735
|
-
|
|
14102
|
+
else if (matchesAttributePath(path, valueField)) {
|
|
14103
|
+
if (downsample) {
|
|
14104
|
+
// The value column is reduced to <field>_avg / _min / _max — split them out so the
|
|
14105
|
+
// avg drives the line and min/max form the envelope band.
|
|
14106
|
+
const lower = path.toLowerCase();
|
|
14107
|
+
if (lower.endsWith('_min'))
|
|
14108
|
+
minValue = this.toNumber(cell.value);
|
|
14109
|
+
else if (lower.endsWith('_max'))
|
|
14110
|
+
maxValue = this.toNumber(cell.value);
|
|
14111
|
+
else
|
|
14112
|
+
lineValue = this.toNumber(cell.value); // _avg (or an unsuffixed value)
|
|
14113
|
+
}
|
|
14114
|
+
else {
|
|
14115
|
+
const val = cell.value;
|
|
14116
|
+
lineValue = typeof val === 'number' ? val : parseFloat(String(val));
|
|
14117
|
+
if (isNaN(lineValue))
|
|
14118
|
+
lineValue = 0;
|
|
14119
|
+
}
|
|
13736
14120
|
}
|
|
13737
|
-
else if (unitField && matchesAttributePath(
|
|
14121
|
+
else if (unitField && matchesAttributePath(path, unitField)) {
|
|
13738
14122
|
unitValue = String(cell.value ?? '');
|
|
13739
14123
|
}
|
|
13740
14124
|
}
|
|
@@ -13747,7 +14131,13 @@ class LineChartWidgetComponent {
|
|
|
13747
14131
|
if (!dataMap.has(categoryValue)) {
|
|
13748
14132
|
dataMap.set(categoryValue, new Map());
|
|
13749
14133
|
}
|
|
13750
|
-
dataMap.get(categoryValue).set(seriesGroupValue,
|
|
14134
|
+
dataMap.get(categoryValue).set(seriesGroupValue, lineValue);
|
|
14135
|
+
if (downsample && minValue !== null && maxValue !== null) {
|
|
14136
|
+
if (!bandMap.has(categoryValue)) {
|
|
14137
|
+
bandMap.set(categoryValue, new Map());
|
|
14138
|
+
}
|
|
14139
|
+
bandMap.get(categoryValue).set(seriesGroupValue, { from: minValue, to: maxValue });
|
|
14140
|
+
}
|
|
13751
14141
|
// Track unit per series
|
|
13752
14142
|
if (unitField && unitValue) {
|
|
13753
14143
|
seriesUnitMap.set(seriesGroupValue, unitValue);
|
|
@@ -13776,17 +14166,23 @@ class LineChartWidgetComponent {
|
|
|
13776
14166
|
});
|
|
13777
14167
|
}
|
|
13778
14168
|
// Build series data
|
|
13779
|
-
const seriesData = seriesGroups.map(seriesGroup => {
|
|
14169
|
+
const seriesData = seriesGroups.map((seriesGroup, index) => {
|
|
13780
14170
|
const data = categoryKeys.map(categoryKey => {
|
|
13781
14171
|
return dataMap.get(categoryKey)?.get(seriesGroup) ?? null;
|
|
13782
14172
|
});
|
|
14173
|
+
// Build the min/max envelope band only when downsampling produced one for this series.
|
|
14174
|
+
const band = downsample && bandMap.size > 0
|
|
14175
|
+
? categoryKeys.map(categoryKey => bandMap.get(categoryKey)?.get(seriesGroup) ?? null)
|
|
14176
|
+
: undefined;
|
|
13783
14177
|
const unit = seriesUnitMap.get(seriesGroup);
|
|
13784
14178
|
const axisName = unit ? `unit_${this.sanitizeAxisName(unit)}` : undefined;
|
|
13785
14179
|
return {
|
|
13786
14180
|
name: seriesGroup,
|
|
13787
14181
|
data,
|
|
14182
|
+
band,
|
|
13788
14183
|
unit,
|
|
13789
|
-
axisName
|
|
14184
|
+
axisName,
|
|
14185
|
+
color: SERIES_PALETTE[index % SERIES_PALETTE.length]
|
|
13790
14186
|
};
|
|
13791
14187
|
});
|
|
13792
14188
|
this._categories.set(categories);
|
|
@@ -13823,6 +14219,13 @@ class LineChartWidgetComponent {
|
|
|
13823
14219
|
sanitizeAxisName(name) {
|
|
13824
14220
|
return name.replace(/[^a-zA-Z0-9]/g, '_');
|
|
13825
14221
|
}
|
|
14222
|
+
/** Parses a cell value to a number, or null when missing / non-numeric (renders as a gap). */
|
|
14223
|
+
toNumber(value) {
|
|
14224
|
+
if (value === null || value === undefined)
|
|
14225
|
+
return null;
|
|
14226
|
+
const n = typeof value === 'number' ? value : parseFloat(String(value));
|
|
14227
|
+
return isNaN(n) ? null : n;
|
|
14228
|
+
}
|
|
13826
14229
|
convertFiltersToDto(filters) {
|
|
13827
14230
|
const variables = this.stateService.getVariables();
|
|
13828
14231
|
return this.variableService.convertToFieldFilterDto(filters, variables);
|
|
@@ -13841,6 +14244,11 @@ class LineChartWidgetComponent {
|
|
|
13841
14244
|
<span>{{ error() }}</span>
|
|
13842
14245
|
</div>
|
|
13843
14246
|
} @else {
|
|
14247
|
+
@if (dataInfo(); as info) {
|
|
14248
|
+
<span class="data-count" [title]="'Loaded rows · distinct category points (totalCount ' + info.total + ')'">
|
|
14249
|
+
{{ info.rows }} rows · {{ info.points }} pts
|
|
14250
|
+
</span>
|
|
14251
|
+
}
|
|
13844
14252
|
<kendo-chart class="chart-container" [plotArea]="{ background: 'transparent', margin: { top: 0, right: 0, bottom: 0, left: 0 } }">
|
|
13845
14253
|
<kendo-chart-area [background]="'transparent'"></kendo-chart-area>
|
|
13846
14254
|
|
|
@@ -13885,12 +14293,26 @@ class LineChartWidgetComponent {
|
|
|
13885
14293
|
|
|
13886
14294
|
<kendo-chart-series>
|
|
13887
14295
|
@for (series of seriesData(); track series.name) {
|
|
14296
|
+
@if (series.band) {
|
|
14297
|
+
<kendo-chart-series-item
|
|
14298
|
+
[type]="'rangeArea'"
|
|
14299
|
+
[data]="series.band"
|
|
14300
|
+
[fromField]="'from'"
|
|
14301
|
+
[toField]="'to'"
|
|
14302
|
+
[name]="series.name + ' (min/max)'"
|
|
14303
|
+
[axis]="series.axisName ?? ''"
|
|
14304
|
+
[color]="series.color"
|
|
14305
|
+
[opacity]="0.18"
|
|
14306
|
+
[markers]="{ visible: false }">
|
|
14307
|
+
</kendo-chart-series-item>
|
|
14308
|
+
}
|
|
13888
14309
|
<kendo-chart-series-item
|
|
13889
14310
|
[type]="chartType()"
|
|
13890
14311
|
[style]="'smooth'"
|
|
13891
14312
|
[data]="series.data"
|
|
13892
14313
|
[name]="series.name"
|
|
13893
14314
|
[axis]="series.axisName ?? ''"
|
|
14315
|
+
[color]="series.color"
|
|
13894
14316
|
[opacity]="0.7"
|
|
13895
14317
|
[markers]="{ visible: config.showMarkers ?? false }">
|
|
13896
14318
|
</kendo-chart-series-item>
|
|
@@ -13913,7 +14335,7 @@ class LineChartWidgetComponent {
|
|
|
13913
14335
|
</kendo-chart>
|
|
13914
14336
|
}
|
|
13915
14337
|
</div>
|
|
13916
|
-
`, isInline: true, styles: [":host{display:block;width:100%;height:100%}.line-chart-widget{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;padding:8px;box-sizing:border-box;overflow:hidden}.line-chart-widget.loading,.line-chart-widget.error{opacity:.7}.loading-indicator,.error-message{display:flex;align-items:center;justify-content:center;height:100%;width:100%}.loading-indicator span{font-size:1.5rem;color:var(--kendo-color-subtle, #6c757d)}.error-message span{color:var(--kendo-color-error, #dc3545);font-size:.875rem}.chart-container{width:100%;height:100%}kendo-chart{width:100%;height:100%}.chart-tooltip{padding:4px 8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ChartsModule }, { kind: "component", type: i1$7.ChartComponent, selector: "kendo-chart", inputs: ["pannable", "renderAs", "seriesColors", "subtitle", "title", "noData", "observeStyles", "transitions", "zoomable", "axisDefaults", "categoryAxis", "chartArea", "legend", "panes", "paneDefaults", "plotArea", "series", "seriesDefaults", "tooltip", "valueAxis", "xAxis", "yAxis", "resizeRateLimit", "popupSettings", "drilldownLevel"], outputs: ["axisLabelClick", "drag", "dragEnd", "dragStart", "legendItemHover", "legendItemLeave", "noteClick", "noteHover", "noteLeave", "paneRender", "plotAreaClick", "plotAreaHover", "plotAreaLeave", "render", "select", "selectEnd", "selectStart", "seriesClick", "drilldown", "seriesHover", "seriesOver", "seriesLeave", "zoom", "zoomEnd", "zoomStart", "legendItemClick", "drilldownLevelChange"], exportAs: ["kendoChart"] }, { kind: "directive", type: i1$7.SeriesTooltipTemplateDirective, selector: "[kendoChartSeriesTooltipTemplate]" }, { kind: "component", type: i1$7.CategoryAxisComponent, selector: "kendo-chart-category-axis" }, { kind: "component", type: i1$7.CategoryAxisItemComponent, selector: "kendo-chart-category-axis-item", inputs: ["autoBaseUnitSteps", "axisCrossingValue", "background", "baseUnit", "baseUnitStep", "categories", "color", "justified", "line", "majorGridLines", "majorTicks", "max", "maxDateGroups", "maxDivisions", "min", "minorGridLines", "minorTicks", "name", "pane", "plotBands", "reverse", "roundToBaseUnit", "startAngle", "type", "visible", "weekStartDay", "crosshair", "labels", "notes", "select", "title", "rangeLabels", "highlight"] }, { kind: "component", type: i1$7.CategoryAxisLabelsComponent, selector: "kendo-chart-category-axis-item-labels", inputs: ["background", "border", "color", "content", "culture", "dateFormats", "font", "format", "margin", "mirror", "padding", "position", "rotation", "skip", "step", "visible", "visual"] }, { kind: "component", type: i1$7.ChartAreaComponent, selector: "kendo-chart-area", inputs: ["background", "border", "height", "margin", "opacity", "width"] }, { kind: "component", type: i1$7.LegendComponent, selector: "kendo-chart-legend", inputs: ["align", "background", "border", "height", "labels", "margin", "offsetX", "offsetY", "orientation", "padding", "position", "reverse", "visible", "width", "markers", "spacing", "inactiveItems", "item", "title", "focusHighlight"] }, { kind: "component", type: i1$7.SeriesComponent, selector: "kendo-chart-series" }, { kind: "component", type: i1$7.SeriesItemComponent, selector: "kendo-chart-series-item", inputs: ["aggregate", "autoFit", "axis", "border", "categoryAxis", "categoryField", "closeField", "color", "colorField", "connectors", "currentField", "dashType", "data", "downColor", "downColorField", "drilldownField", "dynamicHeight", "dynamicSlope", "errorHighField", "errorLowField", "explodeField", "field", "fromField", "gap", "highField", "holeSize", "line", "lowField", "lowerField", "margin", "maxSize", "mean", "meanField", "median", "medianField", "minSize", "missingValues", "name", "neckRatio", "negativeColor", "negativeValues", "noteTextField", "opacity", "openField", "outliersField", "overlay", "padding", "q1Field", "q3Field", "segmentSpacing", "size", "sizeField", "spacing", "stack", "startAngle", "lineStyle", "summaryField", "target", "toField", "type", "upperField", "visible", "visibleInLegend", "visibleInLegendField", "visual", "width", "whiskers", "xAxis", "xErrorHighField", "xErrorLowField", "xField", "yAxis", "yErrorHighField", "yErrorLowField", "yField", "zIndex", "trendline", "for", "legendItem", "pattern", "patternField", "errorBars", "extremes", "highlight", "labels", "markers", "notes", "outliers", "tooltip"] }, { kind: "component", type: i1$7.TooltipComponent, selector: "kendo-chart-tooltip", inputs: ["background", "border", "color", "font", "format", "opacity", "padding", "shared", "visible"] }, { kind: "component", type: i1$7.ValueAxisComponent, selector: "kendo-chart-value-axis" }, { kind: "component", type: i1$7.ValueAxisItemComponent, selector: "kendo-chart-value-axis-item", inputs: ["axisCrossingValue", "background", "color", "line", "majorGridLines", "majorTicks", "majorUnit", "max", "min", "minorGridLines", "minorTicks", "minorUnit", "name", "narrowRange", "pane", "plotBands", "reverse", "type", "visible", "crosshair", "labels", "notes", "title"] }, { kind: "component", type: WidgetNotConfiguredComponent, selector: "mm-widget-not-configured" }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
14338
|
+
`, isInline: true, styles: [":host{display:block;width:100%;height:100%}.line-chart-widget{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;padding:8px;box-sizing:border-box;overflow:hidden}.data-count{position:absolute;top:2px;right:6px;z-index:2;font-size:.7rem;line-height:1;opacity:.55;color:var(--kendo-color-subtle, #6c757d);pointer-events:none;-webkit-user-select:none;user-select:none;font-variant-numeric:tabular-nums}.line-chart-widget.loading,.line-chart-widget.error{opacity:.7}.loading-indicator,.error-message{display:flex;align-items:center;justify-content:center;height:100%;width:100%}.loading-indicator span{font-size:1.5rem;color:var(--kendo-color-subtle, #6c757d)}.error-message span{color:var(--kendo-color-error, #dc3545);font-size:.875rem}.chart-container{width:100%;height:100%}kendo-chart{width:100%;height:100%}.chart-tooltip{padding:4px 8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ChartsModule }, { kind: "component", type: i1$7.ChartComponent, selector: "kendo-chart", inputs: ["pannable", "renderAs", "seriesColors", "subtitle", "title", "noData", "observeStyles", "transitions", "zoomable", "axisDefaults", "categoryAxis", "chartArea", "legend", "panes", "paneDefaults", "plotArea", "series", "seriesDefaults", "tooltip", "valueAxis", "xAxis", "yAxis", "resizeRateLimit", "popupSettings", "drilldownLevel"], outputs: ["axisLabelClick", "drag", "dragEnd", "dragStart", "legendItemHover", "legendItemLeave", "noteClick", "noteHover", "noteLeave", "paneRender", "plotAreaClick", "plotAreaHover", "plotAreaLeave", "render", "select", "selectEnd", "selectStart", "seriesClick", "drilldown", "seriesHover", "seriesOver", "seriesLeave", "zoom", "zoomEnd", "zoomStart", "legendItemClick", "drilldownLevelChange"], exportAs: ["kendoChart"] }, { kind: "directive", type: i1$7.SeriesTooltipTemplateDirective, selector: "[kendoChartSeriesTooltipTemplate]" }, { kind: "component", type: i1$7.CategoryAxisComponent, selector: "kendo-chart-category-axis" }, { kind: "component", type: i1$7.CategoryAxisItemComponent, selector: "kendo-chart-category-axis-item", inputs: ["autoBaseUnitSteps", "axisCrossingValue", "background", "baseUnit", "baseUnitStep", "categories", "color", "justified", "line", "majorGridLines", "majorTicks", "max", "maxDateGroups", "maxDivisions", "min", "minorGridLines", "minorTicks", "name", "pane", "plotBands", "reverse", "roundToBaseUnit", "startAngle", "type", "visible", "weekStartDay", "crosshair", "labels", "notes", "select", "title", "rangeLabels", "highlight"] }, { kind: "component", type: i1$7.CategoryAxisLabelsComponent, selector: "kendo-chart-category-axis-item-labels", inputs: ["background", "border", "color", "content", "culture", "dateFormats", "font", "format", "margin", "mirror", "padding", "position", "rotation", "skip", "step", "visible", "visual"] }, { kind: "component", type: i1$7.ChartAreaComponent, selector: "kendo-chart-area", inputs: ["background", "border", "height", "margin", "opacity", "width"] }, { kind: "component", type: i1$7.LegendComponent, selector: "kendo-chart-legend", inputs: ["align", "background", "border", "height", "labels", "margin", "offsetX", "offsetY", "orientation", "padding", "position", "reverse", "visible", "width", "markers", "spacing", "inactiveItems", "item", "title", "focusHighlight"] }, { kind: "component", type: i1$7.SeriesComponent, selector: "kendo-chart-series" }, { kind: "component", type: i1$7.SeriesItemComponent, selector: "kendo-chart-series-item", inputs: ["aggregate", "autoFit", "axis", "border", "categoryAxis", "categoryField", "closeField", "color", "colorField", "connectors", "currentField", "dashType", "data", "downColor", "downColorField", "drilldownField", "dynamicHeight", "dynamicSlope", "errorHighField", "errorLowField", "explodeField", "field", "fromField", "gap", "highField", "holeSize", "line", "lowField", "lowerField", "margin", "maxSize", "mean", "meanField", "median", "medianField", "minSize", "missingValues", "name", "neckRatio", "negativeColor", "negativeValues", "noteTextField", "opacity", "openField", "outliersField", "overlay", "padding", "q1Field", "q3Field", "segmentSpacing", "size", "sizeField", "spacing", "stack", "startAngle", "lineStyle", "summaryField", "target", "toField", "type", "upperField", "visible", "visibleInLegend", "visibleInLegendField", "visual", "width", "whiskers", "xAxis", "xErrorHighField", "xErrorLowField", "xField", "yAxis", "yErrorHighField", "yErrorLowField", "yField", "zIndex", "trendline", "for", "legendItem", "pattern", "patternField", "errorBars", "extremes", "highlight", "labels", "markers", "notes", "outliers", "tooltip"] }, { kind: "component", type: i1$7.TooltipComponent, selector: "kendo-chart-tooltip", inputs: ["background", "border", "color", "font", "format", "opacity", "padding", "shared", "visible"] }, { kind: "component", type: i1$7.ValueAxisComponent, selector: "kendo-chart-value-axis" }, { kind: "component", type: i1$7.ValueAxisItemComponent, selector: "kendo-chart-value-axis-item", inputs: ["axisCrossingValue", "background", "color", "line", "majorGridLines", "majorTicks", "majorUnit", "max", "min", "minorGridLines", "minorTicks", "minorUnit", "name", "narrowRange", "pane", "plotBands", "reverse", "type", "visible", "crosshair", "labels", "notes", "title"] }, { kind: "component", type: WidgetNotConfiguredComponent, selector: "mm-widget-not-configured" }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
13917
14339
|
}
|
|
13918
14340
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: LineChartWidgetComponent, decorators: [{
|
|
13919
14341
|
type: Component,
|
|
@@ -13934,6 +14356,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
13934
14356
|
<span>{{ error() }}</span>
|
|
13935
14357
|
</div>
|
|
13936
14358
|
} @else {
|
|
14359
|
+
@if (dataInfo(); as info) {
|
|
14360
|
+
<span class="data-count" [title]="'Loaded rows · distinct category points (totalCount ' + info.total + ')'">
|
|
14361
|
+
{{ info.rows }} rows · {{ info.points }} pts
|
|
14362
|
+
</span>
|
|
14363
|
+
}
|
|
13937
14364
|
<kendo-chart class="chart-container" [plotArea]="{ background: 'transparent', margin: { top: 0, right: 0, bottom: 0, left: 0 } }">
|
|
13938
14365
|
<kendo-chart-area [background]="'transparent'"></kendo-chart-area>
|
|
13939
14366
|
|
|
@@ -13978,12 +14405,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
13978
14405
|
|
|
13979
14406
|
<kendo-chart-series>
|
|
13980
14407
|
@for (series of seriesData(); track series.name) {
|
|
14408
|
+
@if (series.band) {
|
|
14409
|
+
<kendo-chart-series-item
|
|
14410
|
+
[type]="'rangeArea'"
|
|
14411
|
+
[data]="series.band"
|
|
14412
|
+
[fromField]="'from'"
|
|
14413
|
+
[toField]="'to'"
|
|
14414
|
+
[name]="series.name + ' (min/max)'"
|
|
14415
|
+
[axis]="series.axisName ?? ''"
|
|
14416
|
+
[color]="series.color"
|
|
14417
|
+
[opacity]="0.18"
|
|
14418
|
+
[markers]="{ visible: false }">
|
|
14419
|
+
</kendo-chart-series-item>
|
|
14420
|
+
}
|
|
13981
14421
|
<kendo-chart-series-item
|
|
13982
14422
|
[type]="chartType()"
|
|
13983
14423
|
[style]="'smooth'"
|
|
13984
14424
|
[data]="series.data"
|
|
13985
14425
|
[name]="series.name"
|
|
13986
14426
|
[axis]="series.axisName ?? ''"
|
|
14427
|
+
[color]="series.color"
|
|
13987
14428
|
[opacity]="0.7"
|
|
13988
14429
|
[markers]="{ visible: config.showMarkers ?? false }">
|
|
13989
14430
|
</kendo-chart-series-item>
|
|
@@ -14006,7 +14447,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
14006
14447
|
</kendo-chart>
|
|
14007
14448
|
}
|
|
14008
14449
|
</div>
|
|
14009
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block;width:100%;height:100%}.line-chart-widget{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;padding:8px;box-sizing:border-box;overflow:hidden}.line-chart-widget.loading,.line-chart-widget.error{opacity:.7}.loading-indicator,.error-message{display:flex;align-items:center;justify-content:center;height:100%;width:100%}.loading-indicator span{font-size:1.5rem;color:var(--kendo-color-subtle, #6c757d)}.error-message span{color:var(--kendo-color-error, #dc3545);font-size:.875rem}.chart-container{width:100%;height:100%}kendo-chart{width:100%;height:100%}.chart-tooltip{padding:4px 8px}\n"] }]
|
|
14450
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block;width:100%;height:100%}.line-chart-widget{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;padding:8px;box-sizing:border-box;overflow:hidden}.data-count{position:absolute;top:2px;right:6px;z-index:2;font-size:.7rem;line-height:1;opacity:.55;color:var(--kendo-color-subtle, #6c757d);pointer-events:none;-webkit-user-select:none;user-select:none;font-variant-numeric:tabular-nums}.line-chart-widget.loading,.line-chart-widget.error{opacity:.7}.loading-indicator,.error-message{display:flex;align-items:center;justify-content:center;height:100%;width:100%}.loading-indicator span{font-size:1.5rem;color:var(--kendo-color-subtle, #6c757d)}.error-message span{color:var(--kendo-color-error, #dc3545);font-size:.875rem}.chart-container{width:100%;height:100%}kendo-chart{width:100%;height:100%}.chart-tooltip{padding:4px 8px}\n"] }]
|
|
14010
14451
|
}], propDecorators: { config: [{
|
|
14011
14452
|
type: Input
|
|
14012
14453
|
}] } });
|
|
@@ -14026,6 +14467,7 @@ class LineChartConfigDialogComponent {
|
|
|
14026
14467
|
initialQueryName;
|
|
14027
14468
|
initialQueryFamily;
|
|
14028
14469
|
initialIgnoreTimeFilter;
|
|
14470
|
+
initialEntitySelectorId;
|
|
14029
14471
|
initialChartType;
|
|
14030
14472
|
initialCategoryField;
|
|
14031
14473
|
initialSeriesGroupField;
|
|
@@ -14046,6 +14488,12 @@ class LineChartConfigDialogComponent {
|
|
|
14046
14488
|
nonNumericColumns = [];
|
|
14047
14489
|
/** Per-widget opt-out of the MeshBoard time-filter → stream-data binding. */
|
|
14048
14490
|
ignoreTimeFilter = false;
|
|
14491
|
+
/** Asset-scope binding: id of the entity selector whose selection scopes the stream-data query. */
|
|
14492
|
+
entitySelectorId;
|
|
14493
|
+
/** Entity selectors available on the current MeshBoard (for the scope picker). */
|
|
14494
|
+
get availableEntitySelectors() {
|
|
14495
|
+
return this.stateService.getEntitySelectors();
|
|
14496
|
+
}
|
|
14049
14497
|
/** Family of the currently selected query — gates the time-filter opt-out toggle. */
|
|
14050
14498
|
get selectedQueryFamily() {
|
|
14051
14499
|
return queryFamily(this.selectedPersistentQuery?.ckTypeId) ?? this.initialQueryFamily ?? null;
|
|
@@ -14087,6 +14535,7 @@ class LineChartConfigDialogComponent {
|
|
|
14087
14535
|
}));
|
|
14088
14536
|
// Initialize form with initial values
|
|
14089
14537
|
this.ignoreTimeFilter = this.initialIgnoreTimeFilter ?? false;
|
|
14538
|
+
this.entitySelectorId = this.initialEntitySelectorId;
|
|
14090
14539
|
this.form.chartType = this.initialChartType ?? 'line';
|
|
14091
14540
|
this.form.categoryField = this.initialCategoryField ?? '';
|
|
14092
14541
|
this.form.seriesGroupField = this.initialSeriesGroupField ?? '';
|
|
@@ -14205,6 +14654,7 @@ class LineChartConfigDialogComponent {
|
|
|
14205
14654
|
queryName: this.selectedPersistentQuery.name,
|
|
14206
14655
|
queryFamily: family,
|
|
14207
14656
|
ignoreTimeFilter: this.ignoreTimeFilter,
|
|
14657
|
+
entitySelectorId: this.entitySelectorId,
|
|
14208
14658
|
chartType: this.form.chartType,
|
|
14209
14659
|
categoryField: this.form.categoryField,
|
|
14210
14660
|
seriesGroupField: this.form.seriesGroupField,
|
|
@@ -14228,7 +14678,7 @@ class LineChartConfigDialogComponent {
|
|
|
14228
14678
|
this.windowRef.close();
|
|
14229
14679
|
}
|
|
14230
14680
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: LineChartConfigDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14231
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: LineChartConfigDialogComponent, isStandalone: true, selector: "mm-line-chart-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialSeriesGroupField: "initialSeriesGroupField", initialValueField: "initialValueField", initialUnitField: "initialUnitField", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialShowMarkers: "initialShowMarkers", initialReferenceLines: "initialReferenceLines", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
14681
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: LineChartConfigDialogComponent, isStandalone: true, selector: "mm-line-chart-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialChartType: "initialChartType", initialCategoryField: "initialCategoryField", initialSeriesGroupField: "initialSeriesGroupField", initialValueField: "initialValueField", initialUnitField: "initialUnitField", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialShowMarkers: "initialShowMarkers", initialReferenceLines: "initialReferenceLines", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
14232
14682
|
<div class="config-container">
|
|
14233
14683
|
|
|
14234
14684
|
<div class="config-form" [class.loading]="isLoadingInitial">
|
|
@@ -14253,6 +14703,12 @@ class LineChartConfigDialogComponent {
|
|
|
14253
14703
|
[family]="selectedQueryFamily"
|
|
14254
14704
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
14255
14705
|
</mm-sd-time-filter-toggle>
|
|
14706
|
+
|
|
14707
|
+
<mm-entity-selector-scope-picker
|
|
14708
|
+
[family]="selectedQueryFamily"
|
|
14709
|
+
[selectors]="availableEntitySelectors"
|
|
14710
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
14711
|
+
</mm-entity-selector-scope-picker>
|
|
14256
14712
|
</div>
|
|
14257
14713
|
|
|
14258
14714
|
<!-- Field Mapping Section -->
|
|
@@ -14436,7 +14892,7 @@ class LineChartConfigDialogComponent {
|
|
|
14436
14892
|
</button>
|
|
14437
14893
|
</div>
|
|
14438
14894
|
</div>
|
|
14439
|
-
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.chart-type-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.form-row{display:flex;gap:24px;align-items:center}.checkbox-field{flex-direction:row;align-items:center;margin-bottom:0}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{margin-top:8px}.form-section h4{margin:0 0 4px;font-size:.95rem;font-weight:600}.reference-line-row{display:flex;gap:8px;align-items:center;margin-bottom:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
14895
|
+
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.chart-type-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.form-row{display:flex;gap:24px;align-items:center}.checkbox-field{flex-direction:row;align-items:center;margin-bottom:0}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.form-section{margin-top:8px}.form-section h4{margin:0 0 4px;font-size:.95rem;font-weight:600}.reference-line-row{display:flex;gap:8px;align-items:center;margin-bottom:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
14440
14896
|
}
|
|
14441
14897
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: LineChartConfigDialogComponent, decorators: [{
|
|
14442
14898
|
type: Component,
|
|
@@ -14450,6 +14906,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
14450
14906
|
FieldFilterEditorComponent,
|
|
14451
14907
|
QuerySelectorComponent,
|
|
14452
14908
|
SdTimeFilterToggleComponent,
|
|
14909
|
+
EntitySelectorScopePickerComponent,
|
|
14453
14910
|
LoadingOverlayComponent
|
|
14454
14911
|
], template: `
|
|
14455
14912
|
<div class="config-container">
|
|
@@ -14476,6 +14933,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
14476
14933
|
[family]="selectedQueryFamily"
|
|
14477
14934
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
14478
14935
|
</mm-sd-time-filter-toggle>
|
|
14936
|
+
|
|
14937
|
+
<mm-entity-selector-scope-picker
|
|
14938
|
+
[family]="selectedQueryFamily"
|
|
14939
|
+
[selectors]="availableEntitySelectors"
|
|
14940
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
14941
|
+
</mm-entity-selector-scope-picker>
|
|
14479
14942
|
</div>
|
|
14480
14943
|
|
|
14481
14944
|
<!-- Field Mapping Section -->
|
|
@@ -14671,6 +15134,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
14671
15134
|
type: Input
|
|
14672
15135
|
}], initialIgnoreTimeFilter: [{
|
|
14673
15136
|
type: Input
|
|
15137
|
+
}], initialEntitySelectorId: [{
|
|
15138
|
+
type: Input
|
|
14674
15139
|
}], initialChartType: [{
|
|
14675
15140
|
type: Input
|
|
14676
15141
|
}], initialCategoryField: [{
|
|
@@ -14866,7 +15331,12 @@ class HeatmapWidgetComponent {
|
|
|
14866
15331
|
}
|
|
14867
15332
|
buildStreamDataArgs() {
|
|
14868
15333
|
const ds = this.config.dataSource;
|
|
14869
|
-
|
|
15334
|
+
const timeArgs = this.stateService.resolveStreamDataTimeArgs(ds.ignoreTimeFilter);
|
|
15335
|
+
const rtIds = this.stateService.resolveStreamDataRtIds(ds.entitySelectorId);
|
|
15336
|
+
if (!timeArgs && !rtIds) {
|
|
15337
|
+
return undefined;
|
|
15338
|
+
}
|
|
15339
|
+
return { ...timeArgs, rtIds };
|
|
14870
15340
|
}
|
|
14871
15341
|
/**
|
|
14872
15342
|
* Processes query rows into heatmap data.
|
|
@@ -15219,6 +15689,7 @@ class HeatmapConfigDialogComponent {
|
|
|
15219
15689
|
initialQueryName;
|
|
15220
15690
|
initialQueryFamily;
|
|
15221
15691
|
initialIgnoreTimeFilter;
|
|
15692
|
+
initialEntitySelectorId;
|
|
15222
15693
|
initialDateField;
|
|
15223
15694
|
initialDateEndField;
|
|
15224
15695
|
initialValueField;
|
|
@@ -15236,6 +15707,7 @@ class HeatmapConfigDialogComponent {
|
|
|
15236
15707
|
// Persistent Query
|
|
15237
15708
|
selectedPersistentQuery = null;
|
|
15238
15709
|
ignoreTimeFilter = false;
|
|
15710
|
+
entitySelectorId;
|
|
15239
15711
|
queryColumns = [];
|
|
15240
15712
|
numericColumns = [];
|
|
15241
15713
|
dateTimeColumns = [];
|
|
@@ -15284,6 +15756,10 @@ class HeatmapConfigDialogComponent {
|
|
|
15284
15756
|
get isValid() {
|
|
15285
15757
|
return this.selectedPersistentQuery !== null && this.form.dateField !== '';
|
|
15286
15758
|
}
|
|
15759
|
+
/** Entity selectors available on the current MeshBoard (for the scope picker). */
|
|
15760
|
+
get availableEntitySelectors() {
|
|
15761
|
+
return this.stateService.getEntitySelectors();
|
|
15762
|
+
}
|
|
15287
15763
|
get selectedQueryFamily() {
|
|
15288
15764
|
return queryFamily(this.selectedPersistentQuery?.ckTypeId) ?? this.initialQueryFamily ?? null;
|
|
15289
15765
|
}
|
|
@@ -15306,6 +15782,7 @@ class HeatmapConfigDialogComponent {
|
|
|
15306
15782
|
this.form.compactNumbers = this.initialCompactNumbers ?? false;
|
|
15307
15783
|
this.form.valueMultiplier = this.initialValueMultiplier ?? 1;
|
|
15308
15784
|
this.ignoreTimeFilter = this.initialIgnoreTimeFilter ?? false;
|
|
15785
|
+
this.entitySelectorId = this.initialEntitySelectorId;
|
|
15309
15786
|
// Initialize filters
|
|
15310
15787
|
if (this.initialFilters && this.initialFilters.length > 0) {
|
|
15311
15788
|
this.filters = this.initialFilters.map((f, index) => ({
|
|
@@ -15423,6 +15900,7 @@ class HeatmapConfigDialogComponent {
|
|
|
15423
15900
|
queryName: this.selectedPersistentQuery.name,
|
|
15424
15901
|
queryFamily: family,
|
|
15425
15902
|
ignoreTimeFilter: this.ignoreTimeFilter,
|
|
15903
|
+
entitySelectorId: this.entitySelectorId,
|
|
15426
15904
|
dateField: this.form.dateField,
|
|
15427
15905
|
dateEndField: this.form.dateEndField || undefined,
|
|
15428
15906
|
valueField: this.form.valueField || undefined,
|
|
@@ -15441,7 +15919,7 @@ class HeatmapConfigDialogComponent {
|
|
|
15441
15919
|
this.windowRef.close();
|
|
15442
15920
|
}
|
|
15443
15921
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: HeatmapConfigDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
15444
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: HeatmapConfigDialogComponent, isStandalone: true, selector: "mm-heatmap-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialDateField: "initialDateField", initialDateEndField: "initialDateEndField", initialValueField: "initialValueField", initialAggregation: "initialAggregation", initialColorScheme: "initialColorScheme", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialDecimalPlaces: "initialDecimalPlaces", initialCompactNumbers: "initialCompactNumbers", initialValueMultiplier: "initialValueMultiplier", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
15922
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: HeatmapConfigDialogComponent, isStandalone: true, selector: "mm-heatmap-config-dialog", inputs: { initialQueryRtId: "initialQueryRtId", initialQueryName: "initialQueryName", initialQueryFamily: "initialQueryFamily", initialIgnoreTimeFilter: "initialIgnoreTimeFilter", initialEntitySelectorId: "initialEntitySelectorId", initialDateField: "initialDateField", initialDateEndField: "initialDateEndField", initialValueField: "initialValueField", initialAggregation: "initialAggregation", initialColorScheme: "initialColorScheme", initialShowLegend: "initialShowLegend", initialLegendPosition: "initialLegendPosition", initialDecimalPlaces: "initialDecimalPlaces", initialCompactNumbers: "initialCompactNumbers", initialValueMultiplier: "initialValueMultiplier", initialFilters: "initialFilters" }, viewQueries: [{ propertyName: "querySelector", first: true, predicate: ["querySelector"], descendants: true }], ngImport: i0, template: `
|
|
15445
15923
|
<div class="config-container">
|
|
15446
15924
|
|
|
15447
15925
|
<div class="config-form" [class.loading]="isLoadingInitial">
|
|
@@ -15466,6 +15944,12 @@ class HeatmapConfigDialogComponent {
|
|
|
15466
15944
|
[family]="selectedQueryFamily"
|
|
15467
15945
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
15468
15946
|
</mm-sd-time-filter-toggle>
|
|
15947
|
+
|
|
15948
|
+
<mm-entity-selector-scope-picker
|
|
15949
|
+
[family]="selectedQueryFamily"
|
|
15950
|
+
[selectors]="availableEntitySelectors"
|
|
15951
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
15952
|
+
</mm-entity-selector-scope-picker>
|
|
15469
15953
|
</div>
|
|
15470
15954
|
|
|
15471
15955
|
<!-- Field Mapping Section -->
|
|
@@ -15655,7 +16139,7 @@ class HeatmapConfigDialogComponent {
|
|
|
15655
16139
|
</button>
|
|
15656
16140
|
</div>
|
|
15657
16141
|
</div>
|
|
15658
|
-
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.color-scheme-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.color-scheme-preview{display:flex;align-items:center;gap:6px}.color-swatch{display:inline-block;width:16px;height:16px;border-radius:3px;border:1px solid var(--kendo-color-border, #dee2e6)}.form-row{display:flex;gap:24px}.checkbox-field{flex-direction:row;align-items:center}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
16142
|
+
`, isInline: true, styles: [":host{display:block;height:100%}.config-container{display:flex;flex-direction:column;height:100%}.action-bar{display:flex;justify-content:flex-end;gap:8px;padding:8px 16px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.config-form{display:flex;flex-direction:column;gap:20px;flex:1;overflow-y:auto;padding:16px;position:relative}.config-form.loading{pointer-events:none}.config-section{padding:16px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.section-title{margin:0 0 16px;font-size:1rem;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.section-hint{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.form-field:last-child{margin-bottom:0}.form-field label{font-weight:600;font-size:.9rem;color:var(--kendo-color-on-app-surface, #212529)}.required{color:var(--kendo-color-error, #dc3545)}.field-hint{margin:0;font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}.color-scheme-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.radio-label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.color-scheme-preview{display:flex;align-items:center;gap:6px}.color-swatch{display:inline-block;width:16px;height:16px;border-radius:3px;border:1px solid var(--kendo-color-border, #dee2e6)}.form-row{display:flex;gap:24px}.checkbox-field{flex-direction:row;align-items:center}.checkbox-field label{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400}.column-item{display:flex;justify-content:space-between;gap:16px}.column-path{font-weight:500}.column-type{font-size:.8rem;color:var(--kendo-color-subtle, #6c757d)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "directive", type: i3.RadioButtonDirective, selector: "input[kendoRadioButton]", inputs: ["size"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "directive", type: i4.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: FieldFilterEditorComponent, selector: "mm-field-filter-editor", inputs: ["availableAttributes", "ckTypeId", "hideNavigationProperties", "attributePaths", "enableVariables", "availableVariables", "filters"], outputs: ["filtersChange"] }, { kind: "component", type: QuerySelectorComponent, selector: "mm-query-selector", inputs: ["placeholder", "hint", "disabled", "acceptFamilies"], outputs: ["querySelected", "queriesLoaded"] }, { kind: "component", type: SdTimeFilterToggleComponent, selector: "mm-sd-time-filter-toggle", inputs: ["family", "ignoreTimeFilter"], outputs: ["ignoreTimeFilterChange"] }, { kind: "component", type: EntitySelectorScopePickerComponent, selector: "mm-entity-selector-scope-picker", inputs: ["family", "entitySelectorId", "selectors"], outputs: ["entitySelectorIdChange"] }, { kind: "component", type: LoadingOverlayComponent, selector: "mm-loading-overlay", inputs: ["loading"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
15659
16143
|
}
|
|
15660
16144
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: HeatmapConfigDialogComponent, decorators: [{
|
|
15661
16145
|
type: Component,
|
|
@@ -15669,6 +16153,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
15669
16153
|
FieldFilterEditorComponent,
|
|
15670
16154
|
QuerySelectorComponent,
|
|
15671
16155
|
SdTimeFilterToggleComponent,
|
|
16156
|
+
EntitySelectorScopePickerComponent,
|
|
15672
16157
|
LoadingOverlayComponent
|
|
15673
16158
|
], template: `
|
|
15674
16159
|
<div class="config-container">
|
|
@@ -15695,6 +16180,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
15695
16180
|
[family]="selectedQueryFamily"
|
|
15696
16181
|
[(ignoreTimeFilter)]="ignoreTimeFilter">
|
|
15697
16182
|
</mm-sd-time-filter-toggle>
|
|
16183
|
+
|
|
16184
|
+
<mm-entity-selector-scope-picker
|
|
16185
|
+
[family]="selectedQueryFamily"
|
|
16186
|
+
[selectors]="availableEntitySelectors"
|
|
16187
|
+
[(entitySelectorId)]="entitySelectorId">
|
|
16188
|
+
</mm-entity-selector-scope-picker>
|
|
15698
16189
|
</div>
|
|
15699
16190
|
|
|
15700
16191
|
<!-- Field Mapping Section -->
|
|
@@ -15896,6 +16387,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
15896
16387
|
type: Input
|
|
15897
16388
|
}], initialIgnoreTimeFilter: [{
|
|
15898
16389
|
type: Input
|
|
16390
|
+
}], initialEntitySelectorId: [{
|
|
16391
|
+
type: Input
|
|
15899
16392
|
}], initialDateField: [{
|
|
15900
16393
|
type: Input
|
|
15901
16394
|
}], initialDateEndField: [{
|
|
@@ -25958,6 +26451,9 @@ function buildDataSourceFromPersisted(data, config) {
|
|
|
25958
26451
|
if (typeof config['ignoreTimeFilter'] === 'boolean') {
|
|
25959
26452
|
persisted.ignoreTimeFilter = config['ignoreTimeFilter'];
|
|
25960
26453
|
}
|
|
26454
|
+
if (typeof config['entitySelectorId'] === 'string' && config['entitySelectorId']) {
|
|
26455
|
+
persisted.entitySelectorId = config['entitySelectorId'];
|
|
26456
|
+
}
|
|
25961
26457
|
return persisted;
|
|
25962
26458
|
}
|
|
25963
26459
|
if (data.dataSourceType === 'static') {
|
|
@@ -26080,6 +26576,7 @@ function registerDefaultWidgets(registry) {
|
|
|
26080
26576
|
initialQueryName: isPersistentQuery ? kpiWidget.dataSource.queryName : undefined,
|
|
26081
26577
|
initialQueryFamily: isPersistentQuery ? kpiWidget.dataSource.queryFamily : undefined,
|
|
26082
26578
|
initialIgnoreTimeFilter: isPersistentQuery ? kpiWidget.dataSource.ignoreTimeFilter : undefined,
|
|
26579
|
+
initialEntitySelectorId: isPersistentQuery ? kpiWidget.dataSource.entitySelectorId : undefined,
|
|
26083
26580
|
initialQueryMode: kpiWidget.queryMode,
|
|
26084
26581
|
initialQueryValueField: kpiWidget.queryValueField,
|
|
26085
26582
|
initialQueryCategoryField: kpiWidget.queryCategoryField,
|
|
@@ -26126,7 +26623,8 @@ function registerDefaultWidgets(registry) {
|
|
|
26126
26623
|
queryRtId: result.queryRtId,
|
|
26127
26624
|
queryName: result.queryName,
|
|
26128
26625
|
queryFamily: result.queryFamily,
|
|
26129
|
-
ignoreTimeFilter: result.ignoreTimeFilter
|
|
26626
|
+
ignoreTimeFilter: result.ignoreTimeFilter,
|
|
26627
|
+
entitySelectorId: result.entitySelectorId
|
|
26130
26628
|
};
|
|
26131
26629
|
return {
|
|
26132
26630
|
...widget,
|
|
@@ -26203,6 +26701,9 @@ function registerDefaultWidgets(registry) {
|
|
|
26203
26701
|
}),
|
|
26204
26702
|
...(widget.dataSource.ignoreTimeFilter && {
|
|
26205
26703
|
ignoreTimeFilter: true
|
|
26704
|
+
}),
|
|
26705
|
+
...(widget.dataSource.entitySelectorId && {
|
|
26706
|
+
entitySelectorId: widget.dataSource.entitySelectorId
|
|
26206
26707
|
})
|
|
26207
26708
|
})
|
|
26208
26709
|
}
|
|
@@ -26369,7 +26870,8 @@ function registerDefaultWidgets(registry) {
|
|
|
26369
26870
|
initialQueryRtId: isPersistentQuery ? dataSource.queryRtId : undefined,
|
|
26370
26871
|
initialQueryName: isPersistentQuery ? dataSource.queryName : undefined,
|
|
26371
26872
|
initialQueryFamily: isPersistentQuery ? dataSource.queryFamily : undefined,
|
|
26372
|
-
initialIgnoreTimeFilter: isPersistentQuery ? dataSource.ignoreTimeFilter : undefined
|
|
26873
|
+
initialIgnoreTimeFilter: isPersistentQuery ? dataSource.ignoreTimeFilter : undefined,
|
|
26874
|
+
initialEntitySelectorId: isPersistentQuery ? dataSource.entitySelectorId : undefined
|
|
26373
26875
|
};
|
|
26374
26876
|
},
|
|
26375
26877
|
applyConfigResult: (widget, result) => {
|
|
@@ -26380,7 +26882,8 @@ function registerDefaultWidgets(registry) {
|
|
|
26380
26882
|
queryRtId: result.queryRtId,
|
|
26381
26883
|
queryName: result.queryName,
|
|
26382
26884
|
queryFamily: result.queryFamily,
|
|
26383
|
-
ignoreTimeFilter: result.ignoreTimeFilter
|
|
26885
|
+
ignoreTimeFilter: result.ignoreTimeFilter,
|
|
26886
|
+
entitySelectorId: result.entitySelectorId
|
|
26384
26887
|
};
|
|
26385
26888
|
// Convert filters from DTO to widget format
|
|
26386
26889
|
const filters = result.filters?.map(f => ({
|
|
@@ -26451,7 +26954,8 @@ function registerDefaultWidgets(registry) {
|
|
|
26451
26954
|
queryName: queryDataSource.queryName,
|
|
26452
26955
|
queryRtId: queryDataSource.queryRtId,
|
|
26453
26956
|
...(queryDataSource.queryFamily && { queryFamily: queryDataSource.queryFamily }),
|
|
26454
|
-
...(queryDataSource.ignoreTimeFilter && { ignoreTimeFilter: true })
|
|
26957
|
+
...(queryDataSource.ignoreTimeFilter && { ignoreTimeFilter: true }),
|
|
26958
|
+
...(queryDataSource.entitySelectorId && { entitySelectorId: queryDataSource.entitySelectorId })
|
|
26455
26959
|
})
|
|
26456
26960
|
}
|
|
26457
26961
|
};
|
|
@@ -26498,6 +27002,7 @@ function registerDefaultWidgets(registry) {
|
|
|
26498
27002
|
initialQueryName: isPersistentQuery ? gaugeWidget.dataSource.queryName : undefined,
|
|
26499
27003
|
initialQueryFamily: isPersistentQuery ? gaugeWidget.dataSource.queryFamily : undefined,
|
|
26500
27004
|
initialIgnoreTimeFilter: isPersistentQuery ? gaugeWidget.dataSource.ignoreTimeFilter : undefined,
|
|
27005
|
+
initialEntitySelectorId: isPersistentQuery ? gaugeWidget.dataSource.entitySelectorId : undefined,
|
|
26501
27006
|
initialQueryMode: gaugeWidget.queryMode,
|
|
26502
27007
|
initialQueryValueField: gaugeWidget.queryValueField,
|
|
26503
27008
|
initialQueryCategoryField: gaugeWidget.queryCategoryField,
|
|
@@ -26529,7 +27034,8 @@ function registerDefaultWidgets(registry) {
|
|
|
26529
27034
|
queryRtId: result.queryRtId,
|
|
26530
27035
|
queryName: result.queryName,
|
|
26531
27036
|
queryFamily: result.queryFamily,
|
|
26532
|
-
ignoreTimeFilter: result.ignoreTimeFilter
|
|
27037
|
+
ignoreTimeFilter: result.ignoreTimeFilter,
|
|
27038
|
+
entitySelectorId: result.entitySelectorId
|
|
26533
27039
|
};
|
|
26534
27040
|
return {
|
|
26535
27041
|
...widget,
|
|
@@ -26617,6 +27123,9 @@ function registerDefaultWidgets(registry) {
|
|
|
26617
27123
|
}),
|
|
26618
27124
|
...(widget.dataSource.ignoreTimeFilter && {
|
|
26619
27125
|
ignoreTimeFilter: true
|
|
27126
|
+
}),
|
|
27127
|
+
...(widget.dataSource.entitySelectorId && {
|
|
27128
|
+
entitySelectorId: widget.dataSource.entitySelectorId
|
|
26620
27129
|
})
|
|
26621
27130
|
})
|
|
26622
27131
|
}
|
|
@@ -26688,6 +27197,7 @@ function registerDefaultWidgets(registry) {
|
|
|
26688
27197
|
initialQueryName: isPersistentQuery ? dataSource.queryName : undefined,
|
|
26689
27198
|
initialQueryFamily: isPersistentQuery ? dataSource.queryFamily : undefined,
|
|
26690
27199
|
initialIgnoreTimeFilter: isPersistentQuery ? dataSource.ignoreTimeFilter : undefined,
|
|
27200
|
+
initialEntitySelectorId: isPersistentQuery ? dataSource.entitySelectorId : undefined,
|
|
26691
27201
|
initialCkQueryTarget: isCkQuery ? dataSource.queryTarget : undefined,
|
|
26692
27202
|
initialCkGroupBy: isCkQuery ? dataSource.groupBy : undefined,
|
|
26693
27203
|
initialChartType: pieWidget.chartType,
|
|
@@ -26722,7 +27232,8 @@ function registerDefaultWidgets(registry) {
|
|
|
26722
27232
|
queryRtId: result.queryRtId ?? '',
|
|
26723
27233
|
queryName: result.queryName,
|
|
26724
27234
|
queryFamily: result.queryFamily,
|
|
26725
|
-
ignoreTimeFilter: result.ignoreTimeFilter
|
|
27235
|
+
ignoreTimeFilter: result.ignoreTimeFilter,
|
|
27236
|
+
entitySelectorId: result.entitySelectorId
|
|
26726
27237
|
};
|
|
26727
27238
|
}
|
|
26728
27239
|
return {
|
|
@@ -26790,6 +27301,9 @@ function registerDefaultWidgets(registry) {
|
|
|
26790
27301
|
...(dataSource.ignoreTimeFilter && {
|
|
26791
27302
|
ignoreTimeFilter: true
|
|
26792
27303
|
}),
|
|
27304
|
+
...(dataSource.entitySelectorId && {
|
|
27305
|
+
entitySelectorId: dataSource.entitySelectorId
|
|
27306
|
+
}),
|
|
26793
27307
|
filters: widget.filters
|
|
26794
27308
|
}
|
|
26795
27309
|
};
|
|
@@ -26853,6 +27367,7 @@ function registerDefaultWidgets(registry) {
|
|
|
26853
27367
|
initialQueryName: isPersistentQuery ? dataSource.queryName : undefined,
|
|
26854
27368
|
initialQueryFamily: isPersistentQuery ? dataSource.queryFamily : undefined,
|
|
26855
27369
|
initialIgnoreTimeFilter: isPersistentQuery ? dataSource.ignoreTimeFilter : undefined,
|
|
27370
|
+
initialEntitySelectorId: isPersistentQuery ? dataSource.entitySelectorId : undefined,
|
|
26856
27371
|
initialChartType: barWidget.chartType,
|
|
26857
27372
|
initialCategoryField: barWidget.categoryField,
|
|
26858
27373
|
initialSeries: barWidget.series,
|
|
@@ -26872,7 +27387,8 @@ function registerDefaultWidgets(registry) {
|
|
|
26872
27387
|
queryRtId: result.queryRtId,
|
|
26873
27388
|
queryName: result.queryName,
|
|
26874
27389
|
queryFamily: result.queryFamily,
|
|
26875
|
-
ignoreTimeFilter: result.ignoreTimeFilter
|
|
27390
|
+
ignoreTimeFilter: result.ignoreTimeFilter,
|
|
27391
|
+
entitySelectorId: result.entitySelectorId
|
|
26876
27392
|
};
|
|
26877
27393
|
// Convert filters from DTO to widget format
|
|
26878
27394
|
const filters = result.filters?.map(f => ({
|
|
@@ -26934,6 +27450,9 @@ function registerDefaultWidgets(registry) {
|
|
|
26934
27450
|
...(widget.dataSource.ignoreTimeFilter && {
|
|
26935
27451
|
ignoreTimeFilter: true
|
|
26936
27452
|
}),
|
|
27453
|
+
...(widget.dataSource.entitySelectorId && {
|
|
27454
|
+
entitySelectorId: widget.dataSource.entitySelectorId
|
|
27455
|
+
}),
|
|
26937
27456
|
filters: widget.filters
|
|
26938
27457
|
}
|
|
26939
27458
|
}),
|
|
@@ -26980,6 +27499,7 @@ function registerDefaultWidgets(registry) {
|
|
|
26980
27499
|
initialQueryName: isPersistentQuery ? dataSource.queryName : undefined,
|
|
26981
27500
|
initialQueryFamily: isPersistentQuery ? dataSource.queryFamily : undefined,
|
|
26982
27501
|
initialIgnoreTimeFilter: isPersistentQuery ? dataSource.ignoreTimeFilter : undefined,
|
|
27502
|
+
initialEntitySelectorId: isPersistentQuery ? dataSource.entitySelectorId : undefined,
|
|
26983
27503
|
initialChartType: lineWidget.chartType,
|
|
26984
27504
|
initialCategoryField: lineWidget.categoryField,
|
|
26985
27505
|
initialSeriesGroupField: lineWidget.seriesGroupField,
|
|
@@ -26998,7 +27518,8 @@ function registerDefaultWidgets(registry) {
|
|
|
26998
27518
|
queryRtId: result.queryRtId,
|
|
26999
27519
|
queryName: result.queryName,
|
|
27000
27520
|
queryFamily: result.queryFamily,
|
|
27001
|
-
ignoreTimeFilter: result.ignoreTimeFilter
|
|
27521
|
+
ignoreTimeFilter: result.ignoreTimeFilter,
|
|
27522
|
+
entitySelectorId: result.entitySelectorId
|
|
27002
27523
|
};
|
|
27003
27524
|
const filters = result.filters?.map(f => ({
|
|
27004
27525
|
attributePath: f.attributePath,
|
|
@@ -27055,6 +27576,9 @@ function registerDefaultWidgets(registry) {
|
|
|
27055
27576
|
...(widget.dataSource.ignoreTimeFilter && {
|
|
27056
27577
|
ignoreTimeFilter: true
|
|
27057
27578
|
}),
|
|
27579
|
+
...(widget.dataSource.entitySelectorId && {
|
|
27580
|
+
entitySelectorId: widget.dataSource.entitySelectorId
|
|
27581
|
+
}),
|
|
27058
27582
|
filters: widget.filters
|
|
27059
27583
|
}
|
|
27060
27584
|
}),
|
|
@@ -27529,6 +28053,7 @@ function registerDefaultWidgets(registry) {
|
|
|
27529
28053
|
initialQueryName: isPersistentQuery ? dataSource.queryName : undefined,
|
|
27530
28054
|
initialQueryFamily: isPersistentQuery ? dataSource.queryFamily : undefined,
|
|
27531
28055
|
initialIgnoreTimeFilter: isPersistentQuery ? dataSource.ignoreTimeFilter : undefined,
|
|
28056
|
+
initialEntitySelectorId: isPersistentQuery ? dataSource.entitySelectorId : undefined,
|
|
27532
28057
|
initialDateField: heatmapWidget.dateField,
|
|
27533
28058
|
initialDateEndField: heatmapWidget.dateEndField,
|
|
27534
28059
|
initialValueField: heatmapWidget.valueField,
|
|
@@ -27548,7 +28073,8 @@ function registerDefaultWidgets(registry) {
|
|
|
27548
28073
|
queryRtId: result.queryRtId,
|
|
27549
28074
|
queryName: result.queryName,
|
|
27550
28075
|
queryFamily: result.queryFamily,
|
|
27551
|
-
ignoreTimeFilter: result.ignoreTimeFilter
|
|
28076
|
+
ignoreTimeFilter: result.ignoreTimeFilter,
|
|
28077
|
+
entitySelectorId: result.entitySelectorId
|
|
27552
28078
|
};
|
|
27553
28079
|
const filters = result.filters?.map(f => ({
|
|
27554
28080
|
attributePath: f.attributePath,
|
|
@@ -27607,6 +28133,9 @@ function registerDefaultWidgets(registry) {
|
|
|
27607
28133
|
...(widget.dataSource.ignoreTimeFilter && {
|
|
27608
28134
|
ignoreTimeFilter: true
|
|
27609
28135
|
}),
|
|
28136
|
+
...(widget.dataSource.entitySelectorId && {
|
|
28137
|
+
entitySelectorId: widget.dataSource.entitySelectorId
|
|
28138
|
+
}),
|
|
27610
28139
|
filters: widget.filters
|
|
27611
28140
|
}
|
|
27612
28141
|
}),
|
|
@@ -28061,6 +28590,15 @@ class EntitySelectorEditorComponent {
|
|
|
28061
28590
|
editMappings = [];
|
|
28062
28591
|
editShowInToolbar = true;
|
|
28063
28592
|
editDefaultRtId = '';
|
|
28593
|
+
// Child scope (stream-data): optional one-hop traversal resolving the picked
|
|
28594
|
+
// entity to the child source rtIds a stream-data widget scopes by.
|
|
28595
|
+
editChildScopeTargetCkTypeId = '';
|
|
28596
|
+
editChildScopeTargetCkTypeItem = null;
|
|
28597
|
+
editChildScopeRoleId = '';
|
|
28598
|
+
// Parent → children via System/ParentChild is reached INBOUND (the child holds
|
|
28599
|
+
// the association to its parent), so 'in' is the correct default for a
|
|
28600
|
+
// childScope that resolves a picked parent to its children.
|
|
28601
|
+
editChildScopeDirection = 'in';
|
|
28064
28602
|
// Data sources for the default entity picker (created when CK type is set)
|
|
28065
28603
|
defaultEntityDataSource = null;
|
|
28066
28604
|
defaultEntityDialogDataSource = null;
|
|
@@ -28076,6 +28614,10 @@ class EntitySelectorEditorComponent {
|
|
|
28076
28614
|
this.editMappings = [];
|
|
28077
28615
|
this.editShowInToolbar = true;
|
|
28078
28616
|
this.editDefaultRtId = '';
|
|
28617
|
+
this.editChildScopeTargetCkTypeId = '';
|
|
28618
|
+
this.editChildScopeTargetCkTypeItem = null;
|
|
28619
|
+
this.editChildScopeRoleId = 'System/ParentChild';
|
|
28620
|
+
this.editChildScopeDirection = 'in';
|
|
28079
28621
|
this.defaultEntityDataSource = null;
|
|
28080
28622
|
this.defaultEntityDialogDataSource = null;
|
|
28081
28623
|
this.isEditing = true;
|
|
@@ -28100,6 +28642,17 @@ class EntitySelectorEditorComponent {
|
|
|
28100
28642
|
this.editMappings = [...selector.attributeMappings];
|
|
28101
28643
|
this.editShowInToolbar = selector.showInToolbar !== false;
|
|
28102
28644
|
this.editDefaultRtId = selector.defaultRtId ?? '';
|
|
28645
|
+
this.editChildScopeTargetCkTypeId = selector.childScope?.targetCkTypeId ?? '';
|
|
28646
|
+
this.editChildScopeTargetCkTypeItem = selector.childScope?.targetCkTypeId
|
|
28647
|
+
? {
|
|
28648
|
+
fullName: selector.childScope.targetCkTypeId,
|
|
28649
|
+
rtCkTypeId: selector.childScope.targetCkTypeId,
|
|
28650
|
+
isAbstract: false,
|
|
28651
|
+
isFinal: false
|
|
28652
|
+
}
|
|
28653
|
+
: null;
|
|
28654
|
+
this.editChildScopeRoleId = selector.childScope?.roleId ?? 'System/ParentChild';
|
|
28655
|
+
this.editChildScopeDirection = selector.childScope?.direction ?? 'in';
|
|
28103
28656
|
this.updateDefaultEntityDataSources();
|
|
28104
28657
|
this.isEditing = true;
|
|
28105
28658
|
this.editingStateChange.emit(true);
|
|
@@ -28152,6 +28705,20 @@ class EntitySelectorEditorComponent {
|
|
|
28152
28705
|
};
|
|
28153
28706
|
});
|
|
28154
28707
|
}
|
|
28708
|
+
/**
|
|
28709
|
+
* Handles child-scope target CK type selection.
|
|
28710
|
+
*/
|
|
28711
|
+
onChildScopeCkTypeSelected(ckType) {
|
|
28712
|
+
this.editChildScopeTargetCkTypeId = ckType.rtCkTypeId;
|
|
28713
|
+
this.editChildScopeTargetCkTypeItem = ckType;
|
|
28714
|
+
}
|
|
28715
|
+
/**
|
|
28716
|
+
* Handles child-scope target CK type cleared.
|
|
28717
|
+
*/
|
|
28718
|
+
onChildScopeCkTypeCleared() {
|
|
28719
|
+
this.editChildScopeTargetCkTypeId = '';
|
|
28720
|
+
this.editChildScopeTargetCkTypeItem = null;
|
|
28721
|
+
}
|
|
28155
28722
|
/**
|
|
28156
28723
|
* Handles default entity selection from the entity picker.
|
|
28157
28724
|
*/
|
|
@@ -28170,13 +28737,23 @@ class EntitySelectorEditorComponent {
|
|
|
28170
28737
|
saveEdit() {
|
|
28171
28738
|
if (!this.isEditValid())
|
|
28172
28739
|
return;
|
|
28740
|
+
// Only persist a childScope when both the target type and role are set;
|
|
28741
|
+
// otherwise leave it undefined (the picked entity itself is the scope).
|
|
28742
|
+
const childScope = this.editChildScopeTargetCkTypeId && this.editChildScopeRoleId.trim()
|
|
28743
|
+
? {
|
|
28744
|
+
targetCkTypeId: this.editChildScopeTargetCkTypeId,
|
|
28745
|
+
roleId: this.editChildScopeRoleId.trim(),
|
|
28746
|
+
direction: this.editChildScopeDirection
|
|
28747
|
+
}
|
|
28748
|
+
: undefined;
|
|
28173
28749
|
const selector = {
|
|
28174
28750
|
id: this.editId,
|
|
28175
28751
|
label: this.editLabel.trim(),
|
|
28176
28752
|
ckTypeId: this.editCkTypeId,
|
|
28177
28753
|
attributeMappings: this.editMappings,
|
|
28178
28754
|
showInToolbar: this.editShowInToolbar,
|
|
28179
|
-
defaultRtId: this.editDefaultRtId.trim() || undefined
|
|
28755
|
+
defaultRtId: this.editDefaultRtId.trim() || undefined,
|
|
28756
|
+
childScope
|
|
28180
28757
|
};
|
|
28181
28758
|
if (this.editingIndex !== null) {
|
|
28182
28759
|
this.entitySelectors = this.entitySelectors.map((es, i) => i === this.editingIndex ? selector : es);
|
|
@@ -28296,7 +28873,7 @@ class EntitySelectorEditorComponent {
|
|
|
28296
28873
|
this.entitySelectorsChange.emit([...this.entitySelectors]);
|
|
28297
28874
|
}
|
|
28298
28875
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: EntitySelectorEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
28299
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: EntitySelectorEditorComponent, isStandalone: true, selector: "mm-entity-selector-editor", inputs: { entitySelectors: "entitySelectors", existingVariableNames: "existingVariableNames" }, outputs: { entitySelectorsChange: "entitySelectorsChange", editingStateChange: "editingStateChange" }, ngImport: i0, template: "<div class=\"entity-selector-editor\">\n @if (!isEditing) {\n <!-- Selector List -->\n <div class=\"selector-list\">\n @for (selector of entitySelectors; track selector.id; let i = $index) {\n <div class=\"selector-item\">\n <div class=\"selector-info\">\n <span class=\"selector-label\">{{ selector.label }}</span>\n <span class=\"selector-mode\">{{ getModeLabel(selector) }}</span>\n <span class=\"selector-ck-type\">{{ selector.ckTypeId }}</span>\n <span class=\"selector-mappings\">{{ getMappingSummary(selector) }}</span>\n </div>\n <div class=\"selector-actions\">\n <button\n kendoButton\n [svgIcon]=\"pencilIcon\"\n (click)=\"editSelector(i)\"\n fillMode=\"flat\"\n size=\"small\"\n title=\"Edit selector\">\n </button>\n <button\n kendoButton\n [svgIcon]=\"trashIcon\"\n (click)=\"removeSelector(i)\"\n fillMode=\"flat\"\n size=\"small\"\n title=\"Remove selector\"\n class=\"remove-btn\">\n </button>\n </div>\n </div>\n }\n\n @if (entitySelectors.length === 0) {\n <div class=\"empty-state\">\n No entity selectors configured. Add one to enable entity-based variables.\n </div>\n }\n </div>\n\n <div class=\"add-button-row\">\n <button\n kendoButton\n [svgIcon]=\"plusIcon\"\n (click)=\"addSelector()\"\n themeColor=\"primary\">\n Add Entity Selector\n </button>\n </div>\n } @else {\n <!-- Edit Form -->\n <div class=\"edit-panel\">\n <div class=\"edit-panel-header\">\n {{ editingIndex !== null ? 'Edit Entity Selector' : 'New Entity Selector' }}\n </div>\n <div class=\"edit-form\">\n <div class=\"form-field\">\n <label class=\"field-label\">ID *</label>\n <kendo-textbox\n [(ngModel)]=\"editId\"\n placeholder=\"e.g., mp\"\n [readonly]=\"editingIndex !== null\">\n </kendo-textbox>\n @if (isDuplicateId(editId, editingIndex)) {\n <span class=\"field-error\">ID must be unique</span>\n }\n <span class=\"field-hint\">Used in URL parameters (es_<id>=<rtId>)</span>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Label *</label>\n <kendo-textbox\n [(ngModel)]=\"editLabel\"\n placeholder=\"e.g., Metering Point\">\n </kendo-textbox>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">CK Type *</label>\n <mm-ck-type-selector-input\n [ngModel]=\"editCkTypeItem\"\n [placeholder]=\"'Select CK type...'\"\n (ckTypeSelected)=\"onCkTypeSelected($event)\"\n (ckTypeCleared)=\"onCkTypeCleared()\">\n </mm-ck-type-selector-input>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Attribute Mappings *</label>\n <button\n kendoButton\n (click)=\"selectAttributes()\"\n [disabled]=\"!editCkTypeId\"\n fillMode=\"outline\"\n size=\"small\">\n Select Attributes...\n </button>\n\n @if (editMappings.length > 0) {\n <div class=\"mappings-list\">\n <div class=\"mappings-header\">\n <span class=\"mappings-header-attr\">Attribute</span>\n <span class=\"mappings-header-var\">Variable Name</span>\n </div>\n @for (mapping of editMappings; track mapping.attributePath; let j = $index) {\n <div class=\"mapping-item\">\n <span class=\"mapping-path\">{{ mapping.attributePath }}</span>\n <span class=\"mapping-arrow\">→</span>\n <div class=\"mapping-var-field\">\n <div class=\"mapping-var-input-wrapper\">\n <span class=\"mapping-var-prefix\">$</span>\n <kendo-textbox\n [(ngModel)]=\"mapping.variableName\"\n size=\"small\"\n class=\"mapping-var-input\"\n placeholder=\"variableName\"\n [class.invalid]=\"getVariableNameError(mapping)\">\n </kendo-textbox>\n </div>\n @if (getVariableNameError(mapping); as error) {\n <span class=\"field-error\">{{ error }}</span>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"form-field\">\n <div class=\"checkbox-row\">\n <input\n type=\"checkbox\"\n kendoCheckBox\n [(ngModel)]=\"editShowInToolbar\"\n id=\"showInToolbar\" />\n <label class=\"field-label checkbox-label\" for=\"showInToolbar\">Show in Toolbar</label>\n </div>\n <span class=\"field-hint\">\n @if (editShowInToolbar) {\n Users can select an entity from a dropdown in the toolbar.\n } @else {\n Hidden selector \u2014 variables are resolved from the default entity below.\n }\n </span>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Default Entity{{ !editShowInToolbar ? ' *' : '' }}</label>\n @if (defaultEntityDataSource) {\n <mm-entity-select-input\n [dataSource]=\"defaultEntityDataSource\"\n [dialogDataSource]=\"defaultEntityDialogDataSource!\"\n [placeholder]=\"'Select default entity...'\"\n [dialogTitle]=\"'Select Default ' + editLabel\"\n (entitySelected)=\"onDefaultEntitySelected($event)\"\n (entityCleared)=\"onDefaultEntityCleared()\">\n </mm-entity-select-input>\n } @else {\n <span class=\"field-hint\">Select a CK type first to pick a default entity.</span>\n }\n @if (editDefaultRtId) {\n <span class=\"field-hint\">Selected: {{ editDefaultRtId }}</span>\n }\n @if (!editShowInToolbar && !editDefaultRtId) {\n <span class=\"field-error\">A default entity is required when not shown in toolbar.</span>\n }\n <span class=\"field-hint\">\n @if (editShowInToolbar) {\n Optional \u2014 pre-selected entity when the MeshBoard loads.\n } @else {\n This entity's attributes will be used to populate the variables.\n }\n </span>\n </div>\n\n <div class=\"edit-actions mm-dialog-actions\">\n <button kendoButton (click)=\"cancelEdit()\" fillMode=\"flat\">\n Cancel\n </button>\n <button\n kendoButton\n (click)=\"saveEdit()\"\n [disabled]=\"!isEditValid()\"\n themeColor=\"primary\">\n {{ editingIndex !== null ? 'Update' : 'Add' }}\n </button>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".entity-selector-editor{display:flex;flex-direction:column;gap:1.25rem}.selector-list{display:flex;flex-direction:column;gap:.5rem}.selector-item{display:flex;justify-content:space-between;align-items:center;padding:.75rem 1rem;background:var(--kendo-color-surface-alt, #fafafa);border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px}.selector-item .selector-info{display:flex;flex-direction:column;gap:.25rem;min-width:0;flex:1}.selector-item .selector-label{font-weight:500;color:var(--kendo-color-on-app-surface, #424242)}.selector-item .selector-mode{font-size:.75rem;font-weight:500;color:var(--kendo-color-info, #0288d1)}.selector-item .selector-ck-type{font-size:.8rem;color:var(--kendo-color-subtle, #757575);font-family:Consolas,Monaco,monospace}.selector-item .selector-mappings{font-size:.8rem;color:var(--kendo-color-primary, #3f51b5);font-family:Consolas,Monaco,monospace}.selector-item .selector-actions{display:flex;gap:.25rem;flex-shrink:0}.selector-item .remove-btn{color:var(--kendo-color-error, #f44336)}.empty-state{padding:1.5rem;text-align:center;color:var(--kendo-color-subtle, #757575);font-size:.875rem}.add-button-row{display:flex;justify-content:flex-start}.edit-panel{border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px;overflow:hidden}.edit-panel-header{padding:.625rem 1rem;font-weight:600;font-size:.875rem;color:var(--kendo-color-on-primary, #ffffff);background:var(--kendo-color-primary, #3f51b5)}.edit-form{display:flex;flex-direction:column;gap:1.25rem;padding:1.25rem}.edit-form .form-field{display:flex;flex-direction:column;gap:.5rem}.edit-form .field-label{font-weight:500;font-size:.875rem;text-transform:uppercase;color:var(--kendo-color-on-app-surface, #424242)}.edit-form .field-hint{font-size:.75rem;color:var(--kendo-color-subtle, #757575)}.edit-form .field-error{font-size:.75rem;color:var(--kendo-color-error, #f44336)}.edit-form .checkbox-row{display:flex;align-items:center;gap:.5rem}.edit-form .checkbox-row .checkbox-label{margin:0;cursor:pointer}.mappings-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.5rem;padding:.75rem;background:var(--kendo-color-surface-alt, #fafafa);border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px}.mappings-header{display:flex;align-items:center;gap:.5rem;font-size:.75rem;font-weight:600;color:var(--kendo-color-subtle, #757575);padding-bottom:.25rem;border-bottom:1px solid var(--kendo-color-border, #e0e0e0)}.mappings-header .mappings-header-attr{min-width:150px}.mappings-header .mappings-header-var{margin-left:1.75rem}.mapping-item{display:flex;align-items:flex-start;gap:.5rem}.mapping-item .mapping-path{font-size:.8rem;font-family:Consolas,Monaco,monospace;color:var(--kendo-color-subtle, #757575);min-width:150px;padding-top:5px}.mapping-item .mapping-arrow{color:var(--kendo-color-subtle, #757575);flex-shrink:0;padding-top:5px}.mapping-item .mapping-var-field{display:flex;flex-direction:column;gap:2px;flex:1;min-width:100px}.mapping-item .mapping-var-input-wrapper{display:flex;align-items:center;gap:0}.mapping-item .mapping-var-prefix{font-family:Consolas,Monaco,monospace;font-size:.875rem;font-weight:600;color:var(--kendo-color-primary, #3f51b5);padding-right:2px;flex-shrink:0}.mapping-item .mapping-var-input{flex:1}.mapping-item .mapping-var-input.invalid ::ng-deep .k-input{border-color:var(--kendo-color-error, #f44336)}.edit-actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:.5rem;padding-top:.75rem;border-top:1px solid var(--kendo-color-border, #e0e0e0)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "ngmodule", type: LabelModule }, { kind: "directive", type: i4$1.LabelDirective, selector: "label[for]", inputs: ["for", "labelClass"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "messages", "dialogMessages", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: EntitySelectInputComponent, selector: "mm-entity-select-input", inputs: ["dataSource", "placeholder", "minSearchLength", "maxResults", "debounceMs", "prefix", "initialDisplayValue", "dialogDataSource", "dialogTitle", "multiSelect", "advancedSearchLabel", "dialogMessages", "messages", "disabled", "required"], outputs: ["entitySelected", "entityCleared", "entitiesSelected"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
28876
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: EntitySelectorEditorComponent, isStandalone: true, selector: "mm-entity-selector-editor", inputs: { entitySelectors: "entitySelectors", existingVariableNames: "existingVariableNames" }, outputs: { entitySelectorsChange: "entitySelectorsChange", editingStateChange: "editingStateChange" }, ngImport: i0, template: "<div class=\"entity-selector-editor\">\n @if (!isEditing) {\n <!-- Selector List -->\n <div class=\"selector-list\">\n @for (selector of entitySelectors; track selector.id; let i = $index) {\n <div class=\"selector-item\">\n <div class=\"selector-info\">\n <span class=\"selector-label\">{{ selector.label }}</span>\n <span class=\"selector-mode\">{{ getModeLabel(selector) }}</span>\n <span class=\"selector-ck-type\">{{ selector.ckTypeId }}</span>\n <span class=\"selector-mappings\">{{ getMappingSummary(selector) }}</span>\n </div>\n <div class=\"selector-actions\">\n <button\n kendoButton\n [svgIcon]=\"pencilIcon\"\n (click)=\"editSelector(i)\"\n fillMode=\"flat\"\n size=\"small\"\n title=\"Edit selector\">\n </button>\n <button\n kendoButton\n [svgIcon]=\"trashIcon\"\n (click)=\"removeSelector(i)\"\n fillMode=\"flat\"\n size=\"small\"\n title=\"Remove selector\"\n class=\"remove-btn\">\n </button>\n </div>\n </div>\n }\n\n @if (entitySelectors.length === 0) {\n <div class=\"empty-state\">\n No entity selectors configured. Add one to enable entity-based variables.\n </div>\n }\n </div>\n\n <div class=\"add-button-row\">\n <button\n kendoButton\n [svgIcon]=\"plusIcon\"\n (click)=\"addSelector()\"\n themeColor=\"primary\">\n Add Entity Selector\n </button>\n </div>\n } @else {\n <!-- Edit Form -->\n <div class=\"edit-panel\">\n <div class=\"edit-panel-header\">\n {{ editingIndex !== null ? 'Edit Entity Selector' : 'New Entity Selector' }}\n </div>\n <div class=\"edit-form\">\n <div class=\"form-field\">\n <label class=\"field-label\">ID *</label>\n <kendo-textbox\n [(ngModel)]=\"editId\"\n placeholder=\"e.g., mp\"\n [readonly]=\"editingIndex !== null\">\n </kendo-textbox>\n @if (isDuplicateId(editId, editingIndex)) {\n <span class=\"field-error\">ID must be unique</span>\n }\n <span class=\"field-hint\">Used in URL parameters (es_<id>=<rtId>)</span>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Label *</label>\n <kendo-textbox\n [(ngModel)]=\"editLabel\"\n placeholder=\"e.g., Metering Point\">\n </kendo-textbox>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">CK Type *</label>\n <mm-ck-type-selector-input\n [ngModel]=\"editCkTypeItem\"\n [placeholder]=\"'Select CK type...'\"\n (ckTypeSelected)=\"onCkTypeSelected($event)\"\n (ckTypeCleared)=\"onCkTypeCleared()\">\n </mm-ck-type-selector-input>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Attribute Mappings *</label>\n <button\n kendoButton\n (click)=\"selectAttributes()\"\n [disabled]=\"!editCkTypeId\"\n fillMode=\"outline\"\n size=\"small\">\n Select Attributes...\n </button>\n\n @if (editMappings.length > 0) {\n <div class=\"mappings-list\">\n <div class=\"mappings-header\">\n <span class=\"mappings-header-attr\">Attribute</span>\n <span class=\"mappings-header-var\">Variable Name</span>\n </div>\n @for (mapping of editMappings; track mapping.attributePath; let j = $index) {\n <div class=\"mapping-item\">\n <span class=\"mapping-path\">{{ mapping.attributePath }}</span>\n <span class=\"mapping-arrow\">→</span>\n <div class=\"mapping-var-field\">\n <div class=\"mapping-var-input-wrapper\">\n <span class=\"mapping-var-prefix\">$</span>\n <kendo-textbox\n [(ngModel)]=\"mapping.variableName\"\n size=\"small\"\n class=\"mapping-var-input\"\n placeholder=\"variableName\"\n [class.invalid]=\"getVariableNameError(mapping)\">\n </kendo-textbox>\n </div>\n @if (getVariableNameError(mapping); as error) {\n <span class=\"field-error\">{{ error }}</span>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"form-field\">\n <div class=\"checkbox-row\">\n <input\n type=\"checkbox\"\n kendoCheckBox\n [(ngModel)]=\"editShowInToolbar\"\n id=\"showInToolbar\" />\n <label class=\"field-label checkbox-label\" for=\"showInToolbar\">Show in Toolbar</label>\n </div>\n <span class=\"field-hint\">\n @if (editShowInToolbar) {\n Users can select an entity from a dropdown in the toolbar.\n } @else {\n Hidden selector \u2014 variables are resolved from the default entity below.\n }\n </span>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Default Entity{{ !editShowInToolbar ? ' *' : '' }}</label>\n @if (defaultEntityDataSource) {\n <mm-entity-select-input\n [dataSource]=\"defaultEntityDataSource\"\n [dialogDataSource]=\"defaultEntityDialogDataSource!\"\n [placeholder]=\"'Select default entity...'\"\n [dialogTitle]=\"'Select Default ' + editLabel\"\n (entitySelected)=\"onDefaultEntitySelected($event)\"\n (entityCleared)=\"onDefaultEntityCleared()\">\n </mm-entity-select-input>\n } @else {\n <span class=\"field-hint\">Select a CK type first to pick a default entity.</span>\n }\n @if (editDefaultRtId) {\n <span class=\"field-hint\">Selected: {{ editDefaultRtId }}</span>\n }\n @if (!editShowInToolbar && !editDefaultRtId) {\n <span class=\"field-error\">A default entity is required when not shown in toolbar.</span>\n }\n <span class=\"field-hint\">\n @if (editShowInToolbar) {\n Optional \u2014 pre-selected entity when the MeshBoard loads.\n } @else {\n This entity's attributes will be used to populate the variables.\n }\n </span>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Child Scope (stream-data)</label>\n <span class=\"field-hint\">\n Optional. Resolves the picked entity to its child source rtIds (one\n association hop) so a stream-data widget can scope to them \u2014 e.g. a\n MeteringPoint resolved to its EnergyMeasurement rtIds. Leave empty to\n scope by the picked entity's own rtId.\n </span>\n <mm-ck-type-selector-input\n [ngModel]=\"editChildScopeTargetCkTypeItem\"\n [placeholder]=\"'Child CK type (e.g. EnergyMeasurement)...'\"\n (ckTypeSelected)=\"onChildScopeCkTypeSelected($event)\"\n (ckTypeCleared)=\"onChildScopeCkTypeCleared()\">\n </mm-ck-type-selector-input>\n <kendo-textbox\n [(ngModel)]=\"editChildScopeRoleId\"\n placeholder=\"Association role (e.g. System/ParentChild)\">\n </kendo-textbox>\n <label class=\"field-label\">Direction</label>\n <select [(ngModel)]=\"editChildScopeDirection\" class=\"child-scope-direction\">\n <option value=\"out\">Outbound (parent \u2192 child)</option>\n <option value=\"in\">Inbound (child \u2192 parent)</option>\n </select>\n </div>\n\n <div class=\"edit-actions mm-dialog-actions\">\n <button kendoButton (click)=\"cancelEdit()\" fillMode=\"flat\">\n Cancel\n </button>\n <button\n kendoButton\n (click)=\"saveEdit()\"\n [disabled]=\"!isEditValid()\"\n themeColor=\"primary\">\n {{ editingIndex !== null ? 'Update' : 'Add' }}\n </button>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".entity-selector-editor{display:flex;flex-direction:column;gap:1.25rem}.selector-list{display:flex;flex-direction:column;gap:.5rem}.selector-item{display:flex;justify-content:space-between;align-items:center;padding:.75rem 1rem;background:var(--kendo-color-surface-alt, #fafafa);border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px}.selector-item .selector-info{display:flex;flex-direction:column;gap:.25rem;min-width:0;flex:1}.selector-item .selector-label{font-weight:500;color:var(--kendo-color-on-app-surface, #424242)}.selector-item .selector-mode{font-size:.75rem;font-weight:500;color:var(--kendo-color-info, #0288d1)}.selector-item .selector-ck-type{font-size:.8rem;color:var(--kendo-color-subtle, #757575);font-family:Consolas,Monaco,monospace}.selector-item .selector-mappings{font-size:.8rem;color:var(--kendo-color-primary, #3f51b5);font-family:Consolas,Monaco,monospace}.selector-item .selector-actions{display:flex;gap:.25rem;flex-shrink:0}.selector-item .remove-btn{color:var(--kendo-color-error, #f44336)}.empty-state{padding:1.5rem;text-align:center;color:var(--kendo-color-subtle, #757575);font-size:.875rem}.add-button-row{display:flex;justify-content:flex-start}.edit-panel{border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px;overflow:hidden}.edit-panel-header{padding:.625rem 1rem;font-weight:600;font-size:.875rem;color:var(--kendo-color-on-primary, #ffffff);background:var(--kendo-color-primary, #3f51b5)}.edit-form{display:flex;flex-direction:column;gap:1.25rem;padding:1.25rem}.edit-form .form-field{display:flex;flex-direction:column;gap:.5rem}.edit-form .field-label{font-weight:500;font-size:.875rem;text-transform:uppercase;color:var(--kendo-color-on-app-surface, #424242)}.edit-form .field-hint{font-size:.75rem;color:var(--kendo-color-subtle, #757575)}.edit-form .field-error{font-size:.75rem;color:var(--kendo-color-error, #f44336)}.edit-form .checkbox-row{display:flex;align-items:center;gap:.5rem}.edit-form .checkbox-row .checkbox-label{margin:0;cursor:pointer}.mappings-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.5rem;padding:.75rem;background:var(--kendo-color-surface-alt, #fafafa);border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px}.mappings-header{display:flex;align-items:center;gap:.5rem;font-size:.75rem;font-weight:600;color:var(--kendo-color-subtle, #757575);padding-bottom:.25rem;border-bottom:1px solid var(--kendo-color-border, #e0e0e0)}.mappings-header .mappings-header-attr{min-width:150px}.mappings-header .mappings-header-var{margin-left:1.75rem}.mapping-item{display:flex;align-items:flex-start;gap:.5rem}.mapping-item .mapping-path{font-size:.8rem;font-family:Consolas,Monaco,monospace;color:var(--kendo-color-subtle, #757575);min-width:150px;padding-top:5px}.mapping-item .mapping-arrow{color:var(--kendo-color-subtle, #757575);flex-shrink:0;padding-top:5px}.mapping-item .mapping-var-field{display:flex;flex-direction:column;gap:2px;flex:1;min-width:100px}.mapping-item .mapping-var-input-wrapper{display:flex;align-items:center;gap:0}.mapping-item .mapping-var-prefix{font-family:Consolas,Monaco,monospace;font-size:.875rem;font-weight:600;color:var(--kendo-color-primary, #3f51b5);padding-right:2px;flex-shrink:0}.mapping-item .mapping-var-input{flex:1}.mapping-item .mapping-var-input.invalid ::ng-deep .k-input{border-color:var(--kendo-color-error, #f44336)}.edit-actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:.5rem;padding-top:.75rem;border-top:1px solid var(--kendo-color-border, #e0e0e0)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i3.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "directive", type: i3.CheckBoxDirective, selector: "input[kendoCheckBox]", inputs: ["size", "rounded"] }, { kind: "ngmodule", type: LabelModule }, { kind: "directive", type: i4$1.LabelDirective, selector: "label[for]", inputs: ["for", "labelClass"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "messages", "dialogMessages", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: EntitySelectInputComponent, selector: "mm-entity-select-input", inputs: ["dataSource", "placeholder", "minSearchLength", "maxResults", "debounceMs", "prefix", "initialDisplayValue", "dialogDataSource", "dialogTitle", "multiSelect", "advancedSearchLabel", "dialogMessages", "messages", "disabled", "required"], outputs: ["entitySelected", "entityCleared", "entitiesSelected"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
28300
28877
|
}
|
|
28301
28878
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: EntitySelectorEditorComponent, decorators: [{
|
|
28302
28879
|
type: Component,
|
|
@@ -28309,7 +28886,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
28309
28886
|
SVGIconModule,
|
|
28310
28887
|
CkTypeSelectorInputComponent,
|
|
28311
28888
|
EntitySelectInputComponent
|
|
28312
|
-
], changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"entity-selector-editor\">\n @if (!isEditing) {\n <!-- Selector List -->\n <div class=\"selector-list\">\n @for (selector of entitySelectors; track selector.id; let i = $index) {\n <div class=\"selector-item\">\n <div class=\"selector-info\">\n <span class=\"selector-label\">{{ selector.label }}</span>\n <span class=\"selector-mode\">{{ getModeLabel(selector) }}</span>\n <span class=\"selector-ck-type\">{{ selector.ckTypeId }}</span>\n <span class=\"selector-mappings\">{{ getMappingSummary(selector) }}</span>\n </div>\n <div class=\"selector-actions\">\n <button\n kendoButton\n [svgIcon]=\"pencilIcon\"\n (click)=\"editSelector(i)\"\n fillMode=\"flat\"\n size=\"small\"\n title=\"Edit selector\">\n </button>\n <button\n kendoButton\n [svgIcon]=\"trashIcon\"\n (click)=\"removeSelector(i)\"\n fillMode=\"flat\"\n size=\"small\"\n title=\"Remove selector\"\n class=\"remove-btn\">\n </button>\n </div>\n </div>\n }\n\n @if (entitySelectors.length === 0) {\n <div class=\"empty-state\">\n No entity selectors configured. Add one to enable entity-based variables.\n </div>\n }\n </div>\n\n <div class=\"add-button-row\">\n <button\n kendoButton\n [svgIcon]=\"plusIcon\"\n (click)=\"addSelector()\"\n themeColor=\"primary\">\n Add Entity Selector\n </button>\n </div>\n } @else {\n <!-- Edit Form -->\n <div class=\"edit-panel\">\n <div class=\"edit-panel-header\">\n {{ editingIndex !== null ? 'Edit Entity Selector' : 'New Entity Selector' }}\n </div>\n <div class=\"edit-form\">\n <div class=\"form-field\">\n <label class=\"field-label\">ID *</label>\n <kendo-textbox\n [(ngModel)]=\"editId\"\n placeholder=\"e.g., mp\"\n [readonly]=\"editingIndex !== null\">\n </kendo-textbox>\n @if (isDuplicateId(editId, editingIndex)) {\n <span class=\"field-error\">ID must be unique</span>\n }\n <span class=\"field-hint\">Used in URL parameters (es_<id>=<rtId>)</span>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Label *</label>\n <kendo-textbox\n [(ngModel)]=\"editLabel\"\n placeholder=\"e.g., Metering Point\">\n </kendo-textbox>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">CK Type *</label>\n <mm-ck-type-selector-input\n [ngModel]=\"editCkTypeItem\"\n [placeholder]=\"'Select CK type...'\"\n (ckTypeSelected)=\"onCkTypeSelected($event)\"\n (ckTypeCleared)=\"onCkTypeCleared()\">\n </mm-ck-type-selector-input>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Attribute Mappings *</label>\n <button\n kendoButton\n (click)=\"selectAttributes()\"\n [disabled]=\"!editCkTypeId\"\n fillMode=\"outline\"\n size=\"small\">\n Select Attributes...\n </button>\n\n @if (editMappings.length > 0) {\n <div class=\"mappings-list\">\n <div class=\"mappings-header\">\n <span class=\"mappings-header-attr\">Attribute</span>\n <span class=\"mappings-header-var\">Variable Name</span>\n </div>\n @for (mapping of editMappings; track mapping.attributePath; let j = $index) {\n <div class=\"mapping-item\">\n <span class=\"mapping-path\">{{ mapping.attributePath }}</span>\n <span class=\"mapping-arrow\">→</span>\n <div class=\"mapping-var-field\">\n <div class=\"mapping-var-input-wrapper\">\n <span class=\"mapping-var-prefix\">$</span>\n <kendo-textbox\n [(ngModel)]=\"mapping.variableName\"\n size=\"small\"\n class=\"mapping-var-input\"\n placeholder=\"variableName\"\n [class.invalid]=\"getVariableNameError(mapping)\">\n </kendo-textbox>\n </div>\n @if (getVariableNameError(mapping); as error) {\n <span class=\"field-error\">{{ error }}</span>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"form-field\">\n <div class=\"checkbox-row\">\n <input\n type=\"checkbox\"\n kendoCheckBox\n [(ngModel)]=\"editShowInToolbar\"\n id=\"showInToolbar\" />\n <label class=\"field-label checkbox-label\" for=\"showInToolbar\">Show in Toolbar</label>\n </div>\n <span class=\"field-hint\">\n @if (editShowInToolbar) {\n Users can select an entity from a dropdown in the toolbar.\n } @else {\n Hidden selector \u2014 variables are resolved from the default entity below.\n }\n </span>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Default Entity{{ !editShowInToolbar ? ' *' : '' }}</label>\n @if (defaultEntityDataSource) {\n <mm-entity-select-input\n [dataSource]=\"defaultEntityDataSource\"\n [dialogDataSource]=\"defaultEntityDialogDataSource!\"\n [placeholder]=\"'Select default entity...'\"\n [dialogTitle]=\"'Select Default ' + editLabel\"\n (entitySelected)=\"onDefaultEntitySelected($event)\"\n (entityCleared)=\"onDefaultEntityCleared()\">\n </mm-entity-select-input>\n } @else {\n <span class=\"field-hint\">Select a CK type first to pick a default entity.</span>\n }\n @if (editDefaultRtId) {\n <span class=\"field-hint\">Selected: {{ editDefaultRtId }}</span>\n }\n @if (!editShowInToolbar && !editDefaultRtId) {\n <span class=\"field-error\">A default entity is required when not shown in toolbar.</span>\n }\n <span class=\"field-hint\">\n @if (editShowInToolbar) {\n Optional \u2014 pre-selected entity when the MeshBoard loads.\n } @else {\n This entity's attributes will be used to populate the variables.\n }\n </span>\n </div>\n\n <div class=\"edit-actions mm-dialog-actions\">\n <button kendoButton (click)=\"cancelEdit()\" fillMode=\"flat\">\n Cancel\n </button>\n <button\n kendoButton\n (click)=\"saveEdit()\"\n [disabled]=\"!isEditValid()\"\n themeColor=\"primary\">\n {{ editingIndex !== null ? 'Update' : 'Add' }}\n </button>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".entity-selector-editor{display:flex;flex-direction:column;gap:1.25rem}.selector-list{display:flex;flex-direction:column;gap:.5rem}.selector-item{display:flex;justify-content:space-between;align-items:center;padding:.75rem 1rem;background:var(--kendo-color-surface-alt, #fafafa);border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px}.selector-item .selector-info{display:flex;flex-direction:column;gap:.25rem;min-width:0;flex:1}.selector-item .selector-label{font-weight:500;color:var(--kendo-color-on-app-surface, #424242)}.selector-item .selector-mode{font-size:.75rem;font-weight:500;color:var(--kendo-color-info, #0288d1)}.selector-item .selector-ck-type{font-size:.8rem;color:var(--kendo-color-subtle, #757575);font-family:Consolas,Monaco,monospace}.selector-item .selector-mappings{font-size:.8rem;color:var(--kendo-color-primary, #3f51b5);font-family:Consolas,Monaco,monospace}.selector-item .selector-actions{display:flex;gap:.25rem;flex-shrink:0}.selector-item .remove-btn{color:var(--kendo-color-error, #f44336)}.empty-state{padding:1.5rem;text-align:center;color:var(--kendo-color-subtle, #757575);font-size:.875rem}.add-button-row{display:flex;justify-content:flex-start}.edit-panel{border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px;overflow:hidden}.edit-panel-header{padding:.625rem 1rem;font-weight:600;font-size:.875rem;color:var(--kendo-color-on-primary, #ffffff);background:var(--kendo-color-primary, #3f51b5)}.edit-form{display:flex;flex-direction:column;gap:1.25rem;padding:1.25rem}.edit-form .form-field{display:flex;flex-direction:column;gap:.5rem}.edit-form .field-label{font-weight:500;font-size:.875rem;text-transform:uppercase;color:var(--kendo-color-on-app-surface, #424242)}.edit-form .field-hint{font-size:.75rem;color:var(--kendo-color-subtle, #757575)}.edit-form .field-error{font-size:.75rem;color:var(--kendo-color-error, #f44336)}.edit-form .checkbox-row{display:flex;align-items:center;gap:.5rem}.edit-form .checkbox-row .checkbox-label{margin:0;cursor:pointer}.mappings-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.5rem;padding:.75rem;background:var(--kendo-color-surface-alt, #fafafa);border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px}.mappings-header{display:flex;align-items:center;gap:.5rem;font-size:.75rem;font-weight:600;color:var(--kendo-color-subtle, #757575);padding-bottom:.25rem;border-bottom:1px solid var(--kendo-color-border, #e0e0e0)}.mappings-header .mappings-header-attr{min-width:150px}.mappings-header .mappings-header-var{margin-left:1.75rem}.mapping-item{display:flex;align-items:flex-start;gap:.5rem}.mapping-item .mapping-path{font-size:.8rem;font-family:Consolas,Monaco,monospace;color:var(--kendo-color-subtle, #757575);min-width:150px;padding-top:5px}.mapping-item .mapping-arrow{color:var(--kendo-color-subtle, #757575);flex-shrink:0;padding-top:5px}.mapping-item .mapping-var-field{display:flex;flex-direction:column;gap:2px;flex:1;min-width:100px}.mapping-item .mapping-var-input-wrapper{display:flex;align-items:center;gap:0}.mapping-item .mapping-var-prefix{font-family:Consolas,Monaco,monospace;font-size:.875rem;font-weight:600;color:var(--kendo-color-primary, #3f51b5);padding-right:2px;flex-shrink:0}.mapping-item .mapping-var-input{flex:1}.mapping-item .mapping-var-input.invalid ::ng-deep .k-input{border-color:var(--kendo-color-error, #f44336)}.edit-actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:.5rem;padding-top:.75rem;border-top:1px solid var(--kendo-color-border, #e0e0e0)}\n"] }]
|
|
28889
|
+
], changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"entity-selector-editor\">\n @if (!isEditing) {\n <!-- Selector List -->\n <div class=\"selector-list\">\n @for (selector of entitySelectors; track selector.id; let i = $index) {\n <div class=\"selector-item\">\n <div class=\"selector-info\">\n <span class=\"selector-label\">{{ selector.label }}</span>\n <span class=\"selector-mode\">{{ getModeLabel(selector) }}</span>\n <span class=\"selector-ck-type\">{{ selector.ckTypeId }}</span>\n <span class=\"selector-mappings\">{{ getMappingSummary(selector) }}</span>\n </div>\n <div class=\"selector-actions\">\n <button\n kendoButton\n [svgIcon]=\"pencilIcon\"\n (click)=\"editSelector(i)\"\n fillMode=\"flat\"\n size=\"small\"\n title=\"Edit selector\">\n </button>\n <button\n kendoButton\n [svgIcon]=\"trashIcon\"\n (click)=\"removeSelector(i)\"\n fillMode=\"flat\"\n size=\"small\"\n title=\"Remove selector\"\n class=\"remove-btn\">\n </button>\n </div>\n </div>\n }\n\n @if (entitySelectors.length === 0) {\n <div class=\"empty-state\">\n No entity selectors configured. Add one to enable entity-based variables.\n </div>\n }\n </div>\n\n <div class=\"add-button-row\">\n <button\n kendoButton\n [svgIcon]=\"plusIcon\"\n (click)=\"addSelector()\"\n themeColor=\"primary\">\n Add Entity Selector\n </button>\n </div>\n } @else {\n <!-- Edit Form -->\n <div class=\"edit-panel\">\n <div class=\"edit-panel-header\">\n {{ editingIndex !== null ? 'Edit Entity Selector' : 'New Entity Selector' }}\n </div>\n <div class=\"edit-form\">\n <div class=\"form-field\">\n <label class=\"field-label\">ID *</label>\n <kendo-textbox\n [(ngModel)]=\"editId\"\n placeholder=\"e.g., mp\"\n [readonly]=\"editingIndex !== null\">\n </kendo-textbox>\n @if (isDuplicateId(editId, editingIndex)) {\n <span class=\"field-error\">ID must be unique</span>\n }\n <span class=\"field-hint\">Used in URL parameters (es_<id>=<rtId>)</span>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Label *</label>\n <kendo-textbox\n [(ngModel)]=\"editLabel\"\n placeholder=\"e.g., Metering Point\">\n </kendo-textbox>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">CK Type *</label>\n <mm-ck-type-selector-input\n [ngModel]=\"editCkTypeItem\"\n [placeholder]=\"'Select CK type...'\"\n (ckTypeSelected)=\"onCkTypeSelected($event)\"\n (ckTypeCleared)=\"onCkTypeCleared()\">\n </mm-ck-type-selector-input>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Attribute Mappings *</label>\n <button\n kendoButton\n (click)=\"selectAttributes()\"\n [disabled]=\"!editCkTypeId\"\n fillMode=\"outline\"\n size=\"small\">\n Select Attributes...\n </button>\n\n @if (editMappings.length > 0) {\n <div class=\"mappings-list\">\n <div class=\"mappings-header\">\n <span class=\"mappings-header-attr\">Attribute</span>\n <span class=\"mappings-header-var\">Variable Name</span>\n </div>\n @for (mapping of editMappings; track mapping.attributePath; let j = $index) {\n <div class=\"mapping-item\">\n <span class=\"mapping-path\">{{ mapping.attributePath }}</span>\n <span class=\"mapping-arrow\">→</span>\n <div class=\"mapping-var-field\">\n <div class=\"mapping-var-input-wrapper\">\n <span class=\"mapping-var-prefix\">$</span>\n <kendo-textbox\n [(ngModel)]=\"mapping.variableName\"\n size=\"small\"\n class=\"mapping-var-input\"\n placeholder=\"variableName\"\n [class.invalid]=\"getVariableNameError(mapping)\">\n </kendo-textbox>\n </div>\n @if (getVariableNameError(mapping); as error) {\n <span class=\"field-error\">{{ error }}</span>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"form-field\">\n <div class=\"checkbox-row\">\n <input\n type=\"checkbox\"\n kendoCheckBox\n [(ngModel)]=\"editShowInToolbar\"\n id=\"showInToolbar\" />\n <label class=\"field-label checkbox-label\" for=\"showInToolbar\">Show in Toolbar</label>\n </div>\n <span class=\"field-hint\">\n @if (editShowInToolbar) {\n Users can select an entity from a dropdown in the toolbar.\n } @else {\n Hidden selector \u2014 variables are resolved from the default entity below.\n }\n </span>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Default Entity{{ !editShowInToolbar ? ' *' : '' }}</label>\n @if (defaultEntityDataSource) {\n <mm-entity-select-input\n [dataSource]=\"defaultEntityDataSource\"\n [dialogDataSource]=\"defaultEntityDialogDataSource!\"\n [placeholder]=\"'Select default entity...'\"\n [dialogTitle]=\"'Select Default ' + editLabel\"\n (entitySelected)=\"onDefaultEntitySelected($event)\"\n (entityCleared)=\"onDefaultEntityCleared()\">\n </mm-entity-select-input>\n } @else {\n <span class=\"field-hint\">Select a CK type first to pick a default entity.</span>\n }\n @if (editDefaultRtId) {\n <span class=\"field-hint\">Selected: {{ editDefaultRtId }}</span>\n }\n @if (!editShowInToolbar && !editDefaultRtId) {\n <span class=\"field-error\">A default entity is required when not shown in toolbar.</span>\n }\n <span class=\"field-hint\">\n @if (editShowInToolbar) {\n Optional \u2014 pre-selected entity when the MeshBoard loads.\n } @else {\n This entity's attributes will be used to populate the variables.\n }\n </span>\n </div>\n\n <div class=\"form-field\">\n <label class=\"field-label\">Child Scope (stream-data)</label>\n <span class=\"field-hint\">\n Optional. Resolves the picked entity to its child source rtIds (one\n association hop) so a stream-data widget can scope to them \u2014 e.g. a\n MeteringPoint resolved to its EnergyMeasurement rtIds. Leave empty to\n scope by the picked entity's own rtId.\n </span>\n <mm-ck-type-selector-input\n [ngModel]=\"editChildScopeTargetCkTypeItem\"\n [placeholder]=\"'Child CK type (e.g. EnergyMeasurement)...'\"\n (ckTypeSelected)=\"onChildScopeCkTypeSelected($event)\"\n (ckTypeCleared)=\"onChildScopeCkTypeCleared()\">\n </mm-ck-type-selector-input>\n <kendo-textbox\n [(ngModel)]=\"editChildScopeRoleId\"\n placeholder=\"Association role (e.g. System/ParentChild)\">\n </kendo-textbox>\n <label class=\"field-label\">Direction</label>\n <select [(ngModel)]=\"editChildScopeDirection\" class=\"child-scope-direction\">\n <option value=\"out\">Outbound (parent \u2192 child)</option>\n <option value=\"in\">Inbound (child \u2192 parent)</option>\n </select>\n </div>\n\n <div class=\"edit-actions mm-dialog-actions\">\n <button kendoButton (click)=\"cancelEdit()\" fillMode=\"flat\">\n Cancel\n </button>\n <button\n kendoButton\n (click)=\"saveEdit()\"\n [disabled]=\"!isEditValid()\"\n themeColor=\"primary\">\n {{ editingIndex !== null ? 'Update' : 'Add' }}\n </button>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".entity-selector-editor{display:flex;flex-direction:column;gap:1.25rem}.selector-list{display:flex;flex-direction:column;gap:.5rem}.selector-item{display:flex;justify-content:space-between;align-items:center;padding:.75rem 1rem;background:var(--kendo-color-surface-alt, #fafafa);border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px}.selector-item .selector-info{display:flex;flex-direction:column;gap:.25rem;min-width:0;flex:1}.selector-item .selector-label{font-weight:500;color:var(--kendo-color-on-app-surface, #424242)}.selector-item .selector-mode{font-size:.75rem;font-weight:500;color:var(--kendo-color-info, #0288d1)}.selector-item .selector-ck-type{font-size:.8rem;color:var(--kendo-color-subtle, #757575);font-family:Consolas,Monaco,monospace}.selector-item .selector-mappings{font-size:.8rem;color:var(--kendo-color-primary, #3f51b5);font-family:Consolas,Monaco,monospace}.selector-item .selector-actions{display:flex;gap:.25rem;flex-shrink:0}.selector-item .remove-btn{color:var(--kendo-color-error, #f44336)}.empty-state{padding:1.5rem;text-align:center;color:var(--kendo-color-subtle, #757575);font-size:.875rem}.add-button-row{display:flex;justify-content:flex-start}.edit-panel{border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px;overflow:hidden}.edit-panel-header{padding:.625rem 1rem;font-weight:600;font-size:.875rem;color:var(--kendo-color-on-primary, #ffffff);background:var(--kendo-color-primary, #3f51b5)}.edit-form{display:flex;flex-direction:column;gap:1.25rem;padding:1.25rem}.edit-form .form-field{display:flex;flex-direction:column;gap:.5rem}.edit-form .field-label{font-weight:500;font-size:.875rem;text-transform:uppercase;color:var(--kendo-color-on-app-surface, #424242)}.edit-form .field-hint{font-size:.75rem;color:var(--kendo-color-subtle, #757575)}.edit-form .field-error{font-size:.75rem;color:var(--kendo-color-error, #f44336)}.edit-form .checkbox-row{display:flex;align-items:center;gap:.5rem}.edit-form .checkbox-row .checkbox-label{margin:0;cursor:pointer}.mappings-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.5rem;padding:.75rem;background:var(--kendo-color-surface-alt, #fafafa);border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px}.mappings-header{display:flex;align-items:center;gap:.5rem;font-size:.75rem;font-weight:600;color:var(--kendo-color-subtle, #757575);padding-bottom:.25rem;border-bottom:1px solid var(--kendo-color-border, #e0e0e0)}.mappings-header .mappings-header-attr{min-width:150px}.mappings-header .mappings-header-var{margin-left:1.75rem}.mapping-item{display:flex;align-items:flex-start;gap:.5rem}.mapping-item .mapping-path{font-size:.8rem;font-family:Consolas,Monaco,monospace;color:var(--kendo-color-subtle, #757575);min-width:150px;padding-top:5px}.mapping-item .mapping-arrow{color:var(--kendo-color-subtle, #757575);flex-shrink:0;padding-top:5px}.mapping-item .mapping-var-field{display:flex;flex-direction:column;gap:2px;flex:1;min-width:100px}.mapping-item .mapping-var-input-wrapper{display:flex;align-items:center;gap:0}.mapping-item .mapping-var-prefix{font-family:Consolas,Monaco,monospace;font-size:.875rem;font-weight:600;color:var(--kendo-color-primary, #3f51b5);padding-right:2px;flex-shrink:0}.mapping-item .mapping-var-input{flex:1}.mapping-item .mapping-var-input.invalid ::ng-deep .k-input{border-color:var(--kendo-color-error, #f44336)}.edit-actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:.5rem;padding-top:.75rem;border-top:1px solid var(--kendo-color-border, #e0e0e0)}\n"] }]
|
|
28313
28890
|
}], propDecorators: { entitySelectors: [{
|
|
28314
28891
|
type: Input
|
|
28315
28892
|
}], existingVariableNames: [{
|
|
@@ -30602,6 +31179,8 @@ class MeshBoardViewComponent {
|
|
|
30602
31179
|
this.stateService.updateEntitySelectorSelection(selectorId, undefined);
|
|
30603
31180
|
// Clear variables for this selector
|
|
30604
31181
|
this.stateService.clearEntitySelectorVariables(selectorId);
|
|
31182
|
+
// Clear the resolved stream-data scope rtIds for this selector
|
|
31183
|
+
this.stateService.clearEntitySelectorRtIds(selectorId);
|
|
30605
31184
|
// Sync to URL
|
|
30606
31185
|
this.writeEntitySelectorsToUrl();
|
|
30607
31186
|
// Refresh widgets
|
|
@@ -30662,6 +31241,11 @@ class MeshBoardViewComponent {
|
|
|
30662
31241
|
values.push({ name: rtIdVariableName, value: rtId, type: 'string' });
|
|
30663
31242
|
}
|
|
30664
31243
|
this.stateService.setEntitySelectorVariables(selector.id, values);
|
|
31244
|
+
// Resolve the stream-data scope rtIds for this selection (one-hop
|
|
31245
|
+
// childScope traversal, or the picked entity itself). Runs alongside the
|
|
31246
|
+
// variable resolution so widgets bound to this selector can scope their
|
|
31247
|
+
// stream-data query by the resolved source rtIds.
|
|
31248
|
+
await this.resolveEntitySelectorScopeRtIds(selector, rtId);
|
|
30665
31249
|
return entity.rtWellKnownName || entity.rtId;
|
|
30666
31250
|
}
|
|
30667
31251
|
catch (error) {
|
|
@@ -30669,6 +31253,38 @@ class MeshBoardViewComponent {
|
|
|
30669
31253
|
return undefined;
|
|
30670
31254
|
}
|
|
30671
31255
|
}
|
|
31256
|
+
/**
|
|
31257
|
+
* Resolves the set of source rtIds that a stream-data widget bound to this
|
|
31258
|
+
* selector should be scoped to, and caches them on the state service.
|
|
31259
|
+
*
|
|
31260
|
+
* When the selector defines a {@link EntitySelectorChildScope}, the picked
|
|
31261
|
+
* entity's children of `targetCkTypeId` reached via `roleId`/`direction`
|
|
31262
|
+
* become the scope (e.g. MeteringPoint → its EnergyMeasurement rtIds). With
|
|
31263
|
+
* no childScope, the picked entity's own rtId is the scope (direct keying).
|
|
31264
|
+
*/
|
|
31265
|
+
async resolveEntitySelectorScopeRtIds(selector, rtId) {
|
|
31266
|
+
const childScope = selector.childScope;
|
|
31267
|
+
if (!childScope?.targetCkTypeId || !childScope.roleId) {
|
|
31268
|
+
this.stateService.setEntitySelectorRtIds(selector.id, [rtId]);
|
|
31269
|
+
return;
|
|
31270
|
+
}
|
|
31271
|
+
try {
|
|
31272
|
+
const targets = await firstValueFrom(this.dataService.fetchAssociationTargets(rtId, selector.ckTypeId, childScope.targetCkTypeId, childScope.roleId,
|
|
31273
|
+
// Parent → children via System/ParentChild is an INBOUND hop (the child
|
|
31274
|
+
// owns the association to its parent), so 'in' is the default.
|
|
31275
|
+
childScope.direction ?? 'in'));
|
|
31276
|
+
const childRtIds = (targets ?? [])
|
|
31277
|
+
.map(t => String(t.rtId))
|
|
31278
|
+
.filter(id => id.length > 0);
|
|
31279
|
+
this.stateService.setEntitySelectorRtIds(selector.id, childRtIds);
|
|
31280
|
+
}
|
|
31281
|
+
catch (error) {
|
|
31282
|
+
console.error(`Error resolving child scope for selector '${selector.id}':`, error);
|
|
31283
|
+
// Empty scope is safer than a stale one: the bound widget falls back to
|
|
31284
|
+
// its persisted scope rather than querying the wrong asset.
|
|
31285
|
+
this.stateService.setEntitySelectorRtIds(selector.id, []);
|
|
31286
|
+
}
|
|
31287
|
+
}
|
|
30672
31288
|
/**
|
|
30673
31289
|
* Writes entity selector selections to URL query parameters.
|
|
30674
31290
|
* Format: es_<selectorId>=<rtId>
|