@meshmakers/octo-ui 3.4.1450 → 3.4.1490
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -0
- package/entity-forms/README.md +460 -0
- package/fesm2022/meshmakers-octo-ui-branding-settings.mjs +2 -2
- package/fesm2022/meshmakers-octo-ui-branding-settings.mjs.map +1 -1
- package/fesm2022/meshmakers-octo-ui-entity-forms.mjs +7880 -0
- package/fesm2022/meshmakers-octo-ui-entity-forms.mjs.map +1 -0
- package/fesm2022/meshmakers-octo-ui-tree-navigation-settings.mjs +2 -2
- package/fesm2022/meshmakers-octo-ui-tree-navigation-settings.mjs.map +1 -1
- package/fesm2022/meshmakers-octo-ui.mjs +985 -402
- package/fesm2022/meshmakers-octo-ui.mjs.map +1 -1
- package/lib/runtime-browser/styles/_button.scss +87 -0
- package/lib/runtime-browser/styles/_field-input.scss +16 -0
- package/lib/runtime-browser/styles/_flat-button.scss +14 -0
- package/lib/runtime-browser/styles/_index.scss +1 -1
- package/lib/runtime-browser/styles/_styles.scss +760 -1407
- package/lib/runtime-browser/styles/_theme.scss +248 -288
- package/lib/runtime-browser/styles/_variables.scss +26 -41
- package/package.json +5 -1
- package/types/meshmakers-octo-ui-entity-forms.d.ts +2594 -0
- package/types/meshmakers-octo-ui.d.ts +197 -4
- package/lib/runtime-browser/styles/_lcars-button.scss +0 -57
- package/lib/runtime-browser/styles/_lcars-flat-btn.scss +0 -11
- package/lib/runtime-browser/styles/_lcars-input.scss +0 -13
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, ChangeDetectionStrategy, Component, Injectable, Input, EventEmitter, Output, ElementRef, forwardRef, ViewChild, signal, computed, input, model, output, effect, untracked, Directive,
|
|
2
|
+
import { inject, ChangeDetectionStrategy, Component, Injectable, Input, EventEmitter, Output, LOCALE_ID, ElementRef, forwardRef, ViewChild, signal, computed, input, model, output, effect, untracked, Directive, booleanAttribute, viewChild, afterEveryRender, InjectionToken, HostListener, makeEnvironmentProviders } from '@angular/core';
|
|
3
3
|
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
|
4
|
-
import { AttributeSelectorService, AttributeValueTypeDto as AttributeValueTypeDto$1, CkTypeSelectorService, CkTypeAttributeService, GetEntitiesByCkTypeDtoGQL, RuntimeEntitySelectDataSource, RuntimeEntityDialogDataSource, SearchFilterTypesDto, SortOrdersDto, FieldFilterOperatorsDto, GetCkTypesDtoGQL, GetCkModelByIdDtoGQL, GraphDirectionDto, CkTypeMetaData, AssociationModOptionsDto, GraphQL, DeleteStrategiesDto, CommunicationService, provideOctoServices } from '@meshmakers/octo-services';
|
|
4
|
+
import { AttributeSelectorService, AttributeValueTypeDto as AttributeValueTypeDto$1, CkTypeSelectorService, CkTypeAttributeService, toSecretState, secretStateFromAttribute, isSecretValueType, isSecretStateObject, secretStatusOf, formatSecretStatus, GetEntitiesByCkTypeDtoGQL, RuntimeEntitySelectDataSource, RuntimeEntityDialogDataSource, SearchFilterTypesDto, SortOrdersDto, FieldFilterOperatorsDto, GetCkTypesDtoGQL, GetCkModelByIdDtoGQL, GraphDirectionDto, CkTypeMetaData, AssociationModOptionsDto, GraphQL, isSecretAttributeCandidate, toUniqueCamelCaseNames, toCamelCaseAttributeName, DeleteStrategiesDto, CommunicationService, provideOctoServices } from '@meshmakers/octo-services';
|
|
5
5
|
import { Roles, provideMmSharedAuth } from '@meshmakers/shared-auth';
|
|
6
|
-
import { WindowStateService, EntitySelectInputComponent, DataSourceTyped, HierarchyDataSourceBase, NotificationDisplayService, TreeComponent, ListViewComponent, FetchResultTyped, DataSourceBase, InputService, BaseTreeDetailComponent,
|
|
6
|
+
import { WindowStateService, EntitySelectInputComponent, DataSourceTyped, HierarchyDataSourceBase, NotificationDisplayService, TreeComponent, ListViewComponent, FetchResultTyped, DataSourceBase, MM_ACTION_ICONS, ConfirmationService, InputService, BaseTreeDetailComponent, provideMmSharedUi } from '@meshmakers/shared-ui';
|
|
7
7
|
import * as i1$2 from '@angular/common';
|
|
8
|
-
import { CommonModule, Location } from '@angular/common';
|
|
8
|
+
import { CommonModule, formatDate, Location } from '@angular/common';
|
|
9
9
|
import * as i1 from '@angular/forms';
|
|
10
10
|
import { FormsModule, FormControl, ReactiveFormsModule, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormArray, Validators, FormGroup, FormBuilder } from '@angular/forms';
|
|
11
11
|
import * as i1$1 from '@progress/kendo-angular-buttons';
|
|
@@ -19,8 +19,8 @@ import * as i5$1 from '@progress/kendo-angular-icons';
|
|
|
19
19
|
import { IconsModule, SVGIconModule, SVGIconComponent } from '@progress/kendo-angular-icons';
|
|
20
20
|
import * as i5 from '@progress/kendo-angular-inputs';
|
|
21
21
|
import { InputsModule, TextBoxModule, KENDO_INPUTS, SwitchModule } from '@progress/kendo-angular-inputs';
|
|
22
|
-
import { searchIcon, sortAscSmallIcon, sortDescSmallIcon, filterClearIcon, fileIcon, folderIcon, calendarIcon, checkboxCheckedIcon, listUnorderedIcon, chevronRightIcon, chevronDownIcon, downloadIcon, windowIcon, arrowRightIcon, arrowLeftIcon, chevronDoubleRightIcon, chevronDoubleLeftIcon, arrowUpIcon, arrowDownIcon, pencilIcon, trashIcon, copyIcon, folderMoreIcon, gearIcon, folderOpenIcon, plusIcon, minusIcon, dollarIcon, hyperlinkOpenIcon, infoCircleIcon, eyeIcon, arrowRotateCcwIcon, locationsIcon, arrowRotateCwIcon,
|
|
23
|
-
import { Subject, firstValueFrom, Subscription, of, forkJoin, map as map$1,
|
|
22
|
+
import { searchIcon, sortAscSmallIcon, sortDescSmallIcon, filterClearIcon, fileIcon, folderIcon, calendarIcon, checkboxCheckedIcon, listUnorderedIcon, chevronRightIcon, chevronDownIcon, downloadIcon, windowIcon, arrowRightIcon, arrowLeftIcon, chevronDoubleRightIcon, chevronDoubleLeftIcon, arrowUpIcon, arrowDownIcon, pencilIcon, trashIcon, copyIcon, folderMoreIcon, gearIcon, folderOpenIcon, plusIcon, minusIcon, dollarIcon, hyperlinkOpenIcon, infoCircleIcon, eyeIcon, arrowRotateCcwIcon, locationsIcon, arrowRotateCwIcon, checkCircleIcon, exclamationCircleIcon, xCircleIcon, warningCircleIcon, gridIcon, xIcon, linkIcon, lightbulbOutlineIcon, brightnessContrastIcon } from '@progress/kendo-svg-icons';
|
|
23
|
+
import { Subject, firstValueFrom, Subscription, of, forkJoin, map as map$1, catchError as catchError$1, takeUntil as takeUntil$1, defer, from, switchMap as switchMap$1, finalize, startWith } from 'rxjs';
|
|
24
24
|
import { debounceTime, distinctUntilChanged, map, switchMap, tap, catchError, takeUntil } from 'rxjs/operators';
|
|
25
25
|
import { LoaderModule, BadgeModule } from '@progress/kendo-angular-indicators';
|
|
26
26
|
import * as i1$3 from 'apollo-angular';
|
|
@@ -266,6 +266,8 @@ class AttributeSortSelectorDialogComponent {
|
|
|
266
266
|
kendoButton
|
|
267
267
|
[svgIcon]="searchIcon"
|
|
268
268
|
fillMode="clear"
|
|
269
|
+
title="Search"
|
|
270
|
+
aria-label="Search"
|
|
269
271
|
></button>
|
|
270
272
|
</ng-template>
|
|
271
273
|
</kendo-textbox>
|
|
@@ -340,7 +342,7 @@ class AttributeSortSelectorDialogComponent {
|
|
|
340
342
|
"
|
|
341
343
|
(click)="setSortOrder('ascending')"
|
|
342
344
|
class="sort-button"
|
|
343
|
-
title="Ascending"
|
|
345
|
+
title="Ascending" aria-label="Ascending"
|
|
344
346
|
></button>
|
|
345
347
|
<button
|
|
346
348
|
kendoButton
|
|
@@ -353,7 +355,7 @@ class AttributeSortSelectorDialogComponent {
|
|
|
353
355
|
"
|
|
354
356
|
(click)="setSortOrder('descending')"
|
|
355
357
|
class="sort-button"
|
|
356
|
-
title="Descending"
|
|
358
|
+
title="Descending" aria-label="Descending"
|
|
357
359
|
></button>
|
|
358
360
|
</div>
|
|
359
361
|
|
|
@@ -447,6 +449,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
447
449
|
kendoButton
|
|
448
450
|
[svgIcon]="searchIcon"
|
|
449
451
|
fillMode="clear"
|
|
452
|
+
title="Search"
|
|
453
|
+
aria-label="Search"
|
|
450
454
|
></button>
|
|
451
455
|
</ng-template>
|
|
452
456
|
</kendo-textbox>
|
|
@@ -521,7 +525,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
521
525
|
"
|
|
522
526
|
(click)="setSortOrder('ascending')"
|
|
523
527
|
class="sort-button"
|
|
524
|
-
title="Ascending"
|
|
528
|
+
title="Ascending" aria-label="Ascending"
|
|
525
529
|
></button>
|
|
526
530
|
<button
|
|
527
531
|
kendoButton
|
|
@@ -534,7 +538,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
534
538
|
"
|
|
535
539
|
(click)="setSortOrder('descending')"
|
|
536
540
|
class="sort-button"
|
|
537
|
-
title="Descending"
|
|
541
|
+
title="Descending" aria-label="Descending"
|
|
538
542
|
></button>
|
|
539
543
|
</div>
|
|
540
544
|
|
|
@@ -919,13 +923,13 @@ class CkTypeSelectorDialogComponent {
|
|
|
919
923
|
[placeholder]="_messages.typeSearchPlaceholder"
|
|
920
924
|
class="filter-input">
|
|
921
925
|
<ng-template kendoTextBoxSuffixTemplate>
|
|
922
|
-
<button kendoButton [svgIcon]="searchIcon" fillMode="clear" size="small"></button>
|
|
926
|
+
<button kendoButton [svgIcon]="searchIcon" fillMode="clear" size="small" title="Search" aria-label="Search"></button>
|
|
923
927
|
</ng-template>
|
|
924
928
|
</kendo-textbox>
|
|
925
929
|
</div>
|
|
926
930
|
<div class="filter-item filter-actions">
|
|
927
931
|
<label> </label>
|
|
928
|
-
<button kendoButton [svgIcon]="filterClearIcon" (click)="clearFilters()" [title]="_messages.clearFiltersTitle"></button>
|
|
932
|
+
<button kendoButton [svgIcon]="filterClearIcon" (click)="clearFilters()" [title]="_messages.clearFiltersTitle" [attr.aria-label]="_messages.clearFiltersTitle"></button>
|
|
929
933
|
</div>
|
|
930
934
|
</div>
|
|
931
935
|
</div>
|
|
@@ -986,7 +990,7 @@ class CkTypeSelectorDialogComponent {
|
|
|
986
990
|
<button kendoButton themeColor="primary" [disabled]="!selectedType || (selectedType.isAbstract && !allowAbstract)" (click)="onConfirm()">{{ _messages.ok }}</button>
|
|
987
991
|
</div>
|
|
988
992
|
</div>
|
|
989
|
-
`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%}.ck-type-selector-container{display:flex;flex-direction:column;flex:1;min-height:0;padding:20px;box-sizing:border-box;gap:12px}.filter-container{margin-bottom:16px;flex-shrink:0}.filter-row{display:flex;gap:16px;align-items:flex-end}.filter-item{display:flex;flex-direction:column;gap:4px}.filter-item label{font-size:12px;font-weight:500}.filter-item.flex-grow{flex:1}.filter-item.filter-actions{flex-shrink:0}.filter-input{min-width:180px}.grid-container{flex:1;min-height:0;display:flex;flex-direction:column}.grid-container kendo-grid,.grid-container .type-grid{flex:1;min-height:200px}.type-grid{border-radius:4px}.type-grid ::ng-deep .k-grid-table tbody tr{cursor:pointer}.abstract-type{font-style:italic;opacity:.7}.final-type{font-weight:600}.type-badge{display:inline-block;font-size:10px;padding:1px 6px;border-radius:10px;margin-left:8px
|
|
993
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%}.ck-type-selector-container{display:flex;flex-direction:column;flex:1;min-height:0;padding:20px;box-sizing:border-box;gap:12px}.filter-container{margin-bottom:16px;flex-shrink:0}.filter-row{display:flex;gap:16px;align-items:flex-end}.filter-item{display:flex;flex-direction:column;gap:4px}.filter-item label{font-size:12px;font-weight:500}.filter-item.flex-grow{flex:1}.filter-item.filter-actions{flex-shrink:0}.filter-input{min-width:180px}.grid-container{flex:1;min-height:0;display:flex;flex-direction:column}.grid-container kendo-grid,.grid-container .type-grid{flex:1;min-height:200px}.type-grid{border-radius:4px}.type-grid ::ng-deep .k-grid-table tbody tr{cursor:pointer}.abstract-type{font-style:italic;opacity:.7}.final-type{font-weight:600}.type-badge{display:inline-block;font-size:10px;padding:1px 6px;border-radius:10px;margin-left:8px}.type-badge.abstract{background-color:var(--kendo-color-warning, #ffc107);color:var(--kendo-color-on-warning, #000);opacity:.8}.type-badge.final{background-color:var(--kendo-color-success, #28a745);color:var(--kendo-color-on-success, #fff);opacity:.8}.selection-info{margin-top:12px;padding:8px 12px;background:var(--kendo-color-success-subtle, #d4edda);border:1px solid var(--kendo-color-success, #28a745);border-radius:4px;font-size:14px;flex-shrink:0}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;padding:8px 20px 0;flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: GridModule }, { kind: "component", type: i3.GridComponent, selector: "kendo-grid", inputs: ["data", "pageSize", "height", "rowHeight", "adaptiveMode", "detailRowHeight", "skip", "scrollable", "selectable", "sort", "size", "trackBy", "filter", "group", "virtualColumns", "filterable", "sortable", "pageable", "groupable", "gridResizable", "rowReorderable", "navigable", "autoSize", "rowClass", "rowSticky", "rowSelected", "isRowSelectable", "cellSelected", "resizable", "reorderable", "loading", "columnMenu", "hideHeader", "showInactiveTools", "isDetailExpanded", "isGroupExpanded", "dataLayoutMode", "pinnable", "pinnedTopRows", "pinnedBottomRows", "isRowPinnable"], outputs: ["filterChange", "pageChange", "groupChange", "sortChange", "selectionChange", "rowReorder", "rowPinChange", "dataStateChange", "gridStateChange", "groupExpand", "groupCollapse", "detailExpand", "detailCollapse", "edit", "cancel", "save", "remove", "add", "cellClose", "cellClick", "pdfExport", "excelExport", "csvExport", "columnResize", "columnReorder", "columnVisibilityChange", "columnLockedChange", "columnStickyChange", "scrollBottom", "contentScroll"], exportAs: ["kendoGrid"] }, { kind: "directive", type: i3.SelectionDirective, selector: "[kendoGridSelectBy]" }, { kind: "component", type: i3.CustomMessagesComponent, selector: "kendo-grid-messages" }, { kind: "component", type: i3.ColumnComponent, selector: "kendo-grid-column", inputs: ["field", "format", "sortable", "groupable", "editor", "filter", "filterVariant", "filterable", "editable"] }, { kind: "directive", type: i3.CellTemplateDirective, selector: "[kendoGridCellTemplate]" }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i1$1.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: i5.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: i5.TextBoxSuffixTemplateDirective, selector: "[kendoTextBoxSuffixTemplate]", inputs: ["showSeparator"] }, { kind: "ngmodule", type: DropDownsModule }, { kind: "component", type: i3$1.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: "ngmodule", type: IconsModule }, { kind: "ngmodule", type: LoaderModule }, { kind: "ngmodule", type: WindowModule }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
990
994
|
}
|
|
991
995
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: CkTypeSelectorDialogComponent, decorators: [{
|
|
992
996
|
type: Component,
|
|
@@ -1024,13 +1028,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
1024
1028
|
[placeholder]="_messages.typeSearchPlaceholder"
|
|
1025
1029
|
class="filter-input">
|
|
1026
1030
|
<ng-template kendoTextBoxSuffixTemplate>
|
|
1027
|
-
<button kendoButton [svgIcon]="searchIcon" fillMode="clear" size="small"></button>
|
|
1031
|
+
<button kendoButton [svgIcon]="searchIcon" fillMode="clear" size="small" title="Search" aria-label="Search"></button>
|
|
1028
1032
|
</ng-template>
|
|
1029
1033
|
</kendo-textbox>
|
|
1030
1034
|
</div>
|
|
1031
1035
|
<div class="filter-item filter-actions">
|
|
1032
1036
|
<label> </label>
|
|
1033
|
-
<button kendoButton [svgIcon]="filterClearIcon" (click)="clearFilters()" [title]="_messages.clearFiltersTitle"></button>
|
|
1037
|
+
<button kendoButton [svgIcon]="filterClearIcon" (click)="clearFilters()" [title]="_messages.clearFiltersTitle" [attr.aria-label]="_messages.clearFiltersTitle"></button>
|
|
1034
1038
|
</div>
|
|
1035
1039
|
</div>
|
|
1036
1040
|
</div>
|
|
@@ -1091,7 +1095,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
1091
1095
|
<button kendoButton themeColor="primary" [disabled]="!selectedType || (selectedType.isAbstract && !allowAbstract)" (click)="onConfirm()">{{ _messages.ok }}</button>
|
|
1092
1096
|
</div>
|
|
1093
1097
|
</div>
|
|
1094
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:flex;flex-direction:column;height:100%}.ck-type-selector-container{display:flex;flex-direction:column;flex:1;min-height:0;padding:20px;box-sizing:border-box;gap:12px}.filter-container{margin-bottom:16px;flex-shrink:0}.filter-row{display:flex;gap:16px;align-items:flex-end}.filter-item{display:flex;flex-direction:column;gap:4px}.filter-item label{font-size:12px;font-weight:500}.filter-item.flex-grow{flex:1}.filter-item.filter-actions{flex-shrink:0}.filter-input{min-width:180px}.grid-container{flex:1;min-height:0;display:flex;flex-direction:column}.grid-container kendo-grid,.grid-container .type-grid{flex:1;min-height:200px}.type-grid{border-radius:4px}.type-grid ::ng-deep .k-grid-table tbody tr{cursor:pointer}.abstract-type{font-style:italic;opacity:.7}.final-type{font-weight:600}.type-badge{display:inline-block;font-size:10px;padding:1px 6px;border-radius:10px;margin-left:8px
|
|
1098
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:flex;flex-direction:column;height:100%}.ck-type-selector-container{display:flex;flex-direction:column;flex:1;min-height:0;padding:20px;box-sizing:border-box;gap:12px}.filter-container{margin-bottom:16px;flex-shrink:0}.filter-row{display:flex;gap:16px;align-items:flex-end}.filter-item{display:flex;flex-direction:column;gap:4px}.filter-item label{font-size:12px;font-weight:500}.filter-item.flex-grow{flex:1}.filter-item.filter-actions{flex-shrink:0}.filter-input{min-width:180px}.grid-container{flex:1;min-height:0;display:flex;flex-direction:column}.grid-container kendo-grid,.grid-container .type-grid{flex:1;min-height:200px}.type-grid{border-radius:4px}.type-grid ::ng-deep .k-grid-table tbody tr{cursor:pointer}.abstract-type{font-style:italic;opacity:.7}.final-type{font-weight:600}.type-badge{display:inline-block;font-size:10px;padding:1px 6px;border-radius:10px;margin-left:8px}.type-badge.abstract{background-color:var(--kendo-color-warning, #ffc107);color:var(--kendo-color-on-warning, #000);opacity:.8}.type-badge.final{background-color:var(--kendo-color-success, #28a745);color:var(--kendo-color-on-success, #fff);opacity:.8}.selection-info{margin-top:12px;padding:8px 12px;background:var(--kendo-color-success-subtle, #d4edda);border:1px solid var(--kendo-color-success, #28a745);border-radius:4px;font-size:14px;flex-shrink:0}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;padding:8px 20px 0;flex-shrink:0}\n"] }]
|
|
1095
1099
|
}], propDecorators: { messages: [{
|
|
1096
1100
|
type: Input
|
|
1097
1101
|
}] } });
|
|
@@ -1196,6 +1200,8 @@ var AttributeValueTypeDto;
|
|
|
1196
1200
|
AttributeValueTypeDto["IntArrayDto"] = "INT_ARRAY";
|
|
1197
1201
|
AttributeValueTypeDto["RecordDto"] = "RECORD";
|
|
1198
1202
|
AttributeValueTypeDto["RecordArrayDto"] = "RECORD_ARRAY";
|
|
1203
|
+
/** SECRET value type (AB#5528): the value is never read; `value` holds a `SecretState`. */
|
|
1204
|
+
AttributeValueTypeDto["SecretDto"] = "SECRET";
|
|
1199
1205
|
AttributeValueTypeDto["StringDto"] = "STRING";
|
|
1200
1206
|
AttributeValueTypeDto["StringArrayDto"] = "STRING_ARRAY";
|
|
1201
1207
|
AttributeValueTypeDto["TimeSpanDto"] = "TIME_SPAN";
|
|
@@ -1434,6 +1440,24 @@ class PropertyConverterService {
|
|
|
1434
1440
|
* Convert a single attribute to PropertyGridItem
|
|
1435
1441
|
*/
|
|
1436
1442
|
convertSingleAttribute(attr, index, ckAttributeMap) {
|
|
1443
|
+
// SECRET (AB#5528): never a value — the set / not-set state is shown as a read-only badge.
|
|
1444
|
+
const ckType = attr?.attributeName ? ckAttributeMap.get(attr.attributeName) : undefined;
|
|
1445
|
+
const marker = attr?.value && typeof attr.value === 'object' && 'isSet' in attr.value
|
|
1446
|
+
? toSecretState(attr.value)
|
|
1447
|
+
: null;
|
|
1448
|
+
const secretState = secretStateFromAttribute(attr) ?? (isSecretValueType(ckType) ? marker : null);
|
|
1449
|
+
if (secretState || isSecretValueType(ckType)) {
|
|
1450
|
+
return {
|
|
1451
|
+
id: `attr_${index}_${attr?.attributeName || 'unknown'}`,
|
|
1452
|
+
name: attr?.attributeName || `attribute_${index}`,
|
|
1453
|
+
displayName: attr?.attributeName || `attribute_${index}`,
|
|
1454
|
+
value: secretState ?? { isSet: false, keyMissing: false, setAt: null },
|
|
1455
|
+
type: AttributeValueTypeDto.SecretDto,
|
|
1456
|
+
category: DefaultPropertyCategory.Attributes,
|
|
1457
|
+
readOnly: true,
|
|
1458
|
+
description: `Attribute: ${attr?.attributeName} (secret, write-only)`
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1437
1461
|
const value = this.convertRtEntityAttributeValueSync(attr?.value);
|
|
1438
1462
|
return {
|
|
1439
1463
|
id: `attr_${index}_${attr?.attributeName || 'unknown'}`,
|
|
@@ -1484,6 +1508,7 @@ class PropertyConverterService {
|
|
|
1484
1508
|
'RECORD_ARRAY': AttributeValueTypeDto.RecordArrayDto,
|
|
1485
1509
|
'STRING': AttributeValueTypeDto.StringDto,
|
|
1486
1510
|
'STRING_ARRAY': AttributeValueTypeDto.StringArrayDto,
|
|
1511
|
+
'SECRET': AttributeValueTypeDto.SecretDto,
|
|
1487
1512
|
'TIME_SPAN': AttributeValueTypeDto.TimeSpanDto
|
|
1488
1513
|
};
|
|
1489
1514
|
return typeMap[ckType] || AttributeValueTypeDto.StringDto;
|
|
@@ -1930,7 +1955,7 @@ class RecordDetailDialogComponent {
|
|
|
1930
1955
|
</kendo-grid>
|
|
1931
1956
|
}
|
|
1932
1957
|
</div>
|
|
1933
|
-
`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}.record-detail-content{display:flex;flex-direction:column;height:100%;gap:8px;padding:12px 16px;box-sizing:border-box;overflow:hidden}.record-toolbar{display:flex;align-items:center;gap:8px;flex-shrink:0;padding-bottom:4px;border-bottom:1px solid var(--kendo-color-border, #dee2e6)}.toolbar-spacer{flex:1}.search-input{flex:0 1 220px;min-width:0;padding:4px 8px;font:inherit;color:var(--kendo-color-on-app-surface, #1d1b20);background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:3px;outline:none}.search-input::placeholder{color:var(--kendo-color-subtle, #6c757d)}.search-input:focus{border-color:var(--kendo-color-primary, #0d6efd)}.search-clear{flex-shrink:0;width:22px;height:22px;padding:0;background:transparent;border:none;cursor:pointer;font-size:1.1em;line-height:1;color:var(--kendo-color-subtle, #6c757d);border-radius:3px}.search-clear:hover{color:var(--kendo-color-on-app-surface, #1d1b20);background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 8%,transparent)}.match-count{flex-shrink:0;font-size:.8em;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.no-matches{padding:16px;text-align:center;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.record-array-list{display:flex;flex-direction:column;gap:8px;overflow-y:auto;flex:1;min-height:0}.record-array-item{display:block;flex-shrink:0;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;overflow:hidden}.array-item-header{display:flex;align-items:center;gap:8px;padding:6px 10px;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--kendo-color-surface-alt, #f8f9fa);transition:background-color .15s ease}.array-item-header:hover{background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent)}.record-chevron{width:14px;height:14px;color:var(--kendo-color-subtle);flex-shrink:0}.array-item-index{font-family:Roboto Mono,monospace;font-size:.8em;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.array-item-label{font-size:.85em;color:var(--kendo-color-on-app-surface, #1d1b20);font-weight:500}.array-item-summary{margin-left:auto;font-size:.75em;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.detail-grid{display:block!important;height:auto!important;border:none;border-top:1px solid var(--kendo-color-border, #dee2e6)}:host ::ng-deep .detail-grid .k-grid-aria-root{height:auto}.property-name-cell{display:flex;align-items:center;gap:8px}.type-icon{width:16px;height:16px;opacity:.7}.property-name{font-weight:500}.property-value{word-break:break-word;white-space:pre-wrap}.type-badge{font-size:.75em;padding:2px 6px;border-radius:3px;
|
|
1958
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}.record-detail-content{display:flex;flex-direction:column;height:100%;gap:8px;padding:12px 16px;box-sizing:border-box;overflow:hidden}.record-toolbar{display:flex;align-items:center;gap:8px;flex-shrink:0;padding-bottom:4px;border-bottom:1px solid var(--kendo-color-border, #dee2e6)}.toolbar-spacer{flex:1}.search-input{flex:0 1 220px;min-width:0;padding:4px 8px;font:inherit;color:var(--kendo-color-on-app-surface, #1d1b20);background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:3px;outline:none}.search-input::placeholder{color:var(--kendo-color-subtle, #6c757d)}.search-input:focus{border-color:var(--kendo-color-primary, #0d6efd)}.search-clear{flex-shrink:0;width:22px;height:22px;padding:0;background:transparent;border:none;cursor:pointer;font-size:1.1em;line-height:1;color:var(--kendo-color-subtle, #6c757d);border-radius:3px}.search-clear:hover{color:var(--kendo-color-on-app-surface, #1d1b20);background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 8%,transparent)}.match-count{flex-shrink:0;font-size:.8em;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.no-matches{padding:16px;text-align:center;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.record-array-list{display:flex;flex-direction:column;gap:8px;overflow-y:auto;flex:1;min-height:0}.record-array-item{display:block;flex-shrink:0;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;overflow:hidden}.array-item-header{display:flex;align-items:center;gap:8px;padding:6px 10px;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--kendo-color-surface-alt, #f8f9fa);transition:background-color .15s ease}.array-item-header:hover{background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent)}.record-chevron{width:14px;height:14px;color:var(--kendo-color-subtle);flex-shrink:0}.array-item-index{font-family:Roboto Mono,monospace;font-size:.8em;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.array-item-label{font-size:.85em;color:var(--kendo-color-on-app-surface, #1d1b20);font-weight:500}.array-item-summary{margin-left:auto;font-size:.75em;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.detail-grid{display:block!important;height:auto!important;border:none;border-top:1px solid var(--kendo-color-border, #dee2e6)}:host ::ng-deep .detail-grid .k-grid-aria-root{height:auto}.property-name-cell{display:flex;align-items:center;gap:8px}.type-icon{width:16px;height:16px;opacity:.7}.property-name{font-weight:500}.property-value{word-break:break-word;white-space:pre-wrap}.type-badge{font-size:.75em;padding:2px 6px;border-radius:3px;font-weight:500;background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 12%,transparent);color:var(--kendo-color-on-app-surface, #1d1b20)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: GridModule }, { kind: "component", type: i3.GridComponent, selector: "kendo-grid", inputs: ["data", "pageSize", "height", "rowHeight", "adaptiveMode", "detailRowHeight", "skip", "scrollable", "selectable", "sort", "size", "trackBy", "filter", "group", "virtualColumns", "filterable", "sortable", "pageable", "groupable", "gridResizable", "rowReorderable", "navigable", "autoSize", "rowClass", "rowSticky", "rowSelected", "isRowSelectable", "cellSelected", "resizable", "reorderable", "loading", "columnMenu", "hideHeader", "showInactiveTools", "isDetailExpanded", "isGroupExpanded", "dataLayoutMode", "pinnable", "pinnedTopRows", "pinnedBottomRows", "isRowPinnable"], outputs: ["filterChange", "pageChange", "groupChange", "sortChange", "selectionChange", "rowReorder", "rowPinChange", "dataStateChange", "gridStateChange", "groupExpand", "groupCollapse", "detailExpand", "detailCollapse", "edit", "cancel", "save", "remove", "add", "cellClose", "cellClick", "pdfExport", "excelExport", "csvExport", "columnResize", "columnReorder", "columnVisibilityChange", "columnLockedChange", "columnStickyChange", "scrollBottom", "contentScroll"], exportAs: ["kendoGrid"] }, { kind: "component", type: i3.ColumnComponent, selector: "kendo-grid-column", inputs: ["field", "format", "sortable", "groupable", "editor", "filter", "filterVariant", "filterable", "editable"] }, { kind: "directive", type: i3.CellTemplateDirective, selector: "[kendoGridCellTemplate]" }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: i5$1.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
1934
1959
|
}
|
|
1935
1960
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: RecordDetailDialogComponent, decorators: [{
|
|
1936
1961
|
type: Component,
|
|
@@ -2041,7 +2066,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
2041
2066
|
</kendo-grid>
|
|
2042
2067
|
}
|
|
2043
2068
|
</div>
|
|
2044
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}.record-detail-content{display:flex;flex-direction:column;height:100%;gap:8px;padding:12px 16px;box-sizing:border-box;overflow:hidden}.record-toolbar{display:flex;align-items:center;gap:8px;flex-shrink:0;padding-bottom:4px;border-bottom:1px solid var(--kendo-color-border, #dee2e6)}.toolbar-spacer{flex:1}.search-input{flex:0 1 220px;min-width:0;padding:4px 8px;font:inherit;color:var(--kendo-color-on-app-surface, #1d1b20);background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:3px;outline:none}.search-input::placeholder{color:var(--kendo-color-subtle, #6c757d)}.search-input:focus{border-color:var(--kendo-color-primary, #0d6efd)}.search-clear{flex-shrink:0;width:22px;height:22px;padding:0;background:transparent;border:none;cursor:pointer;font-size:1.1em;line-height:1;color:var(--kendo-color-subtle, #6c757d);border-radius:3px}.search-clear:hover{color:var(--kendo-color-on-app-surface, #1d1b20);background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 8%,transparent)}.match-count{flex-shrink:0;font-size:.8em;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.no-matches{padding:16px;text-align:center;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.record-array-list{display:flex;flex-direction:column;gap:8px;overflow-y:auto;flex:1;min-height:0}.record-array-item{display:block;flex-shrink:0;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;overflow:hidden}.array-item-header{display:flex;align-items:center;gap:8px;padding:6px 10px;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--kendo-color-surface-alt, #f8f9fa);transition:background-color .15s ease}.array-item-header:hover{background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent)}.record-chevron{width:14px;height:14px;color:var(--kendo-color-subtle);flex-shrink:0}.array-item-index{font-family:Roboto Mono,monospace;font-size:.8em;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.array-item-label{font-size:.85em;color:var(--kendo-color-on-app-surface, #1d1b20);font-weight:500}.array-item-summary{margin-left:auto;font-size:.75em;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.detail-grid{display:block!important;height:auto!important;border:none;border-top:1px solid var(--kendo-color-border, #dee2e6)}:host ::ng-deep .detail-grid .k-grid-aria-root{height:auto}.property-name-cell{display:flex;align-items:center;gap:8px}.type-icon{width:16px;height:16px;opacity:.7}.property-name{font-weight:500}.property-value{word-break:break-word;white-space:pre-wrap}.type-badge{font-size:.75em;padding:2px 6px;border-radius:3px;
|
|
2069
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}.record-detail-content{display:flex;flex-direction:column;height:100%;gap:8px;padding:12px 16px;box-sizing:border-box;overflow:hidden}.record-toolbar{display:flex;align-items:center;gap:8px;flex-shrink:0;padding-bottom:4px;border-bottom:1px solid var(--kendo-color-border, #dee2e6)}.toolbar-spacer{flex:1}.search-input{flex:0 1 220px;min-width:0;padding:4px 8px;font:inherit;color:var(--kendo-color-on-app-surface, #1d1b20);background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:3px;outline:none}.search-input::placeholder{color:var(--kendo-color-subtle, #6c757d)}.search-input:focus{border-color:var(--kendo-color-primary, #0d6efd)}.search-clear{flex-shrink:0;width:22px;height:22px;padding:0;background:transparent;border:none;cursor:pointer;font-size:1.1em;line-height:1;color:var(--kendo-color-subtle, #6c757d);border-radius:3px}.search-clear:hover{color:var(--kendo-color-on-app-surface, #1d1b20);background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 8%,transparent)}.match-count{flex-shrink:0;font-size:.8em;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.no-matches{padding:16px;text-align:center;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.record-array-list{display:flex;flex-direction:column;gap:8px;overflow-y:auto;flex:1;min-height:0}.record-array-item{display:block;flex-shrink:0;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;overflow:hidden}.array-item-header{display:flex;align-items:center;gap:8px;padding:6px 10px;cursor:pointer;-webkit-user-select:none;user-select:none;background:var(--kendo-color-surface-alt, #f8f9fa);transition:background-color .15s ease}.array-item-header:hover{background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent)}.record-chevron{width:14px;height:14px;color:var(--kendo-color-subtle);flex-shrink:0}.array-item-index{font-family:Roboto Mono,monospace;font-size:.8em;font-weight:600;color:var(--kendo-color-primary, #0d6efd)}.array-item-label{font-size:.85em;color:var(--kendo-color-on-app-surface, #1d1b20);font-weight:500}.array-item-summary{margin-left:auto;font-size:.75em;color:var(--kendo-color-subtle, #6c757d);font-style:italic}.detail-grid{display:block!important;height:auto!important;border:none;border-top:1px solid var(--kendo-color-border, #dee2e6)}:host ::ng-deep .detail-grid .k-grid-aria-root{height:auto}.property-name-cell{display:flex;align-items:center;gap:8px}.type-icon{width:16px;height:16px;opacity:.7}.property-name{font-weight:500}.property-value{word-break:break-word;white-space:pre-wrap}.type-badge{font-size:.75em;padding:2px 6px;border-radius:3px;font-weight:500;background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 12%,transparent);color:var(--kendo-color-on-app-surface, #1d1b20)}\n"] }]
|
|
2045
2070
|
}], propDecorators: { attributeName: [{
|
|
2046
2071
|
type: Input
|
|
2047
2072
|
}], value: [{
|
|
@@ -2052,6 +2077,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
2052
2077
|
type: Output
|
|
2053
2078
|
}] } });
|
|
2054
2079
|
|
|
2080
|
+
/**
|
|
2081
|
+
* A secret record member as projected by the server (AB#5528): the marker `{ isSet }` (optionally
|
|
2082
|
+
* with `keyMissing` / `setAt`), or a normalised `SecretState`. Nothing else has exactly these keys.
|
|
2083
|
+
*/
|
|
2084
|
+
function isSecretMarker(value) {
|
|
2085
|
+
return isSecretStateObject(value);
|
|
2086
|
+
}
|
|
2055
2087
|
/**
|
|
2056
2088
|
* Component for displaying property values with appropriate formatting
|
|
2057
2089
|
*/
|
|
@@ -2065,6 +2097,9 @@ class PropertyValueDisplayComponent {
|
|
|
2065
2097
|
// Expansion state
|
|
2066
2098
|
isExpanded = false;
|
|
2067
2099
|
windowService = inject(WindowService);
|
|
2100
|
+
locale = inject(LOCALE_ID);
|
|
2101
|
+
/** Non-null when the value is a secret state (SECRET value type or record member marker). */
|
|
2102
|
+
secretStatus = null;
|
|
2068
2103
|
// Pre-computed template properties — recomputed in ngOnInit and ngOnChanges so Kendo Grid row recycling (cell component reuse with new inputs) does not display stale values.
|
|
2069
2104
|
expandableRecord = false;
|
|
2070
2105
|
complexType = false;
|
|
@@ -2111,6 +2146,7 @@ class PropertyValueDisplayComponent {
|
|
|
2111
2146
|
this.recomputeDerivedValues();
|
|
2112
2147
|
}
|
|
2113
2148
|
recomputeDerivedValues() {
|
|
2149
|
+
this.secretStatus = this.computeSecretStatus();
|
|
2114
2150
|
this.expandableRecord = this.computeIsExpandableRecord();
|
|
2115
2151
|
this.complexType = this.computeIsComplexType();
|
|
2116
2152
|
this.binaryLinkedWithDownload = this.computeIsBinaryLinkedWithDownload();
|
|
@@ -2133,7 +2169,18 @@ class PropertyValueDisplayComponent {
|
|
|
2133
2169
|
this.formattedBinarySize = '';
|
|
2134
2170
|
}
|
|
2135
2171
|
}
|
|
2172
|
+
/** Set / not set / key missing for a SECRET value or a record member marker `{ isSet }` (AB#5528). */
|
|
2173
|
+
computeSecretStatus() {
|
|
2174
|
+
if (this.type !== AttributeValueTypeDto.SecretDto && !isSecretMarker(this.value)) {
|
|
2175
|
+
return null;
|
|
2176
|
+
}
|
|
2177
|
+
return secretStatusOf(this.value);
|
|
2178
|
+
}
|
|
2136
2179
|
computeFormattedValue() {
|
|
2180
|
+
if (this.secretStatus) {
|
|
2181
|
+
const v = (this.value ?? {});
|
|
2182
|
+
return formatSecretStatus(toSecretState({ isSet: v.isSet === true, keyMissing: v.keyMissing, setAt: v.setAt }), (date) => formatDate(date, 'medium', this.locale));
|
|
2183
|
+
}
|
|
2137
2184
|
if (this.value === null) {
|
|
2138
2185
|
return '<null>';
|
|
2139
2186
|
}
|
|
@@ -2438,6 +2485,9 @@ class PropertyValueDisplayComponent {
|
|
|
2438
2485
|
if (value === null || value === undefined) {
|
|
2439
2486
|
return AttributeValueTypeDto.StringDto;
|
|
2440
2487
|
}
|
|
2488
|
+
if (isSecretMarker(value)) {
|
|
2489
|
+
return AttributeValueTypeDto.SecretDto;
|
|
2490
|
+
}
|
|
2441
2491
|
if (typeof value === 'boolean') {
|
|
2442
2492
|
return AttributeValueTypeDto.BooleanDto;
|
|
2443
2493
|
}
|
|
@@ -2529,7 +2579,7 @@ class PropertyValueDisplayComponent {
|
|
|
2529
2579
|
size="small"
|
|
2530
2580
|
fillMode="flat"
|
|
2531
2581
|
[svgIcon]="windowIcon"
|
|
2532
|
-
title="Show details"
|
|
2582
|
+
title="Show details" aria-label="Show details"
|
|
2533
2583
|
class="detail-button"
|
|
2534
2584
|
(click)="openDetailDialog($event)">
|
|
2535
2585
|
</button>
|
|
@@ -2609,6 +2659,9 @@ class PropertyValueDisplayComponent {
|
|
|
2609
2659
|
</div>
|
|
2610
2660
|
}
|
|
2611
2661
|
</div>
|
|
2662
|
+
} @else if (secretStatus) {
|
|
2663
|
+
<!-- SECRET (AB#5528): set / not set / key missing badge, never a value -->
|
|
2664
|
+
<span class="secret-badge" [ngClass]="'secret-badge--' + secretStatus" [attr.data-secret-state]="secretStatus">{{ formattedValue }}</span>
|
|
2612
2665
|
} @else if (binaryLinkedWithDownload) {
|
|
2613
2666
|
<!-- Binary Linked with download capability -->
|
|
2614
2667
|
<div class="binary-linked-display">
|
|
@@ -2655,7 +2708,7 @@ class PropertyValueDisplayComponent {
|
|
|
2655
2708
|
}
|
|
2656
2709
|
|
|
2657
2710
|
</div>
|
|
2658
|
-
`, isInline: true, styles: [".property-value-display{display:flex;align-items:flex-start;gap:8px;width:100%;min-width:0}.text-display,.default-display{word-break:break-word;white-space:pre-wrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.json-display{font-family:Roboto Mono,monospace;font-size:.8em;white-space:pre-wrap;word-break:break-word;margin:0;flex:1;min-width:0}.type-indicator{font-family:Roboto Mono,monospace;font-size:.7em;padding:1px 5px;background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 12%,transparent);border-radius:3px;color:var(--kendo-color-on-app-surface, #1d1b20);white-space:nowrap;flex-shrink:0}.expandable-record{width:100%}.record-header{display:flex;align-items:center;gap:6px;cursor:pointer;padding:2px 0;border-radius:3px;transition:background-color .15s ease}.record-header:hover{background-color:var(--kendo-color-base-subtle, rgba(0,0,0,.04))}.expand-icon{flex-shrink:0;width:14px;height:14px;color:var(--kendo-color-subtle)}.record-summary{color:var(--kendo-color-subtle);font-size:.85em;font-style:italic;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.detail-button{flex-shrink:0;opacity:.6;transition:opacity .15s ease}.detail-button:hover{opacity:1}.record-content{margin-left:20px;padding-left:8px;border-left:1px solid var(--kendo-color-border, #dee2e6)}.array-item{margin:4px 0}.array-index{font-family:Roboto Mono,monospace;font-size:.8em;color:var(--kendo-color-subtle)}.record-array-list{max-height:320px;overflow-y:auto}.record-table-container{max-height:320px;overflow:auto;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:3px;margin-top:4px}.record-table{width:100%;border-collapse:collapse;font-size:.85em;table-layout:auto}.record-table th{position:sticky;top:0;z-index:1;background:var(--kendo-color-surface-alt, #f8f9fa);color:var(--kendo-color-subtle);text-align:left;padding:4px 8px;border-bottom:1px solid var(--kendo-color-border, #dee2e6);font-weight:500;font-size:.85em;white-space:nowrap}.record-table td{padding:3px 8px;border-bottom:1px solid color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 8%,transparent);vertical-align:top;word-break:break-word}.record-table tr:last-child td{border-bottom:none}.record-table tr:hover td{background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent)}.record-table .row-index{color:var(--kendo-color-subtle);font-family:Roboto Mono,monospace;font-size:.85em;text-align:right;width:1px;white-space:nowrap}.nested-properties{margin-left:8px}.nested-property{display:flex;align-items:flex-start;gap:8px;padding:2px 0}.property-key{font-weight:500;white-space:nowrap;flex-shrink:0;color:var(--kendo-color-subtle);font-size:.85em}.binary-linked-display{display:flex;align-items:center;gap:12px;width:100%}.binary-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.filename{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-size{font-size:.85em;color:var(--kendo-color-subtle);flex-shrink:0}.content-type{font-size:.75em;padding:2px 6px;background:var(--kendo-color-base-subtle);border-radius:3px;color:var(--kendo-color-subtle);flex-shrink:0}\n"], dependencies: [{ kind: "component", type: PropertyValueDisplayComponent, selector: "mm-property-value-display", inputs: ["value", "type", "displayMode", "attributeName"], outputs: ["binaryDownload"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: i5$1.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2711
|
+
`, isInline: true, styles: [".property-value-display{display:flex;align-items:flex-start;gap:8px;width:100%;min-width:0}.text-display,.default-display{word-break:break-word;white-space:pre-wrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.json-display{font-family:Roboto Mono,monospace;font-size:.8em;white-space:pre-wrap;word-break:break-word;margin:0;flex:1;min-width:0}.type-indicator{font-family:Roboto Mono,monospace;font-size:.7em;padding:1px 5px;background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 12%,transparent);border-radius:3px;color:var(--kendo-color-on-app-surface, #1d1b20);white-space:nowrap;flex-shrink:0}.expandable-record{width:100%}.record-header{display:flex;align-items:center;gap:6px;cursor:pointer;padding:2px 0;border-radius:3px;transition:background-color .15s ease}.record-header:hover{background-color:var(--kendo-color-base-subtle, rgba(0,0,0,.04))}.expand-icon{flex-shrink:0;width:14px;height:14px;color:var(--kendo-color-subtle)}.record-summary{color:var(--kendo-color-subtle);font-size:.85em;font-style:italic;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.detail-button{flex-shrink:0;opacity:.6;transition:opacity .15s ease}.detail-button:hover{opacity:1}.record-content{margin-left:20px;padding-left:8px;border-left:1px solid var(--kendo-color-border, #dee2e6)}.array-item{margin:4px 0}.array-index{font-family:Roboto Mono,monospace;font-size:.8em;color:var(--kendo-color-subtle)}.record-array-list{max-height:320px;overflow-y:auto}.record-table-container{max-height:320px;overflow:auto;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:3px;margin-top:4px}.record-table{width:100%;border-collapse:collapse;font-size:.85em;table-layout:auto}.record-table th{position:sticky;top:0;z-index:1;background:var(--kendo-color-surface-alt, #f8f9fa);color:var(--kendo-color-subtle);text-align:left;padding:4px 8px;border-bottom:1px solid var(--kendo-color-border, #dee2e6);font-weight:500;font-size:.85em;white-space:nowrap}.record-table td{padding:3px 8px;border-bottom:1px solid color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 8%,transparent);vertical-align:top;word-break:break-word}.record-table tr:last-child td{border-bottom:none}.record-table tr:hover td{background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent)}.record-table .row-index{color:var(--kendo-color-subtle);font-family:Roboto Mono,monospace;font-size:.85em;text-align:right;width:1px;white-space:nowrap}.nested-properties{margin-left:8px}.nested-property{display:flex;align-items:flex-start;gap:8px;padding:2px 0}.property-key{font-weight:500;white-space:nowrap;flex-shrink:0;color:var(--kendo-color-subtle);font-size:.85em}.binary-linked-display{display:flex;align-items:center;gap:12px;width:100%}.binary-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.filename{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-size{font-size:.85em;color:var(--kendo-color-subtle);flex-shrink:0}.secret-badge{display:inline-block;font-size:.85em;padding:1px 8px;border-radius:999px;background:var(--kendo-color-base-subtle);color:var(--kendo-color-subtle)}.secret-badge--set{background:var(--kendo-color-success-subtle);color:var(--kendo-color-success-on-subtle)}.secret-badge--keyMissing{background:var(--kendo-color-warning-subtle);color:var(--kendo-color-warning-on-subtle)}.content-type{font-size:.75em;padding:2px 6px;background:var(--kendo-color-base-subtle);border-radius:3px;color:var(--kendo-color-subtle);flex-shrink:0}\n"], dependencies: [{ kind: "component", type: PropertyValueDisplayComponent, selector: "mm-property-value-display", inputs: ["value", "type", "displayMode", "attributeName"], outputs: ["binaryDownload"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: i5$1.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2659
2712
|
}
|
|
2660
2713
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PropertyValueDisplayComponent, decorators: [{
|
|
2661
2714
|
type: Component,
|
|
@@ -2676,7 +2729,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
2676
2729
|
size="small"
|
|
2677
2730
|
fillMode="flat"
|
|
2678
2731
|
[svgIcon]="windowIcon"
|
|
2679
|
-
title="Show details"
|
|
2732
|
+
title="Show details" aria-label="Show details"
|
|
2680
2733
|
class="detail-button"
|
|
2681
2734
|
(click)="openDetailDialog($event)">
|
|
2682
2735
|
</button>
|
|
@@ -2756,6 +2809,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
2756
2809
|
</div>
|
|
2757
2810
|
}
|
|
2758
2811
|
</div>
|
|
2812
|
+
} @else if (secretStatus) {
|
|
2813
|
+
<!-- SECRET (AB#5528): set / not set / key missing badge, never a value -->
|
|
2814
|
+
<span class="secret-badge" [ngClass]="'secret-badge--' + secretStatus" [attr.data-secret-state]="secretStatus">{{ formattedValue }}</span>
|
|
2759
2815
|
} @else if (binaryLinkedWithDownload) {
|
|
2760
2816
|
<!-- Binary Linked with download capability -->
|
|
2761
2817
|
<div class="binary-linked-display">
|
|
@@ -2802,7 +2858,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
2802
2858
|
}
|
|
2803
2859
|
|
|
2804
2860
|
</div>
|
|
2805
|
-
`, styles: [".property-value-display{display:flex;align-items:flex-start;gap:8px;width:100%;min-width:0}.text-display,.default-display{word-break:break-word;white-space:pre-wrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.json-display{font-family:Roboto Mono,monospace;font-size:.8em;white-space:pre-wrap;word-break:break-word;margin:0;flex:1;min-width:0}.type-indicator{font-family:Roboto Mono,monospace;font-size:.7em;padding:1px 5px;background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 12%,transparent);border-radius:3px;color:var(--kendo-color-on-app-surface, #1d1b20);white-space:nowrap;flex-shrink:0}.expandable-record{width:100%}.record-header{display:flex;align-items:center;gap:6px;cursor:pointer;padding:2px 0;border-radius:3px;transition:background-color .15s ease}.record-header:hover{background-color:var(--kendo-color-base-subtle, rgba(0,0,0,.04))}.expand-icon{flex-shrink:0;width:14px;height:14px;color:var(--kendo-color-subtle)}.record-summary{color:var(--kendo-color-subtle);font-size:.85em;font-style:italic;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.detail-button{flex-shrink:0;opacity:.6;transition:opacity .15s ease}.detail-button:hover{opacity:1}.record-content{margin-left:20px;padding-left:8px;border-left:1px solid var(--kendo-color-border, #dee2e6)}.array-item{margin:4px 0}.array-index{font-family:Roboto Mono,monospace;font-size:.8em;color:var(--kendo-color-subtle)}.record-array-list{max-height:320px;overflow-y:auto}.record-table-container{max-height:320px;overflow:auto;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:3px;margin-top:4px}.record-table{width:100%;border-collapse:collapse;font-size:.85em;table-layout:auto}.record-table th{position:sticky;top:0;z-index:1;background:var(--kendo-color-surface-alt, #f8f9fa);color:var(--kendo-color-subtle);text-align:left;padding:4px 8px;border-bottom:1px solid var(--kendo-color-border, #dee2e6);font-weight:500;font-size:.85em;white-space:nowrap}.record-table td{padding:3px 8px;border-bottom:1px solid color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 8%,transparent);vertical-align:top;word-break:break-word}.record-table tr:last-child td{border-bottom:none}.record-table tr:hover td{background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent)}.record-table .row-index{color:var(--kendo-color-subtle);font-family:Roboto Mono,monospace;font-size:.85em;text-align:right;width:1px;white-space:nowrap}.nested-properties{margin-left:8px}.nested-property{display:flex;align-items:flex-start;gap:8px;padding:2px 0}.property-key{font-weight:500;white-space:nowrap;flex-shrink:0;color:var(--kendo-color-subtle);font-size:.85em}.binary-linked-display{display:flex;align-items:center;gap:12px;width:100%}.binary-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.filename{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-size{font-size:.85em;color:var(--kendo-color-subtle);flex-shrink:0}.content-type{font-size:.75em;padding:2px 6px;background:var(--kendo-color-base-subtle);border-radius:3px;color:var(--kendo-color-subtle);flex-shrink:0}\n"] }]
|
|
2861
|
+
`, styles: [".property-value-display{display:flex;align-items:flex-start;gap:8px;width:100%;min-width:0}.text-display,.default-display{word-break:break-word;white-space:pre-wrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.json-display{font-family:Roboto Mono,monospace;font-size:.8em;white-space:pre-wrap;word-break:break-word;margin:0;flex:1;min-width:0}.type-indicator{font-family:Roboto Mono,monospace;font-size:.7em;padding:1px 5px;background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 12%,transparent);border-radius:3px;color:var(--kendo-color-on-app-surface, #1d1b20);white-space:nowrap;flex-shrink:0}.expandable-record{width:100%}.record-header{display:flex;align-items:center;gap:6px;cursor:pointer;padding:2px 0;border-radius:3px;transition:background-color .15s ease}.record-header:hover{background-color:var(--kendo-color-base-subtle, rgba(0,0,0,.04))}.expand-icon{flex-shrink:0;width:14px;height:14px;color:var(--kendo-color-subtle)}.record-summary{color:var(--kendo-color-subtle);font-size:.85em;font-style:italic;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.detail-button{flex-shrink:0;opacity:.6;transition:opacity .15s ease}.detail-button:hover{opacity:1}.record-content{margin-left:20px;padding-left:8px;border-left:1px solid var(--kendo-color-border, #dee2e6)}.array-item{margin:4px 0}.array-index{font-family:Roboto Mono,monospace;font-size:.8em;color:var(--kendo-color-subtle)}.record-array-list{max-height:320px;overflow-y:auto}.record-table-container{max-height:320px;overflow:auto;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:3px;margin-top:4px}.record-table{width:100%;border-collapse:collapse;font-size:.85em;table-layout:auto}.record-table th{position:sticky;top:0;z-index:1;background:var(--kendo-color-surface-alt, #f8f9fa);color:var(--kendo-color-subtle);text-align:left;padding:4px 8px;border-bottom:1px solid var(--kendo-color-border, #dee2e6);font-weight:500;font-size:.85em;white-space:nowrap}.record-table td{padding:3px 8px;border-bottom:1px solid color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 8%,transparent);vertical-align:top;word-break:break-word}.record-table tr:last-child td{border-bottom:none}.record-table tr:hover td{background:color-mix(in srgb,var(--kendo-color-on-app-surface, #1d1b20) 6%,transparent)}.record-table .row-index{color:var(--kendo-color-subtle);font-family:Roboto Mono,monospace;font-size:.85em;text-align:right;width:1px;white-space:nowrap}.nested-properties{margin-left:8px}.nested-property{display:flex;align-items:flex-start;gap:8px;padding:2px 0}.property-key{font-weight:500;white-space:nowrap;flex-shrink:0;color:var(--kendo-color-subtle);font-size:.85em}.binary-linked-display{display:flex;align-items:center;gap:12px;width:100%}.binary-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.filename{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-size{font-size:.85em;color:var(--kendo-color-subtle);flex-shrink:0}.secret-badge{display:inline-block;font-size:.85em;padding:1px 8px;border-radius:999px;background:var(--kendo-color-base-subtle);color:var(--kendo-color-subtle)}.secret-badge--set{background:var(--kendo-color-success-subtle);color:var(--kendo-color-success-on-subtle)}.secret-badge--keyMissing{background:var(--kendo-color-warning-subtle);color:var(--kendo-color-warning-on-subtle)}.content-type{font-size:.75em;padding:2px 6px;background:var(--kendo-color-base-subtle);border-radius:3px;color:var(--kendo-color-subtle);flex-shrink:0}\n"] }]
|
|
2806
2862
|
}], propDecorators: { value: [{
|
|
2807
2863
|
type: Input
|
|
2808
2864
|
}], type: [{
|
|
@@ -3052,7 +3108,7 @@ class PropertyGridComponent {
|
|
|
3052
3108
|
|
|
3053
3109
|
</kendo-grid>
|
|
3054
3110
|
</div>
|
|
3055
|
-
`, isInline: true, styles: [".mm-property-grid{display:flex;flex-direction:column;border:1px solid var(--kendo-color-border);border-radius:4px;overflow:hidden}.search-toolbar{padding:8px;border-bottom:1px solid var(--kendo-color-border);background:var(--kendo-color-base-subtle)}.property-grid{flex:1;border:none}.property-name-cell{display:flex;align-items:center;gap:8px;min-height:24px}.type-icon{width:16px;height:16px;opacity:.7}.property-info{display:flex;align-items:center;gap:4px;flex:1}.property-name{font-weight:500}.required-indicator{color:var(--kendo-color-error);font-weight:700}.readonly-indicator{font-size:12px;opacity:.7}.property-editor{width:100%;min-width:200px}.validation-error{color:var(--kendo-color-error);font-size:.8em;margin-top:4px}.type-badge{font-size:.75em;padding:2px 6px;border-radius:3px;
|
|
3111
|
+
`, isInline: true, styles: [".mm-property-grid{display:flex;flex-direction:column;border:1px solid var(--kendo-color-border);border-radius:4px;overflow:hidden}.search-toolbar{padding:8px;border-bottom:1px solid var(--kendo-color-border);background:var(--kendo-color-base-subtle)}.property-grid{flex:1;border:none}.property-name-cell{display:flex;align-items:center;gap:8px;min-height:24px}.type-icon{width:16px;height:16px;opacity:.7}.property-info{display:flex;align-items:center;gap:4px;flex:1}.property-name{font-weight:500}.required-indicator{color:var(--kendo-color-error);font-weight:700}.readonly-indicator{font-size:12px;opacity:.7}.property-editor{width:100%;min-width:200px}.validation-error{color:var(--kendo-color-error);font-size:.8em;margin-top:4px}.type-badge{font-size:.75em;padding:2px 6px;border-radius:3px;font-weight:500;background:var(--kendo-color-base-subtle);color:var(--kendo-color-on-base)}.grid-toolbar{padding:8px;border-top:1px solid var(--kendo-color-border);background:var(--kendo-color-base-subtle);display:flex;align-items:center;gap:8px}.changes-indicator{margin-left:auto;font-size:.9em;color:var(--kendo-color-primary);font-style:italic}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: GridModule }, { kind: "component", type: i3.GridComponent, selector: "kendo-grid", inputs: ["data", "pageSize", "height", "rowHeight", "adaptiveMode", "detailRowHeight", "skip", "scrollable", "selectable", "sort", "size", "trackBy", "filter", "group", "virtualColumns", "filterable", "sortable", "pageable", "groupable", "gridResizable", "rowReorderable", "navigable", "autoSize", "rowClass", "rowSticky", "rowSelected", "isRowSelectable", "cellSelected", "resizable", "reorderable", "loading", "columnMenu", "hideHeader", "showInactiveTools", "isDetailExpanded", "isGroupExpanded", "dataLayoutMode", "pinnable", "pinnedTopRows", "pinnedBottomRows", "isRowPinnable"], outputs: ["filterChange", "pageChange", "groupChange", "sortChange", "selectionChange", "rowReorder", "rowPinChange", "dataStateChange", "gridStateChange", "groupExpand", "groupCollapse", "detailExpand", "detailCollapse", "edit", "cancel", "save", "remove", "add", "cellClose", "cellClick", "pdfExport", "excelExport", "csvExport", "columnResize", "columnReorder", "columnVisibilityChange", "columnLockedChange", "columnStickyChange", "scrollBottom", "contentScroll"], exportAs: ["kendoGrid"] }, { kind: "component", type: i3.ColumnComponent, selector: "kendo-grid-column", inputs: ["field", "format", "sortable", "groupable", "editor", "filter", "filterVariant", "filterable", "editable"] }, { kind: "directive", type: i3.CellTemplateDirective, selector: "[kendoGridCellTemplate]" }, { kind: "ngmodule", type: InputsModule }, { kind: "component", type: i5.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: "ngmodule", type: ButtonsModule }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: i5$1.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }, { kind: "component", type: PropertyValueDisplayComponent, selector: "mm-property-value-display", inputs: ["value", "type", "displayMode", "attributeName"], outputs: ["binaryDownload"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
3056
3112
|
}
|
|
3057
3113
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PropertyGridComponent, decorators: [{
|
|
3058
3114
|
type: Component,
|
|
@@ -3148,7 +3204,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
3148
3204
|
|
|
3149
3205
|
</kendo-grid>
|
|
3150
3206
|
</div>
|
|
3151
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".mm-property-grid{display:flex;flex-direction:column;border:1px solid var(--kendo-color-border);border-radius:4px;overflow:hidden}.search-toolbar{padding:8px;border-bottom:1px solid var(--kendo-color-border);background:var(--kendo-color-base-subtle)}.property-grid{flex:1;border:none}.property-name-cell{display:flex;align-items:center;gap:8px;min-height:24px}.type-icon{width:16px;height:16px;opacity:.7}.property-info{display:flex;align-items:center;gap:4px;flex:1}.property-name{font-weight:500}.required-indicator{color:var(--kendo-color-error);font-weight:700}.readonly-indicator{font-size:12px;opacity:.7}.property-editor{width:100%;min-width:200px}.validation-error{color:var(--kendo-color-error);font-size:.8em;margin-top:4px}.type-badge{font-size:.75em;padding:2px 6px;border-radius:3px;
|
|
3207
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".mm-property-grid{display:flex;flex-direction:column;border:1px solid var(--kendo-color-border);border-radius:4px;overflow:hidden}.search-toolbar{padding:8px;border-bottom:1px solid var(--kendo-color-border);background:var(--kendo-color-base-subtle)}.property-grid{flex:1;border:none}.property-name-cell{display:flex;align-items:center;gap:8px;min-height:24px}.type-icon{width:16px;height:16px;opacity:.7}.property-info{display:flex;align-items:center;gap:4px;flex:1}.property-name{font-weight:500}.required-indicator{color:var(--kendo-color-error);font-weight:700}.readonly-indicator{font-size:12px;opacity:.7}.property-editor{width:100%;min-width:200px}.validation-error{color:var(--kendo-color-error);font-size:.8em;margin-top:4px}.type-badge{font-size:.75em;padding:2px 6px;border-radius:3px;font-weight:500;background:var(--kendo-color-base-subtle);color:var(--kendo-color-on-base)}.grid-toolbar{padding:8px;border-top:1px solid var(--kendo-color-border);background:var(--kendo-color-base-subtle);display:flex;align-items:center;gap:8px}.changes-indicator{margin-left:auto;font-size:.9em;color:var(--kendo-color-primary);font-style:italic}\n"] }]
|
|
3152
3208
|
}], propDecorators: { data: [{
|
|
3153
3209
|
type: Input
|
|
3154
3210
|
}], config: [{
|
|
@@ -3521,7 +3577,7 @@ class CkTypeSelectorInputComponent {
|
|
|
3521
3577
|
type="button"
|
|
3522
3578
|
[svgIcon]="searchIcon"
|
|
3523
3579
|
[disabled]="disabled"
|
|
3524
|
-
[title]="advancedSearchLabel || _messages.advancedSearchLabel"
|
|
3580
|
+
[title]="advancedSearchLabel || _messages.advancedSearchLabel" [attr.aria-label]="advancedSearchLabel || _messages.advancedSearchLabel"
|
|
3525
3581
|
class="dialog-button"
|
|
3526
3582
|
(click)="openDialog()">
|
|
3527
3583
|
</button>
|
|
@@ -3598,7 +3654,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
3598
3654
|
type="button"
|
|
3599
3655
|
[svgIcon]="searchIcon"
|
|
3600
3656
|
[disabled]="disabled"
|
|
3601
|
-
[title]="advancedSearchLabel || _messages.advancedSearchLabel"
|
|
3657
|
+
[title]="advancedSearchLabel || _messages.advancedSearchLabel" [attr.aria-label]="advancedSearchLabel || _messages.advancedSearchLabel"
|
|
3602
3658
|
class="dialog-button"
|
|
3603
3659
|
(click)="openDialog()">
|
|
3604
3660
|
</button>
|
|
@@ -4145,6 +4201,8 @@ class AttributeSelectorDialogComponent {
|
|
|
4145
4201
|
kendoButton
|
|
4146
4202
|
[svgIcon]="searchIcon"
|
|
4147
4203
|
fillMode="clear"
|
|
4204
|
+
title="Search"
|
|
4205
|
+
aria-label="Search"
|
|
4148
4206
|
></button>
|
|
4149
4207
|
</ng-template>
|
|
4150
4208
|
</kendo-textbox>
|
|
@@ -4235,14 +4293,14 @@ class AttributeSelectorDialogComponent {
|
|
|
4235
4293
|
[svgIcon]="arrowRightIcon"
|
|
4236
4294
|
[disabled]="selectedAvailableKeys.length === 0"
|
|
4237
4295
|
(click)="addSelected()"
|
|
4238
|
-
title="Add selected"
|
|
4296
|
+
title="Add selected" aria-label="Add selected"
|
|
4239
4297
|
></button>
|
|
4240
4298
|
<button
|
|
4241
4299
|
kendoButton
|
|
4242
4300
|
[svgIcon]="arrowLeftIcon"
|
|
4243
4301
|
[disabled]="selectedChosenKeys.length === 0"
|
|
4244
4302
|
(click)="removeSelected()"
|
|
4245
|
-
title="Remove selected"
|
|
4303
|
+
title="Remove selected" aria-label="Remove selected"
|
|
4246
4304
|
></button>
|
|
4247
4305
|
<div class="separator"></div>
|
|
4248
4306
|
<button
|
|
@@ -4250,14 +4308,14 @@ class AttributeSelectorDialogComponent {
|
|
|
4250
4308
|
[svgIcon]="chevronDoubleRightIcon"
|
|
4251
4309
|
[disabled]="availableAttributes.length === 0"
|
|
4252
4310
|
(click)="addAll()"
|
|
4253
|
-
title="Add all"
|
|
4311
|
+
title="Add all" aria-label="Add all"
|
|
4254
4312
|
></button>
|
|
4255
4313
|
<button
|
|
4256
4314
|
kendoButton
|
|
4257
4315
|
[svgIcon]="chevronDoubleLeftIcon"
|
|
4258
4316
|
[disabled]="selectedAttributes.length === 0"
|
|
4259
4317
|
(click)="removeAll()"
|
|
4260
|
-
title="Remove all"
|
|
4318
|
+
title="Remove all" aria-label="Remove all"
|
|
4261
4319
|
></button>
|
|
4262
4320
|
</div>
|
|
4263
4321
|
|
|
@@ -4300,7 +4358,7 @@ class AttributeSelectorDialogComponent {
|
|
|
4300
4358
|
fillMode="flat"
|
|
4301
4359
|
size="small"
|
|
4302
4360
|
[svgIcon]="pencilIcon"
|
|
4303
|
-
title="Edit entity selector (pin the target entity)"
|
|
4361
|
+
title="Edit entity selector (pin the target entity)" aria-label="Edit entity selector (pin the target entity)"
|
|
4304
4362
|
(click)="openSelectorEditor(dataItem); $event.stopPropagation()"
|
|
4305
4363
|
></button>
|
|
4306
4364
|
}
|
|
@@ -4315,14 +4373,14 @@ class AttributeSelectorDialogComponent {
|
|
|
4315
4373
|
[svgIcon]="arrowUpIcon"
|
|
4316
4374
|
[disabled]="!canMoveUp()"
|
|
4317
4375
|
(click)="moveUp()"
|
|
4318
|
-
title="Move up"
|
|
4376
|
+
title="Move up" aria-label="Move up"
|
|
4319
4377
|
></button>
|
|
4320
4378
|
<button
|
|
4321
4379
|
kendoButton
|
|
4322
4380
|
[svgIcon]="arrowDownIcon"
|
|
4323
4381
|
[disabled]="!canMoveDown()"
|
|
4324
4382
|
(click)="moveDown()"
|
|
4325
|
-
title="Move down"
|
|
4383
|
+
title="Move down" aria-label="Move down"
|
|
4326
4384
|
></button>
|
|
4327
4385
|
</div>
|
|
4328
4386
|
</div>
|
|
@@ -4435,6 +4493,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
4435
4493
|
kendoButton
|
|
4436
4494
|
[svgIcon]="searchIcon"
|
|
4437
4495
|
fillMode="clear"
|
|
4496
|
+
title="Search"
|
|
4497
|
+
aria-label="Search"
|
|
4438
4498
|
></button>
|
|
4439
4499
|
</ng-template>
|
|
4440
4500
|
</kendo-textbox>
|
|
@@ -4525,14 +4585,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
4525
4585
|
[svgIcon]="arrowRightIcon"
|
|
4526
4586
|
[disabled]="selectedAvailableKeys.length === 0"
|
|
4527
4587
|
(click)="addSelected()"
|
|
4528
|
-
title="Add selected"
|
|
4588
|
+
title="Add selected" aria-label="Add selected"
|
|
4529
4589
|
></button>
|
|
4530
4590
|
<button
|
|
4531
4591
|
kendoButton
|
|
4532
4592
|
[svgIcon]="arrowLeftIcon"
|
|
4533
4593
|
[disabled]="selectedChosenKeys.length === 0"
|
|
4534
4594
|
(click)="removeSelected()"
|
|
4535
|
-
title="Remove selected"
|
|
4595
|
+
title="Remove selected" aria-label="Remove selected"
|
|
4536
4596
|
></button>
|
|
4537
4597
|
<div class="separator"></div>
|
|
4538
4598
|
<button
|
|
@@ -4540,14 +4600,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
4540
4600
|
[svgIcon]="chevronDoubleRightIcon"
|
|
4541
4601
|
[disabled]="availableAttributes.length === 0"
|
|
4542
4602
|
(click)="addAll()"
|
|
4543
|
-
title="Add all"
|
|
4603
|
+
title="Add all" aria-label="Add all"
|
|
4544
4604
|
></button>
|
|
4545
4605
|
<button
|
|
4546
4606
|
kendoButton
|
|
4547
4607
|
[svgIcon]="chevronDoubleLeftIcon"
|
|
4548
4608
|
[disabled]="selectedAttributes.length === 0"
|
|
4549
4609
|
(click)="removeAll()"
|
|
4550
|
-
title="Remove all"
|
|
4610
|
+
title="Remove all" aria-label="Remove all"
|
|
4551
4611
|
></button>
|
|
4552
4612
|
</div>
|
|
4553
4613
|
|
|
@@ -4590,7 +4650,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
4590
4650
|
fillMode="flat"
|
|
4591
4651
|
size="small"
|
|
4592
4652
|
[svgIcon]="pencilIcon"
|
|
4593
|
-
title="Edit entity selector (pin the target entity)"
|
|
4653
|
+
title="Edit entity selector (pin the target entity)" aria-label="Edit entity selector (pin the target entity)"
|
|
4594
4654
|
(click)="openSelectorEditor(dataItem); $event.stopPropagation()"
|
|
4595
4655
|
></button>
|
|
4596
4656
|
}
|
|
@@ -4605,14 +4665,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
4605
4665
|
[svgIcon]="arrowUpIcon"
|
|
4606
4666
|
[disabled]="!canMoveUp()"
|
|
4607
4667
|
(click)="moveUp()"
|
|
4608
|
-
title="Move up"
|
|
4668
|
+
title="Move up" aria-label="Move up"
|
|
4609
4669
|
></button>
|
|
4610
4670
|
<button
|
|
4611
4671
|
kendoButton
|
|
4612
4672
|
[svgIcon]="arrowDownIcon"
|
|
4613
4673
|
[disabled]="!canMoveDown()"
|
|
4614
4674
|
(click)="moveDown()"
|
|
4615
|
-
title="Move down"
|
|
4675
|
+
title="Move down" aria-label="Move down"
|
|
4616
4676
|
></button>
|
|
4617
4677
|
</div>
|
|
4618
4678
|
</div>
|
|
@@ -4996,7 +5056,7 @@ class RuntimeEntityVariableDialogComponent {
|
|
|
4996
5056
|
[svgIcon]="trashIcon"
|
|
4997
5057
|
fillMode="flat"
|
|
4998
5058
|
themeColor="error"
|
|
4999
|
-
title="Remove">
|
|
5059
|
+
title="Remove" aria-label="Remove">
|
|
5000
5060
|
</button>
|
|
5001
5061
|
</div>
|
|
5002
5062
|
</div>
|
|
@@ -5089,7 +5149,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
5089
5149
|
[svgIcon]="trashIcon"
|
|
5090
5150
|
fillMode="flat"
|
|
5091
5151
|
themeColor="error"
|
|
5092
|
-
title="Remove">
|
|
5152
|
+
title="Remove" aria-label="Remove">
|
|
5093
5153
|
</button>
|
|
5094
5154
|
</div>
|
|
5095
5155
|
</div>
|
|
@@ -5157,7 +5217,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
5157
5217
|
}] });
|
|
5158
5218
|
|
|
5159
5219
|
const GetRuntimeEntityByIdDocumentDto = gql `
|
|
5160
|
-
query getRuntimeEntityById($rtId: OctoObjectId!, $ckTypeId: String!) {
|
|
5220
|
+
query getRuntimeEntityById($rtId: OctoObjectId!, $ckTypeId: String!, $attributeNames: [String!]!) {
|
|
5161
5221
|
runtime {
|
|
5162
5222
|
runtimeEntities(ckId: $ckTypeId, rtId: $rtId) {
|
|
5163
5223
|
items {
|
|
@@ -5168,10 +5228,13 @@ const GetRuntimeEntityByIdDocumentDto = gql `
|
|
|
5168
5228
|
rtWellKnownName
|
|
5169
5229
|
rtCreationDateTime
|
|
5170
5230
|
rtChangedDateTime
|
|
5171
|
-
attributes(resolveEnumValuesToNames: true) {
|
|
5231
|
+
attributes(attributeNames: $attributeNames, resolveEnumValuesToNames: true) {
|
|
5172
5232
|
items {
|
|
5173
5233
|
attributeName
|
|
5174
5234
|
value
|
|
5235
|
+
secretIsSet
|
|
5236
|
+
secretKeyMissing
|
|
5237
|
+
secretSetAt
|
|
5175
5238
|
}
|
|
5176
5239
|
}
|
|
5177
5240
|
associations {
|
|
@@ -5219,6 +5282,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
5219
5282
|
* `sourceAttributePath` fallback when no specific state is configured.
|
|
5220
5283
|
*/
|
|
5221
5284
|
const DEFAULT_DATA_POINT = 'currentValue';
|
|
5285
|
+
/**
|
|
5286
|
+
* Attributes {@link extractDataPoints} reads, as the SECRET-safe `attributeNames` filter of
|
|
5287
|
+
* `getRuntimeEntityById` (AB#5542). The filter also applies inside records, so the record
|
|
5288
|
+
* sub-attributes (`name`, `currentValue`) are part of the same list.
|
|
5289
|
+
*/
|
|
5290
|
+
const DATA_POINT_ATTRIBUTE_NAMES = ['currentValue', 'states', 'dataPoints', 'name'];
|
|
5222
5291
|
/**
|
|
5223
5292
|
* Extracts the available data points (name + last known value) from an
|
|
5224
5293
|
* entity's attribute list. Always includes {@link DEFAULT_DATA_POINT} first
|
|
@@ -5373,7 +5442,7 @@ class DataPointResolverService {
|
|
|
5373
5442
|
try {
|
|
5374
5443
|
const entity = await firstValueFrom(this.getRuntimeEntityByIdGQL
|
|
5375
5444
|
.fetch({
|
|
5376
|
-
variables: { rtId, ckTypeId },
|
|
5445
|
+
variables: { rtId, ckTypeId, attributeNames: [...DATA_POINT_ATTRIBUTE_NAMES] },
|
|
5377
5446
|
fetchPolicy: 'network-only',
|
|
5378
5447
|
})
|
|
5379
5448
|
.pipe(map$1(r => r.data?.runtime?.runtimeEntities?.items?.[0] ?? null)));
|
|
@@ -5701,6 +5770,14 @@ class EntityIdInfoComponent {
|
|
|
5701
5770
|
rtCkTypeId;
|
|
5702
5771
|
/** The CkTypeId - full versioned Construction Kit type ID (e.g., System.Communication-2.0.3/MeshAdapter-1) */
|
|
5703
5772
|
ckTypeId;
|
|
5773
|
+
/** Button text (translatable, AB#5623). Default `Copy ID`. */
|
|
5774
|
+
buttonText = 'Copy ID';
|
|
5775
|
+
/** Tooltip of the button (translatable, AB#5623). Default `Copy Entity ID to clipboard`. */
|
|
5776
|
+
tooltip = 'Copy Entity ID to clipboard';
|
|
5777
|
+
/** Notification after copying; `{label}` is replaced by the copied ID kind (AB#5623). Default `{label} copied`. */
|
|
5778
|
+
copiedMessage = '{label} copied';
|
|
5779
|
+
/** Notification when copying failed (AB#5623). Default `Failed to copy to clipboard`. */
|
|
5780
|
+
copyFailedMessage = 'Failed to copy to clipboard';
|
|
5704
5781
|
get copyOptions() {
|
|
5705
5782
|
const fullCkTypeId = this.ckTypeId || this.rtCkTypeId;
|
|
5706
5783
|
const rtEntityId = `${this.rtCkTypeId}@${this.rtId}`;
|
|
@@ -5735,21 +5812,21 @@ class EntityIdInfoComponent {
|
|
|
5735
5812
|
async copyToClipboard(option) {
|
|
5736
5813
|
try {
|
|
5737
5814
|
await navigator.clipboard.writeText(option.value);
|
|
5738
|
-
this.notificationService.showSuccess(
|
|
5815
|
+
this.notificationService.showSuccess(this.copiedMessage.split('{label}').join(option.label), 2000);
|
|
5739
5816
|
}
|
|
5740
5817
|
catch (error) {
|
|
5741
5818
|
console.error('Failed to copy to clipboard:', error);
|
|
5742
|
-
this.notificationService.showError(
|
|
5819
|
+
this.notificationService.showError(this.copyFailedMessage);
|
|
5743
5820
|
}
|
|
5744
5821
|
}
|
|
5745
5822
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: EntityIdInfoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5746
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.5", type: EntityIdInfoComponent, isStandalone: true, selector: "mm-entity-id-info", inputs: { rtId: "rtId", rtCkTypeId: "rtCkTypeId", ckTypeId: "ckTypeId" }, ngImport: i0, template: `
|
|
5823
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.5", type: EntityIdInfoComponent, isStandalone: true, selector: "mm-entity-id-info", inputs: { rtId: "rtId", rtCkTypeId: "rtCkTypeId", ckTypeId: "ckTypeId", buttonText: "buttonText", tooltip: "tooltip", copiedMessage: "copiedMessage", copyFailedMessage: "copyFailedMessage" }, ngImport: i0, template: `
|
|
5747
5824
|
<kendo-dropdownbutton
|
|
5748
5825
|
[data]="copyOptions"
|
|
5749
5826
|
[svgIcon]="copyIcon"
|
|
5750
5827
|
look="flat"
|
|
5751
5828
|
size="small"
|
|
5752
|
-
title="
|
|
5829
|
+
[title]="tooltip"
|
|
5753
5830
|
(itemClick)="copyToClipboard($event)">
|
|
5754
5831
|
<ng-template kendoDropDownButtonItemTemplate let-item>
|
|
5755
5832
|
<div class="copy-item">
|
|
@@ -5757,9 +5834,9 @@ class EntityIdInfoComponent {
|
|
|
5757
5834
|
<span class="copy-value">{{ item.displayText }}</span>
|
|
5758
5835
|
</div>
|
|
5759
5836
|
</ng-template>
|
|
5760
|
-
|
|
5837
|
+
{{ buttonText }}
|
|
5761
5838
|
</kendo-dropdownbutton>
|
|
5762
|
-
`, isInline: true, styles: [":host{display:inline-block}.copy-item{display:flex;flex-direction:column;gap:2px;padding:8px 12px;width:100%}.copy-label{font-size:.7rem;font-weight:600;color:var(--kendo-color-primary, #64ceb9)
|
|
5839
|
+
`, isInline: true, styles: [":host{display:inline-block}.copy-item{display:flex;flex-direction:column;gap:2px;padding:8px 12px;width:100%}.copy-label{font-size:.7rem;font-weight:600;color:var(--kendo-color-primary, #64ceb9)}.copy-value{font-family:Roboto Mono,monospace;font-size:.75rem;color:var(--kendo-color-subtle, #9292a6);word-break:break-all}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i1$1.DropDownButtonComponent, selector: "kendo-dropdownbutton", inputs: ["arrowIcon", "icon", "svgIcon", "iconClass", "imageUrl", "textField", "data", "size", "rounded", "fillMode", "themeColor", "buttonAttributes"], outputs: ["itemClick", "focus", "blur"], exportAs: ["kendoDropDownButton"] }, { kind: "directive", type: i1$1.ButtonItemTemplateDirective, selector: "[kendoDropDownButtonItemTemplate],[kendoSplitButtonItemTemplate]" }, { kind: "ngmodule", type: SVGIconModule }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
5763
5840
|
}
|
|
5764
5841
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: EntityIdInfoComponent, decorators: [{
|
|
5765
5842
|
type: Component,
|
|
@@ -5773,7 +5850,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
5773
5850
|
[svgIcon]="copyIcon"
|
|
5774
5851
|
look="flat"
|
|
5775
5852
|
size="small"
|
|
5776
|
-
title="
|
|
5853
|
+
[title]="tooltip"
|
|
5777
5854
|
(itemClick)="copyToClipboard($event)">
|
|
5778
5855
|
<ng-template kendoDropDownButtonItemTemplate let-item>
|
|
5779
5856
|
<div class="copy-item">
|
|
@@ -5781,9 +5858,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
5781
5858
|
<span class="copy-value">{{ item.displayText }}</span>
|
|
5782
5859
|
</div>
|
|
5783
5860
|
</ng-template>
|
|
5784
|
-
|
|
5861
|
+
{{ buttonText }}
|
|
5785
5862
|
</kendo-dropdownbutton>
|
|
5786
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:inline-block}.copy-item{display:flex;flex-direction:column;gap:2px;padding:8px 12px;width:100%}.copy-label{font-size:.7rem;font-weight:600;color:var(--kendo-color-primary, #64ceb9)
|
|
5863
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:inline-block}.copy-item{display:flex;flex-direction:column;gap:2px;padding:8px 12px;width:100%}.copy-label{font-size:.7rem;font-weight:600;color:var(--kendo-color-primary, #64ceb9)}.copy-value{font-family:Roboto Mono,monospace;font-size:.75rem;color:var(--kendo-color-subtle, #9292a6);word-break:break-all}\n"] }]
|
|
5787
5864
|
}], propDecorators: { rtId: [{
|
|
5788
5865
|
type: Input,
|
|
5789
5866
|
args: [{ required: true }]
|
|
@@ -5792,6 +5869,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
5792
5869
|
args: [{ required: true }]
|
|
5793
5870
|
}], ckTypeId: [{
|
|
5794
5871
|
type: Input
|
|
5872
|
+
}], buttonText: [{
|
|
5873
|
+
type: Input
|
|
5874
|
+
}], tooltip: [{
|
|
5875
|
+
type: Input
|
|
5876
|
+
}], copiedMessage: [{
|
|
5877
|
+
type: Input
|
|
5878
|
+
}], copyFailedMessage: [{
|
|
5879
|
+
type: Input
|
|
5795
5880
|
}] } });
|
|
5796
5881
|
|
|
5797
5882
|
const DeleteEntitiesDocumentDto = gql `
|
|
@@ -6069,12 +6154,7 @@ const UpdateRuntimeEntitiesDocumentDto = gql `
|
|
|
6069
6154
|
runtimeEntities {
|
|
6070
6155
|
update(entities: $entities) {
|
|
6071
6156
|
rtId
|
|
6072
|
-
|
|
6073
|
-
items {
|
|
6074
|
-
attributeName
|
|
6075
|
-
value
|
|
6076
|
-
}
|
|
6077
|
-
}
|
|
6157
|
+
ckTypeId
|
|
6078
6158
|
}
|
|
6079
6159
|
}
|
|
6080
6160
|
}
|
|
@@ -8923,6 +9003,10 @@ class FieldFilterEditorComponent {
|
|
|
8923
9003
|
dataItem.useVariable
|
|
8924
9004
|
? 'Switch to literal value'
|
|
8925
9005
|
: 'Use variable'
|
|
9006
|
+
" [attr.aria-label]="
|
|
9007
|
+
dataItem.useVariable
|
|
9008
|
+
? 'Switch to literal value'
|
|
9009
|
+
: 'Use variable'
|
|
8926
9010
|
"
|
|
8927
9011
|
class="variable-toggle"
|
|
8928
9012
|
></button>
|
|
@@ -8939,7 +9023,7 @@ class FieldFilterEditorComponent {
|
|
|
8939
9023
|
fillMode="flat"
|
|
8940
9024
|
themeColor="error"
|
|
8941
9025
|
(click)="removeFilter(dataItem)"
|
|
8942
|
-
title="Remove this filter"
|
|
9026
|
+
title="Remove this filter" aria-label="Remove this filter"
|
|
8943
9027
|
></button>
|
|
8944
9028
|
</ng-template>
|
|
8945
9029
|
</kendo-grid-column>
|
|
@@ -9235,6 +9319,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
9235
9319
|
dataItem.useVariable
|
|
9236
9320
|
? 'Switch to literal value'
|
|
9237
9321
|
: 'Use variable'
|
|
9322
|
+
" [attr.aria-label]="
|
|
9323
|
+
dataItem.useVariable
|
|
9324
|
+
? 'Switch to literal value'
|
|
9325
|
+
: 'Use variable'
|
|
9238
9326
|
"
|
|
9239
9327
|
class="variable-toggle"
|
|
9240
9328
|
></button>
|
|
@@ -9251,7 +9339,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
9251
9339
|
fillMode="flat"
|
|
9252
9340
|
themeColor="error"
|
|
9253
9341
|
(click)="removeFilter(dataItem)"
|
|
9254
|
-
title="Remove this filter"
|
|
9342
|
+
title="Remove this filter" aria-label="Remove this filter"
|
|
9255
9343
|
></button>
|
|
9256
9344
|
</ng-template>
|
|
9257
9345
|
</kendo-grid-column>
|
|
@@ -9486,6 +9574,165 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
9486
9574
|
type: Input
|
|
9487
9575
|
}] } });
|
|
9488
9576
|
|
|
9577
|
+
/** Marks projected content that replaces the page title text: `<span mmPageTitle>…</span>`. */
|
|
9578
|
+
class PageTitleDirective {
|
|
9579
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PageTitleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
9580
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.5", type: PageTitleDirective, isStandalone: true, selector: "[mmPageTitle]", ngImport: i0 });
|
|
9581
|
+
}
|
|
9582
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PageTitleDirective, decorators: [{
|
|
9583
|
+
type: Directive,
|
|
9584
|
+
args: [{ selector: '[mmPageTitle]', standalone: true }]
|
|
9585
|
+
}] });
|
|
9586
|
+
/** Marks projected content shown under the title: `<span mmPageSubtitle>…</span>`. */
|
|
9587
|
+
class PageSubtitleDirective {
|
|
9588
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PageSubtitleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
9589
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.5", type: PageSubtitleDirective, isStandalone: true, selector: "[mmPageSubtitle]", ngImport: i0 });
|
|
9590
|
+
}
|
|
9591
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PageSubtitleDirective, decorators: [{
|
|
9592
|
+
type: Directive,
|
|
9593
|
+
args: [{ selector: '[mmPageSubtitle]', standalone: true }]
|
|
9594
|
+
}] });
|
|
9595
|
+
/** Marks projected page actions (buttons), rendered at the end of the header: `<div mmPageActions>…</div>`. */
|
|
9596
|
+
class PageActionsDirective {
|
|
9597
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PageActionsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
9598
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.5", type: PageActionsDirective, isStandalone: true, selector: "[mmPageActions]", ngImport: i0 });
|
|
9599
|
+
}
|
|
9600
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PageActionsDirective, decorators: [{
|
|
9601
|
+
type: Directive,
|
|
9602
|
+
args: [{ selector: '[mmPageActions]', standalone: true }]
|
|
9603
|
+
}] });
|
|
9604
|
+
/** True when a slot container holds an element or non-blank text. */
|
|
9605
|
+
function hasProjectedContent(element) {
|
|
9606
|
+
if (!element) {
|
|
9607
|
+
return false;
|
|
9608
|
+
}
|
|
9609
|
+
return Array.from(element.childNodes).some((node) => node.nodeType === Node.ELEMENT_NODE ||
|
|
9610
|
+
(node.nodeType === Node.TEXT_NODE && (node.textContent ?? '').trim() !== ''));
|
|
9611
|
+
}
|
|
9612
|
+
/**
|
|
9613
|
+
* Page layout: an optional header (title, subtitle, actions) above a content
|
|
9614
|
+
* area. Replaces the retired LCARS page triple (header, content panel and
|
|
9615
|
+
* READY footer); there is no footer.
|
|
9616
|
+
*
|
|
9617
|
+
* The header renders only when there is something to show — a `pageTitle` /
|
|
9618
|
+
* `pageSubtitle` input or projected `[mmPageTitle]`, `[mmPageSubtitle]` or
|
|
9619
|
+
* `[mmPageActions]` content — so pages inside a space shell, which already
|
|
9620
|
+
* shows the area title, can use `<mm-page>` as a bare content frame.
|
|
9621
|
+
* Projected content is detected from the rendered DOM, so the slots work
|
|
9622
|
+
* whether or not the consumer imports the marker directives (`MM_PAGE`).
|
|
9623
|
+
*
|
|
9624
|
+
* ```html
|
|
9625
|
+
* <mm-page pageTitle="Adapters" pageSubtitle="12 registered">
|
|
9626
|
+
* <div mmPageActions>
|
|
9627
|
+
* <button kendoButton themeColor="primary">New adapter</button>
|
|
9628
|
+
* </div>
|
|
9629
|
+
* <mm-list-view …></mm-list-view>
|
|
9630
|
+
* </mm-page>
|
|
9631
|
+
* ```
|
|
9632
|
+
*
|
|
9633
|
+
* The header is a plain `<div>` (no banner landmark) and the title defaults to
|
|
9634
|
+
* heading level 2 — the app/space shell owns level 1. Styling is token-based
|
|
9635
|
+
* (`--theme-*` with neutral fallbacks); the host fills its parent
|
|
9636
|
+
* (`height: 100%`) and the content area scrolls.
|
|
9637
|
+
*/
|
|
9638
|
+
class PageComponent {
|
|
9639
|
+
/** Title text. Alternatively project `[mmPageTitle]` content. */
|
|
9640
|
+
pageTitle = input(undefined, /* @ts-ignore */
|
|
9641
|
+
...(ngDevMode ? [{ debugName: "pageTitle" }] : /* istanbul ignore next */ []));
|
|
9642
|
+
/** Subtitle text under the title. Alternatively project `[mmPageSubtitle]` content. */
|
|
9643
|
+
pageSubtitle = input(undefined, /* @ts-ignore */
|
|
9644
|
+
...(ngDevMode ? [{ debugName: "pageSubtitle" }] : /* istanbul ignore next */ []));
|
|
9645
|
+
/** `aria-level` of the title. Defaults to 2 — the app/space shell owns level 1. */
|
|
9646
|
+
headingLevel = input(2, /* @ts-ignore */
|
|
9647
|
+
...(ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []));
|
|
9648
|
+
/** Pad the content area with the page gutter. Set `false` for full-bleed grids and editors. */
|
|
9649
|
+
padded = input(true, { ...(ngDevMode ? { debugName: "padded" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
9650
|
+
titleSlot = viewChild('titleSlot', /* @ts-ignore */
|
|
9651
|
+
...(ngDevMode ? [{ debugName: "titleSlot" }] : /* istanbul ignore next */ []));
|
|
9652
|
+
subtitleSlot = viewChild('subtitleSlot', /* @ts-ignore */
|
|
9653
|
+
...(ngDevMode ? [{ debugName: "subtitleSlot" }] : /* istanbul ignore next */ []));
|
|
9654
|
+
actionsSlot = viewChild('actionsSlot', /* @ts-ignore */
|
|
9655
|
+
...(ngDevMode ? [{ debugName: "actionsSlot" }] : /* istanbul ignore next */ []));
|
|
9656
|
+
/** Which slots currently hold projected content (read from the DOM after each render). */
|
|
9657
|
+
projected = signal({ title: false, subtitle: false, actions: false }, /* @ts-ignore */
|
|
9658
|
+
...(ngDevMode ? [{ debugName: "projected" }] : /* istanbul ignore next */ []));
|
|
9659
|
+
hasTitle = computed(() => !!this.pageTitle() || this.projected().title, /* @ts-ignore */
|
|
9660
|
+
...(ngDevMode ? [{ debugName: "hasTitle" }] : /* istanbul ignore next */ []));
|
|
9661
|
+
hasSubtitle = computed(() => !!this.pageSubtitle() || this.projected().subtitle, /* @ts-ignore */
|
|
9662
|
+
...(ngDevMode ? [{ debugName: "hasSubtitle" }] : /* istanbul ignore next */ []));
|
|
9663
|
+
hasHeader = computed(() => this.hasTitle() || this.hasSubtitle() || this.projected().actions, /* @ts-ignore */
|
|
9664
|
+
...(ngDevMode ? [{ debugName: "hasHeader" }] : /* istanbul ignore next */ []));
|
|
9665
|
+
constructor() {
|
|
9666
|
+
// Projected nodes can appear or disappear with the consumer's own control
|
|
9667
|
+
// flow, so re-check after every render; the signal only changes (and only
|
|
9668
|
+
// schedules another pass) when a slot actually flips.
|
|
9669
|
+
afterEveryRender({
|
|
9670
|
+
read: () => {
|
|
9671
|
+
const next = {
|
|
9672
|
+
title: hasProjectedContent(this.titleSlot()?.nativeElement),
|
|
9673
|
+
subtitle: hasProjectedContent(this.subtitleSlot()?.nativeElement),
|
|
9674
|
+
actions: hasProjectedContent(this.actionsSlot()?.nativeElement),
|
|
9675
|
+
};
|
|
9676
|
+
const current = this.projected();
|
|
9677
|
+
if (next.title !== current.title ||
|
|
9678
|
+
next.subtitle !== current.subtitle ||
|
|
9679
|
+
next.actions !== current.actions) {
|
|
9680
|
+
this.projected.set(next);
|
|
9681
|
+
}
|
|
9682
|
+
},
|
|
9683
|
+
});
|
|
9684
|
+
}
|
|
9685
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9686
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.5", type: PageComponent, isStandalone: true, selector: "mm-page", inputs: { pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, pageSubtitle: { classPropertyName: "pageSubtitle", publicName: "pageSubtitle", isSignal: true, isRequired: false, transformFunction: null }, headingLevel: { classPropertyName: "headingLevel", publicName: "headingLevel", isSignal: true, isRequired: false, transformFunction: null }, padded: { classPropertyName: "padded", publicName: "padded", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.mm-page--flush": "!padded()", "class.mm-page--headerless": "!hasHeader()" }, classAttribute: "mm-page" }, viewQueries: [{ propertyName: "titleSlot", first: true, predicate: ["titleSlot"], descendants: true, isSignal: true }, { propertyName: "subtitleSlot", first: true, predicate: ["subtitleSlot"], descendants: true, isSignal: true }, { propertyName: "actionsSlot", first: true, predicate: ["actionsSlot"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
9687
|
+
<div class="mm-page__header" [hidden]="!hasHeader()">
|
|
9688
|
+
<div class="mm-page__heading">
|
|
9689
|
+
<div class="mm-page__title" role="heading" [attr.aria-level]="headingLevel()" [hidden]="!hasTitle()">
|
|
9690
|
+
{{ pageTitle() ?? '' }}<span #titleSlot class="mm-page__slot"><ng-content select="[mmPageTitle]" /></span>
|
|
9691
|
+
</div>
|
|
9692
|
+
<div class="mm-page__subtitle" [hidden]="!hasSubtitle()">
|
|
9693
|
+
{{ pageSubtitle() ?? '' }}<span #subtitleSlot class="mm-page__slot"><ng-content select="[mmPageSubtitle]" /></span>
|
|
9694
|
+
</div>
|
|
9695
|
+
</div>
|
|
9696
|
+
<div #actionsSlot class="mm-page__actions" [hidden]="!projected().actions">
|
|
9697
|
+
<ng-content select="[mmPageActions]" />
|
|
9698
|
+
</div>
|
|
9699
|
+
</div>
|
|
9700
|
+
<div class="mm-page__content">
|
|
9701
|
+
<ng-content />
|
|
9702
|
+
</div>
|
|
9703
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0;box-sizing:border-box;color:var(--theme-text-primary, inherit);font-family:var(--theme-font-ui, inherit)}[hidden]{display:none!important}.mm-page__slot{display:contents}.mm-page__header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--theme-space-3, 12px) var(--theme-space-4, 16px);padding:var(--theme-space-4, 16px) var(--theme-space-4, 16px) var(--theme-space-3, 12px);flex:0 0 auto}.mm-page__heading{display:flex;flex-direction:column;gap:var(--theme-space-1, 4px);min-width:0}.mm-page__title{margin:0;font-family:var(--theme-font-display, inherit);font-size:1.25rem;line-height:1.4;font-weight:600;color:var(--theme-text-primary, inherit);overflow-wrap:anywhere}.mm-page__subtitle{font-size:.875rem;line-height:1.45;color:var(--theme-text-secondary, inherit);overflow-wrap:anywhere}.mm-page__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--theme-space-2, 8px);margin-left:auto}.mm-page__content{flex:1 1 auto;min-height:0;overflow:auto;padding:0 var(--theme-space-4, 16px) var(--theme-space-4, 16px)}:host(.mm-page--headerless) .mm-page__content{padding-top:var(--theme-space-4, 16px)}:host(.mm-page--flush) .mm-page__content{padding:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9704
|
+
}
|
|
9705
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: PageComponent, decorators: [{
|
|
9706
|
+
type: Component,
|
|
9707
|
+
args: [{ selector: 'mm-page', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
9708
|
+
class: 'mm-page',
|
|
9709
|
+
'[class.mm-page--flush]': '!padded()',
|
|
9710
|
+
'[class.mm-page--headerless]': '!hasHeader()',
|
|
9711
|
+
}, template: `
|
|
9712
|
+
<div class="mm-page__header" [hidden]="!hasHeader()">
|
|
9713
|
+
<div class="mm-page__heading">
|
|
9714
|
+
<div class="mm-page__title" role="heading" [attr.aria-level]="headingLevel()" [hidden]="!hasTitle()">
|
|
9715
|
+
{{ pageTitle() ?? '' }}<span #titleSlot class="mm-page__slot"><ng-content select="[mmPageTitle]" /></span>
|
|
9716
|
+
</div>
|
|
9717
|
+
<div class="mm-page__subtitle" [hidden]="!hasSubtitle()">
|
|
9718
|
+
{{ pageSubtitle() ?? '' }}<span #subtitleSlot class="mm-page__slot"><ng-content select="[mmPageSubtitle]" /></span>
|
|
9719
|
+
</div>
|
|
9720
|
+
</div>
|
|
9721
|
+
<div #actionsSlot class="mm-page__actions" [hidden]="!projected().actions">
|
|
9722
|
+
<ng-content select="[mmPageActions]" />
|
|
9723
|
+
</div>
|
|
9724
|
+
</div>
|
|
9725
|
+
<div class="mm-page__content">
|
|
9726
|
+
<ng-content />
|
|
9727
|
+
</div>
|
|
9728
|
+
`, styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0;box-sizing:border-box;color:var(--theme-text-primary, inherit);font-family:var(--theme-font-ui, inherit)}[hidden]{display:none!important}.mm-page__slot{display:contents}.mm-page__header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--theme-space-3, 12px) var(--theme-space-4, 16px);padding:var(--theme-space-4, 16px) var(--theme-space-4, 16px) var(--theme-space-3, 12px);flex:0 0 auto}.mm-page__heading{display:flex;flex-direction:column;gap:var(--theme-space-1, 4px);min-width:0}.mm-page__title{margin:0;font-family:var(--theme-font-display, inherit);font-size:1.25rem;line-height:1.4;font-weight:600;color:var(--theme-text-primary, inherit);overflow-wrap:anywhere}.mm-page__subtitle{font-size:.875rem;line-height:1.45;color:var(--theme-text-secondary, inherit);overflow-wrap:anywhere}.mm-page__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--theme-space-2, 8px);margin-left:auto}.mm-page__content{flex:1 1 auto;min-height:0;overflow:auto;padding:0 var(--theme-space-4, 16px) var(--theme-space-4, 16px)}:host(.mm-page--headerless) .mm-page__content{padding-top:var(--theme-space-4, 16px)}:host(.mm-page--flush) .mm-page__content{padding:0}\n"] }]
|
|
9729
|
+
}], ctorParameters: () => [], propDecorators: { pageTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageTitle", required: false }] }], pageSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSubtitle", required: false }] }], headingLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "headingLevel", required: false }] }], padded: [{ type: i0.Input, args: [{ isSignal: true, alias: "padded", required: false }] }], titleSlot: [{ type: i0.ViewChild, args: ['titleSlot', { isSignal: true }] }], subtitleSlot: [{ type: i0.ViewChild, args: ['subtitleSlot', { isSignal: true }] }], actionsSlot: [{ type: i0.ViewChild, args: ['actionsSlot', { isSignal: true }] }] } });
|
|
9730
|
+
/**
|
|
9731
|
+
* Everything a template needs for `<mm-page>` and its slots:
|
|
9732
|
+
* `imports: [...MM_PAGE]` (or `imports: [MM_PAGE]`).
|
|
9733
|
+
*/
|
|
9734
|
+
const MM_PAGE = [PageComponent, PageTitleDirective, PageSubtitleDirective, PageActionsDirective];
|
|
9735
|
+
|
|
9489
9736
|
const CreateEntitiesDocumentDto = gql `
|
|
9490
9737
|
mutation CreateEntities($entities: [RtEntityInput]!) {
|
|
9491
9738
|
runtime {
|
|
@@ -9662,6 +9909,8 @@ const DEFAULT_RUNTIME_BROWSER_MESSAGES = {
|
|
|
9662
9909
|
unloadRecord: 'Unload',
|
|
9663
9910
|
longitudeHint: 'The longitude of the point on the Earth surface (-180 to 180 degrees).',
|
|
9664
9911
|
latitudeHint: 'The latitude of the point on the Earth surface (-90 to 90 degrees).',
|
|
9912
|
+
secretWriteOnlyHint: 'Write-only. The stored value is never shown; leave empty to keep it.',
|
|
9913
|
+
recordWithSecretNotSaved: 'Some changed fields contain secret values that are never loaded here; those changes were not saved.',
|
|
9665
9914
|
title: 'Runtime Browser',
|
|
9666
9915
|
badgeLabel: 'Entities & Data',
|
|
9667
9916
|
titlePrefix: 'REPOSITORY',
|
|
@@ -9709,6 +9958,9 @@ const DEFAULT_RUNTIME_BROWSER_MESSAGES = {
|
|
|
9709
9958
|
create: 'Create',
|
|
9710
9959
|
edit: 'Edit',
|
|
9711
9960
|
delete: 'Delete',
|
|
9961
|
+
confirmDeleteEntityTitle: 'Delete {name}?',
|
|
9962
|
+
confirmDeleteEntityConsequence: 'The entity and all its child entities are erased. This cannot be undone.',
|
|
9963
|
+
confirmDeleteEntityConfirmText: 'Delete entity',
|
|
9712
9964
|
createEntity: 'Create Entity',
|
|
9713
9965
|
updateEntity: 'Update Entity',
|
|
9714
9966
|
name: 'Name',
|
|
@@ -9757,6 +10009,7 @@ const DEFAULT_RUNTIME_BROWSER_MESSAGES = {
|
|
|
9757
10009
|
treeMoveToRootUnsupported: 'Moving item to the root of the tree is not supported',
|
|
9758
10010
|
treeMoveOnRootUnsupported: 'Moving item on the root of the tree is not supported',
|
|
9759
10011
|
mappingHeader: 'MAPPING',
|
|
10012
|
+
mappingRemove: 'Remove mapping',
|
|
9760
10013
|
mappingSourceDataPoint: 'Source Data Point',
|
|
9761
10014
|
mappingAddMapping: '+ Add Mapping',
|
|
9762
10015
|
mappingSaveAll: 'Save All Mappings',
|
|
@@ -9817,7 +10070,7 @@ class DataMappingListComponent {
|
|
|
9817
10070
|
this.mappingChanged.emit(mapping);
|
|
9818
10071
|
}
|
|
9819
10072
|
plusIcon = plusIcon;
|
|
9820
|
-
trashIcon =
|
|
10073
|
+
trashIcon = MM_ACTION_ICONS.delete;
|
|
9821
10074
|
linkIcon = hyperlinkOpenIcon;
|
|
9822
10075
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: DataMappingListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9823
10076
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: DataMappingListComponent, isStandalone: true, selector: "mm-data-mapping-list", inputs: { messages: "messages", mappings: "mappings", sourceEntity: "sourceEntity", expressionValidator: "expressionValidator" }, outputs: { addMapping: "addMapping", removeMapping: "removeMapping", selectTarget: "selectTarget", selectSourceAttribute: "selectSourceAttribute", selectTargetAttribute: "selectTargetAttribute", mappingChanged: "mappingChanged", navigateToTarget: "navigateToTarget", saveAll: "saveAll" }, ngImport: i0, template: `
|
|
@@ -9837,7 +10090,9 @@ class DataMappingListComponent {
|
|
|
9837
10090
|
<div class="mapping-card">
|
|
9838
10091
|
<div class="mapping-card-header">
|
|
9839
10092
|
<span class="mapping-name">{{ mapping.name || ((messages?.mappingHeader ?? 'MAPPING') + ' ' + ($index + 1)) }}</span>
|
|
9840
|
-
<button kendoButton fillMode="flat" size="small" [svgIcon]="trashIcon"
|
|
10093
|
+
<button kendoButton fillMode="flat" size="small" themeColor="error" [svgIcon]="trashIcon"
|
|
10094
|
+
[title]="messages?.mappingRemove ?? 'Remove mapping'" data-action="delete"
|
|
10095
|
+
[attr.aria-label]="(messages?.mappingRemove ?? 'Remove mapping') + ' ' + (mapping.name || ((messages?.mappingHeader ?? 'MAPPING') + ' ' + ($index + 1)))"
|
|
9841
10096
|
(click)="removeMapping.emit(mapping)"></button>
|
|
9842
10097
|
</div>
|
|
9843
10098
|
<div class="mapping-card-body">
|
|
@@ -9871,7 +10126,7 @@ class DataMappingListComponent {
|
|
|
9871
10126
|
<span class="entity-name">{{ mapping.targetName || mapping.targetRtId }}</span>
|
|
9872
10127
|
@if (mapping.targetRtId) {
|
|
9873
10128
|
<button kendoButton fillMode="flat" size="small" [svgIcon]="linkIcon"
|
|
9874
|
-
title="Navigate to entity"
|
|
10129
|
+
title="Navigate to entity" aria-label="Navigate to entity"
|
|
9875
10130
|
(click)="navigateToTarget.emit(mapping)"></button>
|
|
9876
10131
|
}
|
|
9877
10132
|
</div>
|
|
@@ -9912,7 +10167,7 @@ class DataMappingListComponent {
|
|
|
9912
10167
|
</div>
|
|
9913
10168
|
}
|
|
9914
10169
|
</div>
|
|
9915
|
-
`, isInline: true, styles: [".mapping-list{display:flex;flex-direction:column;gap:12px}.mapping-toolbar{display:flex;justify-content:flex-end}.mapping-empty-hint{text-align:center;padding:16px;color:var(--kendo-color-subtle, #6c757d);font-size:.85rem}.mapping-card{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;overflow:hidden}.mapping-card-header{display:flex;align-items:center;justify-content:space-between;padding:6px 12px;font-size:.75rem;font-weight:700;
|
|
10170
|
+
`, isInline: true, styles: [".mapping-list{display:flex;flex-direction:column;gap:12px}.mapping-toolbar{display:flex;justify-content:flex-end}.mapping-empty-hint{text-align:center;padding:16px;color:var(--kendo-color-subtle, #6c757d);font-size:.85rem}.mapping-card{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;overflow:hidden}.mapping-card-header{display:flex;align-items:center;justify-content:space-between;padding:6px 12px;font-size:.75rem;font-weight:700;color:var(--kendo-color-on-primary, #ffffff);background:var(--kendo-color-primary, #ff6358)}.mapping-card-header .mapping-name{flex:1}.mapping-card-body{padding:10px 12px;display:flex;flex-direction:column;gap:8px}.mapping-row{display:flex;flex-direction:column;gap:3px}.mapping-row label{font-size:.7rem;font-weight:600;color:var(--kendo-color-subtle, #6c757d)}.target-display{display:flex;align-items:center;gap:8px;padding:4px 8px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;background:var(--kendo-color-surface-alt, #f8f9fa);min-height:30px}.target-display .target-info{flex:1;font-size:.85rem;font-family:monospace}.mapping-actions{display:flex;justify-content:flex-end;padding-top:4px}.entity-info-display{display:flex;flex-direction:column;gap:2px;padding:4px 8px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;background:var(--kendo-color-surface-alt, #f8f9fa)}.entity-info-main{display:flex;align-items:center;gap:4px}.entity-name{flex:1;font-size:.85rem;font-weight:600}.entity-info-details{display:flex;align-items:center;gap:2px;font-size:.7rem;font-family:monospace;color:var(--kendo-color-subtle, #6c757d)}.entity-detail-separator{color:var(--kendo-color-subtle, #6c757d)}.expression-feedback{font-size:.75rem;padding:2px 0;font-family:monospace}.expression-error{color:var(--kendo-color-error, #dc3545)}.expression-success{color:var(--kendo-color-success, #28a745)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: TextBoxModule }, { kind: "component", type: i5.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: SVGIconModule }, { kind: "component", type: DataPointPickerComponent, selector: "mm-data-point-picker", inputs: ["entity", "entityRtId", "entityCkTypeId", "value", "placeholder", "disabled"], outputs: ["valueChange", "filterChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
9916
10171
|
}
|
|
9917
10172
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: DataMappingListComponent, decorators: [{
|
|
9918
10173
|
type: Component,
|
|
@@ -9940,7 +10195,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
9940
10195
|
<div class="mapping-card">
|
|
9941
10196
|
<div class="mapping-card-header">
|
|
9942
10197
|
<span class="mapping-name">{{ mapping.name || ((messages?.mappingHeader ?? 'MAPPING') + ' ' + ($index + 1)) }}</span>
|
|
9943
|
-
<button kendoButton fillMode="flat" size="small" [svgIcon]="trashIcon"
|
|
10198
|
+
<button kendoButton fillMode="flat" size="small" themeColor="error" [svgIcon]="trashIcon"
|
|
10199
|
+
[title]="messages?.mappingRemove ?? 'Remove mapping'" data-action="delete"
|
|
10200
|
+
[attr.aria-label]="(messages?.mappingRemove ?? 'Remove mapping') + ' ' + (mapping.name || ((messages?.mappingHeader ?? 'MAPPING') + ' ' + ($index + 1)))"
|
|
9944
10201
|
(click)="removeMapping.emit(mapping)"></button>
|
|
9945
10202
|
</div>
|
|
9946
10203
|
<div class="mapping-card-body">
|
|
@@ -9974,7 +10231,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
9974
10231
|
<span class="entity-name">{{ mapping.targetName || mapping.targetRtId }}</span>
|
|
9975
10232
|
@if (mapping.targetRtId) {
|
|
9976
10233
|
<button kendoButton fillMode="flat" size="small" [svgIcon]="linkIcon"
|
|
9977
|
-
title="Navigate to entity"
|
|
10234
|
+
title="Navigate to entity" aria-label="Navigate to entity"
|
|
9978
10235
|
(click)="navigateToTarget.emit(mapping)"></button>
|
|
9979
10236
|
}
|
|
9980
10237
|
</div>
|
|
@@ -10015,7 +10272,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
10015
10272
|
</div>
|
|
10016
10273
|
}
|
|
10017
10274
|
</div>
|
|
10018
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".mapping-list{display:flex;flex-direction:column;gap:12px}.mapping-toolbar{display:flex;justify-content:flex-end}.mapping-empty-hint{text-align:center;padding:16px;color:var(--kendo-color-subtle, #6c757d);font-size:.85rem}.mapping-card{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;overflow:hidden}.mapping-card-header{display:flex;align-items:center;justify-content:space-between;padding:6px 12px;font-size:.75rem;font-weight:700;
|
|
10275
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".mapping-list{display:flex;flex-direction:column;gap:12px}.mapping-toolbar{display:flex;justify-content:flex-end}.mapping-empty-hint{text-align:center;padding:16px;color:var(--kendo-color-subtle, #6c757d);font-size:.85rem}.mapping-card{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;overflow:hidden}.mapping-card-header{display:flex;align-items:center;justify-content:space-between;padding:6px 12px;font-size:.75rem;font-weight:700;color:var(--kendo-color-on-primary, #ffffff);background:var(--kendo-color-primary, #ff6358)}.mapping-card-header .mapping-name{flex:1}.mapping-card-body{padding:10px 12px;display:flex;flex-direction:column;gap:8px}.mapping-row{display:flex;flex-direction:column;gap:3px}.mapping-row label{font-size:.7rem;font-weight:600;color:var(--kendo-color-subtle, #6c757d)}.target-display{display:flex;align-items:center;gap:8px;padding:4px 8px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;background:var(--kendo-color-surface-alt, #f8f9fa);min-height:30px}.target-display .target-info{flex:1;font-size:.85rem;font-family:monospace}.mapping-actions{display:flex;justify-content:flex-end;padding-top:4px}.entity-info-display{display:flex;flex-direction:column;gap:2px;padding:4px 8px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;background:var(--kendo-color-surface-alt, #f8f9fa)}.entity-info-main{display:flex;align-items:center;gap:4px}.entity-name{flex:1;font-size:.85rem;font-weight:600}.entity-info-details{display:flex;align-items:center;gap:2px;font-size:.7rem;font-family:monospace;color:var(--kendo-color-subtle, #6c757d)}.entity-detail-separator{color:var(--kendo-color-subtle, #6c757d)}.expression-feedback{font-size:.75rem;padding:2px 0;font-family:monospace}.expression-error{color:var(--kendo-color-error, #dc3545)}.expression-success{color:var(--kendo-color-success, #28a745)}\n"] }]
|
|
10019
10276
|
}], propDecorators: { messages: [{
|
|
10020
10277
|
type: Input
|
|
10021
10278
|
}], mappings: [{
|
|
@@ -10367,7 +10624,7 @@ class EntityDetailViewComponent {
|
|
|
10367
10624
|
fillMode="flat"
|
|
10368
10625
|
size="small"
|
|
10369
10626
|
[svgIcon]="copyIcon"
|
|
10370
|
-
[title]="_messages.copyToClipboard"
|
|
10627
|
+
[title]="_messages.copyToClipboard" [attr.aria-label]="_messages.copyToClipboard"
|
|
10371
10628
|
(click)="copyToClipboard(entity.rtId, _messages.runtimeId)"
|
|
10372
10629
|
></button>
|
|
10373
10630
|
</div>
|
|
@@ -10381,7 +10638,7 @@ class EntityDetailViewComponent {
|
|
|
10381
10638
|
fillMode="flat"
|
|
10382
10639
|
size="small"
|
|
10383
10640
|
[svgIcon]="copyIcon"
|
|
10384
|
-
[title]="_messages.copyToClipboard"
|
|
10641
|
+
[title]="_messages.copyToClipboard" [attr.aria-label]="_messages.copyToClipboard"
|
|
10385
10642
|
(click)="copyToClipboard(entity.ckTypeId, _messages.typeId)"
|
|
10386
10643
|
></button>
|
|
10387
10644
|
</div>
|
|
@@ -10395,7 +10652,7 @@ class EntityDetailViewComponent {
|
|
|
10395
10652
|
fillMode="flat"
|
|
10396
10653
|
size="small"
|
|
10397
10654
|
[svgIcon]="copyIcon"
|
|
10398
|
-
[title]="_messages.copyEntityIdentifierToClipboard"
|
|
10655
|
+
[title]="_messages.copyEntityIdentifierToClipboard" [attr.aria-label]="_messages.copyEntityIdentifierToClipboard"
|
|
10399
10656
|
(click)="
|
|
10400
10657
|
copyToClipboard(
|
|
10401
10658
|
getEntityIdentifier(),
|
|
@@ -10566,7 +10823,7 @@ class EntityDetailViewComponent {
|
|
|
10566
10823
|
</kendo-tabstrip>
|
|
10567
10824
|
</div>
|
|
10568
10825
|
}
|
|
10569
|
-
`, isInline: true, styles: [".loading-state,.error-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;text-align:center;min-height:200px}.loading-state .error-message,.error-state .error-message{margin-bottom:16px;font-family:Roboto,sans-serif;color:#e74c3c}.entity-content{flex:1;display:flex;flex-direction:column;gap:24px}.entity-content .basic-info-card{padding:20px 24px;background:linear-gradient(180deg,var(--iron-navy),var(--surface-elevated));border:1px solid var(--octo-mint-30);border-radius:4px 16px;position:relative;box-shadow:0 4px 20px #0006,0 0 15px var(--octo-mint-08)}.entity-content .basic-info-card:before{content:\"\";position:absolute;top:0;left:0;width:4px;height:100%;background:linear-gradient(180deg,var(--octo-mint),var(--neo-cyan),var(--royal-violet));box-shadow:0 0 10px var(--octo-mint-50);border-radius:4px 0 0 4px}.entity-content .basic-info-card .basic-info-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:20px}.entity-content .basic-info-card .basic-info-grid .info-item{display:flex;flex-direction:column;gap:8px}.entity-content .basic-info-card .basic-info-grid .info-item label{font-family:Montserrat,sans-serif;font-weight:600;font-size:.75rem;letter-spacing:.5px;text-transform:uppercase;color:var(--octo-mint-80)}.entity-content .basic-info-card .basic-info-grid .info-item .value{font-family:Roboto Mono,monospace;font-size:.875rem;color:rgba(var(--octo-text-color),.9);word-break:break-word;background:var(--deep-sea-40);padding:8px 12px;border-radius:4px;border:1px solid var(--octo-mint-15)}.entity-content .basic-info-card .basic-info-grid .info-item.with-action .value-with-action{display:flex;align-items:center}.entity-content .basic-info-card .basic-info-grid .info-item.with-action .value-with-action .value{flex:1;font-family:Roboto Mono,monospace;font-size:.875rem;color:rgba(var(--octo-text-color),.9);word-break:break-word}.entity-content .entity-tabs{flex:1;min-height:400px;background:linear-gradient(180deg,var(--iron-navy),var(--surface-elevated));border:1px solid var(--octo-mint-30);border-radius:4px 16px;overflow:hidden;position:relative}.entity-content .entity-tabs:before{content:\"\";position:absolute;top:0;left:0;width:4px;height:100%;background:linear-gradient(180deg,var(--octo-mint),var(--neo-cyan),var(--royal-violet));box-shadow:0 0 10px var(--octo-mint-50);z-index:1}.entity-content .entity-tabs ::ng-deep .k-tabstrip{background:transparent}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper{background:linear-gradient(90deg,var(--octo-mint-10),transparent);border-bottom:1px solid var(--octo-mint-20);padding-left:20px}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item{background:transparent;border:none;color:rgba(var(--octo-text-color),.7);font-family:Montserrat,sans-serif;font-weight:600;font-size:.8rem;letter-spacing:.5px;text-transform:uppercase;padding:12px 20px;margin-right:4px;border-radius:4px 4px 0 0;transition:all .2s ease}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item:hover{background:var(--octo-mint-10);color:var(--octo-mint)}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item.k-active{background:linear-gradient(180deg,var(--octo-mint-20),transparent);color:var(--octo-mint);border-bottom:2px solid var(--octo-mint);box-shadow:0 0 10px var(--octo-mint-30)}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-content{background:transparent;border:none;padding:0}.entity-content .entity-tabs .tab-content{padding:20px 24px;height:100%;overflow-y:auto}.entity-content .entity-tabs .tab-content .empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 40px;text-align:center}.entity-content .entity-tabs .tab-content .empty-state kendo-svgicon{font-size:64px;margin-bottom:20px;color:var(--octo-mint-40);text-shadow:0 0 20px var(--octo-mint-30)}.entity-content .entity-tabs .tab-content .empty-state p{margin:0;font-family:Montserrat,sans-serif;font-size:.9rem;color:rgba(var(--octo-text-color),.5);letter-spacing:.5px}.entity-content .entity-tabs .tab-content.properties-tab{padding:0;height:100%}.entity-content .entity-tabs .tab-content.properties-tab mm-property-grid{display:block;height:100%;width:100%}.entity-content .entity-tabs .tab-content.associations-tab{display:flex;flex-direction:column;gap:16px;padding:0;height:100%}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:16px;padding:16px 20px;background:linear-gradient(90deg,var(--octo-mint-05),transparent);border-bottom:1px solid var(--octo-mint-20)}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group{display:flex;align-items:center;gap:10px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group label{font-family:Montserrat,sans-serif;font-weight:600;font-size:.75rem;letter-spacing:.5px;text-transform:uppercase;color:var(--octo-mint-80);white-space:nowrap}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-dropdownlist{width:160px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-textbox{width:220px}.entity-content .entity-tabs .tab-content.associations-tab mm-list-view{flex:1;display:block;height:calc(100% - 70px)}.entity-content .entity-tabs .tab-content.mapping-tab{padding:12px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-empty{display:flex;flex-direction:column;align-items:center;padding:24px 20px;text-align:center}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-empty kendo-svgicon{font-size:36px;margin-bottom:10px;opacity:.5}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-empty p{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-config{display:flex;flex-direction:column;gap:20px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-section{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;overflow:hidden}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-section .section-header{padding:8px 14px;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:1px;color:var(--kendo-color-on-primary, #ffffff);background:var(--kendo-color-primary, #ff6358)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-section .section-body{padding:12px 14px;display:flex;flex-direction:column;gap:10px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-field{display:flex;flex-direction:column;gap:4px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-field label{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--kendo-color-subtle, #6c757d)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-target-display{display:flex;align-items:center;gap:8px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-target-display .target-type{font-size:.75rem;color:var(--kendo-color-subtle, #6c757d);font-family:monospace;padding:2px 6px;border-radius:3px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-target-display .target-name{font-weight:600;flex:1}.entity-content .entity-tabs .tab-content.mapping-tab .field-hint{font-size:.7rem;color:var(--kendo-color-subtle, #6c757d);font-style:italic;line-height:1.3}.entity-content .entity-tabs .tab-content.mapping-tab .attribute-picker{display:flex;align-items:center;gap:8px;padding:4px 10px;border-radius:4px;border:1px solid var(--kendo-color-border, #dee2e6);background:var(--kendo-color-surface-alt, #f8f9fa);min-height:32px}.entity-content .entity-tabs .tab-content.mapping-tab .attribute-picker .attribute-value{flex:1;font-family:monospace;font-size:.85rem}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-actions{display:flex;gap:8px;justify-content:flex-end;padding-top:4px}@media(max-width:768px){.entity-content{gap:16px}.entity-content .basic-info-card{padding:16px 20px}.entity-content .basic-info-card .basic-info-grid{grid-template-columns:1fr;gap:16px}.entity-content .entity-tabs{min-height:300px}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper{padding-left:12px}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item{padding:10px 14px;font-size:.75rem}.entity-content .entity-tabs .tab-content{padding:16px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar{flex-direction:column;align-items:flex-start;gap:12px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group{width:100%}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-dropdownlist,.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-textbox{width:100%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TabStripModule }, { kind: "component", type: i1$4.TabStripComponent, selector: "kendo-tabstrip", inputs: ["height", "animate", "tabAlignment", "tabPosition", "keepTabContent", "closable", "scrollable", "size", "closeIcon", "closeIconClass", "closeSVGIcon", "showContentArea"], outputs: ["tabSelect", "tabClose", "tabScroll"], exportAs: ["kendoTabStrip"] }, { kind: "component", type: i1$4.TabStripTabComponent, selector: "kendo-tabstrip-tab", inputs: ["title", "disabled", "cssClass", "cssStyle", "selected", "closable", "closeIcon", "closeIconClass", "closeSVGIcon"], exportAs: ["kendoTabStripTab"] }, { kind: "directive", type: i1$4.TabContentDirective, selector: "[kendoTabContent]" }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: SVGIconModule }, { kind: "component", type: i5$1.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i1$4.CardComponent, selector: "kendo-card", inputs: ["orientation", "width"] }, { kind: "component", type: i1$4.CardBodyComponent, selector: "kendo-card-body" }, { kind: "component", type: i1$4.CardHeaderComponent, selector: "kendo-card-header" }, { kind: "ngmodule", type: DropDownListModule }, { kind: "component", type: i3$1.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: TextBoxModule }, { kind: "component", type: i5.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: PropertyGridComponent, selector: "mm-property-grid", inputs: ["data", "config", "showTypeColumn", "messages"], outputs: ["propertyChange", "saveRequested", "binaryDownload"] }, { kind: "component", type: ListViewComponent, selector: "mm-list-view", inputs: ["pageSize", "skip", "autoPageSize", "rowIsClickable", "showRowCheckBoxes", "showRowSelectAllCheckBox", "contextMenuType", "leftToolbarActions", "rightToolbarActions", "actionCommandItems", "contextMenuCommandItems", "excelExportFileName", "pdfExportFileName", "pageable", "sortable", "rowFilterEnabled", "searchTextBoxEnabled", "persistListState", "listStateKey", "resizable", "actionsColumnWidth", "hideCheckboxesBelow", "cardModeBelow", "collapseCommandsBelow", "rowClass", "messages", "selectable", "columns"], outputs: ["rowClicked", "resetFilters"] }, { kind: "directive", type: EntityAssociationsDataSourceDirective, selector: "[mmEntityAssociationsDataSource]", exportAs: ["mmEntityAssociationsDataSource"] }, { kind: "component", type: DataMappingListComponent, selector: "mm-data-mapping-list", inputs: ["messages", "mappings", "sourceEntity", "expressionValidator"], outputs: ["addMapping", "removeMapping", "selectTarget", "selectSourceAttribute", "selectTargetAttribute", "mappingChanged", "navigateToTarget", "saveAll"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
10826
|
+
`, isInline: true, styles: [".loading-state,.error-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;text-align:center;min-height:200px}.loading-state .error-message,.error-state .error-message{margin-bottom:16px;font-family:Roboto,sans-serif;color:#e74c3c}.entity-content{flex:1;display:flex;flex-direction:column;gap:24px}.entity-content .basic-info-card{padding:20px 24px;background:var(--theme-bg-elevated);border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-md, 6px);position:relative;box-shadow:0 4px 20px #0006}.entity-content .basic-info-card:before{content:\"\";position:absolute;top:0;left:0;width:4px;height:100%;background:transparent;box-shadow:none;border-radius:4px 0 0 4px}.entity-content .basic-info-card .basic-info-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:20px}.entity-content .basic-info-card .basic-info-grid .info-item{display:flex;flex-direction:column;gap:8px}.entity-content .basic-info-card .basic-info-grid .info-item label{font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-weight:600;font-size:.75rem;color:var(--octo-mint-80)}.entity-content .basic-info-card .basic-info-grid .info-item .value{font-family:Roboto Mono,monospace;font-size:.875rem;color:rgba(var(--octo-text-color),.9);word-break:break-word;background:var(--deep-sea-40);padding:8px 12px;border-radius:4px;border:1px solid var(--octo-mint-15)}.entity-content .basic-info-card .basic-info-grid .info-item.with-action .value-with-action{display:flex;align-items:center}.entity-content .basic-info-card .basic-info-grid .info-item.with-action .value-with-action .value{flex:1;font-family:Roboto Mono,monospace;font-size:.875rem;color:rgba(var(--octo-text-color),.9);word-break:break-word}.entity-content .entity-tabs{flex:1;min-height:400px;background:var(--theme-bg-elevated);border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-md, 6px);overflow:hidden;position:relative}.entity-content .entity-tabs:before{content:\"\";position:absolute;top:0;left:0;width:4px;height:100%;background:transparent;box-shadow:none;z-index:1}.entity-content .entity-tabs ::ng-deep .k-tabstrip{background:transparent}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper{background:var(--theme-bg-elevated);border-bottom:1px solid var(--octo-mint-20);padding-left:20px}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item{background:transparent;border:none;color:rgba(var(--octo-text-color),.7);font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-weight:600;font-size:.8rem;padding:12px 20px;margin-right:4px;border-radius:4px 4px 0 0;transition:all .2s ease}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item:hover{background:var(--octo-mint-10);color:var(--theme-text-accent, var(--octo-mint))}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item.k-active{background:var(--theme-bg-elevated);color:var(--theme-text-accent, var(--octo-mint));border-bottom:2px solid var(--octo-mint);box-shadow:none}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-content{background:transparent;border:none;padding:0}.entity-content .entity-tabs .tab-content{padding:20px 24px;height:100%;overflow-y:auto}.entity-content .entity-tabs .tab-content .empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 40px;text-align:center}.entity-content .entity-tabs .tab-content .empty-state kendo-svgicon{font-size:64px;margin-bottom:20px;color:var(--octo-mint-40)}.entity-content .entity-tabs .tab-content .empty-state p{margin:0;font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-size:.9rem;color:rgba(var(--octo-text-color),.5)}.entity-content .entity-tabs .tab-content.properties-tab{padding:0;height:100%}.entity-content .entity-tabs .tab-content.properties-tab mm-property-grid{display:block;height:100%;width:100%}.entity-content .entity-tabs .tab-content.associations-tab{display:flex;flex-direction:column;gap:16px;padding:0;height:100%}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:16px;padding:16px 20px;background:var(--theme-bg-elevated);border-bottom:1px solid var(--octo-mint-20)}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group{display:flex;align-items:center;gap:10px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group label{font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-weight:600;font-size:.75rem;color:var(--octo-mint-80);white-space:nowrap}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-dropdownlist{width:160px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-textbox{width:220px}.entity-content .entity-tabs .tab-content.associations-tab mm-list-view{flex:1;display:block;height:calc(100% - 70px)}.entity-content .entity-tabs .tab-content.mapping-tab{padding:12px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-empty{display:flex;flex-direction:column;align-items:center;padding:24px 20px;text-align:center}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-empty kendo-svgicon{font-size:36px;margin-bottom:10px;opacity:.5}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-empty p{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-config{display:flex;flex-direction:column;gap:20px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-section{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;overflow:hidden}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-section .section-header{padding:8px 14px;font-size:.75rem;font-weight:700;color:var(--kendo-color-on-primary, #ffffff);background:var(--kendo-color-primary, #ff6358)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-section .section-body{padding:12px 14px;display:flex;flex-direction:column;gap:10px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-field{display:flex;flex-direction:column;gap:4px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-field label{font-size:.75rem;font-weight:600;color:var(--kendo-color-subtle, #6c757d)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-target-display{display:flex;align-items:center;gap:8px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-target-display .target-type{font-size:.75rem;color:var(--kendo-color-subtle, #6c757d);font-family:monospace;padding:2px 6px;border-radius:3px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-target-display .target-name{font-weight:600;flex:1}.entity-content .entity-tabs .tab-content.mapping-tab .field-hint{font-size:.7rem;color:var(--kendo-color-subtle, #6c757d);font-style:italic;line-height:1.3}.entity-content .entity-tabs .tab-content.mapping-tab .attribute-picker{display:flex;align-items:center;gap:8px;padding:4px 10px;border-radius:4px;border:1px solid var(--kendo-color-border, #dee2e6);background:var(--kendo-color-surface-alt, #f8f9fa);min-height:32px}.entity-content .entity-tabs .tab-content.mapping-tab .attribute-picker .attribute-value{flex:1;font-family:monospace;font-size:.85rem}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-actions{display:flex;gap:8px;justify-content:flex-end;padding-top:4px}@media(max-width:768px){.entity-content{gap:16px}.entity-content .basic-info-card{padding:16px 20px}.entity-content .basic-info-card .basic-info-grid{grid-template-columns:1fr;gap:16px}.entity-content .entity-tabs{min-height:300px}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper{padding-left:12px}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item{padding:10px 14px;font-size:.75rem}.entity-content .entity-tabs .tab-content{padding:16px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar{flex-direction:column;align-items:flex-start;gap:12px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group{width:100%}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-dropdownlist,.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-textbox{width:100%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TabStripModule }, { kind: "component", type: i1$4.TabStripComponent, selector: "kendo-tabstrip", inputs: ["height", "animate", "tabAlignment", "tabPosition", "keepTabContent", "closable", "scrollable", "size", "closeIcon", "closeIconClass", "closeSVGIcon", "showContentArea"], outputs: ["tabSelect", "tabClose", "tabScroll"], exportAs: ["kendoTabStrip"] }, { kind: "component", type: i1$4.TabStripTabComponent, selector: "kendo-tabstrip-tab", inputs: ["title", "disabled", "cssClass", "cssStyle", "selected", "closable", "closeIcon", "closeIconClass", "closeSVGIcon"], exportAs: ["kendoTabStripTab"] }, { kind: "directive", type: i1$4.TabContentDirective, selector: "[kendoTabContent]" }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: SVGIconModule }, { kind: "component", type: i5$1.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i1$4.CardComponent, selector: "kendo-card", inputs: ["orientation", "width"] }, { kind: "component", type: i1$4.CardBodyComponent, selector: "kendo-card-body" }, { kind: "component", type: i1$4.CardHeaderComponent, selector: "kendo-card-header" }, { kind: "ngmodule", type: DropDownListModule }, { kind: "component", type: i3$1.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: TextBoxModule }, { kind: "component", type: i5.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: PropertyGridComponent, selector: "mm-property-grid", inputs: ["data", "config", "showTypeColumn", "messages"], outputs: ["propertyChange", "saveRequested", "binaryDownload"] }, { kind: "component", type: ListViewComponent, selector: "mm-list-view", inputs: ["pageSize", "skip", "autoPageSize", "rowIsClickable", "showRowCheckBoxes", "showRowSelectAllCheckBox", "contextMenuType", "leftToolbarActions", "rightToolbarActions", "actionCommandItems", "contextMenuCommandItems", "rowActions", "maxInlineRowActions", "excelExportFileName", "pdfExportFileName", "pageable", "sortable", "rowFilterEnabled", "searchTextBoxEnabled", "persistListState", "listStateKey", "resizable", "actionsColumnWidth", "hideCheckboxesBelow", "cardModeBelow", "collapseCommandsBelow", "hasExternalFilters", "rowClass", "messages", "selectable", "columns", "rowLabelField"], outputs: ["rowClicked", "rowAction", "resetFilters"] }, { kind: "directive", type: EntityAssociationsDataSourceDirective, selector: "[mmEntityAssociationsDataSource]", exportAs: ["mmEntityAssociationsDataSource"] }, { kind: "component", type: DataMappingListComponent, selector: "mm-data-mapping-list", inputs: ["messages", "mappings", "sourceEntity", "expressionValidator"], outputs: ["addMapping", "removeMapping", "selectTarget", "selectSourceAttribute", "selectTargetAttribute", "mappingChanged", "navigateToTarget", "saveAll"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
10570
10827
|
}
|
|
10571
10828
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: EntityDetailViewComponent, decorators: [{
|
|
10572
10829
|
type: Component,
|
|
@@ -10619,7 +10876,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
10619
10876
|
fillMode="flat"
|
|
10620
10877
|
size="small"
|
|
10621
10878
|
[svgIcon]="copyIcon"
|
|
10622
|
-
[title]="_messages.copyToClipboard"
|
|
10879
|
+
[title]="_messages.copyToClipboard" [attr.aria-label]="_messages.copyToClipboard"
|
|
10623
10880
|
(click)="copyToClipboard(entity.rtId, _messages.runtimeId)"
|
|
10624
10881
|
></button>
|
|
10625
10882
|
</div>
|
|
@@ -10633,7 +10890,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
10633
10890
|
fillMode="flat"
|
|
10634
10891
|
size="small"
|
|
10635
10892
|
[svgIcon]="copyIcon"
|
|
10636
|
-
[title]="_messages.copyToClipboard"
|
|
10893
|
+
[title]="_messages.copyToClipboard" [attr.aria-label]="_messages.copyToClipboard"
|
|
10637
10894
|
(click)="copyToClipboard(entity.ckTypeId, _messages.typeId)"
|
|
10638
10895
|
></button>
|
|
10639
10896
|
</div>
|
|
@@ -10647,7 +10904,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
10647
10904
|
fillMode="flat"
|
|
10648
10905
|
size="small"
|
|
10649
10906
|
[svgIcon]="copyIcon"
|
|
10650
|
-
[title]="_messages.copyEntityIdentifierToClipboard"
|
|
10907
|
+
[title]="_messages.copyEntityIdentifierToClipboard" [attr.aria-label]="_messages.copyEntityIdentifierToClipboard"
|
|
10651
10908
|
(click)="
|
|
10652
10909
|
copyToClipboard(
|
|
10653
10910
|
getEntityIdentifier(),
|
|
@@ -10818,7 +11075,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
10818
11075
|
</kendo-tabstrip>
|
|
10819
11076
|
</div>
|
|
10820
11077
|
}
|
|
10821
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".loading-state,.error-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;text-align:center;min-height:200px}.loading-state .error-message,.error-state .error-message{margin-bottom:16px;font-family:Roboto,sans-serif;color:#e74c3c}.entity-content{flex:1;display:flex;flex-direction:column;gap:24px}.entity-content .basic-info-card{padding:20px 24px;background:
|
|
11078
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".loading-state,.error-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;text-align:center;min-height:200px}.loading-state .error-message,.error-state .error-message{margin-bottom:16px;font-family:Roboto,sans-serif;color:#e74c3c}.entity-content{flex:1;display:flex;flex-direction:column;gap:24px}.entity-content .basic-info-card{padding:20px 24px;background:var(--theme-bg-elevated);border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-md, 6px);position:relative;box-shadow:0 4px 20px #0006}.entity-content .basic-info-card:before{content:\"\";position:absolute;top:0;left:0;width:4px;height:100%;background:transparent;box-shadow:none;border-radius:4px 0 0 4px}.entity-content .basic-info-card .basic-info-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:20px}.entity-content .basic-info-card .basic-info-grid .info-item{display:flex;flex-direction:column;gap:8px}.entity-content .basic-info-card .basic-info-grid .info-item label{font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-weight:600;font-size:.75rem;color:var(--octo-mint-80)}.entity-content .basic-info-card .basic-info-grid .info-item .value{font-family:Roboto Mono,monospace;font-size:.875rem;color:rgba(var(--octo-text-color),.9);word-break:break-word;background:var(--deep-sea-40);padding:8px 12px;border-radius:4px;border:1px solid var(--octo-mint-15)}.entity-content .basic-info-card .basic-info-grid .info-item.with-action .value-with-action{display:flex;align-items:center}.entity-content .basic-info-card .basic-info-grid .info-item.with-action .value-with-action .value{flex:1;font-family:Roboto Mono,monospace;font-size:.875rem;color:rgba(var(--octo-text-color),.9);word-break:break-word}.entity-content .entity-tabs{flex:1;min-height:400px;background:var(--theme-bg-elevated);border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-md, 6px);overflow:hidden;position:relative}.entity-content .entity-tabs:before{content:\"\";position:absolute;top:0;left:0;width:4px;height:100%;background:transparent;box-shadow:none;z-index:1}.entity-content .entity-tabs ::ng-deep .k-tabstrip{background:transparent}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper{background:var(--theme-bg-elevated);border-bottom:1px solid var(--octo-mint-20);padding-left:20px}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item{background:transparent;border:none;color:rgba(var(--octo-text-color),.7);font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-weight:600;font-size:.8rem;padding:12px 20px;margin-right:4px;border-radius:4px 4px 0 0;transition:all .2s ease}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item:hover{background:var(--octo-mint-10);color:var(--theme-text-accent, var(--octo-mint))}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item.k-active{background:var(--theme-bg-elevated);color:var(--theme-text-accent, var(--octo-mint));border-bottom:2px solid var(--octo-mint);box-shadow:none}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-content{background:transparent;border:none;padding:0}.entity-content .entity-tabs .tab-content{padding:20px 24px;height:100%;overflow-y:auto}.entity-content .entity-tabs .tab-content .empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 40px;text-align:center}.entity-content .entity-tabs .tab-content .empty-state kendo-svgicon{font-size:64px;margin-bottom:20px;color:var(--octo-mint-40)}.entity-content .entity-tabs .tab-content .empty-state p{margin:0;font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-size:.9rem;color:rgba(var(--octo-text-color),.5)}.entity-content .entity-tabs .tab-content.properties-tab{padding:0;height:100%}.entity-content .entity-tabs .tab-content.properties-tab mm-property-grid{display:block;height:100%;width:100%}.entity-content .entity-tabs .tab-content.associations-tab{display:flex;flex-direction:column;gap:16px;padding:0;height:100%}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:16px;padding:16px 20px;background:var(--theme-bg-elevated);border-bottom:1px solid var(--octo-mint-20)}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group{display:flex;align-items:center;gap:10px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group label{font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-weight:600;font-size:.75rem;color:var(--octo-mint-80);white-space:nowrap}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-dropdownlist{width:160px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-textbox{width:220px}.entity-content .entity-tabs .tab-content.associations-tab mm-list-view{flex:1;display:block;height:calc(100% - 70px)}.entity-content .entity-tabs .tab-content.mapping-tab{padding:12px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-empty{display:flex;flex-direction:column;align-items:center;padding:24px 20px;text-align:center}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-empty kendo-svgicon{font-size:36px;margin-bottom:10px;opacity:.5}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-empty p{margin:0 0 12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-config{display:flex;flex-direction:column;gap:20px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-section{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;overflow:hidden}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-section .section-header{padding:8px 14px;font-size:.75rem;font-weight:700;color:var(--kendo-color-on-primary, #ffffff);background:var(--kendo-color-primary, #ff6358)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-section .section-body{padding:12px 14px;display:flex;flex-direction:column;gap:10px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-field{display:flex;flex-direction:column;gap:4px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-field label{font-size:.75rem;font-weight:600;color:var(--kendo-color-subtle, #6c757d)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-target-display{display:flex;align-items:center;gap:8px}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-target-display .target-type{font-size:.75rem;color:var(--kendo-color-subtle, #6c757d);font-family:monospace;padding:2px 6px;border-radius:3px;background:var(--kendo-color-surface-alt, #f8f9fa);border:1px solid var(--kendo-color-border, #dee2e6)}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-target-display .target-name{font-weight:600;flex:1}.entity-content .entity-tabs .tab-content.mapping-tab .field-hint{font-size:.7rem;color:var(--kendo-color-subtle, #6c757d);font-style:italic;line-height:1.3}.entity-content .entity-tabs .tab-content.mapping-tab .attribute-picker{display:flex;align-items:center;gap:8px;padding:4px 10px;border-radius:4px;border:1px solid var(--kendo-color-border, #dee2e6);background:var(--kendo-color-surface-alt, #f8f9fa);min-height:32px}.entity-content .entity-tabs .tab-content.mapping-tab .attribute-picker .attribute-value{flex:1;font-family:monospace;font-size:.85rem}.entity-content .entity-tabs .tab-content.mapping-tab .mapping-actions{display:flex;gap:8px;justify-content:flex-end;padding-top:4px}@media(max-width:768px){.entity-content{gap:16px}.entity-content .basic-info-card{padding:16px 20px}.entity-content .basic-info-card .basic-info-grid{grid-template-columns:1fr;gap:16px}.entity-content .entity-tabs{min-height:300px}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper{padding-left:12px}.entity-content .entity-tabs ::ng-deep .k-tabstrip .k-tabstrip-items-wrapper .k-tabstrip-items .k-item{padding:10px 14px;font-size:.75rem}.entity-content .entity-tabs .tab-content{padding:16px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar{flex-direction:column;align-items:flex-start;gap:12px}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group{width:100%}.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-dropdownlist,.entity-content .entity-tabs .tab-content.associations-tab .associations-toolbar .filter-group kendo-textbox{width:100%}}\n"] }]
|
|
10822
11079
|
}], ctorParameters: () => [], propDecorators: { entity: [{
|
|
10823
11080
|
type: Input
|
|
10824
11081
|
}], loading: [{
|
|
@@ -10860,18 +11117,424 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
10860
11117
|
args: ['associationsDir', { static: false }]
|
|
10861
11118
|
}] } });
|
|
10862
11119
|
|
|
11120
|
+
const GetSecretSafeTypeAttributesDocumentDto = gql `
|
|
11121
|
+
query getSecretSafeTypeAttributes($rtCkTypeId: String!) {
|
|
11122
|
+
constructionKit {
|
|
11123
|
+
types(rtCkId: $rtCkTypeId, first: 1) {
|
|
11124
|
+
items {
|
|
11125
|
+
attributes {
|
|
11126
|
+
items {
|
|
11127
|
+
attributeName
|
|
11128
|
+
attributeValueType
|
|
11129
|
+
isOptional
|
|
11130
|
+
attribute {
|
|
11131
|
+
metaData {
|
|
11132
|
+
key
|
|
11133
|
+
value
|
|
11134
|
+
}
|
|
11135
|
+
ckRecord {
|
|
11136
|
+
ckRecordId {
|
|
11137
|
+
fullName
|
|
11138
|
+
}
|
|
11139
|
+
}
|
|
11140
|
+
}
|
|
11141
|
+
}
|
|
11142
|
+
}
|
|
11143
|
+
}
|
|
11144
|
+
}
|
|
11145
|
+
}
|
|
11146
|
+
}
|
|
11147
|
+
`;
|
|
11148
|
+
class GetSecretSafeTypeAttributesDtoGQL extends i1$3.Query {
|
|
11149
|
+
document = GetSecretSafeTypeAttributesDocumentDto;
|
|
11150
|
+
constructor(apollo) {
|
|
11151
|
+
super(apollo);
|
|
11152
|
+
}
|
|
11153
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetSecretSafeTypeAttributesDtoGQL, deps: [{ token: i1$3.Apollo }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
11154
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetSecretSafeTypeAttributesDtoGQL, providedIn: 'root' });
|
|
11155
|
+
}
|
|
11156
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetSecretSafeTypeAttributesDtoGQL, decorators: [{
|
|
11157
|
+
type: Injectable,
|
|
11158
|
+
args: [{
|
|
11159
|
+
providedIn: 'root'
|
|
11160
|
+
}]
|
|
11161
|
+
}], ctorParameters: () => [{ type: i1$3.Apollo }] });
|
|
11162
|
+
|
|
11163
|
+
const GetCkAttributesDetailedDocumentDto = gql `
|
|
11164
|
+
query getCkAttributesDetailed($ckId: String!) {
|
|
11165
|
+
constructionKit {
|
|
11166
|
+
types(ckId: $ckId) {
|
|
11167
|
+
items {
|
|
11168
|
+
ckTypeId {
|
|
11169
|
+
fullName
|
|
11170
|
+
}
|
|
11171
|
+
attributes {
|
|
11172
|
+
items {
|
|
11173
|
+
attributeName
|
|
11174
|
+
attributeValueType
|
|
11175
|
+
isOptional
|
|
11176
|
+
autoCompleteValues
|
|
11177
|
+
ckAttributeId {
|
|
11178
|
+
fullName
|
|
11179
|
+
}
|
|
11180
|
+
attribute {
|
|
11181
|
+
ckRecord {
|
|
11182
|
+
ckRecordId {
|
|
11183
|
+
fullName
|
|
11184
|
+
}
|
|
11185
|
+
}
|
|
11186
|
+
ckEnum {
|
|
11187
|
+
ckEnumId {
|
|
11188
|
+
fullName
|
|
11189
|
+
}
|
|
11190
|
+
values {
|
|
11191
|
+
key
|
|
11192
|
+
name
|
|
11193
|
+
}
|
|
11194
|
+
}
|
|
11195
|
+
defaultValues
|
|
11196
|
+
metaData {
|
|
11197
|
+
key
|
|
11198
|
+
value
|
|
11199
|
+
}
|
|
11200
|
+
}
|
|
11201
|
+
}
|
|
11202
|
+
}
|
|
11203
|
+
}
|
|
11204
|
+
}
|
|
11205
|
+
}
|
|
11206
|
+
}
|
|
11207
|
+
`;
|
|
11208
|
+
class GetCkAttributesDetailedDtoGQL extends i1$3.Query {
|
|
11209
|
+
document = GetCkAttributesDetailedDocumentDto;
|
|
11210
|
+
constructor(apollo) {
|
|
11211
|
+
super(apollo);
|
|
11212
|
+
}
|
|
11213
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkAttributesDetailedDtoGQL, deps: [{ token: i1$3.Apollo }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
11214
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkAttributesDetailedDtoGQL, providedIn: 'root' });
|
|
11215
|
+
}
|
|
11216
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkAttributesDetailedDtoGQL, decorators: [{
|
|
11217
|
+
type: Injectable,
|
|
11218
|
+
args: [{
|
|
11219
|
+
providedIn: 'root'
|
|
11220
|
+
}]
|
|
11221
|
+
}], ctorParameters: () => [{ type: i1$3.Apollo }] });
|
|
11222
|
+
|
|
11223
|
+
const GetCkRecordDetailedDocumentDto = gql `
|
|
11224
|
+
query getCkRecordDetailed($ckId: String) {
|
|
11225
|
+
constructionKit {
|
|
11226
|
+
records(ckId: $ckId) {
|
|
11227
|
+
totalCount
|
|
11228
|
+
items {
|
|
11229
|
+
ckRecordId {
|
|
11230
|
+
fullName
|
|
11231
|
+
}
|
|
11232
|
+
isAbstract
|
|
11233
|
+
attributes {
|
|
11234
|
+
items {
|
|
11235
|
+
ckAttributeId {
|
|
11236
|
+
fullName
|
|
11237
|
+
}
|
|
11238
|
+
isOptional
|
|
11239
|
+
attributeName
|
|
11240
|
+
attributeValueType
|
|
11241
|
+
attribute {
|
|
11242
|
+
ckRecord {
|
|
11243
|
+
ckRecordId {
|
|
11244
|
+
fullName
|
|
11245
|
+
}
|
|
11246
|
+
}
|
|
11247
|
+
ckEnum {
|
|
11248
|
+
ckEnumId {
|
|
11249
|
+
fullName
|
|
11250
|
+
}
|
|
11251
|
+
values {
|
|
11252
|
+
key
|
|
11253
|
+
name
|
|
11254
|
+
}
|
|
11255
|
+
}
|
|
11256
|
+
defaultValues
|
|
11257
|
+
metaData {
|
|
11258
|
+
key
|
|
11259
|
+
value
|
|
11260
|
+
}
|
|
11261
|
+
}
|
|
11262
|
+
}
|
|
11263
|
+
}
|
|
11264
|
+
}
|
|
11265
|
+
}
|
|
11266
|
+
}
|
|
11267
|
+
}
|
|
11268
|
+
`;
|
|
11269
|
+
class GetCkRecordDetailedDtoGQL extends i1$3.Query {
|
|
11270
|
+
document = GetCkRecordDetailedDocumentDto;
|
|
11271
|
+
constructor(apollo) {
|
|
11272
|
+
super(apollo);
|
|
11273
|
+
}
|
|
11274
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkRecordDetailedDtoGQL, deps: [{ token: i1$3.Apollo }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
11275
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkRecordDetailedDtoGQL, providedIn: 'root' });
|
|
11276
|
+
}
|
|
11277
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkRecordDetailedDtoGQL, decorators: [{
|
|
11278
|
+
type: Injectable,
|
|
11279
|
+
args: [{
|
|
11280
|
+
providedIn: 'root'
|
|
11281
|
+
}]
|
|
11282
|
+
}], ctorParameters: () => [{ type: i1$3.Apollo }] });
|
|
11283
|
+
|
|
11284
|
+
/**
|
|
11285
|
+
* Resolves raw CK attribute definitions for a CK type or CK record by id.
|
|
11286
|
+
*
|
|
11287
|
+
* Extracted from AttributeDataService to break a potential circular dependency:
|
|
11288
|
+
* AttributeMapperService needs to look up nested record attribute definitions when mapping
|
|
11289
|
+
* RECORD / RECORD_ARRAY values to GraphQL, while AttributeDataService already depends on
|
|
11290
|
+
* AttributeMapperService for mapping raw definitions into form-ready Attribute shapes.
|
|
11291
|
+
*
|
|
11292
|
+
* This resolver is intentionally minimal: it fetches and returns raw CkAttributeMetadata[]
|
|
11293
|
+
* with no mapping. Callers that need form-ready Attribute objects should map them via
|
|
11294
|
+
* AttributeMapperService.mapToFormAttribute.
|
|
11295
|
+
*
|
|
11296
|
+
* Apollo's default cache-first fetchPolicy deduplicates repeated lookups for the same ckId,
|
|
11297
|
+
* so callers do not need to memoize externally.
|
|
11298
|
+
*/
|
|
11299
|
+
class AttributeMetadataResolverService {
|
|
11300
|
+
getCkAttributesDetailedGQL = inject(GetCkAttributesDetailedDtoGQL);
|
|
11301
|
+
getCkRecordDetailedGQL = inject(GetCkRecordDetailedDtoGQL);
|
|
11302
|
+
/**
|
|
11303
|
+
* Fetches raw attribute metadata for a CK type or CK record.
|
|
11304
|
+
* Returns an empty array when the id is missing or the request fails.
|
|
11305
|
+
*/
|
|
11306
|
+
getRawAttributes$(ckId, isRecord = false) {
|
|
11307
|
+
if (!ckId)
|
|
11308
|
+
return of([]);
|
|
11309
|
+
const stream$ = isRecord
|
|
11310
|
+
? this.fetchCkRecordAttributes(ckId)
|
|
11311
|
+
: this.fetchCkAttributes(ckId);
|
|
11312
|
+
return stream$.pipe(catchError$1((err) => {
|
|
11313
|
+
console.error('AttributeMetadataResolverService error:', err);
|
|
11314
|
+
return of([]);
|
|
11315
|
+
}));
|
|
11316
|
+
}
|
|
11317
|
+
fetchCkAttributes(ckTypeId) {
|
|
11318
|
+
return this.getCkAttributesDetailedGQL
|
|
11319
|
+
.fetch({ variables: { ckId: ckTypeId } })
|
|
11320
|
+
.pipe(map$1((res) => (res.data?.constructionKit?.types?.items?.[0]?.attributes?.items ??
|
|
11321
|
+
[]).filter((item) => item != null)));
|
|
11322
|
+
}
|
|
11323
|
+
fetchCkRecordAttributes(ckRecordId) {
|
|
11324
|
+
return this.getCkRecordDetailedGQL
|
|
11325
|
+
.fetch({ variables: { ckId: ckRecordId } })
|
|
11326
|
+
.pipe(map$1((res) => (res.data?.constructionKit?.records?.items?.[0]?.attributes
|
|
11327
|
+
?.items ?? []).filter((item) => item != null)));
|
|
11328
|
+
}
|
|
11329
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AttributeMetadataResolverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
11330
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AttributeMetadataResolverService, providedIn: 'root' });
|
|
11331
|
+
}
|
|
11332
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AttributeMetadataResolverService, decorators: [{
|
|
11333
|
+
type: Injectable,
|
|
11334
|
+
args: [{
|
|
11335
|
+
providedIn: 'root',
|
|
11336
|
+
}]
|
|
11337
|
+
}] });
|
|
11338
|
+
|
|
11339
|
+
/**
|
|
11340
|
+
* Attributes of a `System.Communication/DataPointMapping` entity that the runtime browser reads
|
|
11341
|
+
* (camelCase, as the `attributeNames` filter expects).
|
|
11342
|
+
*/
|
|
11343
|
+
const DATA_POINT_MAPPING_ATTRIBUTE_NAMES = [
|
|
11344
|
+
'name',
|
|
11345
|
+
'enabled',
|
|
11346
|
+
'sourceAttributePath',
|
|
11347
|
+
'targetAttributePath',
|
|
11348
|
+
'mappingExpression',
|
|
11349
|
+
];
|
|
11350
|
+
const RECORD_TYPES$1 = new Set(['RECORD', 'RECORD_ARRAY']);
|
|
11351
|
+
function isRecordType(valueType) {
|
|
11352
|
+
return RECORD_TYPES$1.has((valueType ?? '').toUpperCase());
|
|
11353
|
+
}
|
|
11354
|
+
function isSecret(meta) {
|
|
11355
|
+
return isSecretAttributeCandidate({
|
|
11356
|
+
attributeName: meta.attributeName,
|
|
11357
|
+
attributeValueType: meta.attributeValueType,
|
|
11358
|
+
metaData: meta.attribute?.metaData,
|
|
11359
|
+
});
|
|
11360
|
+
}
|
|
11361
|
+
function recordIdOf(meta) {
|
|
11362
|
+
return isRecordType(meta.attributeValueType) ? meta.attribute?.ckRecord?.ckRecordId?.fullName ?? null : null;
|
|
11363
|
+
}
|
|
11364
|
+
/**
|
|
11365
|
+
* Builds SECRET-safe `attributeNames` lists for the generic runtime documents (AB#5542).
|
|
11366
|
+
*
|
|
11367
|
+
* The generic `attributes` field returns every attribute — credentials included — unless it is
|
|
11368
|
+
* restricted. Screens that show "all attributes" of an arbitrary CK type (property grid, entity
|
|
11369
|
+
* detail, edit form, meshboard widgets) use {@link forCkType}: the CK type's attributes plus the
|
|
11370
|
+
* sub-attributes of its records (the server applies the same filter inside records), minus the
|
|
11371
|
+
* TYPE-AWARE secret candidates (`isSecretAttributeCandidate`: explicit `secret` metadata, or a
|
|
11372
|
+
* textual attribute with a credential-like name). Non-secret attributes are never dropped by name
|
|
11373
|
+
* (`isSecret: BOOLEAN`, a `credentials` RECORD stay in the list). Because one flat list filters
|
|
11374
|
+
* all nesting levels, a name that is a secret anywhere is excluded everywhere; editors must not
|
|
11375
|
+
* write back what was therefore not loaded ({@link SecretSafeAttributeAnalysis.blockedAttributes}).
|
|
11376
|
+
*
|
|
11377
|
+
* All reachable record definitions are loaded first and the "contains a secret / excluded name"
|
|
11378
|
+
* facts are computed over the whole record graph, so recursive record types are handled without
|
|
11379
|
+
* caching a premature "no secret" result for a record reached through a cycle.
|
|
11380
|
+
*
|
|
11381
|
+
* Failures of the type lookup yield an empty list (no attributes) — fail closed. Lookups go
|
|
11382
|
+
* through Apollo's cache, so repeated calls are cheap.
|
|
11383
|
+
*/
|
|
11384
|
+
class SecretSafeAttributeNamesService {
|
|
11385
|
+
resolver = inject(AttributeMetadataResolverService);
|
|
11386
|
+
typeAttributesGQL = inject(GetSecretSafeTypeAttributesDtoGQL);
|
|
11387
|
+
/**
|
|
11388
|
+
* camelCase names of all non-secret attributes (incl. record sub-attributes) of a runtime type.
|
|
11389
|
+
* @param rtCkTypeId the type in RtCkTypeId format (`Basic/TreeNode`, as in `RtEntity.ckTypeId`).
|
|
11390
|
+
* @param options.includeSecretState also list the SECRET-typed attributes (safe to read, see
|
|
11391
|
+
* {@link SecretSafeAttributeAnalysis.secretStateNames}) — the document must select `secretIsSet`.
|
|
11392
|
+
*/
|
|
11393
|
+
async forCkType(rtCkTypeId, options = {}) {
|
|
11394
|
+
const analysis = await this.analyse(rtCkTypeId);
|
|
11395
|
+
return options.includeSecretState
|
|
11396
|
+
? toUniqueCamelCaseNames([...analysis.attributeNames, ...analysis.secretStateNames])
|
|
11397
|
+
: analysis.attributeNames;
|
|
11398
|
+
}
|
|
11399
|
+
/**
|
|
11400
|
+
* Type-aware restriction of a requested name list (e.g. widget-configured fields): the requested
|
|
11401
|
+
* names (camelCased) that are non-secret attributes of the type. Names that are unknown to the
|
|
11402
|
+
* type or secret are dropped; a failed CK lookup yields `[]` (fail closed).
|
|
11403
|
+
*/
|
|
11404
|
+
async restrict(rtCkTypeId, requested) {
|
|
11405
|
+
const wanted = toUniqueCamelCaseNames(requested);
|
|
11406
|
+
if (wanted.length === 0)
|
|
11407
|
+
return [];
|
|
11408
|
+
const safe = new Set(await this.forCkType(rtCkTypeId));
|
|
11409
|
+
return wanted.filter((n) => safe.has(n));
|
|
11410
|
+
}
|
|
11411
|
+
/** Full analysis: safe names, secret names and the attributes an editor must not write back. */
|
|
11412
|
+
async analyse(rtCkTypeId) {
|
|
11413
|
+
if (!rtCkTypeId)
|
|
11414
|
+
return { attributeNames: [], secretNames: [], secretStateNames: [], blockedAttributes: [] };
|
|
11415
|
+
const topLevel = await this.loadType(rtCkTypeId);
|
|
11416
|
+
const records = await this.loadRecordGraph(topLevel);
|
|
11417
|
+
// 1. Names and secrets over the type and every reachable record.
|
|
11418
|
+
const names = [];
|
|
11419
|
+
const secrets = new Set();
|
|
11420
|
+
const secretValueTypeNames = new Set();
|
|
11421
|
+
const heuristicSecrets = new Set();
|
|
11422
|
+
for (const meta of [...topLevel, ...[...records.values()].flat()]) {
|
|
11423
|
+
if (!meta.attributeName)
|
|
11424
|
+
continue;
|
|
11425
|
+
const camel = toCamelCaseAttributeName(meta.attributeName);
|
|
11426
|
+
if (isSecret(meta)) {
|
|
11427
|
+
secrets.add(camel);
|
|
11428
|
+
(isSecretValueType(meta.attributeValueType) ? secretValueTypeNames : heuristicSecrets).add(camel);
|
|
11429
|
+
}
|
|
11430
|
+
else {
|
|
11431
|
+
names.push(meta.attributeName);
|
|
11432
|
+
}
|
|
11433
|
+
}
|
|
11434
|
+
const attributeNames = toUniqueCamelCaseNames(names).filter((n) => !secrets.has(n));
|
|
11435
|
+
const secretStateNames = [...secretValueTypeNames].filter((n) => !heuristicSecrets.has(n));
|
|
11436
|
+
// SECRET-typed sub-attributes count as loaded: the server carries an omitted record member over
|
|
11437
|
+
// from the stored element with the same record key (records with secrets always declare one),
|
|
11438
|
+
// and an echoed `{ isSet }` marker means "unchanged". Only heuristic secrets block a record.
|
|
11439
|
+
const loaded = new Set([...attributeNames, ...secretStateNames]);
|
|
11440
|
+
// 2. Per record type: is every (transitive) sub-attribute loaded? Fixpoint over the graph —
|
|
11441
|
+
// start optimistic, mark incomplete records, propagate until stable (cycle-safe).
|
|
11442
|
+
const incomplete = new Set();
|
|
11443
|
+
for (const [recordId, subs] of records) {
|
|
11444
|
+
// An unknown (failed / empty) record definition counts as incomplete — fail closed.
|
|
11445
|
+
if (subs.length === 0 || subs.some((m) => !m.attributeName || !loaded.has(toCamelCaseAttributeName(m.attributeName)))) {
|
|
11446
|
+
incomplete.add(recordId);
|
|
11447
|
+
}
|
|
11448
|
+
}
|
|
11449
|
+
let changed = true;
|
|
11450
|
+
while (changed) {
|
|
11451
|
+
changed = false;
|
|
11452
|
+
for (const [recordId, subs] of records) {
|
|
11453
|
+
if (incomplete.has(recordId))
|
|
11454
|
+
continue;
|
|
11455
|
+
if (subs.some((m) => { const id = recordIdOf(m); return !!id && incomplete.has(id); })) {
|
|
11456
|
+
incomplete.add(recordId);
|
|
11457
|
+
changed = true;
|
|
11458
|
+
}
|
|
11459
|
+
}
|
|
11460
|
+
}
|
|
11461
|
+
// 3. Top-level attributes an editor must not write back.
|
|
11462
|
+
const blocked = [];
|
|
11463
|
+
for (const meta of topLevel) {
|
|
11464
|
+
if (!meta.attributeName)
|
|
11465
|
+
continue;
|
|
11466
|
+
const name = toCamelCaseAttributeName(meta.attributeName);
|
|
11467
|
+
const recordId = recordIdOf(meta);
|
|
11468
|
+
const secret = isSecret(meta);
|
|
11469
|
+
if (secret && !recordId && !isRecordType(meta.attributeValueType))
|
|
11470
|
+
continue; // write-only scalar
|
|
11471
|
+
if (!loaded.has(name) || (recordId && incomplete.has(recordId))) {
|
|
11472
|
+
blocked.push(name);
|
|
11473
|
+
}
|
|
11474
|
+
}
|
|
11475
|
+
return {
|
|
11476
|
+
attributeNames,
|
|
11477
|
+
secretNames: [...secrets],
|
|
11478
|
+
secretStateNames,
|
|
11479
|
+
blockedAttributes: toUniqueCamelCaseNames(blocked),
|
|
11480
|
+
};
|
|
11481
|
+
}
|
|
11482
|
+
/** Loads every record definition reachable from the type's attributes (each once). */
|
|
11483
|
+
async loadRecordGraph(topLevel) {
|
|
11484
|
+
const records = new Map();
|
|
11485
|
+
let pending = topLevel.map(recordIdOf).filter((id) => !!id);
|
|
11486
|
+
while (pending.length > 0) {
|
|
11487
|
+
const batch = [...new Set(pending)].filter((id) => !records.has(id));
|
|
11488
|
+
pending = [];
|
|
11489
|
+
const loadedBatch = await Promise.all(batch.map((id) => this.loadRecord(id)));
|
|
11490
|
+
batch.forEach((id, i) => {
|
|
11491
|
+
records.set(id, loadedBatch[i]);
|
|
11492
|
+
for (const meta of loadedBatch[i]) {
|
|
11493
|
+
const sub = recordIdOf(meta);
|
|
11494
|
+
if (sub && !records.has(sub))
|
|
11495
|
+
pending.push(sub);
|
|
11496
|
+
}
|
|
11497
|
+
});
|
|
11498
|
+
}
|
|
11499
|
+
return records;
|
|
11500
|
+
}
|
|
11501
|
+
loadType(rtCkTypeId) {
|
|
11502
|
+
return firstValueFrom(this.typeAttributesGQL.fetch({ variables: { rtCkTypeId } }).pipe(map$1((res) => (res.data?.constructionKit?.types?.items?.[0]?.attributes?.items ?? [])
|
|
11503
|
+
.filter((item) => item != null)), catchError$1((err) => {
|
|
11504
|
+
console.error('SecretSafeAttributeNamesService: CK lookup failed', err);
|
|
11505
|
+
return of([]);
|
|
11506
|
+
})));
|
|
11507
|
+
}
|
|
11508
|
+
/** Record sub-attributes by CkRecordId full name (cached by Apollo, errors yield []). */
|
|
11509
|
+
loadRecord(ckRecordId) {
|
|
11510
|
+
return firstValueFrom(this.resolver.getRawAttributes$(ckRecordId, true));
|
|
11511
|
+
}
|
|
11512
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: SecretSafeAttributeNamesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
11513
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: SecretSafeAttributeNamesService, providedIn: 'root' });
|
|
11514
|
+
}
|
|
11515
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: SecretSafeAttributeNamesService, decorators: [{
|
|
11516
|
+
type: Injectable,
|
|
11517
|
+
args: [{ providedIn: 'root' }]
|
|
11518
|
+
}] });
|
|
11519
|
+
|
|
10863
11520
|
class EntityDetailDataSource {
|
|
10864
11521
|
getRuntimeEntityByIdGQL = inject(GetRuntimeEntityByIdDtoGQL);
|
|
11522
|
+
secretSafeNames = inject(SecretSafeAttributeNamesService);
|
|
10865
11523
|
/**
|
|
10866
|
-
* Fetches detailed entity information including attributes and associations
|
|
11524
|
+
* Fetches detailed entity information including attributes and associations.
|
|
11525
|
+
* Attributes are restricted to the type's non-secret attributes (SECRET-safe, AB#5542):
|
|
11526
|
+
* credential-like attributes are never sent to the browser. SECRET-typed attributes (AB#5528)
|
|
11527
|
+
* are read for their state only (`value` null, `secretIsSet`) so the property grid shows a badge.
|
|
10867
11528
|
*/
|
|
10868
11529
|
async fetchEntityDetails(rtId, ckTypeId) {
|
|
10869
11530
|
try {
|
|
11531
|
+
const attributeNames = await this.secretSafeNames.forCkType(ckTypeId, { includeSecretState: true });
|
|
10870
11532
|
const result = await firstValueFrom(this.getRuntimeEntityByIdGQL
|
|
10871
11533
|
.fetch({
|
|
10872
11534
|
variables: {
|
|
10873
11535
|
rtId,
|
|
10874
11536
|
ckTypeId,
|
|
11537
|
+
attributeNames,
|
|
10875
11538
|
},
|
|
10876
11539
|
})
|
|
10877
11540
|
.pipe(map((response) => response.data?.runtime?.runtimeEntities?.items?.[0])));
|
|
@@ -11104,7 +11767,7 @@ class EntityDetailComponent {
|
|
|
11104
11767
|
async loadMappingDetails(rtId, ckTypeId) {
|
|
11105
11768
|
try {
|
|
11106
11769
|
const entityResult = await firstValueFrom(this.getEntityByIdGQL.fetch({
|
|
11107
|
-
variables: { rtId, ckTypeId },
|
|
11770
|
+
variables: { rtId, ckTypeId, attributeNames: [...DATA_POINT_MAPPING_ATTRIBUTE_NAMES] },
|
|
11108
11771
|
}));
|
|
11109
11772
|
const mappingEntity = entityResult.data?.runtime?.runtimeEntities?.items?.[0];
|
|
11110
11773
|
if (!mappingEntity)
|
|
@@ -11359,7 +12022,7 @@ class EntityDetailComponent {
|
|
|
11359
12022
|
>
|
|
11360
12023
|
</mm-entity-detail-view>
|
|
11361
12024
|
</div>
|
|
11362
|
-
`, isInline: true, styles: [":host{display:block;height:100%;width:100%}.entity-detail{height:100%;display:flex;flex-direction:column;padding:24px;box-sizing:border-box;overflow-y:auto}.entity-detail .entity-detail-header{display:flex;align-items:center;gap:20px;margin-bottom:24px;padding:20px 24px;background:
|
|
12025
|
+
`, isInline: true, styles: [":host{display:block;height:100%;width:100%}.entity-detail{height:100%;display:flex;flex-direction:column;padding:24px;box-sizing:border-box;overflow-y:auto}.entity-detail .entity-detail-header{display:flex;align-items:center;gap:20px;margin-bottom:24px;padding:20px 24px;background:var(--theme-bg-elevated);border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-md, 6px);position:relative;box-shadow:0 4px 20px #0006}.entity-detail .entity-detail-header:before{content:\"\";position:absolute;top:0;left:0;width:4px;height:100%;background:transparent;box-shadow:none;border-radius:4px 0 0 4px}.entity-detail .entity-detail-header .header-info{flex:1}.entity-detail .entity-detail-header .header-info .entity-title h2{margin:0 0 8px;font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-size:1.4rem;font-weight:600;color:var(--octo-text-color)}.entity-detail .entity-detail-header .header-info .entity-type{margin:0;font-family:Roboto Mono,monospace;font-size:.8rem;background:var(--deep-sea-60);padding:6px 12px;border-radius:4px;border:1px solid var(--neo-cyan-30);display:inline-block;color:var(--neo-cyan)}.entity-detail mm-entity-detail-view{flex:1;display:flex;flex-direction:column;overflow-y:auto}@media(max-width:768px){.entity-detail{padding:16px}.entity-detail .entity-detail-header{flex-direction:column;align-items:flex-start;gap:12px;padding:16px 20px}.entity-detail .entity-detail-header .header-info .entity-title h2{font-size:1.1rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: SVGIconModule }, { kind: "component", type: EntityDetailViewComponent, selector: "mm-entity-detail-view", inputs: ["entity", "loading", "error", "showHeader", "messages", "showDataMapping", "dataMappings", "expressionValidator"], outputs: ["retry", "propertyChange", "navigateToEntity", "addMappingRequested", "removeMappingRequested", "selectMappingTarget", "selectSourceAttributeRequested", "selectTargetAttributeRequested", "mappingChanged", "saveAllMappingsRequested"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
11363
12026
|
}
|
|
11364
12027
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: EntityDetailComponent, decorators: [{
|
|
11365
12028
|
type: Component,
|
|
@@ -11410,7 +12073,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
11410
12073
|
>
|
|
11411
12074
|
</mm-entity-detail-view>
|
|
11412
12075
|
</div>
|
|
11413
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block;height:100%;width:100%}.entity-detail{height:100%;display:flex;flex-direction:column;padding:24px;box-sizing:border-box;overflow-y:auto}.entity-detail .entity-detail-header{display:flex;align-items:center;gap:20px;margin-bottom:24px;padding:20px 24px;background:
|
|
12076
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block;height:100%;width:100%}.entity-detail{height:100%;display:flex;flex-direction:column;padding:24px;box-sizing:border-box;overflow-y:auto}.entity-detail .entity-detail-header{display:flex;align-items:center;gap:20px;margin-bottom:24px;padding:20px 24px;background:var(--theme-bg-elevated);border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-md, 6px);position:relative;box-shadow:0 4px 20px #0006}.entity-detail .entity-detail-header:before{content:\"\";position:absolute;top:0;left:0;width:4px;height:100%;background:transparent;box-shadow:none;border-radius:4px 0 0 4px}.entity-detail .entity-detail-header .header-info{flex:1}.entity-detail .entity-detail-header .header-info .entity-title h2{margin:0 0 8px;font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-size:1.4rem;font-weight:600;color:var(--octo-text-color)}.entity-detail .entity-detail-header .header-info .entity-type{margin:0;font-family:Roboto Mono,monospace;font-size:.8rem;background:var(--deep-sea-60);padding:6px 12px;border-radius:4px;border:1px solid var(--neo-cyan-30);display:inline-block;color:var(--neo-cyan)}.entity-detail mm-entity-detail-view{flex:1;display:flex;flex-direction:column;overflow-y:auto}@media(max-width:768px){.entity-detail{padding:16px}.entity-detail .entity-detail-header{flex-direction:column;align-items:flex-start;gap:12px;padding:16px 20px}.entity-detail .entity-detail-header .header-info .entity-title h2{font-size:1.1rem}}\n"] }]
|
|
11414
12077
|
}], propDecorators: { messages: [{
|
|
11415
12078
|
type: Input
|
|
11416
12079
|
}] } });
|
|
@@ -11774,174 +12437,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
11774
12437
|
args: [{ providedIn: 'root' }]
|
|
11775
12438
|
}] });
|
|
11776
12439
|
|
|
11777
|
-
const GetCkAttributesDetailedDocumentDto = gql `
|
|
11778
|
-
query getCkAttributesDetailed($ckId: String!) {
|
|
11779
|
-
constructionKit {
|
|
11780
|
-
types(ckId: $ckId) {
|
|
11781
|
-
items {
|
|
11782
|
-
ckTypeId {
|
|
11783
|
-
fullName
|
|
11784
|
-
}
|
|
11785
|
-
attributes {
|
|
11786
|
-
items {
|
|
11787
|
-
attributeName
|
|
11788
|
-
attributeValueType
|
|
11789
|
-
isOptional
|
|
11790
|
-
autoCompleteValues
|
|
11791
|
-
ckAttributeId {
|
|
11792
|
-
fullName
|
|
11793
|
-
}
|
|
11794
|
-
attribute {
|
|
11795
|
-
ckRecord {
|
|
11796
|
-
ckRecordId {
|
|
11797
|
-
fullName
|
|
11798
|
-
}
|
|
11799
|
-
}
|
|
11800
|
-
ckEnum {
|
|
11801
|
-
ckEnumId {
|
|
11802
|
-
fullName
|
|
11803
|
-
}
|
|
11804
|
-
values {
|
|
11805
|
-
key
|
|
11806
|
-
name
|
|
11807
|
-
}
|
|
11808
|
-
}
|
|
11809
|
-
defaultValues
|
|
11810
|
-
}
|
|
11811
|
-
}
|
|
11812
|
-
}
|
|
11813
|
-
}
|
|
11814
|
-
}
|
|
11815
|
-
}
|
|
11816
|
-
}
|
|
11817
|
-
`;
|
|
11818
|
-
class GetCkAttributesDetailedDtoGQL extends i1$3.Query {
|
|
11819
|
-
document = GetCkAttributesDetailedDocumentDto;
|
|
11820
|
-
constructor(apollo) {
|
|
11821
|
-
super(apollo);
|
|
11822
|
-
}
|
|
11823
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkAttributesDetailedDtoGQL, deps: [{ token: i1$3.Apollo }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
11824
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkAttributesDetailedDtoGQL, providedIn: 'root' });
|
|
11825
|
-
}
|
|
11826
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkAttributesDetailedDtoGQL, decorators: [{
|
|
11827
|
-
type: Injectable,
|
|
11828
|
-
args: [{
|
|
11829
|
-
providedIn: 'root'
|
|
11830
|
-
}]
|
|
11831
|
-
}], ctorParameters: () => [{ type: i1$3.Apollo }] });
|
|
11832
|
-
|
|
11833
|
-
const GetCkRecordDetailedDocumentDto = gql `
|
|
11834
|
-
query getCkRecordDetailed($ckId: String) {
|
|
11835
|
-
constructionKit {
|
|
11836
|
-
records(ckId: $ckId) {
|
|
11837
|
-
totalCount
|
|
11838
|
-
items {
|
|
11839
|
-
ckRecordId {
|
|
11840
|
-
fullName
|
|
11841
|
-
}
|
|
11842
|
-
isAbstract
|
|
11843
|
-
attributes {
|
|
11844
|
-
items {
|
|
11845
|
-
ckAttributeId {
|
|
11846
|
-
fullName
|
|
11847
|
-
}
|
|
11848
|
-
isOptional
|
|
11849
|
-
attributeName
|
|
11850
|
-
attributeValueType
|
|
11851
|
-
attribute {
|
|
11852
|
-
ckRecord {
|
|
11853
|
-
ckRecordId {
|
|
11854
|
-
fullName
|
|
11855
|
-
}
|
|
11856
|
-
}
|
|
11857
|
-
ckEnum {
|
|
11858
|
-
ckEnumId {
|
|
11859
|
-
fullName
|
|
11860
|
-
}
|
|
11861
|
-
values {
|
|
11862
|
-
key
|
|
11863
|
-
name
|
|
11864
|
-
}
|
|
11865
|
-
}
|
|
11866
|
-
defaultValues
|
|
11867
|
-
}
|
|
11868
|
-
}
|
|
11869
|
-
}
|
|
11870
|
-
}
|
|
11871
|
-
}
|
|
11872
|
-
}
|
|
11873
|
-
}
|
|
11874
|
-
`;
|
|
11875
|
-
class GetCkRecordDetailedDtoGQL extends i1$3.Query {
|
|
11876
|
-
document = GetCkRecordDetailedDocumentDto;
|
|
11877
|
-
constructor(apollo) {
|
|
11878
|
-
super(apollo);
|
|
11879
|
-
}
|
|
11880
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkRecordDetailedDtoGQL, deps: [{ token: i1$3.Apollo }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
11881
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkRecordDetailedDtoGQL, providedIn: 'root' });
|
|
11882
|
-
}
|
|
11883
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: GetCkRecordDetailedDtoGQL, decorators: [{
|
|
11884
|
-
type: Injectable,
|
|
11885
|
-
args: [{
|
|
11886
|
-
providedIn: 'root'
|
|
11887
|
-
}]
|
|
11888
|
-
}], ctorParameters: () => [{ type: i1$3.Apollo }] });
|
|
11889
|
-
|
|
11890
|
-
/**
|
|
11891
|
-
* Resolves raw CK attribute definitions for a CK type or CK record by id.
|
|
11892
|
-
*
|
|
11893
|
-
* Extracted from AttributeDataService to break a potential circular dependency:
|
|
11894
|
-
* AttributeMapperService needs to look up nested record attribute definitions when mapping
|
|
11895
|
-
* RECORD / RECORD_ARRAY values to GraphQL, while AttributeDataService already depends on
|
|
11896
|
-
* AttributeMapperService for mapping raw definitions into form-ready Attribute shapes.
|
|
11897
|
-
*
|
|
11898
|
-
* This resolver is intentionally minimal: it fetches and returns raw CkAttributeMetadata[]
|
|
11899
|
-
* with no mapping. Callers that need form-ready Attribute objects should map them via
|
|
11900
|
-
* AttributeMapperService.mapToFormAttribute.
|
|
11901
|
-
*
|
|
11902
|
-
* Apollo's default cache-first fetchPolicy deduplicates repeated lookups for the same ckId,
|
|
11903
|
-
* so callers do not need to memoize externally.
|
|
11904
|
-
*/
|
|
11905
|
-
class AttributeMetadataResolverService {
|
|
11906
|
-
getCkAttributesDetailedGQL = inject(GetCkAttributesDetailedDtoGQL);
|
|
11907
|
-
getCkRecordDetailedGQL = inject(GetCkRecordDetailedDtoGQL);
|
|
11908
|
-
/**
|
|
11909
|
-
* Fetches raw attribute metadata for a CK type or CK record.
|
|
11910
|
-
* Returns an empty array when the id is missing or the request fails.
|
|
11911
|
-
*/
|
|
11912
|
-
getRawAttributes$(ckId, isRecord = false) {
|
|
11913
|
-
if (!ckId)
|
|
11914
|
-
return of([]);
|
|
11915
|
-
const stream$ = isRecord
|
|
11916
|
-
? this.fetchCkRecordAttributes(ckId)
|
|
11917
|
-
: this.fetchCkAttributes(ckId);
|
|
11918
|
-
return stream$.pipe(catchError$1((err) => {
|
|
11919
|
-
console.error('AttributeMetadataResolverService error:', err);
|
|
11920
|
-
return of([]);
|
|
11921
|
-
}));
|
|
11922
|
-
}
|
|
11923
|
-
fetchCkAttributes(ckTypeId) {
|
|
11924
|
-
return this.getCkAttributesDetailedGQL
|
|
11925
|
-
.fetch({ variables: { ckId: ckTypeId } })
|
|
11926
|
-
.pipe(map$1((res) => (res.data?.constructionKit?.types?.items?.[0]?.attributes?.items ??
|
|
11927
|
-
[]).filter((item) => item != null)));
|
|
11928
|
-
}
|
|
11929
|
-
fetchCkRecordAttributes(ckRecordId) {
|
|
11930
|
-
return this.getCkRecordDetailedGQL
|
|
11931
|
-
.fetch({ variables: { ckId: ckRecordId } })
|
|
11932
|
-
.pipe(map$1((res) => (res.data?.constructionKit?.records?.items?.[0]?.attributes
|
|
11933
|
-
?.items ?? []).filter((item) => item != null)));
|
|
11934
|
-
}
|
|
11935
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AttributeMetadataResolverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
11936
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AttributeMetadataResolverService, providedIn: 'root' });
|
|
11937
|
-
}
|
|
11938
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AttributeMetadataResolverService, decorators: [{
|
|
11939
|
-
type: Injectable,
|
|
11940
|
-
args: [{
|
|
11941
|
-
providedIn: 'root',
|
|
11942
|
-
}]
|
|
11943
|
-
}] });
|
|
11944
|
-
|
|
11945
12440
|
class AttributeRecognitionService {
|
|
11946
12441
|
isString(attributeValueType) {
|
|
11947
12442
|
return attributeValueType === 'STRING';
|
|
@@ -12094,6 +12589,9 @@ class AttributeMapperService {
|
|
|
12094
12589
|
enumOptions: this.getEnumOptions(attr),
|
|
12095
12590
|
value: parsedValue,
|
|
12096
12591
|
};
|
|
12592
|
+
if (isSecretAttributeCandidate({ attributeName, attributeValueType: type, metaData: attr?.attribute?.metaData })) {
|
|
12593
|
+
attribute.secret = true;
|
|
12594
|
+
}
|
|
12097
12595
|
return attribute;
|
|
12098
12596
|
}
|
|
12099
12597
|
/**
|
|
@@ -12148,6 +12646,11 @@ class AttributeMapperService {
|
|
|
12148
12646
|
if (type === 'BINARY_LINKED') {
|
|
12149
12647
|
return this.mapBinaryLinkedAttribute(key, value, metadata);
|
|
12150
12648
|
}
|
|
12649
|
+
// Secrets are write-only (AB#5542): their stored value is never read, so an empty value means
|
|
12650
|
+
// "keep" — omit it instead of sending null/'' that would clear the stored credential.
|
|
12651
|
+
if (metadata?.secret && (value === null || value === undefined || value === '')) {
|
|
12652
|
+
return null;
|
|
12653
|
+
}
|
|
12151
12654
|
if (value === null || value === undefined) {
|
|
12152
12655
|
return metadata?.isOptional ? { attributeName: key, value: null } : null;
|
|
12153
12656
|
}
|
|
@@ -12850,6 +13353,7 @@ class AttributeDataService {
|
|
|
12850
13353
|
mapper = inject(AttributeMapperService);
|
|
12851
13354
|
resolver = inject(AttributeMetadataResolverService);
|
|
12852
13355
|
getRtEntityAttributesGQL = inject(GetRuntimeEntityByIdDtoGQL);
|
|
13356
|
+
secretSafeNames = inject(SecretSafeAttributeNamesService);
|
|
12853
13357
|
/** Observable of attribute list for a CK type or record. Sorted: required first, optional last. */
|
|
12854
13358
|
getAttributesDefinition$(ckTypeId, isRecord = false) {
|
|
12855
13359
|
if (!ckTypeId)
|
|
@@ -12872,11 +13376,13 @@ class AttributeDataService {
|
|
|
12872
13376
|
return a.isOptional ? 1 : -1;
|
|
12873
13377
|
});
|
|
12874
13378
|
}
|
|
12875
|
-
/**
|
|
13379
|
+
/**
|
|
13380
|
+
* Fetches runtime entity attribute items by rtId and ckTypeId; returns empty array when absent.
|
|
13381
|
+
* Only the type's non-secret attributes are read (SECRET-safe, AB#5542) — secrets stay
|
|
13382
|
+
* write-only in the edit form.
|
|
13383
|
+
*/
|
|
12876
13384
|
fetchRtEntityAttributes(rtId, ckTypeId) {
|
|
12877
|
-
return this.getRtEntityAttributesGQL
|
|
12878
|
-
.fetch({ variables: { rtId: rtId, ckTypeId: ckTypeId } })
|
|
12879
|
-
.pipe(map$1((res) => {
|
|
13385
|
+
return from(this.secretSafeNames.forCkType(ckTypeId)).pipe(switchMap$1((attributeNames) => this.getRtEntityAttributesGQL.fetch({ variables: { rtId, ckTypeId, attributeNames } })), map$1((res) => {
|
|
12880
13386
|
const items = res.data?.runtime?.runtimeEntities?.items?.[0]?.attributes?.items ??
|
|
12881
13387
|
[];
|
|
12882
13388
|
return items
|
|
@@ -12966,6 +13472,8 @@ class AttributeFieldComponent {
|
|
|
12966
13472
|
(click)="handleUndo()"
|
|
12967
13473
|
type="button"
|
|
12968
13474
|
class="undo-button"
|
|
13475
|
+
title="Undo change"
|
|
13476
|
+
aria-label="Undo change"
|
|
12969
13477
|
></button>
|
|
12970
13478
|
}
|
|
12971
13479
|
</div>
|
|
@@ -13005,6 +13513,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
13005
13513
|
(click)="handleUndo()"
|
|
13006
13514
|
type="button"
|
|
13007
13515
|
class="undo-button"
|
|
13516
|
+
title="Undo change"
|
|
13517
|
+
aria-label="Undo change"
|
|
13008
13518
|
></button>
|
|
13009
13519
|
}
|
|
13010
13520
|
</div>
|
|
@@ -13048,6 +13558,12 @@ class AttributesGroupComponent {
|
|
|
13048
13558
|
...(ngDevMode ? [{ debugName: "isRecord" }] : /* istanbul ignore next */ []));
|
|
13049
13559
|
initialValues = input(/* @ts-ignore */
|
|
13050
13560
|
...(ngDevMode ? [undefined, { debugName: "initialValues" }] : /* istanbul ignore next */ []));
|
|
13561
|
+
/**
|
|
13562
|
+
* Edit mode for secrets (AB#5542): secret attributes start empty (their value is never read),
|
|
13563
|
+
* are not required, and an empty value keeps the stored credential.
|
|
13564
|
+
*/
|
|
13565
|
+
secretsWriteOnly = input(false, /* @ts-ignore */
|
|
13566
|
+
...(ngDevMode ? [{ debugName: "secretsWriteOnly" }] : /* istanbul ignore next */ []));
|
|
13051
13567
|
_messages = { ...DEFAULT_RUNTIME_BROWSER_MESSAGES };
|
|
13052
13568
|
set messages(value) {
|
|
13053
13569
|
this._messages = { ...DEFAULT_RUNTIME_BROWSER_MESSAGES, ...(value ?? {}) };
|
|
@@ -13096,9 +13612,12 @@ class AttributesGroupComponent {
|
|
|
13096
13612
|
const rawValue = rawInitial.find((val) => val.attributeName === attrMetadata.attributeName)?.value;
|
|
13097
13613
|
// Use parsed initial when entity data exists; otherwise use attribute.value from resource (already has Default or Empty from mapper)
|
|
13098
13614
|
const hasInitialFromEntity = rawValue !== undefined && rawValue !== null;
|
|
13099
|
-
const
|
|
13100
|
-
|
|
13101
|
-
|
|
13615
|
+
const writeOnlySecret = !!attrMetadata.secret && this.secretsWriteOnly();
|
|
13616
|
+
const finalValue = writeOnlySecret
|
|
13617
|
+
? null
|
|
13618
|
+
: hasInitialFromEntity
|
|
13619
|
+
? this.mapper.getFormValueFromRawInitial(attrMetadata, rawValue)
|
|
13620
|
+
: attrMetadata.value;
|
|
13102
13621
|
if (!form.contains(attrMetadata.attributeName)) {
|
|
13103
13622
|
this.initializeControl(form, attrMetadata, finalValue);
|
|
13104
13623
|
}
|
|
@@ -13159,8 +13678,9 @@ class AttributesGroupComponent {
|
|
|
13159
13678
|
return;
|
|
13160
13679
|
}
|
|
13161
13680
|
else {
|
|
13162
|
-
// Plain text/numeric/etc. field
|
|
13163
|
-
|
|
13681
|
+
// Plain text/numeric/etc. field. A write-only secret may stay empty (= keep, AB#5542).
|
|
13682
|
+
const required = !attr.isOptional && !(attr.secret && this.secretsWriteOnly());
|
|
13683
|
+
control = new FormControl(initialValue, required ? [Validators.required] : []);
|
|
13164
13684
|
}
|
|
13165
13685
|
form.addControl(attr.attributeName, control);
|
|
13166
13686
|
this.setBaselineForAttr(attr, initialValue);
|
|
@@ -13344,7 +13864,7 @@ class AttributesGroupComponent {
|
|
|
13344
13864
|
return EMPTY_INITIAL_VALUES;
|
|
13345
13865
|
}
|
|
13346
13866
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AttributesGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13347
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: AttributesGroupComponent, isStandalone: true, selector: "mm-attributes-group", inputs: { ckId: { classPropertyName: "ckId", publicName: "ckId", isSignal: true, isRequired: true, transformFunction: null }, parentFormGroup: { classPropertyName: "parentFormGroup", publicName: "parentFormGroup", isSignal: true, isRequired: true, transformFunction: null }, isRecord: { classPropertyName: "isRecord", publicName: "isRecord", isSignal: true, isRequired: false, transformFunction: null }, initialValues: { classPropertyName: "initialValues", publicName: "initialValues", isSignal: true, isRequired: false, transformFunction: null }, messages: { classPropertyName: "messages", publicName: "messages", isSignal: false, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
13867
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: AttributesGroupComponent, isStandalone: true, selector: "mm-attributes-group", inputs: { ckId: { classPropertyName: "ckId", publicName: "ckId", isSignal: true, isRequired: true, transformFunction: null }, parentFormGroup: { classPropertyName: "parentFormGroup", publicName: "parentFormGroup", isSignal: true, isRequired: true, transformFunction: null }, isRecord: { classPropertyName: "isRecord", publicName: "isRecord", isSignal: true, isRequired: false, transformFunction: null }, initialValues: { classPropertyName: "initialValues", publicName: "initialValues", isSignal: true, isRequired: false, transformFunction: null }, secretsWriteOnly: { classPropertyName: "secretsWriteOnly", publicName: "secretsWriteOnly", isSignal: true, isRequired: false, transformFunction: null }, messages: { classPropertyName: "messages", publicName: "messages", isSignal: false, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
13348
13868
|
<div class="attributes-form-container" [formGroup]="parentFormGroup()">
|
|
13349
13869
|
<kendo-card [style.margin-bottom.px]="10">
|
|
13350
13870
|
<kendo-card-header>
|
|
@@ -13400,6 +13920,7 @@ class AttributesGroupComponent {
|
|
|
13400
13920
|
[isRecord]="true"
|
|
13401
13921
|
[parentFormGroup]="asFormGroup(item)"
|
|
13402
13922
|
[initialValues]="getRawInitialValue(attr.attributeName, $index)"
|
|
13923
|
+
[secretsWriteOnly]="secretsWriteOnly()"
|
|
13403
13924
|
[messages]="_messages"
|
|
13404
13925
|
/>
|
|
13405
13926
|
</div>
|
|
@@ -13456,6 +13977,7 @@ class AttributesGroupComponent {
|
|
|
13456
13977
|
asFormGroup(parentFormGroup().get(attr.attributeName)!)
|
|
13457
13978
|
"
|
|
13458
13979
|
[initialValues]="getRawInitialValue(attr.attributeName)"
|
|
13980
|
+
[secretsWriteOnly]="secretsWriteOnly()"
|
|
13459
13981
|
[messages]="_messages"
|
|
13460
13982
|
/>
|
|
13461
13983
|
</div>
|
|
@@ -13552,6 +14074,7 @@ class AttributesGroupComponent {
|
|
|
13552
14074
|
[control]="parentFormGroup().get(attr.attributeName)!"
|
|
13553
14075
|
[baselineValue]="getBaselineValue(attr.attributeName)"
|
|
13554
14076
|
[fieldId]="attr.attributeName"
|
|
14077
|
+
[hintText]="attr.secret && secretsWriteOnly() ? (_messages.secretWriteOnlyHint ?? '') : ''"
|
|
13555
14078
|
[errorMessage]="_messages.attributeField?.errorMessage ?? 'This field is required or invalid.'"
|
|
13556
14079
|
>
|
|
13557
14080
|
@if (recognition.isNumber(attr.attributeValueType)) {
|
|
@@ -13634,6 +14157,13 @@ class AttributesGroupComponent {
|
|
|
13634
14157
|
valueField="key"
|
|
13635
14158
|
[valuePrimitive]="true"
|
|
13636
14159
|
/>
|
|
14160
|
+
} @else if (attr.secret) {
|
|
14161
|
+
<kendo-textbox
|
|
14162
|
+
type="password"
|
|
14163
|
+
autocomplete="new-password"
|
|
14164
|
+
[focusableId]="attr.attributeName"
|
|
14165
|
+
[formControlName]="attr.attributeName"
|
|
14166
|
+
/>
|
|
13637
14167
|
} @else {
|
|
13638
14168
|
<kendo-textbox
|
|
13639
14169
|
[focusableId]="attr.attributeName"
|
|
@@ -13646,7 +14176,7 @@ class AttributesGroupComponent {
|
|
|
13646
14176
|
</kendo-card-body>
|
|
13647
14177
|
</kendo-card>
|
|
13648
14178
|
</div>
|
|
13649
|
-
`, isInline: true, styles: [".attributes-form-container ::ng-deep kendo-card kendo-card-body{display:flex;flex-direction:column;gap:16px}.attributes-form-container ::ng-deep kendo-label{display:flex;flex-direction:column;gap:4px}.
|
|
14179
|
+
`, isInline: true, styles: [".attributes-form-container ::ng-deep kendo-card kendo-card-body{display:flex;flex-direction:column;gap:16px}.attributes-form-container ::ng-deep kendo-label{display:flex;flex-direction:column;gap:4px}.header-content{display:flex;flex-direction:column;gap:4px}.record-array-content,.tab-content-wrapper{display:flex;flex-direction:column;gap:16px}.record-actions-info{display:flex;flex-direction:column;gap:12px;padding:16px;background-color:var(--kendo-color-surface-alt, rgba(0, 0, 0, .05));border:1px solid var(--kendo-color-border, rgba(0, 0, 0, .1));border-radius:4px;margin-bottom:16px}.record-actions-description{margin:0;font-size:13px;color:var(--kendo-color-subtle, rgba(0, 0, 0, .6));line-height:1.5}.record-array-actions{display:flex;gap:8px;justify-content:flex-start;padding-top:0}.record-actions{margin-top:16px;display:flex;gap:8px;justify-content:flex-start;padding-top:0}.binary-linked-wrap{display:flex;flex-direction:column;gap:6px}.binary-linked-reference-hint{font-size:.75rem;color:var(--kendo-color-primary, #0f6dff);font-style:italic}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => AttributesGroupComponent), selector: "mm-attributes-group", inputs: ["ckId", "parentFormGroup", "isRecord", "initialValues", "secretsWriteOnly", "messages"] }, { kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "ngmodule", type: i0.forwardRef(() => ReactiveFormsModule) }, { kind: "directive", type: i0.forwardRef(() => i1.NgControlStatus), selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i0.forwardRef(() => i1.NgControlStatusGroup), selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i0.forwardRef(() => i1.FormGroupDirective), selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i0.forwardRef(() => i1.FormControlName), selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i0.forwardRef(() => i1.FormGroupName), selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: i0.forwardRef(() => i1$4.CardComponent), selector: "kendo-card", inputs: ["orientation", "width"] }, { kind: "component", type: i0.forwardRef(() => i1$4.CardBodyComponent), selector: "kendo-card-body" }, { kind: "component", type: i0.forwardRef(() => i1$4.CardHeaderComponent), selector: "kendo-card-header" }, { kind: "component", type: i0.forwardRef(() => i1$4.ExpansionPanelComponent), selector: "kendo-expansionpanel", inputs: ["title", "subtitle", "disabled", "expanded", "svgExpandIcon", "svgCollapseIcon", "expandIcon", "collapseIcon", "animation"], outputs: ["expandedChange", "action", "expand", "collapse"], exportAs: ["kendoExpansionPanel"] }, { kind: "directive", type: i0.forwardRef(() => i1$4.ExpansionPanelTitleDirective), selector: "[kendoExpansionPanelTitleDirective]" }, { kind: "component", type: i0.forwardRef(() => i1$4.TabStripComponent), selector: "kendo-tabstrip", inputs: ["height", "animate", "tabAlignment", "tabPosition", "keepTabContent", "closable", "scrollable", "size", "closeIcon", "closeIconClass", "closeSVGIcon", "showContentArea"], outputs: ["tabSelect", "tabClose", "tabScroll"], exportAs: ["kendoTabStrip"] }, { kind: "component", type: i0.forwardRef(() => i1$4.TabStripTabComponent), selector: "kendo-tabstrip-tab", inputs: ["title", "disabled", "cssClass", "cssStyle", "selected", "closable", "closeIcon", "closeIconClass", "closeSVGIcon"], exportAs: ["kendoTabStripTab"] }, { kind: "directive", type: i0.forwardRef(() => i1$4.TabContentDirective), selector: "[kendoTabContent]" }, { kind: "component", type: i0.forwardRef(() => i5.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: i0.forwardRef(() => i5.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: "component", type: i0.forwardRef(() => i5.SwitchComponent), selector: "kendo-switch", inputs: ["focusableId", "onLabel", "offLabel", "checked", "disabled", "readonly", "tabindex", "size", "thumbRounded", "trackRounded", "tabIndex"], outputs: ["focus", "blur", "valueChange"], exportAs: ["kendoSwitch"] }, { kind: "component", type: i0.forwardRef(() => i1$5.LabelComponent), selector: "kendo-label", inputs: ["text", "for", "optional", "labelCssStyle", "labelCssClass"], exportAs: ["kendoLabel"] }, { kind: "component", type: i0.forwardRef(() => i1$1.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: "component", type: i0.forwardRef(() => i3$1.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: i0.forwardRef(() => i3$1.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: "component", type: i0.forwardRef(() => i7.DateTimePickerComponent), selector: "kendo-datetimepicker", inputs: ["focusableId", "weekDaysFormat", "showOtherMonthDays", "value", "format", "twoDigitYearMax", "tabindex", "disabledDates", "popupSettings", "adaptiveTitle", "adaptiveSubtitle", "disabled", "readonly", "readOnlyInput", "cancelButton", "formatPlaceholder", "placeholder", "steps", "focusedDate", "calendarType", "animateCalendarNavigation", "weekNumber", "min", "max", "rangeValidation", "disabledDatesValidation", "incompleteDateValidation", "autoCorrectParts", "autoSwitchParts", "autoSwitchKeys", "enableMouseWheel", "allowCaretMode", "clearButton", "autoFill", "adaptiveMode", "inputAttributes", "defaultTab", "size", "rounded", "fillMode", "headerTemplate", "footerTemplate", "footer"], outputs: ["valueChange", "open", "close", "focus", "blur", "escape"], exportAs: ["kendo-datetimepicker"] }, { kind: "component", type: i0.forwardRef(() => i7.TimePickerComponent), selector: "kendo-timepicker", inputs: ["focusableId", "disabled", "readonly", "readOnlyInput", "clearButton", "format", "formatPlaceholder", "placeholder", "min", "max", "incompleteDateValidation", "autoSwitchParts", "autoSwitchKeys", "enableMouseWheel", "allowCaretMode", "cancelButton", "nowButton", "steps", "popupSettings", "tabindex", "tabIndex", "adaptiveTitle", "adaptiveSubtitle", "rangeValidation", "adaptiveMode", "value", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "open", "close", "escape"], exportAs: ["kendo-timepicker"] }, { kind: "component", type: i0.forwardRef(() => i8.FileSelectComponent), selector: "kendo-fileselect", inputs: ["name"], outputs: ["valueChange"], exportAs: ["kendoFileSelect"] }, { kind: "component", type: i0.forwardRef(() => i8.CustomMessagesComponent), selector: "kendo-upload-messages, kendo-fileselect-messages, kendo-uploaddropzone-messages" }, { kind: "component", type: i0.forwardRef(() => AttributeFieldComponent), selector: "mm-attribute-field", inputs: ["attribute", "control", "baselineValue", "fieldId", "overrideLabelText", "showUndoButton", "undoButtonSize", "errorMessage", "hintText"], outputs: ["undo"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
13650
14180
|
}
|
|
13651
14181
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: AttributesGroupComponent, decorators: [{
|
|
13652
14182
|
type: Component,
|
|
@@ -13718,6 +14248,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
13718
14248
|
[isRecord]="true"
|
|
13719
14249
|
[parentFormGroup]="asFormGroup(item)"
|
|
13720
14250
|
[initialValues]="getRawInitialValue(attr.attributeName, $index)"
|
|
14251
|
+
[secretsWriteOnly]="secretsWriteOnly()"
|
|
13721
14252
|
[messages]="_messages"
|
|
13722
14253
|
/>
|
|
13723
14254
|
</div>
|
|
@@ -13774,6 +14305,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
13774
14305
|
asFormGroup(parentFormGroup().get(attr.attributeName)!)
|
|
13775
14306
|
"
|
|
13776
14307
|
[initialValues]="getRawInitialValue(attr.attributeName)"
|
|
14308
|
+
[secretsWriteOnly]="secretsWriteOnly()"
|
|
13777
14309
|
[messages]="_messages"
|
|
13778
14310
|
/>
|
|
13779
14311
|
</div>
|
|
@@ -13870,6 +14402,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
13870
14402
|
[control]="parentFormGroup().get(attr.attributeName)!"
|
|
13871
14403
|
[baselineValue]="getBaselineValue(attr.attributeName)"
|
|
13872
14404
|
[fieldId]="attr.attributeName"
|
|
14405
|
+
[hintText]="attr.secret && secretsWriteOnly() ? (_messages.secretWriteOnlyHint ?? '') : ''"
|
|
13873
14406
|
[errorMessage]="_messages.attributeField?.errorMessage ?? 'This field is required or invalid.'"
|
|
13874
14407
|
>
|
|
13875
14408
|
@if (recognition.isNumber(attr.attributeValueType)) {
|
|
@@ -13952,6 +14485,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
13952
14485
|
valueField="key"
|
|
13953
14486
|
[valuePrimitive]="true"
|
|
13954
14487
|
/>
|
|
14488
|
+
} @else if (attr.secret) {
|
|
14489
|
+
<kendo-textbox
|
|
14490
|
+
type="password"
|
|
14491
|
+
autocomplete="new-password"
|
|
14492
|
+
[focusableId]="attr.attributeName"
|
|
14493
|
+
[formControlName]="attr.attributeName"
|
|
14494
|
+
/>
|
|
13955
14495
|
} @else {
|
|
13956
14496
|
<kendo-textbox
|
|
13957
14497
|
[focusableId]="attr.attributeName"
|
|
@@ -13964,8 +14504,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
13964
14504
|
</kendo-card-body>
|
|
13965
14505
|
</kendo-card>
|
|
13966
14506
|
</div>
|
|
13967
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".attributes-form-container ::ng-deep kendo-card kendo-card-body{display:flex;flex-direction:column;gap:16px}.attributes-form-container ::ng-deep kendo-label{display:flex;flex-direction:column;gap:4px}.
|
|
13968
|
-
}], ctorParameters: () => [], propDecorators: { ckId: [{ type: i0.Input, args: [{ isSignal: true, alias: "ckId", required: true }] }], parentFormGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentFormGroup", required: true }] }], isRecord: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRecord", required: false }] }], initialValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialValues", required: false }] }], messages: [{
|
|
14507
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".attributes-form-container ::ng-deep kendo-card kendo-card-body{display:flex;flex-direction:column;gap:16px}.attributes-form-container ::ng-deep kendo-label{display:flex;flex-direction:column;gap:4px}.header-content{display:flex;flex-direction:column;gap:4px}.record-array-content,.tab-content-wrapper{display:flex;flex-direction:column;gap:16px}.record-actions-info{display:flex;flex-direction:column;gap:12px;padding:16px;background-color:var(--kendo-color-surface-alt, rgba(0, 0, 0, .05));border:1px solid var(--kendo-color-border, rgba(0, 0, 0, .1));border-radius:4px;margin-bottom:16px}.record-actions-description{margin:0;font-size:13px;color:var(--kendo-color-subtle, rgba(0, 0, 0, .6));line-height:1.5}.record-array-actions{display:flex;gap:8px;justify-content:flex-start;padding-top:0}.record-actions{margin-top:16px;display:flex;gap:8px;justify-content:flex-start;padding-top:0}.binary-linked-wrap{display:flex;flex-direction:column;gap:6px}.binary-linked-reference-hint{font-size:.75rem;color:var(--kendo-color-primary, #0f6dff);font-style:italic}\n"] }]
|
|
14508
|
+
}], ctorParameters: () => [], propDecorators: { ckId: [{ type: i0.Input, args: [{ isSignal: true, alias: "ckId", required: true }] }], parentFormGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentFormGroup", required: true }] }], isRecord: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRecord", required: false }] }], initialValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialValues", required: false }] }], secretsWriteOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "secretsWriteOnly", required: false }] }], messages: [{
|
|
13969
14509
|
type: Input
|
|
13970
14510
|
}] } });
|
|
13971
14511
|
/** Stable empty array to avoid new [] references that would retrigger effects (infinite loop). */
|
|
@@ -14298,7 +14838,7 @@ class CreateEditorComponent {
|
|
|
14298
14838
|
</button>
|
|
14299
14839
|
</div>
|
|
14300
14840
|
</div>
|
|
14301
|
-
`, isInline: true, styles: [".entity-editor-container{display:flex;flex-direction:column;gap:16px;width:100%}.entity-editor-container ::ng-deep kendo-card{display:grid;grid-template-rows:auto 1fr;grid-template-columns:1fr 1fr;gap:16px;width:100%!important}.entity-editor-container ::ng-deep kendo-card kendo-card-header{grid-column:span 2;grid-row:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body{grid-row:2;grid-column:span 2;display:grid;grid-template-columns:1fr 1fr;gap:16px}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item{display:flex;flex-direction:column}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :first-child{grid-column:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :nth-child(2){grid-column:2}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item label{color:var(--kendo-color-subtle, rgba(0, 0, 0, .7));margin-bottom:8px
|
|
14841
|
+
`, isInline: true, styles: [".entity-editor-container{display:flex;flex-direction:column;gap:16px;width:100%}.entity-editor-container ::ng-deep kendo-card{display:grid;grid-template-rows:auto 1fr;grid-template-columns:1fr 1fr;gap:16px;width:100%!important}.entity-editor-container ::ng-deep kendo-card kendo-card-header{grid-column:span 2;grid-row:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body{grid-row:2;grid-column:span 2;display:grid;grid-template-columns:1fr 1fr;gap:16px}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item{display:flex;flex-direction:column}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :first-child{grid-column:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :nth-child(2){grid-column:2}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item label{color:var(--kendo-color-subtle, rgba(0, 0, 0, .7));margin-bottom:8px}.entity-editor-container .attributes-form-container ::ng-deep kendo-card:not(.basic-info-card) kendo-card-body{display:flex;flex-direction:column;gap:16px}.entity-editor-container .select-type-prompt{grid-column:span 2;color:var(--kendo-color-primary, #0f6dff);background-color:var(--kendo-color-surface-alt, rgba(0, 0, 0, .05));padding:16px;border-radius:8px;text-align:center;border:1px dashed var(--kendo-color-border, rgba(0, 0, 0, .1))}.entity-editor-container .entity-editor-actions{display:flex;flex-direction:row;gap:16px}.entity-editor-container .entity-editor-actions button:disabled{opacity:.6}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i1$4.CardComponent, selector: "kendo-card", inputs: ["orientation", "width"] }, { kind: "component", type: i1$4.CardBodyComponent, selector: "kendo-card-body" }, { kind: "component", type: i1$4.CardHeaderComponent, selector: "kendo-card-header" }, { kind: "component", type: i5.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: i1$1.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: "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: AttributesGroupComponent, selector: "mm-attributes-group", inputs: ["ckId", "parentFormGroup", "isRecord", "initialValues", "secretsWriteOnly", "messages"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
14302
14842
|
}
|
|
14303
14843
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: CreateEditorComponent, decorators: [{
|
|
14304
14844
|
type: Component,
|
|
@@ -14378,9 +14918,45 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
14378
14918
|
</button>
|
|
14379
14919
|
</div>
|
|
14380
14920
|
</div>
|
|
14381
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".entity-editor-container{display:flex;flex-direction:column;gap:16px;width:100%}.entity-editor-container ::ng-deep kendo-card{display:grid;grid-template-rows:auto 1fr;grid-template-columns:1fr 1fr;gap:16px;width:100%!important}.entity-editor-container ::ng-deep kendo-card kendo-card-header{grid-column:span 2;grid-row:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body{grid-row:2;grid-column:span 2;display:grid;grid-template-columns:1fr 1fr;gap:16px}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item{display:flex;flex-direction:column}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :first-child{grid-column:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :nth-child(2){grid-column:2}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item label{color:var(--kendo-color-subtle, rgba(0, 0, 0, .7));margin-bottom:8px
|
|
14921
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".entity-editor-container{display:flex;flex-direction:column;gap:16px;width:100%}.entity-editor-container ::ng-deep kendo-card{display:grid;grid-template-rows:auto 1fr;grid-template-columns:1fr 1fr;gap:16px;width:100%!important}.entity-editor-container ::ng-deep kendo-card kendo-card-header{grid-column:span 2;grid-row:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body{grid-row:2;grid-column:span 2;display:grid;grid-template-columns:1fr 1fr;gap:16px}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item{display:flex;flex-direction:column}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :first-child{grid-column:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :nth-child(2){grid-column:2}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item label{color:var(--kendo-color-subtle, rgba(0, 0, 0, .7));margin-bottom:8px}.entity-editor-container .attributes-form-container ::ng-deep kendo-card:not(.basic-info-card) kendo-card-body{display:flex;flex-direction:column;gap:16px}.entity-editor-container .select-type-prompt{grid-column:span 2;color:var(--kendo-color-primary, #0f6dff);background-color:var(--kendo-color-surface-alt, rgba(0, 0, 0, .05));padding:16px;border-radius:8px;text-align:center;border:1px dashed var(--kendo-color-border, rgba(0, 0, 0, .1))}.entity-editor-container .entity-editor-actions{display:flex;flex-direction:row;gap:16px}.entity-editor-container .entity-editor-actions button:disabled{opacity:.6}\n"] }]
|
|
14382
14922
|
}], ctorParameters: () => [], propDecorators: { createInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "createInput", required: true }] }], messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: false }] }], createOutput: [{ type: i0.Output, args: ["createOutput"] }], cancelRequested: [{ type: i0.Output, args: ["cancelRequested"] }] } });
|
|
14383
14923
|
|
|
14924
|
+
const RECORD_TYPES = new Set(['RECORD', 'RECORD_ARRAY']);
|
|
14925
|
+
/**
|
|
14926
|
+
* Decides what the runtime-browser update editor may write back (AB#5542).
|
|
14927
|
+
*
|
|
14928
|
+
* Only what was loaded completely may be written: an attribute is blocked when the secret-safe
|
|
14929
|
+
* analysis lists it (`blockedAttributes`: records carrying a secret or an excluded sub-attribute,
|
|
14930
|
+
* name collisions) or when it is not part of the loaded `attributeNames` at all (e.g. the CK
|
|
14931
|
+
* lookup failed) — except write-only secret scalars, whose empty value the mapper already omits.
|
|
14932
|
+
*/
|
|
14933
|
+
function planSecretSafeUpdate(mapped, definitions, analysis, formValue, initialJson) {
|
|
14934
|
+
const loaded = new Set(analysis.attributeNames.map((n) => n.toLowerCase()));
|
|
14935
|
+
const listed = new Set(analysis.blockedAttributes.map((n) => n.toLowerCase()));
|
|
14936
|
+
const blocked = new Set();
|
|
14937
|
+
for (const def of definitions) {
|
|
14938
|
+
const name = def.attributeName.toLowerCase();
|
|
14939
|
+
const writeOnlySecret = !!def.secret && !RECORD_TYPES.has(def.attributeValueType?.toUpperCase());
|
|
14940
|
+
if (listed.has(name) || (!writeOnlySecret && !loaded.has(name))) {
|
|
14941
|
+
blocked.add(name);
|
|
14942
|
+
}
|
|
14943
|
+
}
|
|
14944
|
+
let initial = {};
|
|
14945
|
+
try {
|
|
14946
|
+
initial = JSON.parse(initialJson ?? '{}');
|
|
14947
|
+
}
|
|
14948
|
+
catch {
|
|
14949
|
+
initial = {};
|
|
14950
|
+
}
|
|
14951
|
+
const changedKeys = Object.keys(formValue).filter((key) => JSON.stringify(formValue[key]) !== JSON.stringify(initial[key]));
|
|
14952
|
+
return {
|
|
14953
|
+
attributes: mapped.filter((a) => !blocked.has(a.attributeName.toLowerCase())),
|
|
14954
|
+
blocked,
|
|
14955
|
+
blockedChanged: changedKeys.some((key) => blocked.has(key.toLowerCase())),
|
|
14956
|
+
otherChanged: changedKeys.some((key) => !blocked.has(key.toLowerCase())),
|
|
14957
|
+
};
|
|
14958
|
+
}
|
|
14959
|
+
|
|
14384
14960
|
/**
|
|
14385
14961
|
* Editor for updating an existing runtime entity: loads entity data by rtId/ckTypeId, builds attribute form
|
|
14386
14962
|
* via mm-attributes-group, and submits updateRuntimeEntities with mapped attributes. Save is enabled only when
|
|
@@ -14421,6 +14997,7 @@ class UpdateEditorComponent {
|
|
|
14421
14997
|
mapperService = inject(AttributeMapperService);
|
|
14422
14998
|
coordinatorService = inject(AttributeCoordinatorService);
|
|
14423
14999
|
sharedEditor = inject(SharedEditor);
|
|
15000
|
+
secretSafeNames = inject(SecretSafeAttributeNamesService);
|
|
14424
15001
|
dataLoaded = computed(() => !!this.entityData(), /* @ts-ignore */
|
|
14425
15002
|
...(ngDevMode ? [{ debugName: "dataLoaded" }] : /* istanbul ignore next */ []));
|
|
14426
15003
|
isUpdateButtonEnabled = computed(() => {
|
|
@@ -14507,7 +15084,20 @@ class UpdateEditorComponent {
|
|
|
14507
15084
|
this.isUpdating.set(true);
|
|
14508
15085
|
try {
|
|
14509
15086
|
const attributesMetadata = await this.fetchAttributesMetadata(rtCkTypeId);
|
|
14510
|
-
const
|
|
15087
|
+
const formValue = currentForm.getRawValue();
|
|
15088
|
+
const mapped = await firstValueFrom(this.mapFormToAttributes$(formValue, attributesMetadata));
|
|
15089
|
+
const analysis = await this.secretSafeNames.analyse(input.ckTypeId);
|
|
15090
|
+
const plan = planSecretSafeUpdate(mapped, attributesMetadata, analysis, formValue, this.initialValue());
|
|
15091
|
+
if (plan.blockedChanged) {
|
|
15092
|
+
this.sharedEditor.showErrorNotification(this.resolvedMessages().recordWithSecretNotSaved ??
|
|
15093
|
+
DEFAULT_RUNTIME_BROWSER_MESSAGES.recordWithSecretNotSaved ??
|
|
15094
|
+
'');
|
|
15095
|
+
}
|
|
15096
|
+
if (!plan.otherChanged) {
|
|
15097
|
+
// Nothing that may be written back changed — skip the call (one message, AB#5542).
|
|
15098
|
+
return;
|
|
15099
|
+
}
|
|
15100
|
+
const mappedAttributes = plan.attributes;
|
|
14511
15101
|
if (!this.hasValidMappedAttributes(mappedAttributes)) {
|
|
14512
15102
|
this.sharedEditor.showErrorNotification(this.resolvedMessages().failedToUpdateEntity);
|
|
14513
15103
|
return;
|
|
@@ -14608,6 +15198,7 @@ class UpdateEditorComponent {
|
|
|
14608
15198
|
[ckId]="updateInput().rtCkTypeId"
|
|
14609
15199
|
[parentFormGroup]="form()!"
|
|
14610
15200
|
[initialValues]="$safeNavigationMigration(entityData()?.initial)"
|
|
15201
|
+
[secretsWriteOnly]="true"
|
|
14611
15202
|
[isRecord]="false"
|
|
14612
15203
|
[messages]="resolvedMessages()"
|
|
14613
15204
|
/>
|
|
@@ -14635,7 +15226,7 @@ class UpdateEditorComponent {
|
|
|
14635
15226
|
</button>
|
|
14636
15227
|
</div>
|
|
14637
15228
|
</div>
|
|
14638
|
-
`, isInline: true, styles: [".entity-editor-container{display:flex;flex-direction:column;gap:16px;width:100%}.entity-editor-container ::ng-deep kendo-card{display:grid;grid-template-rows:auto 1fr;grid-template-columns:1fr 1fr;gap:16px;width:100%!important}.entity-editor-container ::ng-deep kendo-card kendo-card-header{grid-column:span 2;grid-row:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body{grid-row:2;grid-column:span 2;display:grid;grid-template-columns:1fr 1fr;gap:16px}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item{display:flex;flex-direction:column}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :first-child{grid-column:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :nth-child(2){grid-column:2}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item label{color:var(--kendo-color-subtle, rgba(0, 0, 0, .7));margin-bottom:8px
|
|
15229
|
+
`, isInline: true, styles: [".entity-editor-container{display:flex;flex-direction:column;gap:16px;width:100%}.entity-editor-container ::ng-deep kendo-card{display:grid;grid-template-rows:auto 1fr;grid-template-columns:1fr 1fr;gap:16px;width:100%!important}.entity-editor-container ::ng-deep kendo-card kendo-card-header{grid-column:span 2;grid-row:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body{grid-row:2;grid-column:span 2;display:grid;grid-template-columns:1fr 1fr;gap:16px}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item{display:flex;flex-direction:column}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :first-child{grid-column:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :nth-child(2){grid-column:2}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item label{color:var(--kendo-color-subtle, rgba(0, 0, 0, .7));margin-bottom:8px}.entity-editor-container .attributes-form-container ::ng-deep kendo-card:not(.basic-info-card) kendo-card-body{display:flex;flex-direction:column;gap:16px}.entity-editor-container .select-type-prompt{grid-column:span 2;color:var(--kendo-color-primary, #0f6dff);background-color:var(--kendo-color-surface-alt, rgba(0, 0, 0, .05));padding:16px;border-radius:8px;text-align:center;border:1px dashed var(--kendo-color-border, rgba(0, 0, 0, .1))}.entity-editor-container .entity-editor-actions{display:flex;flex-direction:row;gap:16px}.entity-editor-container .entity-editor-actions button:disabled{opacity:.6}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i1$4.CardComponent, selector: "kendo-card", inputs: ["orientation", "width"] }, { kind: "component", type: i1$4.CardBodyComponent, selector: "kendo-card-body" }, { kind: "component", type: i1$4.CardHeaderComponent, selector: "kendo-card-header" }, { kind: "component", type: i5.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: i1$1.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: "component", type: AttributesGroupComponent, selector: "mm-attributes-group", inputs: ["ckId", "parentFormGroup", "isRecord", "initialValues", "secretsWriteOnly", "messages"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
14639
15230
|
}
|
|
14640
15231
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: UpdateEditorComponent, decorators: [{
|
|
14641
15232
|
type: Component,
|
|
@@ -14697,6 +15288,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
14697
15288
|
[ckId]="updateInput().rtCkTypeId"
|
|
14698
15289
|
[parentFormGroup]="form()!"
|
|
14699
15290
|
[initialValues]="$safeNavigationMigration(entityData()?.initial)"
|
|
15291
|
+
[secretsWriteOnly]="true"
|
|
14700
15292
|
[isRecord]="false"
|
|
14701
15293
|
[messages]="resolvedMessages()"
|
|
14702
15294
|
/>
|
|
@@ -14724,7 +15316,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
14724
15316
|
</button>
|
|
14725
15317
|
</div>
|
|
14726
15318
|
</div>
|
|
14727
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".entity-editor-container{display:flex;flex-direction:column;gap:16px;width:100%}.entity-editor-container ::ng-deep kendo-card{display:grid;grid-template-rows:auto 1fr;grid-template-columns:1fr 1fr;gap:16px;width:100%!important}.entity-editor-container ::ng-deep kendo-card kendo-card-header{grid-column:span 2;grid-row:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body{grid-row:2;grid-column:span 2;display:grid;grid-template-columns:1fr 1fr;gap:16px}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item{display:flex;flex-direction:column}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :first-child{grid-column:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :nth-child(2){grid-column:2}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item label{color:var(--kendo-color-subtle, rgba(0, 0, 0, .7));margin-bottom:8px
|
|
15319
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".entity-editor-container{display:flex;flex-direction:column;gap:16px;width:100%}.entity-editor-container ::ng-deep kendo-card{display:grid;grid-template-rows:auto 1fr;grid-template-columns:1fr 1fr;gap:16px;width:100%!important}.entity-editor-container ::ng-deep kendo-card kendo-card-header{grid-column:span 2;grid-row:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body{grid-row:2;grid-column:span 2;display:grid;grid-template-columns:1fr 1fr;gap:16px}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item{display:flex;flex-direction:column}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :first-child{grid-column:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :nth-child(2){grid-column:2}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item label{color:var(--kendo-color-subtle, rgba(0, 0, 0, .7));margin-bottom:8px}.entity-editor-container .attributes-form-container ::ng-deep kendo-card:not(.basic-info-card) kendo-card-body{display:flex;flex-direction:column;gap:16px}.entity-editor-container .select-type-prompt{grid-column:span 2;color:var(--kendo-color-primary, #0f6dff);background-color:var(--kendo-color-surface-alt, rgba(0, 0, 0, .05));padding:16px;border-radius:8px;text-align:center;border:1px dashed var(--kendo-color-border, rgba(0, 0, 0, .1))}.entity-editor-container .entity-editor-actions{display:flex;flex-direction:row;gap:16px}.entity-editor-container .entity-editor-actions button:disabled{opacity:.6}\n"] }]
|
|
14728
15320
|
}], ctorParameters: () => [], propDecorators: { updateInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "updateInput", required: true }] }], messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: false }] }], updateOutput: [{ type: i0.Output, args: ["updateOutput"] }], cancelRequested: [{ type: i0.Output, args: ["cancelRequested"] }] } });
|
|
14729
15321
|
|
|
14730
15322
|
class RuntimeBrowserDetailsComponent {
|
|
@@ -14749,6 +15341,7 @@ class RuntimeBrowserDetailsComponent {
|
|
|
14749
15341
|
createEntitiesGQL = inject(CreateEntitiesDtoGQL);
|
|
14750
15342
|
updateEntitiesGQL = inject(UpdateRuntimeEntitiesDtoGQL);
|
|
14751
15343
|
deleteEntitiesGQL = inject(DeleteEntitiesDtoGQL);
|
|
15344
|
+
confirmation = inject(ConfirmationService);
|
|
14752
15345
|
entitySelectorDialog = inject(EntitySelectorDialogService);
|
|
14753
15346
|
attributeSelectorDialog = inject(AttributeSelectorDialogService);
|
|
14754
15347
|
// Data Mapping state (list of DataPointMapping entities). Source data points
|
|
@@ -15126,7 +15719,7 @@ class RuntimeBrowserDetailsComponent {
|
|
|
15126
15719
|
try {
|
|
15127
15720
|
// Load entity attributes
|
|
15128
15721
|
const entityResult = await firstValueFrom(this.getEntityByIdGQL.fetch({
|
|
15129
|
-
variables: { rtId, ckTypeId },
|
|
15722
|
+
variables: { rtId, ckTypeId, attributeNames: [...DATA_POINT_MAPPING_ATTRIBUTE_NAMES] },
|
|
15130
15723
|
}));
|
|
15131
15724
|
const mappingEntity = entityResult.data?.runtime?.runtimeEntities?.items?.[0];
|
|
15132
15725
|
if (!mappingEntity)
|
|
@@ -15225,6 +15818,16 @@ class RuntimeBrowserDetailsComponent {
|
|
|
15225
15818
|
async onRemoveMapping(mapping) {
|
|
15226
15819
|
if (!mapping.rtId)
|
|
15227
15820
|
return;
|
|
15821
|
+
// Danger confirmation naming the mapping (AB#5579): the mapping entity is erased.
|
|
15822
|
+
const name = mapping.name || mapping.rtId;
|
|
15823
|
+
if (!await this.confirmation.showDangerConfirm({
|
|
15824
|
+
title: `Delete mapping ${name}?`,
|
|
15825
|
+
targetName: name,
|
|
15826
|
+
consequence: 'The data point mapping is erased. This cannot be undone.',
|
|
15827
|
+
confirmText: 'Delete mapping',
|
|
15828
|
+
})) {
|
|
15829
|
+
return;
|
|
15830
|
+
}
|
|
15228
15831
|
try {
|
|
15229
15832
|
await firstValueFrom(this.deleteEntitiesGQL.mutate({
|
|
15230
15833
|
variables: {
|
|
@@ -15505,7 +16108,7 @@ class RuntimeBrowserDetailsComponent {
|
|
|
15505
16108
|
}
|
|
15506
16109
|
}
|
|
15507
16110
|
</div>
|
|
15508
|
-
`, isInline: true, styles: [":host{display:block;height:100%;width:100%}.runtime-browser-details{display:flex;flex-direction:column;flex:1;min-height:0;padding:24px;box-sizing:border-box;overflow-y:auto;background:
|
|
16111
|
+
`, isInline: true, styles: [":host{display:block;height:100%;width:100%}.runtime-browser-details .entity-details .ck-type-details .entities-table,.runtime-browser-details .entity-details .ck-type-details .type-header,.runtime-browser-details .entity-details .ck-model-details,.runtime-browser-details .entity-details .ck-models-root,.runtime-browser-details .entity-details .details-header{background:var(--theme-bg-elevated, var(--surface-elevated));border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-md, 6px)}.runtime-browser-details .entity-details .ck-type-details .type-header h3,.runtime-browser-details .entity-details .ck-model-details h3,.runtime-browser-details .entity-details .ck-models-root h3,.runtime-browser-details .entity-details .details-header .entity-title h3,.runtime-browser-details .no-selection .placeholder-content h3{font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-size:1.1rem;font-weight:600;color:var(--theme-text-primary, var(--octo-text-color))}.runtime-browser-details .entity-details .ck-type-details .type-header .type-metadata .base-type,.runtime-browser-details .entity-details .details-header .entity-title .entity-type{font-family:var(--theme-font-mono, \"Roboto Mono\", monospace);font-size:.8rem;color:var(--theme-text-code, var(--octo-text-color));background:var(--theme-bg-sunken, var(--deep-sea-60));padding:2px 8px;border-radius:var(--theme-radius-xs, 2px);border:1px solid var(--theme-border-subtle);display:inline-block}.runtime-browser-details{display:flex;flex-direction:column;flex:1;min-height:0;padding:24px;box-sizing:border-box;overflow-y:auto;background:var(--theme-bg-surface, var(--deep-sea))}.runtime-browser-details .no-selection{display:flex;align-items:center;justify-content:center;flex:1;min-height:0}.runtime-browser-details .no-selection .placeholder-content{text-align:center;max-width:400px;padding:40px}.runtime-browser-details .no-selection .placeholder-content .placeholder-icon{margin-bottom:16px}.runtime-browser-details .no-selection .placeholder-content .placeholder-icon .k-icon{font-size:48px;color:var(--theme-text-muted, var(--ash-blue))}.runtime-browser-details .no-selection .placeholder-content h3{margin:0 0 8px}.runtime-browser-details .no-selection .placeholder-content p{margin:0;font-family:var(--theme-font-ui, \"Roboto\", sans-serif);font-size:.9rem;line-height:1.6;color:var(--theme-text-secondary, var(--ash-blue))}.runtime-browser-details .entity-details{height:100%;display:flex;flex-direction:column;overflow:hidden}.runtime-browser-details .entity-details .details-header{display:flex;align-items:center;gap:16px;padding:16px 20px;margin-bottom:20px}.runtime-browser-details .entity-details .details-header .entity-icon{font-size:24px;color:var(--theme-text-secondary, var(--ash-blue))}.runtime-browser-details .entity-details .details-header .entity-title{flex:1}.runtime-browser-details .entity-details .details-header .entity-title h3{margin:0 0 6px}.runtime-browser-details .entity-details .details-header .entity-title .entity-type{margin:0}.runtime-browser-details .entity-details mm-entity-detail-view{flex:1;display:flex;flex-direction:column;overflow-y:auto}.runtime-browser-details .entity-details .ck-model-details,.runtime-browser-details .entity-details .ck-models-root{padding:24px}.runtime-browser-details .entity-details .ck-model-details h3,.runtime-browser-details .entity-details .ck-models-root h3{margin:0 0 20px}.runtime-browser-details .entity-details .ck-model-details p,.runtime-browser-details .entity-details .ck-models-root p{margin:0 0 12px;font-family:var(--theme-font-ui, \"Roboto\", sans-serif);font-size:.9rem;color:var(--theme-text-primary, var(--octo-text-color))}.runtime-browser-details .entity-details .ck-model-details p strong,.runtime-browser-details .entity-details .ck-models-root p strong{font-weight:500;font-size:.85rem;color:var(--theme-text-secondary, var(--ash-blue));margin-right:12px}.runtime-browser-details .entity-details .ck-model-details p.info-text,.runtime-browser-details .entity-details .ck-models-root p.info-text{color:var(--theme-text-secondary, var(--ash-blue));margin-top:24px;padding:12px 16px;background:var(--theme-status-info-subtle, var(--neo-cyan-10));border:1px solid var(--theme-border-subtle);border-radius:var(--theme-radius-sm, 4px)}.runtime-browser-details .entity-details .ck-type-details{display:flex;flex-direction:column;height:100%;padding:0}.runtime-browser-details .entity-details .ck-type-details .type-header{margin-bottom:20px;padding:20px 24px}.runtime-browser-details .entity-details .ck-type-details .type-header h3{margin:0 0 12px}.runtime-browser-details .entity-details .ck-type-details .type-header .type-metadata{display:flex;gap:10px;align-items:center}.runtime-browser-details .entity-details .ck-type-details .type-header .type-metadata .badge{padding:2px 8px;border-radius:var(--theme-radius-xs, 2px);font-family:var(--theme-font-ui, \"Roboto\", sans-serif);font-size:.75rem;font-weight:500}.runtime-browser-details .entity-details .ck-type-details .type-header .type-metadata .badge.abstract{background:var(--theme-ai-subtle, var(--royal-violet-15));border:1px solid transparent;color:var(--theme-ai, var(--royal-violet-light-20))}.runtime-browser-details .entity-details .ck-type-details .type-header .type-metadata .badge.final{background:var(--theme-status-warning-subtle, var(--toffee-15));border:1px solid transparent;color:var(--theme-status-warning, var(--toffee))}.runtime-browser-details .entity-details .ck-type-details .entities-table{flex:1;display:flex;flex-direction:column;overflow:hidden;padding:20px}.runtime-browser-details .entity-details .ck-type-details .entities-table h4{margin:0 0 16px;font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-size:1rem;font-weight:600;color:var(--theme-text-primary, var(--octo-text-color))}.runtime-browser-details .entity-details .ck-type-details .entities-table mm-list-view{flex:1;display:flex;flex-direction:column;overflow:hidden}@media(max-width:768px){.runtime-browser-details{padding:16px}.runtime-browser-details .no-selection .placeholder-content{padding:24px}.runtime-browser-details .entity-details .details-header{flex-direction:column;align-items:flex-start;gap:12px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: SVGIconModule }, { kind: "component", type: EntityDetailViewComponent, selector: "mm-entity-detail-view", inputs: ["entity", "loading", "error", "showHeader", "messages", "showDataMapping", "dataMappings", "expressionValidator"], outputs: ["retry", "propertyChange", "navigateToEntity", "addMappingRequested", "removeMappingRequested", "selectMappingTarget", "selectSourceAttributeRequested", "selectTargetAttributeRequested", "mappingChanged", "saveAllMappingsRequested"] }, { kind: "component", type: ListViewComponent, selector: "mm-list-view", inputs: ["pageSize", "skip", "autoPageSize", "rowIsClickable", "showRowCheckBoxes", "showRowSelectAllCheckBox", "contextMenuType", "leftToolbarActions", "rightToolbarActions", "actionCommandItems", "contextMenuCommandItems", "rowActions", "maxInlineRowActions", "excelExportFileName", "pdfExportFileName", "pageable", "sortable", "rowFilterEnabled", "searchTextBoxEnabled", "persistListState", "listStateKey", "resizable", "actionsColumnWidth", "hideCheckboxesBelow", "cardModeBelow", "collapseCommandsBelow", "hasExternalFilters", "rowClass", "messages", "selectable", "columns", "rowLabelField"], outputs: ["rowClicked", "rowAction", "resetFilters"] }, { kind: "directive", type: CkTypeEntitiesDataSourceDirective, selector: "[mmCkTypeEntitiesDataSource]", exportAs: ["mmCkTypeEntitiesDataSource"] }, { kind: "component", type: CreateEditorComponent, selector: "mm-create-editor-component", inputs: ["createInput", "messages"], outputs: ["createOutput", "cancelRequested"] }, { kind: "component", type: UpdateEditorComponent, selector: "mm-update-editor-component", inputs: ["updateInput", "messages"], outputs: ["updateOutput", "cancelRequested"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
15509
16112
|
}
|
|
15510
16113
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: RuntimeBrowserDetailsComponent, decorators: [{
|
|
15511
16114
|
type: Component,
|
|
@@ -15658,7 +16261,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
15658
16261
|
}
|
|
15659
16262
|
}
|
|
15660
16263
|
</div>
|
|
15661
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block;height:100%;width:100%}.runtime-browser-details{display:flex;flex-direction:column;flex:1;min-height:0;padding:24px;box-sizing:border-box;overflow-y:auto;background:
|
|
16264
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block;height:100%;width:100%}.runtime-browser-details .entity-details .ck-type-details .entities-table,.runtime-browser-details .entity-details .ck-type-details .type-header,.runtime-browser-details .entity-details .ck-model-details,.runtime-browser-details .entity-details .ck-models-root,.runtime-browser-details .entity-details .details-header{background:var(--theme-bg-elevated, var(--surface-elevated));border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-md, 6px)}.runtime-browser-details .entity-details .ck-type-details .type-header h3,.runtime-browser-details .entity-details .ck-model-details h3,.runtime-browser-details .entity-details .ck-models-root h3,.runtime-browser-details .entity-details .details-header .entity-title h3,.runtime-browser-details .no-selection .placeholder-content h3{font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-size:1.1rem;font-weight:600;color:var(--theme-text-primary, var(--octo-text-color))}.runtime-browser-details .entity-details .ck-type-details .type-header .type-metadata .base-type,.runtime-browser-details .entity-details .details-header .entity-title .entity-type{font-family:var(--theme-font-mono, \"Roboto Mono\", monospace);font-size:.8rem;color:var(--theme-text-code, var(--octo-text-color));background:var(--theme-bg-sunken, var(--deep-sea-60));padding:2px 8px;border-radius:var(--theme-radius-xs, 2px);border:1px solid var(--theme-border-subtle);display:inline-block}.runtime-browser-details{display:flex;flex-direction:column;flex:1;min-height:0;padding:24px;box-sizing:border-box;overflow-y:auto;background:var(--theme-bg-surface, var(--deep-sea))}.runtime-browser-details .no-selection{display:flex;align-items:center;justify-content:center;flex:1;min-height:0}.runtime-browser-details .no-selection .placeholder-content{text-align:center;max-width:400px;padding:40px}.runtime-browser-details .no-selection .placeholder-content .placeholder-icon{margin-bottom:16px}.runtime-browser-details .no-selection .placeholder-content .placeholder-icon .k-icon{font-size:48px;color:var(--theme-text-muted, var(--ash-blue))}.runtime-browser-details .no-selection .placeholder-content h3{margin:0 0 8px}.runtime-browser-details .no-selection .placeholder-content p{margin:0;font-family:var(--theme-font-ui, \"Roboto\", sans-serif);font-size:.9rem;line-height:1.6;color:var(--theme-text-secondary, var(--ash-blue))}.runtime-browser-details .entity-details{height:100%;display:flex;flex-direction:column;overflow:hidden}.runtime-browser-details .entity-details .details-header{display:flex;align-items:center;gap:16px;padding:16px 20px;margin-bottom:20px}.runtime-browser-details .entity-details .details-header .entity-icon{font-size:24px;color:var(--theme-text-secondary, var(--ash-blue))}.runtime-browser-details .entity-details .details-header .entity-title{flex:1}.runtime-browser-details .entity-details .details-header .entity-title h3{margin:0 0 6px}.runtime-browser-details .entity-details .details-header .entity-title .entity-type{margin:0}.runtime-browser-details .entity-details mm-entity-detail-view{flex:1;display:flex;flex-direction:column;overflow-y:auto}.runtime-browser-details .entity-details .ck-model-details,.runtime-browser-details .entity-details .ck-models-root{padding:24px}.runtime-browser-details .entity-details .ck-model-details h3,.runtime-browser-details .entity-details .ck-models-root h3{margin:0 0 20px}.runtime-browser-details .entity-details .ck-model-details p,.runtime-browser-details .entity-details .ck-models-root p{margin:0 0 12px;font-family:var(--theme-font-ui, \"Roboto\", sans-serif);font-size:.9rem;color:var(--theme-text-primary, var(--octo-text-color))}.runtime-browser-details .entity-details .ck-model-details p strong,.runtime-browser-details .entity-details .ck-models-root p strong{font-weight:500;font-size:.85rem;color:var(--theme-text-secondary, var(--ash-blue));margin-right:12px}.runtime-browser-details .entity-details .ck-model-details p.info-text,.runtime-browser-details .entity-details .ck-models-root p.info-text{color:var(--theme-text-secondary, var(--ash-blue));margin-top:24px;padding:12px 16px;background:var(--theme-status-info-subtle, var(--neo-cyan-10));border:1px solid var(--theme-border-subtle);border-radius:var(--theme-radius-sm, 4px)}.runtime-browser-details .entity-details .ck-type-details{display:flex;flex-direction:column;height:100%;padding:0}.runtime-browser-details .entity-details .ck-type-details .type-header{margin-bottom:20px;padding:20px 24px}.runtime-browser-details .entity-details .ck-type-details .type-header h3{margin:0 0 12px}.runtime-browser-details .entity-details .ck-type-details .type-header .type-metadata{display:flex;gap:10px;align-items:center}.runtime-browser-details .entity-details .ck-type-details .type-header .type-metadata .badge{padding:2px 8px;border-radius:var(--theme-radius-xs, 2px);font-family:var(--theme-font-ui, \"Roboto\", sans-serif);font-size:.75rem;font-weight:500}.runtime-browser-details .entity-details .ck-type-details .type-header .type-metadata .badge.abstract{background:var(--theme-ai-subtle, var(--royal-violet-15));border:1px solid transparent;color:var(--theme-ai, var(--royal-violet-light-20))}.runtime-browser-details .entity-details .ck-type-details .type-header .type-metadata .badge.final{background:var(--theme-status-warning-subtle, var(--toffee-15));border:1px solid transparent;color:var(--theme-status-warning, var(--toffee))}.runtime-browser-details .entity-details .ck-type-details .entities-table{flex:1;display:flex;flex-direction:column;overflow:hidden;padding:20px}.runtime-browser-details .entity-details .ck-type-details .entities-table h4{margin:0 0 16px;font-family:var(--theme-font-display, \"Montserrat\", sans-serif);font-size:1rem;font-weight:600;color:var(--theme-text-primary, var(--octo-text-color))}.runtime-browser-details .entity-details .ck-type-details .entities-table mm-list-view{flex:1;display:flex;flex-direction:column;overflow:hidden}@media(max-width:768px){.runtime-browser-details{padding:16px}.runtime-browser-details .no-selection .placeholder-content{padding:24px}.runtime-browser-details .entity-details .details-header{flex-direction:column;align-items:flex-start;gap:12px}}\n"] }]
|
|
15662
16265
|
}], propDecorators: { selectedItem: [{
|
|
15663
16266
|
type: Input
|
|
15664
16267
|
}], showDataMapping: [{
|
|
@@ -15679,6 +16282,7 @@ class RuntimeBrowserComponent {
|
|
|
15679
16282
|
dataSource = inject(RuntimeBrowserDataSource);
|
|
15680
16283
|
getRuntimeEntityByIdGQL = inject(GetRuntimeEntityByIdDtoGQL);
|
|
15681
16284
|
inputService = inject(InputService);
|
|
16285
|
+
confirmation = inject(ConfirmationService);
|
|
15682
16286
|
router = inject(Router);
|
|
15683
16287
|
route = inject(ActivatedRoute);
|
|
15684
16288
|
stateService = inject(RuntimeBrowserStateService);
|
|
@@ -15746,7 +16350,7 @@ class RuntimeBrowserComponent {
|
|
|
15746
16350
|
id: 'refresh',
|
|
15747
16351
|
type: 'link',
|
|
15748
16352
|
text: messages.refresh,
|
|
15749
|
-
svgIcon:
|
|
16353
|
+
svgIcon: MM_ACTION_ICONS.refresh,
|
|
15750
16354
|
onClick: async () => await this.onRefresh(),
|
|
15751
16355
|
isDisabled: () => !this.isRefreshButtonEnabled,
|
|
15752
16356
|
},
|
|
@@ -15754,7 +16358,7 @@ class RuntimeBrowserComponent {
|
|
|
15754
16358
|
id: 'create',
|
|
15755
16359
|
type: 'link',
|
|
15756
16360
|
text: messages.create,
|
|
15757
|
-
svgIcon:
|
|
16361
|
+
svgIcon: MM_ACTION_ICONS.add,
|
|
15758
16362
|
onClick: async () => await this.onCreate(),
|
|
15759
16363
|
isDisabled: () => !this.isCreateButtonEnabled,
|
|
15760
16364
|
},
|
|
@@ -15762,7 +16366,7 @@ class RuntimeBrowserComponent {
|
|
|
15762
16366
|
id: 'edit',
|
|
15763
16367
|
type: 'link',
|
|
15764
16368
|
text: messages.edit,
|
|
15765
|
-
svgIcon:
|
|
16369
|
+
svgIcon: MM_ACTION_ICONS.edit,
|
|
15766
16370
|
onClick: async () => await this.onEdit(),
|
|
15767
16371
|
isDisabled: () => !this.isEditButtonEnabled,
|
|
15768
16372
|
},
|
|
@@ -15770,7 +16374,8 @@ class RuntimeBrowserComponent {
|
|
|
15770
16374
|
id: 'delete',
|
|
15771
16375
|
type: 'link',
|
|
15772
16376
|
text: messages.delete,
|
|
15773
|
-
svgIcon:
|
|
16377
|
+
svgIcon: MM_ACTION_ICONS.delete,
|
|
16378
|
+
danger: true,
|
|
15774
16379
|
onClick: async () => await this.onDelete(),
|
|
15775
16380
|
isDisabled: () => !this.isDeleteButtonEnabled,
|
|
15776
16381
|
},
|
|
@@ -16130,14 +16735,27 @@ class RuntimeBrowserComponent {
|
|
|
16130
16735
|
console.warn('No node selected; cannot perform delete operation on unknown node');
|
|
16131
16736
|
return;
|
|
16132
16737
|
}
|
|
16738
|
+
if (!this.isSelectedItemAnRtEntity) {
|
|
16739
|
+
console.warn('Selected item is not a runtime entity, cannot delete.', this.selectedItem);
|
|
16740
|
+
return;
|
|
16741
|
+
}
|
|
16742
|
+
// Danger confirmation naming the entity (AB#5579): the entity and its children are erased.
|
|
16743
|
+
const selected = this.selectedItem;
|
|
16744
|
+
const runtimeEntity = selected.item;
|
|
16745
|
+
const m = this.resolvedMessages();
|
|
16746
|
+
const name = selected.text || runtimeEntity.rtWellKnownName || runtimeEntity.rtId;
|
|
16747
|
+
const confirmed = await this.confirmation.showDangerConfirm({
|
|
16748
|
+
title: (m.confirmDeleteEntityTitle ?? DEFAULT_RUNTIME_BROWSER_MESSAGES.confirmDeleteEntityTitle).replace('{name}', name),
|
|
16749
|
+
targetName: name,
|
|
16750
|
+
consequence: m.confirmDeleteEntityConsequence ?? DEFAULT_RUNTIME_BROWSER_MESSAGES.confirmDeleteEntityConsequence,
|
|
16751
|
+
confirmText: m.confirmDeleteEntityConfirmText ?? DEFAULT_RUNTIME_BROWSER_MESSAGES.confirmDeleteEntityConfirmText,
|
|
16752
|
+
});
|
|
16753
|
+
if (!confirmed || this.selectedItem !== selected) {
|
|
16754
|
+
return;
|
|
16755
|
+
}
|
|
16133
16756
|
try {
|
|
16134
16757
|
this.isLoading = true;
|
|
16135
16758
|
this.treeDetail.setEnabledState(false);
|
|
16136
|
-
if (!this.isSelectedItemAnRtEntity) {
|
|
16137
|
-
console.warn('Selected item is not a runtime entity, cannot delete.', this.selectedItem);
|
|
16138
|
-
return;
|
|
16139
|
-
}
|
|
16140
|
-
const runtimeEntity = this.selectedItem.item;
|
|
16141
16759
|
const parentIdPair = await this.dataSource.getRuntimeEntityParentData(runtimeEntity.ckTypeId, runtimeEntity.rtId);
|
|
16142
16760
|
const deleteState = await this.dataSource.deleteRtEntityAndChildren(this.selectedItem);
|
|
16143
16761
|
if (!deleteState) {
|
|
@@ -16186,6 +16804,8 @@ class RuntimeBrowserComponent {
|
|
|
16186
16804
|
variables: {
|
|
16187
16805
|
ckTypeId: ckTypeId,
|
|
16188
16806
|
rtId: rtId,
|
|
16807
|
+
// Existence check only — no attributes (SECRET-safe, AB#5542).
|
|
16808
|
+
attributeNames: [],
|
|
16189
16809
|
},
|
|
16190
16810
|
}));
|
|
16191
16811
|
const entity = result.data?.runtime?.runtimeEntities?.items?.[0];
|
|
@@ -16283,32 +16903,8 @@ class RuntimeBrowserComponent {
|
|
|
16283
16903
|
}
|
|
16284
16904
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: RuntimeBrowserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
16285
16905
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.5", type: RuntimeBrowserComponent, isStandalone: true, selector: "mm-runtime-browser", inputs: { messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null }, showDataMapping: { classPropertyName: "showDataMapping", publicName: "showDataMapping", isSignal: true, isRequired: false, transformFunction: null }, expressionValidator: { classPropertyName: "expressionValidator", publicName: "expressionValidator", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "treeDetail", first: true, predicate: ["treeDetail"], descendants: true }, { propertyName: "detailsPanel", first: true, predicate: ["detailsPanel"], descendants: true }], ngImport: i0, template: `
|
|
16286
|
-
<
|
|
16287
|
-
|
|
16288
|
-
<div class="lcars-page-header">
|
|
16289
|
-
<div class="lcars-header-accent"></div>
|
|
16290
|
-
<div class="header-content">
|
|
16291
|
-
<h1 class="page-title">
|
|
16292
|
-
<span class="title-prefix">{{
|
|
16293
|
-
resolvedMessages().titlePrefix
|
|
16294
|
-
}}</span>
|
|
16295
|
-
<span class="title-main">{{ resolvedMessages().title }}</span>
|
|
16296
|
-
</h1>
|
|
16297
|
-
<div class="header-stats">
|
|
16298
|
-
<div class="stat-badge">
|
|
16299
|
-
<span class="badge-icon">■</span>
|
|
16300
|
-
<span class="badge-label">{{
|
|
16301
|
-
resolvedMessages().badgeLabel
|
|
16302
|
-
}}</span>
|
|
16303
|
-
</div>
|
|
16304
|
-
</div>
|
|
16305
|
-
</div>
|
|
16306
|
-
<div class="lcars-header-line"></div>
|
|
16307
|
-
</div>
|
|
16308
|
-
|
|
16309
|
-
<!-- Main Content -->
|
|
16310
|
-
<div class="lcars-content-panel">
|
|
16311
|
-
<div class="panel-accent-top"></div>
|
|
16906
|
+
<mm-page class="runtime-browser-container kendo-theme-provider" [pageTitle]="resolvedMessages().title">
|
|
16907
|
+
<div class="runtime-browser-panel">
|
|
16312
16908
|
<mm-perspective-switcher
|
|
16313
16909
|
[perspectives]="perspectives()"
|
|
16314
16910
|
[activeKey]="activePerspectiveKey()"
|
|
@@ -16335,56 +16931,20 @@ class RuntimeBrowserComponent {
|
|
|
16335
16931
|
>
|
|
16336
16932
|
</mm-runtime-browser-details>
|
|
16337
16933
|
</mm-base-tree-detail>
|
|
16338
|
-
<div class="panel-accent-bottom"></div>
|
|
16339
|
-
</div>
|
|
16340
|
-
|
|
16341
|
-
<!-- LCARS Footer -->
|
|
16342
|
-
<div class="lcars-footer">
|
|
16343
|
-
<div class="footer-bar bar-1"></div>
|
|
16344
|
-
<div class="footer-bar bar-2"></div>
|
|
16345
|
-
<div class="footer-bar bar-3"></div>
|
|
16346
|
-
<div class="footer-spacer"></div>
|
|
16347
|
-
<div class="footer-indicator">
|
|
16348
|
-
<span class="indicator-dot"></span>
|
|
16349
|
-
<span class="indicator-text">{{ resolvedMessages().ready }}</span>
|
|
16350
|
-
</div>
|
|
16351
16934
|
</div>
|
|
16352
|
-
</
|
|
16353
|
-
`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}.runtime-browser-
|
|
16935
|
+
</mm-page>
|
|
16936
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}.runtime-browser-panel{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--theme-bg-surface);border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-md, 6px);overflow:hidden}.runtime-browser-panel>mm-base-tree-detail{flex:1;display:flex;flex-direction:column;min-height:0}::ng-deep mm-base-tree-detail .k-splitter{background:transparent;border:none}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar{background:var(--theme-border-subtle);width:4px!important}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar:hover{background:var(--theme-border-strong)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf{font-family:var(--theme-font-ui, \"Roboto\", sans-serif);transition:background-color var(--theme-motion-fast, .12s) var(--theme-motion-easing, ease);border-radius:var(--theme-radius-sm, 4px)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf:hover{background:var(--theme-bg-hover)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected{background:var(--theme-bg-selected);color:var(--theme-text-accent)}::ng-deep mm-base-tree-detail .toolbar{background:var(--theme-bg-elevated);border-bottom:1px solid var(--theme-border-subtle)}::ng-deep mm-base-tree-detail .base-tree-detail-container{height:100%;display:flex;flex-direction:column}::ng-deep mm-base-tree-detail .base-tree-detail-container .k-splitter{flex:1;min-height:0}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane{display:flex!important;flex-direction:column!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details{display:flex!important;flex:1!important;min-height:0!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details>.runtime-browser-details{flex:1;display:flex;flex-direction:column;min-height:0}\n"], dependencies: [{ kind: "component", type: PageComponent, selector: "mm-page", inputs: ["pageTitle", "pageSubtitle", "headingLevel", "padded"] }, { kind: "component", type: BaseTreeDetailComponent, selector: "mm-base-tree-detail", inputs: ["treeDataSource", "leftPaneSize", "leftToolbarActions", "rightToolbarActions"], outputs: ["nodeSelected", "nodeDropped"] }, { kind: "component", type: RuntimeBrowserDetailsComponent, selector: "mm-runtime-browser-details", inputs: ["selectedItem", "showDataMapping", "messages", "expressionValidator"], outputs: ["entitySaved"] }, { kind: "component", type: PerspectiveSwitcherComponent, selector: "mm-perspective-switcher", inputs: ["perspectives", "activeKey", "label"], outputs: ["perspectiveChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
16354
16937
|
}
|
|
16355
16938
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: RuntimeBrowserComponent, decorators: [{
|
|
16356
16939
|
type: Component,
|
|
16357
16940
|
args: [{ selector: 'mm-runtime-browser', imports: [
|
|
16941
|
+
PageComponent,
|
|
16358
16942
|
BaseTreeDetailComponent,
|
|
16359
16943
|
RuntimeBrowserDetailsComponent,
|
|
16360
16944
|
PerspectiveSwitcherComponent,
|
|
16361
16945
|
], template: `
|
|
16362
|
-
<
|
|
16363
|
-
|
|
16364
|
-
<div class="lcars-page-header">
|
|
16365
|
-
<div class="lcars-header-accent"></div>
|
|
16366
|
-
<div class="header-content">
|
|
16367
|
-
<h1 class="page-title">
|
|
16368
|
-
<span class="title-prefix">{{
|
|
16369
|
-
resolvedMessages().titlePrefix
|
|
16370
|
-
}}</span>
|
|
16371
|
-
<span class="title-main">{{ resolvedMessages().title }}</span>
|
|
16372
|
-
</h1>
|
|
16373
|
-
<div class="header-stats">
|
|
16374
|
-
<div class="stat-badge">
|
|
16375
|
-
<span class="badge-icon">■</span>
|
|
16376
|
-
<span class="badge-label">{{
|
|
16377
|
-
resolvedMessages().badgeLabel
|
|
16378
|
-
}}</span>
|
|
16379
|
-
</div>
|
|
16380
|
-
</div>
|
|
16381
|
-
</div>
|
|
16382
|
-
<div class="lcars-header-line"></div>
|
|
16383
|
-
</div>
|
|
16384
|
-
|
|
16385
|
-
<!-- Main Content -->
|
|
16386
|
-
<div class="lcars-content-panel">
|
|
16387
|
-
<div class="panel-accent-top"></div>
|
|
16946
|
+
<mm-page class="runtime-browser-container kendo-theme-provider" [pageTitle]="resolvedMessages().title">
|
|
16947
|
+
<div class="runtime-browser-panel">
|
|
16388
16948
|
<mm-perspective-switcher
|
|
16389
16949
|
[perspectives]="perspectives()"
|
|
16390
16950
|
[activeKey]="activePerspectiveKey()"
|
|
@@ -16411,22 +16971,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
16411
16971
|
>
|
|
16412
16972
|
</mm-runtime-browser-details>
|
|
16413
16973
|
</mm-base-tree-detail>
|
|
16414
|
-
<div class="panel-accent-bottom"></div>
|
|
16415
16974
|
</div>
|
|
16416
|
-
|
|
16417
|
-
|
|
16418
|
-
<div class="lcars-footer">
|
|
16419
|
-
<div class="footer-bar bar-1"></div>
|
|
16420
|
-
<div class="footer-bar bar-2"></div>
|
|
16421
|
-
<div class="footer-bar bar-3"></div>
|
|
16422
|
-
<div class="footer-spacer"></div>
|
|
16423
|
-
<div class="footer-indicator">
|
|
16424
|
-
<span class="indicator-dot"></span>
|
|
16425
|
-
<span class="indicator-text">{{ resolvedMessages().ready }}</span>
|
|
16426
|
-
</div>
|
|
16427
|
-
</div>
|
|
16428
|
-
</div>
|
|
16429
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}.runtime-browser-container{display:flex;flex-direction:column;height:100%;padding:16px;gap:16px}::ng-deep mm-base-tree-detail .k-splitter{background:transparent;border:none}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar{background:linear-gradient(180deg,var(--octo-mint-30),transparent);width:4px!important}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar:hover{background:linear-gradient(180deg,var(--octo-mint-50),var(--octo-mint-20))}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf{font-family:Roboto,sans-serif;transition:all .2s ease;border-radius:4px}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf:hover{background:var(--octo-mint-10);color:var(--octo-mint)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected{background:linear-gradient(90deg,var(--octo-mint-20),transparent);color:var(--octo-mint);border-left:3px solid var(--octo-mint)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected:hover{background:linear-gradient(90deg,var(--octo-mint-25),transparent)}::ng-deep mm-base-tree-detail .toolbar{background:linear-gradient(90deg,var(--octo-mint-05),transparent);border-bottom:1px solid var(--octo-mint-20)}::ng-deep mm-base-tree-detail .base-tree-detail-container{height:100%;display:flex;flex-direction:column}::ng-deep mm-base-tree-detail .base-tree-detail-container .k-splitter{flex:1;min-height:0}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane{display:flex!important;flex-direction:column!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details{display:flex!important;flex:1!important;min-height:0!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details>.runtime-browser-details{flex:1;display:flex;flex-direction:column;min-height:0}@media(max-width:1024px){.runtime-browser-container{padding:12px;gap:12px}}@media(max-width:768px){.runtime-browser-container{padding:8px;gap:10px}}\n"] }]
|
|
16975
|
+
</mm-page>
|
|
16976
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}.runtime-browser-panel{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--theme-bg-surface);border:1px solid var(--theme-border-default);border-radius:var(--theme-radius-md, 6px);overflow:hidden}.runtime-browser-panel>mm-base-tree-detail{flex:1;display:flex;flex-direction:column;min-height:0}::ng-deep mm-base-tree-detail .k-splitter{background:transparent;border:none}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar{background:var(--theme-border-subtle);width:4px!important}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar:hover{background:var(--theme-border-strong)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf{font-family:var(--theme-font-ui, \"Roboto\", sans-serif);transition:background-color var(--theme-motion-fast, .12s) var(--theme-motion-easing, ease);border-radius:var(--theme-radius-sm, 4px)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf:hover{background:var(--theme-bg-hover)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected{background:var(--theme-bg-selected);color:var(--theme-text-accent)}::ng-deep mm-base-tree-detail .toolbar{background:var(--theme-bg-elevated);border-bottom:1px solid var(--theme-border-subtle)}::ng-deep mm-base-tree-detail .base-tree-detail-container{height:100%;display:flex;flex-direction:column}::ng-deep mm-base-tree-detail .base-tree-detail-container .k-splitter{flex:1;min-height:0}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane{display:flex!important;flex-direction:column!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details{display:flex!important;flex:1!important;min-height:0!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details>.runtime-browser-details{flex:1;display:flex;flex-direction:column;min-height:0}\n"] }]
|
|
16430
16977
|
}], propDecorators: { messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: false }] }], showDataMapping: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDataMapping", required: false }] }], expressionValidator: [{ type: i0.Input, args: [{ isSignal: true, alias: "expressionValidator", required: false }] }], treeDetail: [{
|
|
16431
16978
|
type: ViewChild,
|
|
16432
16979
|
args: ['treeDetail', { static: false }]
|
|
@@ -16714,7 +17261,10 @@ const GetDataPointMappingsDocumentDto = gql `
|
|
|
16714
17261
|
rtId
|
|
16715
17262
|
ckTypeId
|
|
16716
17263
|
rtWellKnownName
|
|
16717
|
-
attributes(
|
|
17264
|
+
attributes(
|
|
17265
|
+
attributeNames: ["name", "enabled", "sourceAttributePath", "targetAttributePath", "mappingExpression"]
|
|
17266
|
+
resolveEnumValuesToNames: true
|
|
17267
|
+
) {
|
|
16718
17268
|
items {
|
|
16719
17269
|
attributeName
|
|
16720
17270
|
value
|
|
@@ -16757,6 +17307,7 @@ class DataMappingOverviewComponent {
|
|
|
16757
17307
|
getEntityByIdGQL = inject(GetRuntimeEntityByIdDtoGQL);
|
|
16758
17308
|
updateEntitiesGQL = inject(UpdateRuntimeEntitiesDtoGQL);
|
|
16759
17309
|
deleteEntitiesGQL = inject(DeleteEntitiesDtoGQL);
|
|
17310
|
+
confirmation = inject(ConfirmationService);
|
|
16760
17311
|
navigateToEntity = new EventEmitter();
|
|
16761
17312
|
// State
|
|
16762
17313
|
mappings = signal([], /* @ts-ignore */
|
|
@@ -16787,7 +17338,7 @@ class DataMappingOverviewComponent {
|
|
|
16787
17338
|
checkIcon = checkCircleIcon;
|
|
16788
17339
|
warnIcon = exclamationCircleIcon;
|
|
16789
17340
|
errorIcon = xCircleIcon;
|
|
16790
|
-
deleteIcon =
|
|
17341
|
+
deleteIcon = MM_ACTION_ICONS.delete;
|
|
16791
17342
|
ngOnInit() {
|
|
16792
17343
|
this.loadMappings();
|
|
16793
17344
|
}
|
|
@@ -16846,6 +17397,16 @@ class DataMappingOverviewComponent {
|
|
|
16846
17397
|
}
|
|
16847
17398
|
}
|
|
16848
17399
|
async onDeleteMapping(item) {
|
|
17400
|
+
// Danger confirmation naming the mapping (AB#5579): the mapping entity is erased.
|
|
17401
|
+
const name = item.name || item.rtId;
|
|
17402
|
+
if (!await this.confirmation.showDangerConfirm({
|
|
17403
|
+
title: `Delete mapping ${name}?`,
|
|
17404
|
+
targetName: name,
|
|
17405
|
+
consequence: 'The data point mapping is erased. This cannot be undone.',
|
|
17406
|
+
confirmText: 'Delete mapping',
|
|
17407
|
+
})) {
|
|
17408
|
+
return;
|
|
17409
|
+
}
|
|
16849
17410
|
try {
|
|
16850
17411
|
await firstValueFrom(this.deleteEntitiesGQL.mutate({
|
|
16851
17412
|
variables: {
|
|
@@ -16866,10 +17427,12 @@ class DataMappingOverviewComponent {
|
|
|
16866
17427
|
mapEntityToOverviewItem(entity) {
|
|
16867
17428
|
const attrs = entity.attributes?.items ?? [];
|
|
16868
17429
|
const assocs = entity.associations?.definitions?.items ?? [];
|
|
16869
|
-
|
|
17430
|
+
// The server returns camelCase attribute names; compare case-insensitively.
|
|
17431
|
+
const findAttr = (name) => attrs.find(a => a?.attributeName?.toLowerCase() === name.toLowerCase());
|
|
17432
|
+
const getAttr = (name) => findAttr(name)?.value ?? '';
|
|
16870
17433
|
const mapsFrom = assocs.find(a => a && String(a.ckAssociationRoleId).includes('MapsFrom'));
|
|
16871
17434
|
const mapsTo = assocs.find(a => a && String(a.ckAssociationRoleId).includes('MapsTo'));
|
|
16872
|
-
const enabledRaw =
|
|
17435
|
+
const enabledRaw = findAttr('Enabled')?.value;
|
|
16873
17436
|
const enabled = enabledRaw === true || enabledRaw === 'true' || enabledRaw === 'True';
|
|
16874
17437
|
return {
|
|
16875
17438
|
rtId: String(entity.rtId),
|
|
@@ -16938,11 +17501,12 @@ class DataMappingOverviewComponent {
|
|
|
16938
17501
|
const loadPromises = [...entityRefs.values()].map(async (ref) => {
|
|
16939
17502
|
try {
|
|
16940
17503
|
const result = await firstValueFrom(this.getEntityByIdGQL.fetch({
|
|
16941
|
-
|
|
17504
|
+
// Only the display name is needed (SECRET-safe explicit list, AB#5542).
|
|
17505
|
+
variables: { rtId: ref.rtId, ckTypeId: ref.ckTypeId, attributeNames: ['name'] },
|
|
16942
17506
|
}));
|
|
16943
17507
|
const entity = result.data?.runtime?.runtimeEntities?.items?.[0];
|
|
16944
17508
|
if (entity) {
|
|
16945
|
-
const nameAttr = entity.attributes?.items?.find(a => a?.attributeName === '
|
|
17509
|
+
const nameAttr = entity.attributes?.items?.find(a => a?.attributeName?.toLowerCase() === 'name');
|
|
16946
17510
|
const name = nameAttr?.value
|
|
16947
17511
|
?? entity.rtWellKnownName
|
|
16948
17512
|
?? '';
|
|
@@ -17077,8 +17641,9 @@ class DataMappingOverviewComponent {
|
|
|
17077
17641
|
|
|
17078
17642
|
<kendo-grid-column title="" [width]="50" [sortable]="false">
|
|
17079
17643
|
<ng-template kendoGridCellTemplate let-dataItem>
|
|
17080
|
-
<button kendoButton fillMode="flat" size="small" [svgIcon]="deleteIcon"
|
|
17081
|
-
|
|
17644
|
+
<button kendoButton fillMode="flat" size="small" themeColor="error" [svgIcon]="deleteIcon"
|
|
17645
|
+
title="Delete mapping" [attr.aria-label]="'Delete mapping ' + (dataItem.name || dataItem.rtId)"
|
|
17646
|
+
data-action="delete" (click)="onDeleteMapping(dataItem); $event.stopPropagation()">
|
|
17082
17647
|
</button>
|
|
17083
17648
|
</ng-template>
|
|
17084
17649
|
</kendo-grid-column>
|
|
@@ -17142,7 +17707,7 @@ class DataMappingOverviewComponent {
|
|
|
17142
17707
|
<div class="loading-overlay">Loading mappings...</div>
|
|
17143
17708
|
}
|
|
17144
17709
|
</div>
|
|
17145
|
-
`, isInline: true, styles: [".mapping-overview{display:flex;flex-direction:column;gap:12px;padding:16px}.summary-bar{display:flex;gap:16px;align-items:center;padding:8px 12px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;background:var(--kendo-color-surface-alt, #f8f9fa)}.summary-item{display:flex;flex-direction:column;align-items:center;min-width:60px}.summary-count{font-size:1.2rem;font-weight:700}.summary-label{font-size:.7rem;
|
|
17710
|
+
`, isInline: true, styles: [".mapping-overview{display:flex;flex-direction:column;gap:12px;padding:16px}.summary-bar{display:flex;gap:16px;align-items:center;padding:8px 12px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;background:var(--kendo-color-surface-alt, #f8f9fa)}.summary-item{display:flex;flex-direction:column;align-items:center;min-width:60px}.summary-count{font-size:1.2rem;font-weight:700}.summary-label{font-size:.7rem;color:var(--kendo-color-subtle, #6c757d)}.summary-valid .summary-count{color:var(--kendo-color-success, #28a745)}.summary-warnings .summary-count{color:var(--kendo-color-warning, #ffc107)}.summary-errors .summary-count{color:var(--kendo-color-error, #dc3545)}.summary-disabled .summary-count{color:var(--kendo-color-subtle, #6c757d)}.summary-spacer{flex:1}.status-valid{color:var(--kendo-color-success, #28a745)}.status-warning{color:var(--kendo-color-warning, #ffc107)}.status-error{color:var(--kendo-color-error, #dc3545)}.entity-ref{cursor:pointer;color:var(--kendo-color-primary, #ff6358);font-family:monospace;font-size:.85rem}.entity-ref:hover{text-decoration:underline}.no-target{color:var(--kendo-color-subtle, #6c757d);font-style:italic}.entity-type-hint{font-size:.7rem;color:var(--kendo-color-subtle, #6c757d);font-family:monospace}.expression-cell{font-size:.85rem;background:var(--kendo-color-surface-alt, #f8f9fa);padding:2px 4px;border-radius:3px}.detail-panel{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;padding:12px 16px}.detail-panel h4{margin:0 0 12px;font-size:.9rem;font-weight:600}.detail-grid{display:grid;grid-template-columns:120px 1fr;gap:6px 12px}.detail-row{display:contents}.detail-row label{font-size:.75rem;font-weight:600;color:var(--kendo-color-subtle, #6c757d);padding-top:2px}.detail-row span,.detail-row code{font-size:.85rem}.validation-section{margin-top:12px;padding-top:8px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.validation-section h5{margin:0 0 6px;font-size:.8rem;font-weight:600}.validation-msg{font-size:.8rem;padding:2px 0}.validation-error{color:var(--kendo-color-error, #dc3545)}.validation-warning{color:var(--kendo-color-warning, #ffc107)}.validation-info{color:var(--kendo-color-info, #17a2b8)}.loading-overlay{text-align:center;padding:20px;color:var(--kendo-color-subtle, #6c757d)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: SVGIconModule }, { kind: "component", type: i5$1.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }, { kind: "ngmodule", type: GridModule }, { kind: "component", type: i3.GridComponent, selector: "kendo-grid", inputs: ["data", "pageSize", "height", "rowHeight", "adaptiveMode", "detailRowHeight", "skip", "scrollable", "selectable", "sort", "size", "trackBy", "filter", "group", "virtualColumns", "filterable", "sortable", "pageable", "groupable", "gridResizable", "rowReorderable", "navigable", "autoSize", "rowClass", "rowSticky", "rowSelected", "isRowSelectable", "cellSelected", "resizable", "reorderable", "loading", "columnMenu", "hideHeader", "showInactiveTools", "isDetailExpanded", "isGroupExpanded", "dataLayoutMode", "pinnable", "pinnedTopRows", "pinnedBottomRows", "isRowPinnable"], outputs: ["filterChange", "pageChange", "groupChange", "sortChange", "selectionChange", "rowReorder", "rowPinChange", "dataStateChange", "gridStateChange", "groupExpand", "groupCollapse", "detailExpand", "detailCollapse", "edit", "cancel", "save", "remove", "add", "cellClose", "cellClick", "pdfExport", "excelExport", "csvExport", "columnResize", "columnReorder", "columnVisibilityChange", "columnLockedChange", "columnStickyChange", "scrollBottom", "contentScroll"], exportAs: ["kendoGrid"] }, { kind: "component", type: i3.ColumnComponent, selector: "kendo-grid-column", inputs: ["field", "format", "sortable", "groupable", "editor", "filter", "filterVariant", "filterable", "editable"] }, { kind: "directive", type: i3.CellTemplateDirective, selector: "[kendoGridCellTemplate]" }, { kind: "ngmodule", type: BadgeModule }, { kind: "ngmodule", type: SwitchModule }, { kind: "component", type: i5.SwitchComponent, selector: "kendo-switch", inputs: ["focusableId", "onLabel", "offLabel", "checked", "disabled", "readonly", "tabindex", "size", "thumbRounded", "trackRounded", "tabIndex"], outputs: ["focus", "blur", "valueChange"], exportAs: ["kendoSwitch"] }, { kind: "pipe", type: i1$2.SlicePipe, name: "slice" }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
17146
17711
|
}
|
|
17147
17712
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: DataMappingOverviewComponent, decorators: [{
|
|
17148
17713
|
type: Component,
|
|
@@ -17254,8 +17819,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
17254
17819
|
|
|
17255
17820
|
<kendo-grid-column title="" [width]="50" [sortable]="false">
|
|
17256
17821
|
<ng-template kendoGridCellTemplate let-dataItem>
|
|
17257
|
-
<button kendoButton fillMode="flat" size="small" [svgIcon]="deleteIcon"
|
|
17258
|
-
|
|
17822
|
+
<button kendoButton fillMode="flat" size="small" themeColor="error" [svgIcon]="deleteIcon"
|
|
17823
|
+
title="Delete mapping" [attr.aria-label]="'Delete mapping ' + (dataItem.name || dataItem.rtId)"
|
|
17824
|
+
data-action="delete" (click)="onDeleteMapping(dataItem); $event.stopPropagation()">
|
|
17259
17825
|
</button>
|
|
17260
17826
|
</ng-template>
|
|
17261
17827
|
</kendo-grid-column>
|
|
@@ -17319,7 +17885,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
17319
17885
|
<div class="loading-overlay">Loading mappings...</div>
|
|
17320
17886
|
}
|
|
17321
17887
|
</div>
|
|
17322
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".mapping-overview{display:flex;flex-direction:column;gap:12px;padding:16px}.summary-bar{display:flex;gap:16px;align-items:center;padding:8px 12px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;background:var(--kendo-color-surface-alt, #f8f9fa)}.summary-item{display:flex;flex-direction:column;align-items:center;min-width:60px}.summary-count{font-size:1.2rem;font-weight:700}.summary-label{font-size:.7rem;
|
|
17888
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".mapping-overview{display:flex;flex-direction:column;gap:12px;padding:16px}.summary-bar{display:flex;gap:16px;align-items:center;padding:8px 12px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;background:var(--kendo-color-surface-alt, #f8f9fa)}.summary-item{display:flex;flex-direction:column;align-items:center;min-width:60px}.summary-count{font-size:1.2rem;font-weight:700}.summary-label{font-size:.7rem;color:var(--kendo-color-subtle, #6c757d)}.summary-valid .summary-count{color:var(--kendo-color-success, #28a745)}.summary-warnings .summary-count{color:var(--kendo-color-warning, #ffc107)}.summary-errors .summary-count{color:var(--kendo-color-error, #dc3545)}.summary-disabled .summary-count{color:var(--kendo-color-subtle, #6c757d)}.summary-spacer{flex:1}.status-valid{color:var(--kendo-color-success, #28a745)}.status-warning{color:var(--kendo-color-warning, #ffc107)}.status-error{color:var(--kendo-color-error, #dc3545)}.entity-ref{cursor:pointer;color:var(--kendo-color-primary, #ff6358);font-family:monospace;font-size:.85rem}.entity-ref:hover{text-decoration:underline}.no-target{color:var(--kendo-color-subtle, #6c757d);font-style:italic}.entity-type-hint{font-size:.7rem;color:var(--kendo-color-subtle, #6c757d);font-family:monospace}.expression-cell{font-size:.85rem;background:var(--kendo-color-surface-alt, #f8f9fa);padding:2px 4px;border-radius:3px}.detail-panel{border:1px solid var(--kendo-color-border, #dee2e6);border-radius:6px;padding:12px 16px}.detail-panel h4{margin:0 0 12px;font-size:.9rem;font-weight:600}.detail-grid{display:grid;grid-template-columns:120px 1fr;gap:6px 12px}.detail-row{display:contents}.detail-row label{font-size:.75rem;font-weight:600;color:var(--kendo-color-subtle, #6c757d);padding-top:2px}.detail-row span,.detail-row code{font-size:.85rem}.validation-section{margin-top:12px;padding-top:8px;border-top:1px solid var(--kendo-color-border, #dee2e6)}.validation-section h5{margin:0 0 6px;font-size:.8rem;font-weight:600}.validation-msg{font-size:.8rem;padding:2px 0}.validation-error{color:var(--kendo-color-error, #dc3545)}.validation-warning{color:var(--kendo-color-warning, #ffc107)}.validation-info{color:var(--kendo-color-info, #17a2b8)}.loading-overlay{text-align:center;padding:20px;color:var(--kendo-color-subtle, #6c757d)}\n"] }]
|
|
17323
17889
|
}], propDecorators: { navigateToEntity: [{
|
|
17324
17890
|
type: Output
|
|
17325
17891
|
}] } });
|
|
@@ -17342,7 +17908,10 @@ const GetLatestValidationExecutionDocumentDto = gql `
|
|
|
17342
17908
|
items {
|
|
17343
17909
|
rtId
|
|
17344
17910
|
ckTypeId
|
|
17345
|
-
attributes(
|
|
17911
|
+
attributes(
|
|
17912
|
+
attributeNames: ["outputData", "completedAt"]
|
|
17913
|
+
resolveEnumValuesToNames: true
|
|
17914
|
+
) {
|
|
17346
17915
|
items {
|
|
17347
17916
|
attributeName
|
|
17348
17917
|
value
|
|
@@ -17388,7 +17957,10 @@ const GetNodeMappingsDocumentDto = gql `
|
|
|
17388
17957
|
items {
|
|
17389
17958
|
rtId
|
|
17390
17959
|
ckTypeId
|
|
17391
|
-
attributes(
|
|
17960
|
+
attributes(
|
|
17961
|
+
attributeNames: ["name", "enabled", "sourceAttributePath", "targetAttributePath", "mappingExpression"]
|
|
17962
|
+
resolveEnumValuesToNames: true
|
|
17963
|
+
) {
|
|
17392
17964
|
items {
|
|
17393
17965
|
attributeName
|
|
17394
17966
|
value
|
|
@@ -17847,7 +18419,7 @@ class BulkMappingDialogComponent {
|
|
|
17847
18419
|
[svgIcon]="browseIcon"
|
|
17848
18420
|
[disabled]="!targetCkTypeId()"
|
|
17849
18421
|
(click)="browseTargetAttribute()"
|
|
17850
|
-
title="Browse all attributes (incl. navigation properties)"></button>
|
|
18422
|
+
title="Browse all attributes (incl. navigation properties)" aria-label="Browse all attributes (incl. navigation properties)"></button>
|
|
17851
18423
|
</div>
|
|
17852
18424
|
</div>
|
|
17853
18425
|
</div>
|
|
@@ -17857,7 +18429,7 @@ class BulkMappingDialogComponent {
|
|
|
17857
18429
|
[disabled]="!isValid()">Create {{ sources().length }} mappings</button>
|
|
17858
18430
|
</div>
|
|
17859
18431
|
</div>
|
|
17860
|
-
`, isInline: true, styles: [".bulk-mapping{display:flex;flex-direction:column;height:100%;box-sizing:border-box}.bulk-mapping-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px 18px;display:flex;flex-direction:column;gap:14px}.field-row{display:flex;flex-direction:column;gap:4px}.field-row label{font-size:.72rem;font-weight:600;
|
|
18432
|
+
`, isInline: true, styles: [".bulk-mapping{display:flex;flex-direction:column;height:100%;box-sizing:border-box}.bulk-mapping-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px 18px;display:flex;flex-direction:column;gap:14px}.field-row{display:flex;flex-direction:column;gap:4px}.field-row label{font-size:.72rem;font-weight:600;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.field-row .hint{font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-style:italic}.field-row.inline{flex-direction:row;align-items:center;gap:8px}.source-summary{display:flex;flex-direction:column;gap:2px;padding:6px 10px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:4px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.source-summary .source-count{font-weight:600;font-size:.85rem}.source-summary .source-preview{font-size:.72rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.entity-display{display:flex;flex-direction:column;gap:2px;padding:6px 10px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:4px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.entity-display.empty{flex-direction:row;align-items:center;justify-content:space-between}.entity-main{display:flex;align-items:center;gap:8px}.entity-main .entity-name{flex:1;font-weight:600;font-size:.9rem}.entity-meta{display:flex;align-items:center;flex-wrap:wrap;gap:2px;font-size:.7rem;font-family:monospace;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));word-break:break-all}.entity-meta .sep{opacity:.7}.combo-row{display:flex;align-items:stretch;gap:4px}.combo-row kendo-combobox{flex:1}.loading-pill{margin-left:6px;font-size:.65rem;padding:1px 6px;border-radius:8px;background:color-mix(in srgb,var(--kendo-color-info, #0dcaf0) 18%,transparent);color:var(--kendo-color-info, #0dcaf0);text-transform:none;font-style:italic}.expression-preview{display:flex;align-items:center;flex-wrap:wrap;gap:6px;padding:4px 10px;border-radius:4px;font-size:.75rem;background:color-mix(in srgb,var(--kendo-color-success, #28a745) 10%,transparent)}.expression-preview.expression-preview-error{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 10%,transparent)}.expression-preview .preview-label{font-weight:600;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.expression-preview code{font-family:monospace}.expression-preview .preview-arrow{opacity:.7}.expression-preview .preview-note{font-style:italic;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.expression-preview .preview-error-text{color:var(--kendo-color-error, #dc3545)}.dialog-actions{flex:0 0 auto;display:flex;gap:8px;justify-content:flex-end;padding:10px 18px;border-top:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 70%,transparent)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: ComboBoxModule }, { kind: "component", type: i3$1.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: "ngmodule", type: SwitchModule }, { kind: "component", type: i5.SwitchComponent, selector: "kendo-switch", inputs: ["focusableId", "onLabel", "offLabel", "checked", "disabled", "readonly", "tabindex", "size", "thumbRounded", "trackRounded", "tabIndex"], outputs: ["focus", "blur", "valueChange"], exportAs: ["kendoSwitch"] }, { kind: "ngmodule", type: TextBoxModule }, { kind: "component", type: i5.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: DataPointPickerComponent, selector: "mm-data-point-picker", inputs: ["entity", "entityRtId", "entityCkTypeId", "value", "placeholder", "disabled"], outputs: ["valueChange", "filterChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
17861
18433
|
}
|
|
17862
18434
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: BulkMappingDialogComponent, decorators: [{
|
|
17863
18435
|
type: Component,
|
|
@@ -17973,7 +18545,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
17973
18545
|
[svgIcon]="browseIcon"
|
|
17974
18546
|
[disabled]="!targetCkTypeId()"
|
|
17975
18547
|
(click)="browseTargetAttribute()"
|
|
17976
|
-
title="Browse all attributes (incl. navigation properties)"></button>
|
|
18548
|
+
title="Browse all attributes (incl. navigation properties)" aria-label="Browse all attributes (incl. navigation properties)"></button>
|
|
17977
18549
|
</div>
|
|
17978
18550
|
</div>
|
|
17979
18551
|
</div>
|
|
@@ -17983,7 +18555,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
17983
18555
|
[disabled]="!isValid()">Create {{ sources().length }} mappings</button>
|
|
17984
18556
|
</div>
|
|
17985
18557
|
</div>
|
|
17986
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".bulk-mapping{display:flex;flex-direction:column;height:100%;box-sizing:border-box}.bulk-mapping-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px 18px;display:flex;flex-direction:column;gap:14px}.field-row{display:flex;flex-direction:column;gap:4px}.field-row label{font-size:.72rem;font-weight:600;
|
|
18558
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".bulk-mapping{display:flex;flex-direction:column;height:100%;box-sizing:border-box}.bulk-mapping-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px 18px;display:flex;flex-direction:column;gap:14px}.field-row{display:flex;flex-direction:column;gap:4px}.field-row label{font-size:.72rem;font-weight:600;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.field-row .hint{font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-style:italic}.field-row.inline{flex-direction:row;align-items:center;gap:8px}.source-summary{display:flex;flex-direction:column;gap:2px;padding:6px 10px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:4px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.source-summary .source-count{font-weight:600;font-size:.85rem}.source-summary .source-preview{font-size:.72rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.entity-display{display:flex;flex-direction:column;gap:2px;padding:6px 10px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:4px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.entity-display.empty{flex-direction:row;align-items:center;justify-content:space-between}.entity-main{display:flex;align-items:center;gap:8px}.entity-main .entity-name{flex:1;font-weight:600;font-size:.9rem}.entity-meta{display:flex;align-items:center;flex-wrap:wrap;gap:2px;font-size:.7rem;font-family:monospace;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));word-break:break-all}.entity-meta .sep{opacity:.7}.combo-row{display:flex;align-items:stretch;gap:4px}.combo-row kendo-combobox{flex:1}.loading-pill{margin-left:6px;font-size:.65rem;padding:1px 6px;border-radius:8px;background:color-mix(in srgb,var(--kendo-color-info, #0dcaf0) 18%,transparent);color:var(--kendo-color-info, #0dcaf0);text-transform:none;font-style:italic}.expression-preview{display:flex;align-items:center;flex-wrap:wrap;gap:6px;padding:4px 10px;border-radius:4px;font-size:.75rem;background:color-mix(in srgb,var(--kendo-color-success, #28a745) 10%,transparent)}.expression-preview.expression-preview-error{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 10%,transparent)}.expression-preview .preview-label{font-weight:600;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.expression-preview code{font-family:monospace}.expression-preview .preview-arrow{opacity:.7}.expression-preview .preview-note{font-style:italic;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.expression-preview .preview-error-text{color:var(--kendo-color-error, #dc3545)}.dialog-actions{flex:0 0 auto;display:flex;gap:8px;justify-content:flex-end;padding:10px 18px;border-top:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 70%,transparent)}\n"] }]
|
|
17987
18559
|
}], propDecorators: { sourcePicker: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DataPointPickerComponent), { isSignal: true }] }] } });
|
|
17988
18560
|
|
|
17989
18561
|
const DIALOG_KEY$1 = 'bulk-mapping-dialog';
|
|
@@ -18964,7 +19536,7 @@ class MappingEditDialogComponent {
|
|
|
18964
19536
|
[svgIcon]="icons.regenerate"
|
|
18965
19537
|
[disabled]="!canGenerateName()"
|
|
18966
19538
|
(click)="generateName()"
|
|
18967
|
-
title="Generate name from source + target"></button>
|
|
19539
|
+
title="Generate name from source + target" aria-label="Generate name from source + target"></button>
|
|
18968
19540
|
</div>
|
|
18969
19541
|
</div>
|
|
18970
19542
|
|
|
@@ -19101,7 +19673,7 @@ class MappingEditDialogComponent {
|
|
|
19101
19673
|
[svgIcon]="icons.browse"
|
|
19102
19674
|
[disabled]="!effectiveTargetCkTypeId()"
|
|
19103
19675
|
(click)="browseTargetAttribute()"
|
|
19104
|
-
title="Browse all attributes (incl. navigation properties)"></button>
|
|
19676
|
+
title="Browse all attributes (incl. navigation properties)" aria-label="Browse all attributes (incl. navigation properties)"></button>
|
|
19105
19677
|
</div>
|
|
19106
19678
|
<span class="hint">
|
|
19107
19679
|
@if (effectiveTargetCkTypeId(); as t) {
|
|
@@ -19120,7 +19692,7 @@ class MappingEditDialogComponent {
|
|
|
19120
19692
|
[disabled]="!isValid()">Save</button>
|
|
19121
19693
|
</div>
|
|
19122
19694
|
</div>
|
|
19123
|
-
`, isInline: true, styles: [".mapping-edit{display:flex;flex-direction:column;height:100%;box-sizing:border-box}.mapping-edit-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px 18px;display:flex;flex-direction:column;gap:14px}.field-row{display:flex;flex-direction:column;gap:4px}.field-row label{font-size:.72rem;font-weight:600;
|
|
19695
|
+
`, isInline: true, styles: [".mapping-edit{display:flex;flex-direction:column;height:100%;box-sizing:border-box}.mapping-edit-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px 18px;display:flex;flex-direction:column;gap:14px}.field-row{display:flex;flex-direction:column;gap:4px}.field-row label{font-size:.72rem;font-weight:600;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.field-row .hint{font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-style:italic}.field-row.inline{flex-direction:row;align-items:center;gap:8px}.entity-display{display:flex;flex-direction:column;gap:2px;padding:6px 10px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:4px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.entity-display.empty{flex-direction:row;align-items:center;justify-content:space-between}.entity-main{display:flex;align-items:center;gap:8px}.entity-main .entity-name{flex:1;font-weight:600;font-size:.9rem}.entity-meta{display:flex;align-items:center;flex-wrap:wrap;gap:2px;font-size:.7rem;font-family:monospace;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));word-break:break-all}.entity-meta .sep{opacity:.7}.dialog-actions{flex:0 0 auto;display:flex;gap:8px;justify-content:flex-end;padding:10px 18px;border-top:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 70%,transparent)}.combo-row{display:flex;align-items:stretch;gap:4px}.combo-row kendo-combobox{flex:1}.attribute-option{display:flex;justify-content:space-between;align-items:center;width:100%;gap:8px}.attribute-option .attribute-path{flex:1;font-family:monospace;font-size:.85rem}.attribute-option .attribute-type{font-size:.7rem;padding:1px 6px;border-radius:8px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f0f0f0)) 80%,transparent);color:var(--theme-text-secondary, var(--kendo-color-subtle, #888))}.loading-pill{margin-left:6px;font-size:.65rem;padding:1px 6px;border-radius:8px;background:color-mix(in srgb,var(--kendo-color-info, #0dcaf0) 18%,transparent);color:var(--kendo-color-info, #0dcaf0);text-transform:none;font-style:italic}.expression-preview{display:flex;align-items:center;flex-wrap:wrap;gap:6px;padding:4px 10px;border-radius:4px;font-size:.75rem;background:color-mix(in srgb,var(--kendo-color-success, #28a745) 10%,transparent)}.expression-preview.expression-preview-error{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 10%,transparent)}.expression-preview .preview-label{font-weight:600;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.expression-preview code{font-family:monospace}.expression-preview .preview-arrow{opacity:.7}.expression-preview .preview-note{font-style:italic;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.expression-preview .preview-error-text{color:var(--kendo-color-error, #dc3545)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: ComboBoxModule }, { kind: "component", type: i3$1.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: "directive", type: i3$1.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "ngmodule", type: SVGIconModule }, { kind: "ngmodule", type: SwitchModule }, { kind: "component", type: i5.SwitchComponent, selector: "kendo-switch", inputs: ["focusableId", "onLabel", "offLabel", "checked", "disabled", "readonly", "tabindex", "size", "thumbRounded", "trackRounded", "tabIndex"], outputs: ["focus", "blur", "valueChange"], exportAs: ["kendoSwitch"] }, { kind: "ngmodule", type: TextBoxModule }, { kind: "component", type: i5.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: DataPointPickerComponent, selector: "mm-data-point-picker", inputs: ["entity", "entityRtId", "entityCkTypeId", "value", "placeholder", "disabled"], outputs: ["valueChange", "filterChange"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
19124
19696
|
}
|
|
19125
19697
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: MappingEditDialogComponent, decorators: [{
|
|
19126
19698
|
type: Component,
|
|
@@ -19146,7 +19718,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
19146
19718
|
[svgIcon]="icons.regenerate"
|
|
19147
19719
|
[disabled]="!canGenerateName()"
|
|
19148
19720
|
(click)="generateName()"
|
|
19149
|
-
title="Generate name from source + target"></button>
|
|
19721
|
+
title="Generate name from source + target" aria-label="Generate name from source + target"></button>
|
|
19150
19722
|
</div>
|
|
19151
19723
|
</div>
|
|
19152
19724
|
|
|
@@ -19283,7 +19855,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
19283
19855
|
[svgIcon]="icons.browse"
|
|
19284
19856
|
[disabled]="!effectiveTargetCkTypeId()"
|
|
19285
19857
|
(click)="browseTargetAttribute()"
|
|
19286
|
-
title="Browse all attributes (incl. navigation properties)"></button>
|
|
19858
|
+
title="Browse all attributes (incl. navigation properties)" aria-label="Browse all attributes (incl. navigation properties)"></button>
|
|
19287
19859
|
</div>
|
|
19288
19860
|
<span class="hint">
|
|
19289
19861
|
@if (effectiveTargetCkTypeId(); as t) {
|
|
@@ -19302,7 +19874,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
19302
19874
|
[disabled]="!isValid()">Save</button>
|
|
19303
19875
|
</div>
|
|
19304
19876
|
</div>
|
|
19305
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".mapping-edit{display:flex;flex-direction:column;height:100%;box-sizing:border-box}.mapping-edit-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px 18px;display:flex;flex-direction:column;gap:14px}.field-row{display:flex;flex-direction:column;gap:4px}.field-row label{font-size:.72rem;font-weight:600;
|
|
19877
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".mapping-edit{display:flex;flex-direction:column;height:100%;box-sizing:border-box}.mapping-edit-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px 18px;display:flex;flex-direction:column;gap:14px}.field-row{display:flex;flex-direction:column;gap:4px}.field-row label{font-size:.72rem;font-weight:600;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.field-row .hint{font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-style:italic}.field-row.inline{flex-direction:row;align-items:center;gap:8px}.entity-display{display:flex;flex-direction:column;gap:2px;padding:6px 10px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:4px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.entity-display.empty{flex-direction:row;align-items:center;justify-content:space-between}.entity-main{display:flex;align-items:center;gap:8px}.entity-main .entity-name{flex:1;font-weight:600;font-size:.9rem}.entity-meta{display:flex;align-items:center;flex-wrap:wrap;gap:2px;font-size:.7rem;font-family:monospace;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));word-break:break-all}.entity-meta .sep{opacity:.7}.dialog-actions{flex:0 0 auto;display:flex;gap:8px;justify-content:flex-end;padding:10px 18px;border-top:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 70%,transparent)}.combo-row{display:flex;align-items:stretch;gap:4px}.combo-row kendo-combobox{flex:1}.attribute-option{display:flex;justify-content:space-between;align-items:center;width:100%;gap:8px}.attribute-option .attribute-path{flex:1;font-family:monospace;font-size:.85rem}.attribute-option .attribute-type{font-size:.7rem;padding:1px 6px;border-radius:8px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f0f0f0)) 80%,transparent);color:var(--theme-text-secondary, var(--kendo-color-subtle, #888))}.loading-pill{margin-left:6px;font-size:.65rem;padding:1px 6px;border-radius:8px;background:color-mix(in srgb,var(--kendo-color-info, #0dcaf0) 18%,transparent);color:var(--kendo-color-info, #0dcaf0);text-transform:none;font-style:italic}.expression-preview{display:flex;align-items:center;flex-wrap:wrap;gap:6px;padding:4px 10px;border-radius:4px;font-size:.75rem;background:color-mix(in srgb,var(--kendo-color-success, #28a745) 10%,transparent)}.expression-preview.expression-preview-error{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 10%,transparent)}.expression-preview .preview-label{font-weight:600;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.expression-preview code{font-family:monospace}.expression-preview .preview-arrow{opacity:.7}.expression-preview .preview-note{font-style:italic;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.expression-preview .preview-error-text{color:var(--kendo-color-error, #dc3545)}\n"] }]
|
|
19306
19878
|
}], propDecorators: { sourcePicker: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DataPointPickerComponent), { isSignal: true }] }] } });
|
|
19307
19879
|
/**
|
|
19308
19880
|
* Client-side filter mirroring the substring search Kendo's combobox does
|
|
@@ -19477,15 +20049,15 @@ class MappingCoverageTreeComponent {
|
|
|
19477
20049
|
expressionEvaluator = null;
|
|
19478
20050
|
entitySelected = new EventEmitter();
|
|
19479
20051
|
icons = {
|
|
19480
|
-
refresh:
|
|
20052
|
+
refresh: MM_ACTION_ICONS.refresh,
|
|
19481
20053
|
folderOpen: folderOpenIcon,
|
|
19482
|
-
plus:
|
|
19483
|
-
pencil:
|
|
19484
|
-
trash:
|
|
20054
|
+
plus: MM_ACTION_ICONS.add,
|
|
20055
|
+
pencil: MM_ACTION_ICONS.edit,
|
|
20056
|
+
trash: MM_ACTION_ICONS.delete,
|
|
19485
20057
|
link: linkIcon,
|
|
19486
20058
|
x: xIcon,
|
|
19487
|
-
download:
|
|
19488
|
-
upload:
|
|
20059
|
+
download: MM_ACTION_ICONS.export,
|
|
20060
|
+
upload: MM_ACTION_ICONS.import,
|
|
19489
20061
|
};
|
|
19490
20062
|
/** Selectable tree perspectives (built-in Spatial + per-tenant configured). */
|
|
19491
20063
|
perspectives = signal([
|
|
@@ -20428,6 +21000,8 @@ class MappingCoverageTreeComponent {
|
|
|
20428
21000
|
.fetch({
|
|
20429
21001
|
variables: {
|
|
20430
21002
|
ckTypeId: this.config.validationPipelineCkTypeId,
|
|
21003
|
+
// Only the pipeline definition is read (SECRET-safe explicit list, AB#5542).
|
|
21004
|
+
attributeNames: ['pipelineDefinition'],
|
|
20431
21005
|
first: 200,
|
|
20432
21006
|
after: GraphQL.offsetToCursor(0),
|
|
20433
21007
|
},
|
|
@@ -20669,7 +21243,13 @@ class MappingCoverageTreeComponent {
|
|
|
20669
21243
|
}
|
|
20670
21244
|
}
|
|
20671
21245
|
async deleteMapping(mapping) {
|
|
20672
|
-
const
|
|
21246
|
+
const name = mapping.name || mapping.rtId;
|
|
21247
|
+
const confirmed = await this.confirmation.showDangerConfirm({
|
|
21248
|
+
title: `Delete mapping ${name}?`,
|
|
21249
|
+
targetName: name,
|
|
21250
|
+
consequence: 'The data point mapping is erased. This cannot be undone.',
|
|
21251
|
+
confirmText: 'Delete mapping',
|
|
21252
|
+
});
|
|
20673
21253
|
if (!confirmed)
|
|
20674
21254
|
return;
|
|
20675
21255
|
try {
|
|
@@ -20695,6 +21275,8 @@ class MappingCoverageTreeComponent {
|
|
|
20695
21275
|
.fetch({
|
|
20696
21276
|
variables: {
|
|
20697
21277
|
ckTypeId: this.activeRootCkTypeId(),
|
|
21278
|
+
// Only rt* fields are read (SECRET-safe, AB#5542).
|
|
21279
|
+
attributeNames: [],
|
|
20698
21280
|
first: 200,
|
|
20699
21281
|
after: GraphQL.offsetToCursor(0),
|
|
20700
21282
|
},
|
|
@@ -20801,7 +21383,8 @@ class MappingCoverageTreeComponent {
|
|
|
20801
21383
|
try {
|
|
20802
21384
|
const data = await firstValueFrom(this.getRuntimeEntityByIdGQL
|
|
20803
21385
|
.fetch({
|
|
20804
|
-
|
|
21386
|
+
// Only rtDisplayName is read — no attributes (SECRET-safe, AB#5542).
|
|
21387
|
+
variables: { rtId: ref.rtId, ckTypeId: ref.ckTypeId, attributeNames: [] },
|
|
20805
21388
|
fetchPolicy: 'cache-first',
|
|
20806
21389
|
})
|
|
20807
21390
|
.pipe(map(r => r.data?.runtime?.runtimeEntities?.items?.[0])));
|
|
@@ -20826,7 +21409,7 @@ class MappingCoverageTreeComponent {
|
|
|
20826
21409
|
this.mappings.set(next);
|
|
20827
21410
|
}
|
|
20828
21411
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: MappingCoverageTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
20829
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: MappingCoverageTreeComponent, isStandalone: true, selector: "mm-mapping-coverage-tree", inputs: { config: "config", initialRoot: "initialRoot", tenantId: "tenantId", expressionEvaluator: "expressionEvaluator" }, outputs: { entitySelected: "entitySelected" }, providers: [MappingCoverageTreeDataSource], viewQueries: [{ propertyName: "treeView", first: true, predicate: TreeComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"coverage-root\">\n @if (config.sourceCandidateCkTypeIds.length > 0) {\n <div class=\"coverage-tabs\" role=\"tablist\">\n <button class=\"coverage-tab\"\n [class.active]=\"activeTab() === 'coverage'\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === 'coverage'\"\n (click)=\"selectTab('coverage')\">Coverage Tree</button>\n <button class=\"coverage-tab\"\n [class.active]=\"activeTab() === 'orphans'\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === 'orphans'\"\n (click)=\"selectTab('orphans')\">\n Orphan Sources\n @if (orphanStats(); as s) {\n @if (s.unmapped > 0) { <span class=\"tab-badge\">{{ s.unmapped }}</span> }\n }\n </button>\n </div>\n }\n\n @if (activeTab() === 'coverage') {\n <div class=\"coverage-toolbar\">\n <mm-perspective-switcher\n [perspectives]=\"perspectives()\"\n [activeKey]=\"activePerspectiveKey()\"\n (perspectiveChange)=\"onPerspectiveChange($event)\"></mm-perspective-switcher>\n <label class=\"toolbar-label\">Tree:</label>\n <select class=\"root-select\"\n [value]=\"selectedRoot()?.rtId ?? ''\"\n (change)=\"onRootSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a {{ activeRootCkTypeId() }} \u2014</option>\n @for (root of rootCandidates(); track root.rtId) {\n <option [value]=\"root.rtId\" [title]=\"root.description\">{{ root.name }}</option>\n }\n </select>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n (click)=\"refreshRoots()\" title=\"Refresh tree list\"></button>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.folderOpen\"\n (click)=\"pickRoot()\" title=\"Browse for entity\">Browse...</button>\n\n @if (selectedRoot(); as root) {\n <div class=\"toolbar-spacer\"></div>\n <span class=\"toolbar-meta\">\n <span class=\"meta-name\">{{ root.name }}</span>\n <span class=\"meta-type\">{{ root.ckTypeId }}</span>\n </span>\n }\n </div>\n\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Validation:</label>\n <select class=\"root-select\"\n [value]=\"selectedPipeline()?.rtId ?? ''\"\n (change)=\"onPipelineSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a {{ config.validationPipelineCkTypeId }} \u2014</option>\n @for (p of validationPipelines(); track p.rtId) {\n <option [value]=\"p.rtId\">{{ p.name }}</option>\n }\n </select>\n @if (tenantId) {\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"!selectedPipeline() || validationRunning() || validationLoading()\"\n (click)=\"runValidation()\"\n [title]=\"validationRunning() ? 'Validation running\u2026' : 'Run pipeline + load report'\">\n @if (validationRunning()) { Running\u2026 } @else { Run }\n </button>\n }\n <button kendoButton fillMode=\"solid\" size=\"small\" [svgIcon]=\"icons.refresh\"\n [disabled]=\"!selectedPipeline() || validationLoading() || validationRunning()\"\n (click)=\"refreshValidation()\">Load Report</button>\n @if (validationSummary()) {\n <button kendoButton fillMode=\"flat\" size=\"small\"\n (click)=\"clearValidation()\">Clear</button>\n }\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (validationLoading()) {\n <span class=\"toolbar-meta\">Loading\u2026</span>\n } @else if (validationError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (validationSummary(); as s) {\n <span class=\"validation-summary\">\n <span class=\"badge badge-error\" title=\"error\">{{ s.error }} err</span>\n <span class=\"badge badge-warning\" title=\"warning\">{{ s.warning }} warn</span>\n <span class=\"badge badge-ok\" title=\"ok\">{{ s.ok }} ok</span>\n <span class=\"badge badge-info\" title=\"info / unscoped\">{{ s.info }} info</span>\n <span class=\"badge\">{{ s.total }} total</span>\n @if (validationExecutedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n }\n </div>\n\n @if (tenantId) {\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Generation:</label>\n <select class=\"root-select\"\n [value]=\"selectedGenerationPipeline()?.rtId ?? ''\"\n (change)=\"onGenerationSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick an auto-mapping pipeline \u2014</option>\n @for (p of validationPipelines(); track p.rtId) {\n <option [value]=\"p.rtId\">{{ p.name }}</option>\n }\n </select>\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"!selectedGenerationPipeline() || generationRunning()\"\n (click)=\"runGeneration()\"\n [title]=\"generationRunning() ? 'Generation running\u2026' : 'Run the auto-mapping pipeline and reload counts'\">\n @if (generationRunning()) { Running\u2026 } @else { Generate }\n </button>\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (generationRunning()) {\n <span class=\"toolbar-meta\">Generating mappings\u2026</span>\n } @else if (generationError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (generationStats(); as s) {\n <span class=\"validation-summary\">\n @if (s.totalSuggestions !== undefined) {\n <span class=\"badge badge-ok\" title=\"mapping suggestions produced\">{{ s.totalSuggestions }} mappings</span>\n }\n @if (s.matchedContainers !== undefined && s.totalContainers !== undefined) {\n <span class=\"badge\" title=\"containers (e.g. rooms) matched to a target\">\n {{ s.matchedContainers }}/{{ s.totalContainers }} matched\n </span>\n }\n @if (s.unmatchedContainers) {\n <span class=\"badge badge-warning\"\n [attr.title]=\"'Unmatched: ' + (s.unmatchedContainerNames ?? []).join(', ')\">\n {{ s.unmatchedContainers }} unmatched\n </span>\n }\n @if (generationCompletedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n } @else if (generationCompletedAt(); as ts) {\n <span class=\"toolbar-meta\">Completed {{ ts }} (no statistics in OutputData)</span>\n }\n </div>\n }\n\n @if (tenantId && (exportBackupPipeline() || importBackupPipeline())) {\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Backup:</label>\n <button kendoButton size=\"small\" [svgIcon]=\"icons.download\"\n [disabled]=\"!exportBackupPipeline() || backupRunning() !== null\"\n (click)=\"exportMappings()\"\n title=\"Run the export pipeline and download the mapping document as JSON\">\n @if (backupRunning() === 'export') { Exporting\u2026 } @else { Export }\n </button>\n <button kendoButton size=\"small\" [svgIcon]=\"icons.upload\"\n [disabled]=\"!importBackupPipeline() || backupRunning() !== null\"\n (click)=\"importFileInput.click()\"\n title=\"Import a previously exported mapping document (JSON)\">\n @if (backupRunning() === 'import') { Importing\u2026 } @else { Import\u2026 }\n </button>\n <input #importFileInput type=\"file\" accept=\".json,application/json\" hidden\n (change)=\"onImportFileSelected($event)\" />\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (backupRunning() === 'export') {\n <span class=\"toolbar-meta\">Exporting mappings\u2026</span>\n } @else if (backupRunning() === 'import') {\n <span class=\"toolbar-meta\">Importing mappings\u2026</span>\n } @else if (backupError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (importStats(); as s) {\n <span class=\"validation-summary\">\n @if (s.resolved !== undefined) {\n <span class=\"badge badge-ok\" title=\"mappings resolved and imported\">{{ s.resolved }} imported</span>\n }\n @if (s.unresolved) {\n <span class=\"badge badge-warning\"\n [attr.title]=\"'Unresolved: ' + unresolvedImportNames()\">\n {{ s.unresolved }} unresolved\n </span>\n }\n @if (s.total !== undefined) {\n <span class=\"badge\">{{ s.total }} total</span>\n }\n @if (importCompletedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n } @else if (importCompletedAt(); as ts) {\n <span class=\"toolbar-meta\">Import completed {{ ts }} (no statistics in OutputData)</span>\n }\n </div>\n }\n\n <div class=\"coverage-body\">\n <div class=\"coverage-tree-pane\">\n @if (selectedRoot()) {\n <mm-tree-view\n [dataSource]=\"dataSource\"\n (nodeSelected)=\"onNodeSelected($event)\">\n </mm-tree-view>\n } @else {\n <div class=\"empty-hint\">\n Select a tree to start. Counts in brackets show how many mappings\n point to that node.\n </div>\n }\n </div>\n\n <div class=\"coverage-detail-pane\">\n @if (selectedNode(); as node) {\n <div class=\"detail-header\">\n <div class=\"detail-titles\">\n <h3 class=\"detail-name\">{{ node.name }}</h3>\n <div class=\"detail-subtitle\">{{ node.ckTypeId }}@{{ node.rtId }}</div>\n </div>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n (click)=\"refreshSelected()\" title=\"Refresh\"></button>\n </div>\n\n <div class=\"detail-section-title\">\n <span>Mappings</span>\n @if (summaryLine(); as s) {\n <span class=\"detail-summary\">{{ s }}</span>\n }\n <span class=\"toolbar-spacer\"></span>\n <button kendoButton themeColor=\"primary\" size=\"small\" [svgIcon]=\"icons.plus\"\n (click)=\"addMapping()\">Add</button>\n </div>\n\n @if (mappingsLoading()) {\n <div class=\"empty-hint\">Loading mappings\u2026</div>\n } @else if (mappingsError(); as err) {\n <div class=\"error-hint\">{{ err }}</div>\n } @else if (mappings().length === 0) {\n <div class=\"empty-hint\">\n No mappings reference this node yet. Add one using the button above.\n </div>\n } @else {\n <ul class=\"mapping-list\">\n @for (mapping of mappings(); track trackByRtId($index, mapping)) {\n <li class=\"mapping-row\" [class.mapping-disabled]=\"!mapping.enabled\">\n <div class=\"mapping-line\">\n <span class=\"mapping-name\">\n {{ mapping.name || 'Mapping ' + ($index + 1) }}\n </span>\n @if (!mapping.enabled) {\n <span class=\"mapping-badge mapping-badge-off\">disabled</span>\n }\n </div>\n <div class=\"mapping-details\">\n <span class=\"kv\">\n <span class=\"kv-key\">Source:</span>\n <span class=\"kv-val\">\n {{ mapping.sourceName || mapping.sourceRtId || '\u2014 not linked \u2014' }}\n </span>\n </span>\n @if (mapping.sourceAttributePath) {\n <span class=\"kv\">\n <span class=\"kv-key\">Attr:</span>\n <span class=\"kv-val\">{{ mapping.sourceAttributePath }}</span>\n </span>\n }\n @if (mapping.mappingExpression) {\n <span class=\"kv\">\n <span class=\"kv-key\">Expr:</span>\n <code class=\"kv-val\">{{ mapping.mappingExpression }}</code>\n </span>\n }\n @if (mapping.targetAttributePath) {\n <span class=\"kv\">\n <span class=\"kv-key\">\u2192</span>\n <span class=\"kv-val\">{{ mapping.targetAttributePath }}</span>\n </span>\n }\n </div>\n <div class=\"mapping-actions\">\n <button kendoButton themeColor=\"primary\" fillMode=\"flat\" size=\"small\"\n [svgIcon]=\"icons.pencil\"\n (click)=\"editMapping(mapping)\"\n title=\"Edit mapping\">Edit\u2026</button>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.trash\"\n (click)=\"deleteMapping(mapping)\"\n title=\"Delete mapping\"></button>\n </div>\n </li>\n }\n </ul>\n }\n } @else {\n <div class=\"empty-hint\">\n Select a node from the tree to view and edit its mappings.\n </div>\n }\n </div>\n </div>\n }\n\n @if (activeTab() === 'orphans') {\n <div class=\"coverage-toolbar\">\n <label class=\"toolbar-label\">Source type:</label>\n <select class=\"root-select\"\n [value]=\"orphanCkType() ?? ''\"\n (change)=\"onOrphanCkTypeChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a source type \u2014</option>\n @for (ckType of config.sourceCandidateCkTypeIds; track ckType) {\n <option [value]=\"ckType\">{{ ckType }}</option>\n }\n </select>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n [disabled]=\"!orphanCkType() || orphanLoading()\"\n (click)=\"refreshOrphans()\" title=\"Reload\"></button>\n <span class=\"orphan-search-wrap\">\n <input type=\"text\" class=\"root-select orphan-search\"\n placeholder=\"Search name, room, description\u2026\"\n [value]=\"orphanSearchText()\"\n (input)=\"orphanSearchText.set($any($event.target).value)\" />\n @if (orphanSearchText()) {\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.x\"\n class=\"orphan-search-clear\"\n (click)=\"orphanSearchText.set('')\"\n title=\"Clear search\" aria-label=\"Clear search\"></button>\n }\n </span>\n <label class=\"orphan-toggle\">\n <input type=\"checkbox\" [checked]=\"orphanHideMapped()\" (change)=\"toggleOrphanHideMapped()\" />\n Hide already-mapped\n </label>\n <label class=\"toolbar-label\">Group by:</label>\n <select class=\"root-select\"\n [value]=\"orphanGroupParentType() ?? ''\"\n (change)=\"onOrphanGroupParentTypeChange($any($event.target).value)\">\n <option value=\"\">(no grouping)</option>\n @for (t of orphanAvailableParentTypes(); track t) {\n <option [value]=\"t\">{{ t }}</option>\n }\n </select>\n @if (orphanGroupParentType()) {\n <kendo-multiselect class=\"orphan-group-filter\"\n [data]=\"orphanAvailableGroupNames()\"\n [value]=\"orphanSelectedGroupNames()\"\n (valueChange)=\"onOrphanGroupNamesChange($event)\"\n [autoClose]=\"false\"\n [clearButton]=\"true\"\n size=\"small\"\n placeholder=\"Filter groups\u2026\"\n title=\"Show only the selected groups (e.g. specific categories)\">\n </kendo-multiselect>\n }\n\n <div class=\"toolbar-spacer\"></div>\n\n <button kendoButton size=\"small\" fillMode=\"flat\"\n [disabled]=\"orphanVisibleList().length === 0\"\n (click)=\"selectAllVisibleOrphans()\"\n title=\"Select every row visible under the current filter\">Select all</button>\n <button kendoButton size=\"small\" fillMode=\"flat\"\n [disabled]=\"orphanSelectedCount() === 0\"\n (click)=\"clearOrphanSelection()\">Clear</button>\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"orphanSelectedCount() === 0\"\n (click)=\"bulkMapSelected()\"\n title=\"Create one mapping per selected source (shared target + paths)\">\n Map {{ orphanSelectedCount() }} selected\u2026\n </button>\n\n @if (orphanStats(); as s) {\n <span class=\"validation-summary\">\n @if (orphanSearchText().trim() || orphanSelectedGroupNames().length > 0) {\n <span class=\"badge badge-info\" title=\"rows matching search + group filter\">{{ orphanVisibleList().length }} shown</span>\n }\n <span class=\"badge badge-error\" title=\"unmapped \u2014 no DataPointMapping yet\">{{ s.unmapped }} unmapped</span>\n <span class=\"badge badge-ok\" title=\"already covered by at least one mapping\">{{ s.mapped }} mapped</span>\n <span class=\"badge\">{{ s.total }} total</span>\n </span>\n }\n </div>\n\n <div class=\"orphan-body\">\n @if (orphanLoading()) {\n <div class=\"empty-hint\">Loading source candidates\u2026</div>\n } @else if (orphanError(); as err) {\n <div class=\"error-hint\">{{ err }}</div>\n } @else if (orphanVisibleList().length === 0) {\n <div class=\"empty-hint\">\n @if (orphanSelectedGroupNames().length > 0) {\n No entries in the selected group(s) match the current filters.\n } @else if (orphanSearchText().trim()) {\n No entries match \"{{ orphanSearchText() }}\".\n } @else if (orphanHideMapped()) {\n All {{ orphanCkType() }} entities are mapped at least once. \uD83C\uDF89\n } @else {\n No entities of type {{ orphanCkType() }} found.\n }\n </div>\n } @else if (orphanGroupParentType()) {\n @for (group of orphanGroupedList(); track group.key) {\n <div class=\"orphan-group\">\n <div class=\"orphan-group-header\">\n <span class=\"orphan-group-label\">{{ group.label }}</span>\n <span class=\"orphan-group-count\">{{ group.items.length }}</span>\n </div>\n <ul class=\"orphan-list\">\n @for (item of group.items; track trackOrphanByRtId($index, item)) {\n <ng-container *ngTemplateOutlet=\"orphanRowTpl; context: { $implicit: item }\"></ng-container>\n }\n </ul>\n </div>\n }\n } @else {\n <ul class=\"orphan-list\">\n @for (item of orphanVisibleList(); track trackOrphanByRtId($index, item)) {\n <ng-container *ngTemplateOutlet=\"orphanRowTpl; context: { $implicit: item }\"></ng-container>\n }\n </ul>\n }\n\n <ng-template #orphanRowTpl let-item>\n <li class=\"orphan-row\" [class.orphan-mapped]=\"item.mappingCount > 0\">\n <div class=\"orphan-line\">\n <input type=\"checkbox\" class=\"orphan-check\"\n [checked]=\"isOrphanSelected(item.rtId)\"\n (change)=\"toggleOrphanSelected(item.rtId)\"\n [attr.aria-label]=\"'Select ' + item.name\" />\n <span class=\"orphan-name\">{{ item.name }}</span>\n @if (item.mappingCount > 0) {\n <span class=\"orphan-badge orphan-badge-mapped\">\n {{ item.mappingCount }} mapping{{ item.mappingCount === 1 ? '' : 's' }}\n </span>\n } @else {\n <span class=\"orphan-badge orphan-badge-unmapped\">unmapped</span>\n }\n </div>\n @if (item.parentPath.length > 0) {\n <div class=\"orphan-breadcrumb\" [attr.title]=\"'Parent chain (root-first)'\">\n @for (parent of breadcrumbFor(item); track parent.rtId; let last = $last) {\n <span class=\"crumb\">{{ parent.name }}</span>\n @if (!last) { <span class=\"crumb-sep\">\u203A</span> }\n }\n </div>\n }\n <div class=\"orphan-meta\">\n <span class=\"kv-val\">{{ item.ckTypeId }}@{{ item.rtId }}</span>\n </div>\n @if (item.description) {\n <div class=\"orphan-description\">{{ item.description }}</div>\n }\n <div class=\"orphan-actions\">\n <button kendoButton themeColor=\"primary\" fillMode=\"flat\" size=\"small\"\n [svgIcon]=\"icons.plus\"\n (click)=\"createMappingFromOrphan(item)\"\n title=\"Create mapping pre-linked to this source\">\n Map\u2026\n </button>\n </div>\n </li>\n </ng-template>\n </div>\n }\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0}.coverage-root{display:flex;flex-direction:column;flex:1;min-height:0;gap:12px}.coverage-toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 12px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface-alt, #f8f9fa)) 70%,transparent)}.coverage-toolbar .toolbar-label{flex:0 0 96px;font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.coverage-toolbar .root-select{flex:0 0 280px;min-width:0;padding:4px 8px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:4px;background:var(--theme-bg-elevated, var(--kendo-color-surface, #fff));color:var(--theme-text-primary, inherit);font-size:.9rem;height:30px}.coverage-toolbar .orphan-search-wrap{display:inline-flex;align-items:center;gap:2px}.coverage-toolbar .orphan-search-wrap .orphan-search{flex:1 1 220px;min-width:140px}.coverage-toolbar .orphan-group-filter{flex:0 1 320px;min-width:160px}.coverage-toolbar .toolbar-spacer{flex:1}.coverage-toolbar .toolbar-meta{display:flex;flex-direction:column;align-items:flex-end;line-height:1.1}.coverage-toolbar .toolbar-meta .meta-name{font-size:.85rem;font-weight:600}.coverage-toolbar .toolbar-meta .meta-type{font-size:.7rem;font-family:monospace;color:var(--kendo-color-subtle, #6c757d)}.coverage-body{flex:1;display:flex;gap:12px;min-height:0}@media(max-width:900px){.coverage-body{flex-direction:column}.coverage-tree-pane{flex:0 0 38vh;min-width:0;min-height:180px}.coverage-detail-pane{min-height:180px}.coverage-toolbar .toolbar-label{flex:0 0 auto}.coverage-toolbar .root-select{flex:1 1 200px;max-width:100%}}.coverage-tree-pane{flex:0 0 40%;min-width:240px;display:flex;flex-direction:column;min-height:0;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);color:var(--theme-text-primary, inherit);overflow:auto}.coverage-detail-pane{flex:1;min-width:0;display:flex;flex-direction:column;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);color:var(--theme-text-primary, inherit);padding:12px 14px;gap:12px;overflow:auto}.detail-header{display:flex;align-items:flex-start;gap:8px}.detail-header .detail-titles{flex:1;min-width:0}.detail-header .detail-name{margin:0;font-size:1.05rem;font-weight:600;word-break:break-word}.detail-header .detail-subtitle{font-size:.72rem;font-family:monospace;color:var(--kendo-color-subtle, #6c757d);word-break:break-all}.detail-section-title{display:flex;align-items:center;gap:10px;font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--kendo-color-subtle, #6c757d)}.detail-section-title .toolbar-spacer{flex:1}.detail-section-title .detail-summary{text-transform:none;letter-spacing:0;font-weight:500;color:var(--kendo-color-on-app-surface, inherit);font-size:.78rem}.mapping-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.mapping-row{border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;padding:8px 10px;display:flex;flex-direction:column;gap:6px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.mapping-row.mapping-disabled{opacity:.55}.mapping-line{display:flex;align-items:center;gap:8px}.mapping-line .mapping-name{font-weight:600;font-size:.9rem}.mapping-badge{font-size:.65rem;text-transform:uppercase;letter-spacing:.5px;padding:1px 6px;border-radius:8px;border:1px solid var(--kendo-color-border, #dee2e6)}.mapping-badge.mapping-badge-off{color:var(--kendo-color-subtle, #6c757d)}.mapping-details{display:flex;flex-wrap:wrap;gap:10px;font-size:.8rem}.mapping-details .kv{display:inline-flex;align-items:baseline;gap:4px}.mapping-details .kv-key{font-weight:600;color:var(--kendo-color-subtle, #6c757d)}.mapping-details code.kv-val{font-family:monospace;background:var(--kendo-color-surface, transparent);padding:1px 4px;border-radius:3px}.mapping-actions{display:flex;gap:6px;justify-content:flex-end}.empty-hint,.error-hint{padding:12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d);text-align:center}.error-hint{color:var(--kendo-color-error, #dc3545)}.coverage-tabs{display:flex;gap:0;border-bottom:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6))}.coverage-tab{padding:8px 16px;border:none;background:transparent;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-size:.85rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;display:inline-flex;align-items:center;gap:6px}.coverage-tab:hover{color:var(--theme-text-primary, inherit)}.coverage-tab.active{color:var(--theme-text-accent, var(--kendo-color-primary, #ff6358));border-bottom-color:var(--theme-text-accent, var(--kendo-color-primary, #ff6358))}.coverage-tab .tab-badge{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 22%,transparent);color:var(--kendo-color-error, #dc3545);border-radius:10px;padding:1px 8px;font-size:.7rem;font-weight:700}.orphan-toggle{display:inline-flex;align-items:center;gap:6px;font-size:.8rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));cursor:pointer}.orphan-body{flex:1;min-height:0;overflow:auto;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);padding:8px}.orphan-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.orphan-row{display:flex;flex-direction:column;gap:4px;padding:8px 10px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-left-width:3px;border-left-color:var(--kendo-color-error, #dc3545);border-radius:6px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.orphan-row.orphan-mapped{border-left-color:var(--kendo-color-success, #28a745);opacity:.7}.orphan-row .orphan-line{display:flex;align-items:center;gap:8px}.orphan-row .orphan-line .orphan-check{flex-shrink:0;margin:0;cursor:pointer;accent-color:var(--kendo-color-primary, #ff6358)}.orphan-row .orphan-line .orphan-name{flex:1;font-weight:600;font-size:.9rem}.orphan-row .orphan-badge{font-size:.7rem;padding:1px 8px;border-radius:10px;text-transform:uppercase;letter-spacing:.5px;font-weight:600}.orphan-row .orphan-badge-unmapped{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 22%,transparent);color:var(--kendo-color-error, #dc3545);border:1px solid var(--kendo-color-error, #dc3545)}.orphan-row .orphan-badge-mapped{background:color-mix(in srgb,var(--kendo-color-success, #28a745) 18%,transparent);color:var(--kendo-color-success, #28a745);border:1px solid var(--kendo-color-success, #28a745)}.orphan-row .orphan-meta{font-family:monospace;font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));word-break:break-all}.orphan-row .orphan-breadcrumb{display:flex;flex-wrap:wrap;align-items:center;gap:4px;font-size:.75rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.orphan-row .orphan-breadcrumb .crumb{line-height:1.3}.orphan-row .orphan-breadcrumb .crumb-sep{opacity:.55;font-weight:600}.orphan-row .orphan-description{font-size:.78rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-style:italic}.orphan-row .orphan-actions{display:flex;gap:6px;justify-content:flex-end}.orphan-group{display:flex;flex-direction:column;gap:6px}.orphan-group+.orphan-group{margin-top:14px}.orphan-group .orphan-group-header{display:flex;align-items:baseline;gap:8px;padding:4px 8px;border-bottom:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));font-size:.85rem;font-weight:600;color:var(--theme-text-primary, inherit)}.orphan-group .orphan-group-header .orphan-group-label{flex:1}.orphan-group .orphan-group-header .orphan-group-count{font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f1f3f5)) 80%,transparent);border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:10px;padding:0 8px}.validation-summary{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}.badge{font-size:.7rem;padding:2px 8px;border-radius:10px;background:var(--kendo-color-surface, #f1f3f5);border:1px solid var(--kendo-color-border, #dee2e6)}.badge-error{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 18%,transparent);border-color:var(--kendo-color-error, #dc3545);color:var(--kendo-color-error, #dc3545);font-weight:600}.badge-warning{background:color-mix(in srgb,var(--kendo-color-warning, #ffc107) 22%,transparent);border-color:var(--kendo-color-warning, #ffc107);color:var(--kendo-color-warning-on, #6b5500);font-weight:600}.badge-ok{background:color-mix(in srgb,var(--kendo-color-success, #28a745) 18%,transparent);border-color:var(--kendo-color-success, #28a745);color:var(--kendo-color-success, #28a745);font-weight:600}.badge-info{background:color-mix(in srgb,var(--kendo-color-info, #0dcaf0) 18%,transparent);border-color:var(--kendo-color-info, #0dcaf0);color:var(--kendo-color-info, #0dcaf0)}.validation-error-text{color:var(--kendo-color-error, #dc3545);font-size:.8rem}.validation-timestamp{font-size:.7rem;color:var(--kendo-color-subtle, #6c757d);margin-left:4px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: LayoutModule }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i3$1.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: TreeComponent, selector: "mm-tree-view", inputs: ["dataSource"], outputs: ["nodeSelected", "nodeClick", "nodeDoubleClick", "nodeDrop", "expand", "collapse"] }, { kind: "component", type: PerspectiveSwitcherComponent, selector: "mm-perspective-switcher", inputs: ["perspectives", "activeKey", "label"], outputs: ["perspectiveChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
21412
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: MappingCoverageTreeComponent, isStandalone: true, selector: "mm-mapping-coverage-tree", inputs: { config: "config", initialRoot: "initialRoot", tenantId: "tenantId", expressionEvaluator: "expressionEvaluator" }, outputs: { entitySelected: "entitySelected" }, providers: [MappingCoverageTreeDataSource], viewQueries: [{ propertyName: "treeView", first: true, predicate: TreeComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"coverage-root\">\n @if (config.sourceCandidateCkTypeIds.length > 0) {\n <div class=\"coverage-tabs\" role=\"tablist\">\n <button class=\"coverage-tab\"\n [class.active]=\"activeTab() === 'coverage'\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === 'coverage'\"\n (click)=\"selectTab('coverage')\">Coverage Tree</button>\n <button class=\"coverage-tab\"\n [class.active]=\"activeTab() === 'orphans'\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === 'orphans'\"\n (click)=\"selectTab('orphans')\">\n Orphan Sources\n @if (orphanStats(); as s) {\n @if (s.unmapped > 0) { <span class=\"tab-badge\">{{ s.unmapped }}</span> }\n }\n </button>\n </div>\n }\n\n @if (activeTab() === 'coverage') {\n <div class=\"coverage-toolbar\">\n <mm-perspective-switcher\n [perspectives]=\"perspectives()\"\n [activeKey]=\"activePerspectiveKey()\"\n (perspectiveChange)=\"onPerspectiveChange($event)\"></mm-perspective-switcher>\n <label class=\"toolbar-label\">Tree:</label>\n <select class=\"root-select\"\n [value]=\"selectedRoot()?.rtId ?? ''\"\n (change)=\"onRootSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a {{ activeRootCkTypeId() }} \u2014</option>\n @for (root of rootCandidates(); track root.rtId) {\n <option [value]=\"root.rtId\" [title]=\"root.description\">{{ root.name }}</option>\n }\n </select>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n (click)=\"refreshRoots()\" title=\"Refresh tree list\" aria-label=\"Refresh tree list\"></button>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.folderOpen\"\n (click)=\"pickRoot()\" title=\"Browse for entity\">Browse...</button>\n\n @if (selectedRoot(); as root) {\n <div class=\"toolbar-spacer\"></div>\n <span class=\"toolbar-meta\">\n <span class=\"meta-name\">{{ root.name }}</span>\n <span class=\"meta-type\">{{ root.ckTypeId }}</span>\n </span>\n }\n </div>\n\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Validation:</label>\n <select class=\"root-select\"\n [value]=\"selectedPipeline()?.rtId ?? ''\"\n (change)=\"onPipelineSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a {{ config.validationPipelineCkTypeId }} \u2014</option>\n @for (p of validationPipelines(); track p.rtId) {\n <option [value]=\"p.rtId\">{{ p.name }}</option>\n }\n </select>\n @if (tenantId) {\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"!selectedPipeline() || validationRunning() || validationLoading()\"\n (click)=\"runValidation()\"\n [title]=\"validationRunning() ? 'Validation running\u2026' : 'Run pipeline + load report'\">\n @if (validationRunning()) { Running\u2026 } @else { Run }\n </button>\n }\n <button kendoButton fillMode=\"solid\" size=\"small\" [svgIcon]=\"icons.refresh\"\n [disabled]=\"!selectedPipeline() || validationLoading() || validationRunning()\"\n (click)=\"refreshValidation()\">Load Report</button>\n @if (validationSummary()) {\n <button kendoButton fillMode=\"flat\" size=\"small\"\n (click)=\"clearValidation()\">Clear</button>\n }\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (validationLoading()) {\n <span class=\"toolbar-meta\">Loading\u2026</span>\n } @else if (validationError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (validationSummary(); as s) {\n <span class=\"validation-summary\">\n <span class=\"badge badge-error\" title=\"error\">{{ s.error }} err</span>\n <span class=\"badge badge-warning\" title=\"warning\">{{ s.warning }} warn</span>\n <span class=\"badge badge-ok\" title=\"ok\">{{ s.ok }} ok</span>\n <span class=\"badge badge-info\" title=\"info / unscoped\">{{ s.info }} info</span>\n <span class=\"badge\">{{ s.total }} total</span>\n @if (validationExecutedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n }\n </div>\n\n @if (tenantId) {\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Generation:</label>\n <select class=\"root-select\"\n [value]=\"selectedGenerationPipeline()?.rtId ?? ''\"\n (change)=\"onGenerationSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick an auto-mapping pipeline \u2014</option>\n @for (p of validationPipelines(); track p.rtId) {\n <option [value]=\"p.rtId\">{{ p.name }}</option>\n }\n </select>\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"!selectedGenerationPipeline() || generationRunning()\"\n (click)=\"runGeneration()\"\n [title]=\"generationRunning() ? 'Generation running\u2026' : 'Run the auto-mapping pipeline and reload counts'\">\n @if (generationRunning()) { Running\u2026 } @else { Generate }\n </button>\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (generationRunning()) {\n <span class=\"toolbar-meta\">Generating mappings\u2026</span>\n } @else if (generationError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (generationStats(); as s) {\n <span class=\"validation-summary\">\n @if (s.totalSuggestions !== undefined) {\n <span class=\"badge badge-ok\" title=\"mapping suggestions produced\">{{ s.totalSuggestions }} mappings</span>\n }\n @if (s.matchedContainers !== undefined && s.totalContainers !== undefined) {\n <span class=\"badge\" title=\"containers (e.g. rooms) matched to a target\">\n {{ s.matchedContainers }}/{{ s.totalContainers }} matched\n </span>\n }\n @if (s.unmatchedContainers) {\n <span class=\"badge badge-warning\"\n [attr.title]=\"'Unmatched: ' + (s.unmatchedContainerNames ?? []).join(', ')\">\n {{ s.unmatchedContainers }} unmatched\n </span>\n }\n @if (generationCompletedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n } @else if (generationCompletedAt(); as ts) {\n <span class=\"toolbar-meta\">Completed {{ ts }} (no statistics in OutputData)</span>\n }\n </div>\n }\n\n @if (tenantId && (exportBackupPipeline() || importBackupPipeline())) {\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Backup:</label>\n <button kendoButton size=\"small\" [svgIcon]=\"icons.download\"\n [disabled]=\"!exportBackupPipeline() || backupRunning() !== null\"\n (click)=\"exportMappings()\"\n title=\"Run the export pipeline and download the mapping document as JSON\">\n @if (backupRunning() === 'export') { Exporting\u2026 } @else { Export }\n </button>\n <button kendoButton size=\"small\" [svgIcon]=\"icons.upload\"\n [disabled]=\"!importBackupPipeline() || backupRunning() !== null\"\n (click)=\"importFileInput.click()\"\n title=\"Import a previously exported mapping document (JSON)\">\n @if (backupRunning() === 'import') { Importing\u2026 } @else { Import\u2026 }\n </button>\n <input #importFileInput type=\"file\" accept=\".json,application/json\" hidden\n (change)=\"onImportFileSelected($event)\" />\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (backupRunning() === 'export') {\n <span class=\"toolbar-meta\">Exporting mappings\u2026</span>\n } @else if (backupRunning() === 'import') {\n <span class=\"toolbar-meta\">Importing mappings\u2026</span>\n } @else if (backupError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (importStats(); as s) {\n <span class=\"validation-summary\">\n @if (s.resolved !== undefined) {\n <span class=\"badge badge-ok\" title=\"mappings resolved and imported\">{{ s.resolved }} imported</span>\n }\n @if (s.unresolved) {\n <span class=\"badge badge-warning\"\n [attr.title]=\"'Unresolved: ' + unresolvedImportNames()\">\n {{ s.unresolved }} unresolved\n </span>\n }\n @if (s.total !== undefined) {\n <span class=\"badge\">{{ s.total }} total</span>\n }\n @if (importCompletedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n } @else if (importCompletedAt(); as ts) {\n <span class=\"toolbar-meta\">Import completed {{ ts }} (no statistics in OutputData)</span>\n }\n </div>\n }\n\n <div class=\"coverage-body\">\n <div class=\"coverage-tree-pane\">\n @if (selectedRoot()) {\n <mm-tree-view\n [dataSource]=\"dataSource\"\n (nodeSelected)=\"onNodeSelected($event)\">\n </mm-tree-view>\n } @else {\n <div class=\"empty-hint\">\n Select a tree to start. Counts in brackets show how many mappings\n point to that node.\n </div>\n }\n </div>\n\n <div class=\"coverage-detail-pane\">\n @if (selectedNode(); as node) {\n <div class=\"detail-header\">\n <div class=\"detail-titles\">\n <h3 class=\"detail-name\">{{ node.name }}</h3>\n <div class=\"detail-subtitle\">{{ node.ckTypeId }}@{{ node.rtId }}</div>\n </div>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n (click)=\"refreshSelected()\" title=\"Refresh\" aria-label=\"Refresh mappings\"></button>\n </div>\n\n <div class=\"detail-section-title\">\n <span>Mappings</span>\n @if (summaryLine(); as s) {\n <span class=\"detail-summary\">{{ s }}</span>\n }\n <span class=\"toolbar-spacer\"></span>\n <button kendoButton themeColor=\"primary\" size=\"small\" [svgIcon]=\"icons.plus\"\n (click)=\"addMapping()\">Add</button>\n </div>\n\n @if (mappingsLoading()) {\n <div class=\"empty-hint\">Loading mappings\u2026</div>\n } @else if (mappingsError(); as err) {\n <div class=\"error-hint\">{{ err }}</div>\n } @else if (mappings().length === 0) {\n <div class=\"empty-hint\">\n No mappings reference this node yet. Add one using the button above.\n </div>\n } @else {\n <ul class=\"mapping-list\">\n @for (mapping of mappings(); track trackByRtId($index, mapping)) {\n <li class=\"mapping-row\" [class.mapping-disabled]=\"!mapping.enabled\">\n <div class=\"mapping-line\">\n <span class=\"mapping-name\">\n {{ mapping.name || 'Mapping ' + ($index + 1) }}\n </span>\n @if (!mapping.enabled) {\n <span class=\"mapping-badge mapping-badge-off\">disabled</span>\n }\n </div>\n <div class=\"mapping-details\">\n <span class=\"kv\">\n <span class=\"kv-key\">Source:</span>\n <span class=\"kv-val\">\n {{ mapping.sourceName || mapping.sourceRtId || '\u2014 not linked \u2014' }}\n </span>\n </span>\n @if (mapping.sourceAttributePath) {\n <span class=\"kv\">\n <span class=\"kv-key\">Attr:</span>\n <span class=\"kv-val\">{{ mapping.sourceAttributePath }}</span>\n </span>\n }\n @if (mapping.mappingExpression) {\n <span class=\"kv\">\n <span class=\"kv-key\">Expr:</span>\n <code class=\"kv-val\">{{ mapping.mappingExpression }}</code>\n </span>\n }\n @if (mapping.targetAttributePath) {\n <span class=\"kv\">\n <span class=\"kv-key\">\u2192</span>\n <span class=\"kv-val\">{{ mapping.targetAttributePath }}</span>\n </span>\n }\n </div>\n <div class=\"mapping-actions\">\n <button kendoButton fillMode=\"flat\" size=\"small\"\n [svgIcon]=\"icons.pencil\"\n (click)=\"editMapping(mapping)\"\n title=\"Edit mapping\" [attr.aria-label]=\"'Edit mapping ' + (mapping.name || mapping.rtId)\"></button>\n <button kendoButton fillMode=\"flat\" size=\"small\" themeColor=\"error\" [svgIcon]=\"icons.trash\"\n (click)=\"deleteMapping(mapping)\" data-action=\"delete\"\n title=\"Delete mapping\" [attr.aria-label]=\"'Delete mapping ' + (mapping.name || mapping.rtId)\"></button>\n </div>\n </li>\n }\n </ul>\n }\n } @else {\n <div class=\"empty-hint\">\n Select a node from the tree to view and edit its mappings.\n </div>\n }\n </div>\n </div>\n }\n\n @if (activeTab() === 'orphans') {\n <div class=\"coverage-toolbar\">\n <label class=\"toolbar-label\">Source type:</label>\n <select class=\"root-select\"\n [value]=\"orphanCkType() ?? ''\"\n (change)=\"onOrphanCkTypeChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a source type \u2014</option>\n @for (ckType of config.sourceCandidateCkTypeIds; track ckType) {\n <option [value]=\"ckType\">{{ ckType }}</option>\n }\n </select>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n [disabled]=\"!orphanCkType() || orphanLoading()\"\n (click)=\"refreshOrphans()\" title=\"Reload\" aria-label=\"Reload orphans\"></button>\n <span class=\"orphan-search-wrap\">\n <input type=\"text\" class=\"root-select orphan-search\"\n placeholder=\"Search name, room, description\u2026\"\n [value]=\"orphanSearchText()\"\n (input)=\"orphanSearchText.set($any($event.target).value)\" />\n @if (orphanSearchText()) {\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.x\"\n class=\"orphan-search-clear\"\n (click)=\"orphanSearchText.set('')\"\n title=\"Clear search\" aria-label=\"Clear search\"></button>\n }\n </span>\n <label class=\"orphan-toggle\">\n <input type=\"checkbox\" [checked]=\"orphanHideMapped()\" (change)=\"toggleOrphanHideMapped()\" />\n Hide already-mapped\n </label>\n <label class=\"toolbar-label\">Group by:</label>\n <select class=\"root-select\"\n [value]=\"orphanGroupParentType() ?? ''\"\n (change)=\"onOrphanGroupParentTypeChange($any($event.target).value)\">\n <option value=\"\">(no grouping)</option>\n @for (t of orphanAvailableParentTypes(); track t) {\n <option [value]=\"t\">{{ t }}</option>\n }\n </select>\n @if (orphanGroupParentType()) {\n <kendo-multiselect class=\"orphan-group-filter\"\n [data]=\"orphanAvailableGroupNames()\"\n [value]=\"orphanSelectedGroupNames()\"\n (valueChange)=\"onOrphanGroupNamesChange($event)\"\n [autoClose]=\"false\"\n [clearButton]=\"true\"\n size=\"small\"\n placeholder=\"Filter groups\u2026\"\n title=\"Show only the selected groups (e.g. specific categories)\">\n </kendo-multiselect>\n }\n\n <div class=\"toolbar-spacer\"></div>\n\n <button kendoButton size=\"small\" fillMode=\"flat\"\n [disabled]=\"orphanVisibleList().length === 0\"\n (click)=\"selectAllVisibleOrphans()\"\n title=\"Select every row visible under the current filter\">Select all</button>\n <button kendoButton size=\"small\" fillMode=\"flat\"\n [disabled]=\"orphanSelectedCount() === 0\"\n (click)=\"clearOrphanSelection()\">Clear</button>\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"orphanSelectedCount() === 0\"\n (click)=\"bulkMapSelected()\"\n title=\"Create one mapping per selected source (shared target + paths)\">\n Map {{ orphanSelectedCount() }} selected\u2026\n </button>\n\n @if (orphanStats(); as s) {\n <span class=\"validation-summary\">\n @if (orphanSearchText().trim() || orphanSelectedGroupNames().length > 0) {\n <span class=\"badge badge-info\" title=\"rows matching search + group filter\">{{ orphanVisibleList().length }} shown</span>\n }\n <span class=\"badge badge-error\" title=\"unmapped \u2014 no DataPointMapping yet\">{{ s.unmapped }} unmapped</span>\n <span class=\"badge badge-ok\" title=\"already covered by at least one mapping\">{{ s.mapped }} mapped</span>\n <span class=\"badge\">{{ s.total }} total</span>\n </span>\n }\n </div>\n\n <div class=\"orphan-body\">\n @if (orphanLoading()) {\n <div class=\"empty-hint\">Loading source candidates\u2026</div>\n } @else if (orphanError(); as err) {\n <div class=\"error-hint\">{{ err }}</div>\n } @else if (orphanVisibleList().length === 0) {\n <div class=\"empty-hint\">\n @if (orphanSelectedGroupNames().length > 0) {\n No entries in the selected group(s) match the current filters.\n } @else if (orphanSearchText().trim()) {\n No entries match \"{{ orphanSearchText() }}\".\n } @else if (orphanHideMapped()) {\n All {{ orphanCkType() }} entities are mapped at least once. \uD83C\uDF89\n } @else {\n No entities of type {{ orphanCkType() }} found.\n }\n </div>\n } @else if (orphanGroupParentType()) {\n @for (group of orphanGroupedList(); track group.key) {\n <div class=\"orphan-group\">\n <div class=\"orphan-group-header\">\n <span class=\"orphan-group-label\">{{ group.label }}</span>\n <span class=\"orphan-group-count\">{{ group.items.length }}</span>\n </div>\n <ul class=\"orphan-list\">\n @for (item of group.items; track trackOrphanByRtId($index, item)) {\n <ng-container *ngTemplateOutlet=\"orphanRowTpl; context: { $implicit: item }\"></ng-container>\n }\n </ul>\n </div>\n }\n } @else {\n <ul class=\"orphan-list\">\n @for (item of orphanVisibleList(); track trackOrphanByRtId($index, item)) {\n <ng-container *ngTemplateOutlet=\"orphanRowTpl; context: { $implicit: item }\"></ng-container>\n }\n </ul>\n }\n\n <ng-template #orphanRowTpl let-item>\n <li class=\"orphan-row\" [class.orphan-mapped]=\"item.mappingCount > 0\">\n <div class=\"orphan-line\">\n <input type=\"checkbox\" class=\"orphan-check\"\n [checked]=\"isOrphanSelected(item.rtId)\"\n (change)=\"toggleOrphanSelected(item.rtId)\"\n [attr.aria-label]=\"'Select ' + item.name\" />\n <span class=\"orphan-name\">{{ item.name }}</span>\n @if (item.mappingCount > 0) {\n <span class=\"orphan-badge orphan-badge-mapped\">\n {{ item.mappingCount }} mapping{{ item.mappingCount === 1 ? '' : 's' }}\n </span>\n } @else {\n <span class=\"orphan-badge orphan-badge-unmapped\">unmapped</span>\n }\n </div>\n @if (item.parentPath.length > 0) {\n <div class=\"orphan-breadcrumb\" [attr.title]=\"'Parent chain (root-first)'\">\n @for (parent of breadcrumbFor(item); track parent.rtId; let last = $last) {\n <span class=\"crumb\">{{ parent.name }}</span>\n @if (!last) { <span class=\"crumb-sep\">\u203A</span> }\n }\n </div>\n }\n <div class=\"orphan-meta\">\n <span class=\"kv-val\">{{ item.ckTypeId }}@{{ item.rtId }}</span>\n </div>\n @if (item.description) {\n <div class=\"orphan-description\">{{ item.description }}</div>\n }\n <div class=\"orphan-actions\">\n <button kendoButton themeColor=\"primary\" fillMode=\"flat\" size=\"small\"\n [svgIcon]=\"icons.plus\"\n (click)=\"createMappingFromOrphan(item)\"\n title=\"Create mapping pre-linked to this source\">\n Map\u2026\n </button>\n </div>\n </li>\n </ng-template>\n </div>\n }\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0}.coverage-root{display:flex;flex-direction:column;flex:1;min-height:0;gap:12px}.coverage-toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 12px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface-alt, #f8f9fa)) 70%,transparent)}.coverage-toolbar .toolbar-label{flex:0 0 96px;font-size:.75rem;font-weight:600;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.coverage-toolbar .root-select{flex:0 0 280px;min-width:0;padding:4px 8px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:4px;background:var(--theme-bg-elevated, var(--kendo-color-surface, #fff));color:var(--theme-text-primary, inherit);font-size:.9rem;height:30px}.coverage-toolbar .orphan-search-wrap{display:inline-flex;align-items:center;gap:2px}.coverage-toolbar .orphan-search-wrap .orphan-search{flex:1 1 220px;min-width:140px}.coverage-toolbar .orphan-group-filter{flex:0 1 320px;min-width:160px}.coverage-toolbar .toolbar-spacer{flex:1}.coverage-toolbar .toolbar-meta{display:flex;flex-direction:column;align-items:flex-end;line-height:1.1}.coverage-toolbar .toolbar-meta .meta-name{font-size:.85rem;font-weight:600}.coverage-toolbar .toolbar-meta .meta-type{font-size:.7rem;font-family:monospace;color:var(--kendo-color-subtle, #6c757d)}.coverage-body{flex:1;display:flex;gap:12px;min-height:0}@media(max-width:900px){.coverage-body{flex-direction:column}.coverage-tree-pane{flex:0 0 38vh;min-width:0;min-height:180px}.coverage-detail-pane{min-height:180px}.coverage-toolbar .toolbar-label{flex:0 0 auto}.coverage-toolbar .root-select{flex:1 1 200px;max-width:100%}}.coverage-tree-pane{flex:0 0 40%;min-width:240px;display:flex;flex-direction:column;min-height:0;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);color:var(--theme-text-primary, inherit);overflow:auto}.coverage-detail-pane{flex:1;min-width:0;display:flex;flex-direction:column;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);color:var(--theme-text-primary, inherit);padding:12px 14px;gap:12px;overflow:auto}.detail-header{display:flex;align-items:flex-start;gap:8px}.detail-header .detail-titles{flex:1;min-width:0}.detail-header .detail-name{margin:0;font-size:1.05rem;font-weight:600;word-break:break-word}.detail-header .detail-subtitle{font-size:.72rem;font-family:monospace;color:var(--kendo-color-subtle, #6c757d);word-break:break-all}.detail-section-title{display:flex;align-items:center;gap:10px;font-size:.78rem;font-weight:700;color:var(--kendo-color-subtle, #6c757d)}.detail-section-title .toolbar-spacer{flex:1}.detail-section-title .detail-summary{text-transform:none;font-weight:500;color:var(--kendo-color-on-app-surface, inherit);font-size:.78rem}.mapping-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.mapping-row{border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;padding:8px 10px;display:flex;flex-direction:column;gap:6px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.mapping-row.mapping-disabled{opacity:.55}.mapping-line{display:flex;align-items:center;gap:8px}.mapping-line .mapping-name{font-weight:600;font-size:.9rem}.mapping-badge{font-size:.65rem;padding:1px 6px;border-radius:8px;border:1px solid var(--kendo-color-border, #dee2e6)}.mapping-badge.mapping-badge-off{color:var(--kendo-color-subtle, #6c757d)}.mapping-details{display:flex;flex-wrap:wrap;gap:10px;font-size:.8rem}.mapping-details .kv{display:inline-flex;align-items:baseline;gap:4px}.mapping-details .kv-key{font-weight:600;color:var(--kendo-color-subtle, #6c757d)}.mapping-details code.kv-val{font-family:monospace;background:var(--kendo-color-surface, transparent);padding:1px 4px;border-radius:3px}.mapping-actions{display:flex;gap:6px;justify-content:flex-end}.empty-hint,.error-hint{padding:12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d);text-align:center}.error-hint{color:var(--kendo-color-error, #dc3545)}.coverage-tabs{display:flex;gap:0;border-bottom:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6))}.coverage-tab{padding:8px 16px;border:none;background:transparent;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-size:.85rem;font-weight:600;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;display:inline-flex;align-items:center;gap:6px}.coverage-tab:hover{color:var(--theme-text-primary, inherit)}.coverage-tab.active{color:var(--theme-text-accent, var(--kendo-color-primary, #ff6358));border-bottom-color:var(--theme-text-accent, var(--kendo-color-primary, #ff6358))}.coverage-tab .tab-badge{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 22%,transparent);color:var(--kendo-color-error, #dc3545);border-radius:10px;padding:1px 8px;font-size:.7rem;font-weight:700}.orphan-toggle{display:inline-flex;align-items:center;gap:6px;font-size:.8rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));cursor:pointer}.orphan-body{flex:1;min-height:0;overflow:auto;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);padding:8px}.orphan-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.orphan-row{display:flex;flex-direction:column;gap:4px;padding:8px 10px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-left-width:3px;border-left-color:var(--kendo-color-error, #dc3545);border-radius:6px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.orphan-row.orphan-mapped{border-left-color:var(--kendo-color-success, #28a745);opacity:.7}.orphan-row .orphan-line{display:flex;align-items:center;gap:8px}.orphan-row .orphan-line .orphan-check{flex-shrink:0;margin:0;cursor:pointer;accent-color:var(--kendo-color-primary, #ff6358)}.orphan-row .orphan-line .orphan-name{flex:1;font-weight:600;font-size:.9rem}.orphan-row .orphan-badge{font-size:.7rem;padding:1px 8px;border-radius:10px;font-weight:600}.orphan-row .orphan-badge-unmapped{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 22%,transparent);color:var(--kendo-color-error, #dc3545);border:1px solid var(--kendo-color-error, #dc3545)}.orphan-row .orphan-badge-mapped{background:color-mix(in srgb,var(--kendo-color-success, #28a745) 18%,transparent);color:var(--kendo-color-success, #28a745);border:1px solid var(--kendo-color-success, #28a745)}.orphan-row .orphan-meta{font-family:monospace;font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));word-break:break-all}.orphan-row .orphan-breadcrumb{display:flex;flex-wrap:wrap;align-items:center;gap:4px;font-size:.75rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.orphan-row .orphan-breadcrumb .crumb{line-height:1.3}.orphan-row .orphan-breadcrumb .crumb-sep{opacity:.55;font-weight:600}.orphan-row .orphan-description{font-size:.78rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-style:italic}.orphan-row .orphan-actions{display:flex;gap:6px;justify-content:flex-end}.orphan-group{display:flex;flex-direction:column;gap:6px}.orphan-group+.orphan-group{margin-top:14px}.orphan-group .orphan-group-header{display:flex;align-items:baseline;gap:8px;padding:4px 8px;border-bottom:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));font-size:.85rem;font-weight:600;color:var(--theme-text-primary, inherit)}.orphan-group .orphan-group-header .orphan-group-label{flex:1}.orphan-group .orphan-group-header .orphan-group-count{font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f1f3f5)) 80%,transparent);border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:10px;padding:0 8px}.validation-summary{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}.badge{font-size:.7rem;padding:2px 8px;border-radius:10px;background:var(--kendo-color-surface, #f1f3f5);border:1px solid var(--kendo-color-border, #dee2e6)}.badge-error{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 18%,transparent);border-color:var(--kendo-color-error, #dc3545);color:var(--kendo-color-error, #dc3545);font-weight:600}.badge-warning{background:color-mix(in srgb,var(--kendo-color-warning, #ffc107) 22%,transparent);border-color:var(--kendo-color-warning, #ffc107);color:var(--kendo-color-warning-on, #6b5500);font-weight:600}.badge-ok{background:color-mix(in srgb,var(--kendo-color-success, #28a745) 18%,transparent);border-color:var(--kendo-color-success, #28a745);color:var(--kendo-color-success, #28a745);font-weight:600}.badge-info{background:color-mix(in srgb,var(--kendo-color-info, #0dcaf0) 18%,transparent);border-color:var(--kendo-color-info, #0dcaf0);color:var(--kendo-color-info, #0dcaf0)}.validation-error-text{color:var(--kendo-color-error, #dc3545);font-size:.8rem}.validation-timestamp{font-size:.7rem;color:var(--kendo-color-subtle, #6c757d);margin-left:4px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$1.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: LayoutModule }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i3$1.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: TreeComponent, selector: "mm-tree-view", inputs: ["dataSource"], outputs: ["nodeSelected", "nodeClick", "nodeDoubleClick", "nodeDrop", "expand", "collapse"] }, { kind: "component", type: PerspectiveSwitcherComponent, selector: "mm-perspective-switcher", inputs: ["perspectives", "activeKey", "label"], outputs: ["perspectiveChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
20830
21413
|
}
|
|
20831
21414
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: MappingCoverageTreeComponent, decorators: [{
|
|
20832
21415
|
type: Component,
|
|
@@ -20839,7 +21422,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
20839
21422
|
SVGIconModule,
|
|
20840
21423
|
TreeComponent,
|
|
20841
21424
|
PerspectiveSwitcherComponent,
|
|
20842
|
-
], providers: [MappingCoverageTreeDataSource], template: "<div class=\"coverage-root\">\n @if (config.sourceCandidateCkTypeIds.length > 0) {\n <div class=\"coverage-tabs\" role=\"tablist\">\n <button class=\"coverage-tab\"\n [class.active]=\"activeTab() === 'coverage'\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === 'coverage'\"\n (click)=\"selectTab('coverage')\">Coverage Tree</button>\n <button class=\"coverage-tab\"\n [class.active]=\"activeTab() === 'orphans'\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === 'orphans'\"\n (click)=\"selectTab('orphans')\">\n Orphan Sources\n @if (orphanStats(); as s) {\n @if (s.unmapped > 0) { <span class=\"tab-badge\">{{ s.unmapped }}</span> }\n }\n </button>\n </div>\n }\n\n @if (activeTab() === 'coverage') {\n <div class=\"coverage-toolbar\">\n <mm-perspective-switcher\n [perspectives]=\"perspectives()\"\n [activeKey]=\"activePerspectiveKey()\"\n (perspectiveChange)=\"onPerspectiveChange($event)\"></mm-perspective-switcher>\n <label class=\"toolbar-label\">Tree:</label>\n <select class=\"root-select\"\n [value]=\"selectedRoot()?.rtId ?? ''\"\n (change)=\"onRootSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a {{ activeRootCkTypeId() }} \u2014</option>\n @for (root of rootCandidates(); track root.rtId) {\n <option [value]=\"root.rtId\" [title]=\"root.description\">{{ root.name }}</option>\n }\n </select>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n (click)=\"refreshRoots()\" title=\"Refresh tree list\"></button>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.folderOpen\"\n (click)=\"pickRoot()\" title=\"Browse for entity\">Browse...</button>\n\n @if (selectedRoot(); as root) {\n <div class=\"toolbar-spacer\"></div>\n <span class=\"toolbar-meta\">\n <span class=\"meta-name\">{{ root.name }}</span>\n <span class=\"meta-type\">{{ root.ckTypeId }}</span>\n </span>\n }\n </div>\n\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Validation:</label>\n <select class=\"root-select\"\n [value]=\"selectedPipeline()?.rtId ?? ''\"\n (change)=\"onPipelineSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a {{ config.validationPipelineCkTypeId }} \u2014</option>\n @for (p of validationPipelines(); track p.rtId) {\n <option [value]=\"p.rtId\">{{ p.name }}</option>\n }\n </select>\n @if (tenantId) {\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"!selectedPipeline() || validationRunning() || validationLoading()\"\n (click)=\"runValidation()\"\n [title]=\"validationRunning() ? 'Validation running\u2026' : 'Run pipeline + load report'\">\n @if (validationRunning()) { Running\u2026 } @else { Run }\n </button>\n }\n <button kendoButton fillMode=\"solid\" size=\"small\" [svgIcon]=\"icons.refresh\"\n [disabled]=\"!selectedPipeline() || validationLoading() || validationRunning()\"\n (click)=\"refreshValidation()\">Load Report</button>\n @if (validationSummary()) {\n <button kendoButton fillMode=\"flat\" size=\"small\"\n (click)=\"clearValidation()\">Clear</button>\n }\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (validationLoading()) {\n <span class=\"toolbar-meta\">Loading\u2026</span>\n } @else if (validationError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (validationSummary(); as s) {\n <span class=\"validation-summary\">\n <span class=\"badge badge-error\" title=\"error\">{{ s.error }} err</span>\n <span class=\"badge badge-warning\" title=\"warning\">{{ s.warning }} warn</span>\n <span class=\"badge badge-ok\" title=\"ok\">{{ s.ok }} ok</span>\n <span class=\"badge badge-info\" title=\"info / unscoped\">{{ s.info }} info</span>\n <span class=\"badge\">{{ s.total }} total</span>\n @if (validationExecutedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n }\n </div>\n\n @if (tenantId) {\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Generation:</label>\n <select class=\"root-select\"\n [value]=\"selectedGenerationPipeline()?.rtId ?? ''\"\n (change)=\"onGenerationSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick an auto-mapping pipeline \u2014</option>\n @for (p of validationPipelines(); track p.rtId) {\n <option [value]=\"p.rtId\">{{ p.name }}</option>\n }\n </select>\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"!selectedGenerationPipeline() || generationRunning()\"\n (click)=\"runGeneration()\"\n [title]=\"generationRunning() ? 'Generation running\u2026' : 'Run the auto-mapping pipeline and reload counts'\">\n @if (generationRunning()) { Running\u2026 } @else { Generate }\n </button>\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (generationRunning()) {\n <span class=\"toolbar-meta\">Generating mappings\u2026</span>\n } @else if (generationError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (generationStats(); as s) {\n <span class=\"validation-summary\">\n @if (s.totalSuggestions !== undefined) {\n <span class=\"badge badge-ok\" title=\"mapping suggestions produced\">{{ s.totalSuggestions }} mappings</span>\n }\n @if (s.matchedContainers !== undefined && s.totalContainers !== undefined) {\n <span class=\"badge\" title=\"containers (e.g. rooms) matched to a target\">\n {{ s.matchedContainers }}/{{ s.totalContainers }} matched\n </span>\n }\n @if (s.unmatchedContainers) {\n <span class=\"badge badge-warning\"\n [attr.title]=\"'Unmatched: ' + (s.unmatchedContainerNames ?? []).join(', ')\">\n {{ s.unmatchedContainers }} unmatched\n </span>\n }\n @if (generationCompletedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n } @else if (generationCompletedAt(); as ts) {\n <span class=\"toolbar-meta\">Completed {{ ts }} (no statistics in OutputData)</span>\n }\n </div>\n }\n\n @if (tenantId && (exportBackupPipeline() || importBackupPipeline())) {\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Backup:</label>\n <button kendoButton size=\"small\" [svgIcon]=\"icons.download\"\n [disabled]=\"!exportBackupPipeline() || backupRunning() !== null\"\n (click)=\"exportMappings()\"\n title=\"Run the export pipeline and download the mapping document as JSON\">\n @if (backupRunning() === 'export') { Exporting\u2026 } @else { Export }\n </button>\n <button kendoButton size=\"small\" [svgIcon]=\"icons.upload\"\n [disabled]=\"!importBackupPipeline() || backupRunning() !== null\"\n (click)=\"importFileInput.click()\"\n title=\"Import a previously exported mapping document (JSON)\">\n @if (backupRunning() === 'import') { Importing\u2026 } @else { Import\u2026 }\n </button>\n <input #importFileInput type=\"file\" accept=\".json,application/json\" hidden\n (change)=\"onImportFileSelected($event)\" />\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (backupRunning() === 'export') {\n <span class=\"toolbar-meta\">Exporting mappings\u2026</span>\n } @else if (backupRunning() === 'import') {\n <span class=\"toolbar-meta\">Importing mappings\u2026</span>\n } @else if (backupError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (importStats(); as s) {\n <span class=\"validation-summary\">\n @if (s.resolved !== undefined) {\n <span class=\"badge badge-ok\" title=\"mappings resolved and imported\">{{ s.resolved }} imported</span>\n }\n @if (s.unresolved) {\n <span class=\"badge badge-warning\"\n [attr.title]=\"'Unresolved: ' + unresolvedImportNames()\">\n {{ s.unresolved }} unresolved\n </span>\n }\n @if (s.total !== undefined) {\n <span class=\"badge\">{{ s.total }} total</span>\n }\n @if (importCompletedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n } @else if (importCompletedAt(); as ts) {\n <span class=\"toolbar-meta\">Import completed {{ ts }} (no statistics in OutputData)</span>\n }\n </div>\n }\n\n <div class=\"coverage-body\">\n <div class=\"coverage-tree-pane\">\n @if (selectedRoot()) {\n <mm-tree-view\n [dataSource]=\"dataSource\"\n (nodeSelected)=\"onNodeSelected($event)\">\n </mm-tree-view>\n } @else {\n <div class=\"empty-hint\">\n Select a tree to start. Counts in brackets show how many mappings\n point to that node.\n </div>\n }\n </div>\n\n <div class=\"coverage-detail-pane\">\n @if (selectedNode(); as node) {\n <div class=\"detail-header\">\n <div class=\"detail-titles\">\n <h3 class=\"detail-name\">{{ node.name }}</h3>\n <div class=\"detail-subtitle\">{{ node.ckTypeId }}@{{ node.rtId }}</div>\n </div>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n (click)=\"refreshSelected()\" title=\"Refresh\"></button>\n </div>\n\n <div class=\"detail-section-title\">\n <span>Mappings</span>\n @if (summaryLine(); as s) {\n <span class=\"detail-summary\">{{ s }}</span>\n }\n <span class=\"toolbar-spacer\"></span>\n <button kendoButton themeColor=\"primary\" size=\"small\" [svgIcon]=\"icons.plus\"\n (click)=\"addMapping()\">Add</button>\n </div>\n\n @if (mappingsLoading()) {\n <div class=\"empty-hint\">Loading mappings\u2026</div>\n } @else if (mappingsError(); as err) {\n <div class=\"error-hint\">{{ err }}</div>\n } @else if (mappings().length === 0) {\n <div class=\"empty-hint\">\n No mappings reference this node yet. Add one using the button above.\n </div>\n } @else {\n <ul class=\"mapping-list\">\n @for (mapping of mappings(); track trackByRtId($index, mapping)) {\n <li class=\"mapping-row\" [class.mapping-disabled]=\"!mapping.enabled\">\n <div class=\"mapping-line\">\n <span class=\"mapping-name\">\n {{ mapping.name || 'Mapping ' + ($index + 1) }}\n </span>\n @if (!mapping.enabled) {\n <span class=\"mapping-badge mapping-badge-off\">disabled</span>\n }\n </div>\n <div class=\"mapping-details\">\n <span class=\"kv\">\n <span class=\"kv-key\">Source:</span>\n <span class=\"kv-val\">\n {{ mapping.sourceName || mapping.sourceRtId || '\u2014 not linked \u2014' }}\n </span>\n </span>\n @if (mapping.sourceAttributePath) {\n <span class=\"kv\">\n <span class=\"kv-key\">Attr:</span>\n <span class=\"kv-val\">{{ mapping.sourceAttributePath }}</span>\n </span>\n }\n @if (mapping.mappingExpression) {\n <span class=\"kv\">\n <span class=\"kv-key\">Expr:</span>\n <code class=\"kv-val\">{{ mapping.mappingExpression }}</code>\n </span>\n }\n @if (mapping.targetAttributePath) {\n <span class=\"kv\">\n <span class=\"kv-key\">\u2192</span>\n <span class=\"kv-val\">{{ mapping.targetAttributePath }}</span>\n </span>\n }\n </div>\n <div class=\"mapping-actions\">\n <button kendoButton themeColor=\"primary\" fillMode=\"flat\" size=\"small\"\n [svgIcon]=\"icons.pencil\"\n (click)=\"editMapping(mapping)\"\n title=\"Edit mapping\">Edit\u2026</button>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.trash\"\n (click)=\"deleteMapping(mapping)\"\n title=\"Delete mapping\"></button>\n </div>\n </li>\n }\n </ul>\n }\n } @else {\n <div class=\"empty-hint\">\n Select a node from the tree to view and edit its mappings.\n </div>\n }\n </div>\n </div>\n }\n\n @if (activeTab() === 'orphans') {\n <div class=\"coverage-toolbar\">\n <label class=\"toolbar-label\">Source type:</label>\n <select class=\"root-select\"\n [value]=\"orphanCkType() ?? ''\"\n (change)=\"onOrphanCkTypeChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a source type \u2014</option>\n @for (ckType of config.sourceCandidateCkTypeIds; track ckType) {\n <option [value]=\"ckType\">{{ ckType }}</option>\n }\n </select>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n [disabled]=\"!orphanCkType() || orphanLoading()\"\n (click)=\"refreshOrphans()\" title=\"Reload\"></button>\n <span class=\"orphan-search-wrap\">\n <input type=\"text\" class=\"root-select orphan-search\"\n placeholder=\"Search name, room, description\u2026\"\n [value]=\"orphanSearchText()\"\n (input)=\"orphanSearchText.set($any($event.target).value)\" />\n @if (orphanSearchText()) {\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.x\"\n class=\"orphan-search-clear\"\n (click)=\"orphanSearchText.set('')\"\n title=\"Clear search\" aria-label=\"Clear search\"></button>\n }\n </span>\n <label class=\"orphan-toggle\">\n <input type=\"checkbox\" [checked]=\"orphanHideMapped()\" (change)=\"toggleOrphanHideMapped()\" />\n Hide already-mapped\n </label>\n <label class=\"toolbar-label\">Group by:</label>\n <select class=\"root-select\"\n [value]=\"orphanGroupParentType() ?? ''\"\n (change)=\"onOrphanGroupParentTypeChange($any($event.target).value)\">\n <option value=\"\">(no grouping)</option>\n @for (t of orphanAvailableParentTypes(); track t) {\n <option [value]=\"t\">{{ t }}</option>\n }\n </select>\n @if (orphanGroupParentType()) {\n <kendo-multiselect class=\"orphan-group-filter\"\n [data]=\"orphanAvailableGroupNames()\"\n [value]=\"orphanSelectedGroupNames()\"\n (valueChange)=\"onOrphanGroupNamesChange($event)\"\n [autoClose]=\"false\"\n [clearButton]=\"true\"\n size=\"small\"\n placeholder=\"Filter groups\u2026\"\n title=\"Show only the selected groups (e.g. specific categories)\">\n </kendo-multiselect>\n }\n\n <div class=\"toolbar-spacer\"></div>\n\n <button kendoButton size=\"small\" fillMode=\"flat\"\n [disabled]=\"orphanVisibleList().length === 0\"\n (click)=\"selectAllVisibleOrphans()\"\n title=\"Select every row visible under the current filter\">Select all</button>\n <button kendoButton size=\"small\" fillMode=\"flat\"\n [disabled]=\"orphanSelectedCount() === 0\"\n (click)=\"clearOrphanSelection()\">Clear</button>\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"orphanSelectedCount() === 0\"\n (click)=\"bulkMapSelected()\"\n title=\"Create one mapping per selected source (shared target + paths)\">\n Map {{ orphanSelectedCount() }} selected\u2026\n </button>\n\n @if (orphanStats(); as s) {\n <span class=\"validation-summary\">\n @if (orphanSearchText().trim() || orphanSelectedGroupNames().length > 0) {\n <span class=\"badge badge-info\" title=\"rows matching search + group filter\">{{ orphanVisibleList().length }} shown</span>\n }\n <span class=\"badge badge-error\" title=\"unmapped \u2014 no DataPointMapping yet\">{{ s.unmapped }} unmapped</span>\n <span class=\"badge badge-ok\" title=\"already covered by at least one mapping\">{{ s.mapped }} mapped</span>\n <span class=\"badge\">{{ s.total }} total</span>\n </span>\n }\n </div>\n\n <div class=\"orphan-body\">\n @if (orphanLoading()) {\n <div class=\"empty-hint\">Loading source candidates\u2026</div>\n } @else if (orphanError(); as err) {\n <div class=\"error-hint\">{{ err }}</div>\n } @else if (orphanVisibleList().length === 0) {\n <div class=\"empty-hint\">\n @if (orphanSelectedGroupNames().length > 0) {\n No entries in the selected group(s) match the current filters.\n } @else if (orphanSearchText().trim()) {\n No entries match \"{{ orphanSearchText() }}\".\n } @else if (orphanHideMapped()) {\n All {{ orphanCkType() }} entities are mapped at least once. \uD83C\uDF89\n } @else {\n No entities of type {{ orphanCkType() }} found.\n }\n </div>\n } @else if (orphanGroupParentType()) {\n @for (group of orphanGroupedList(); track group.key) {\n <div class=\"orphan-group\">\n <div class=\"orphan-group-header\">\n <span class=\"orphan-group-label\">{{ group.label }}</span>\n <span class=\"orphan-group-count\">{{ group.items.length }}</span>\n </div>\n <ul class=\"orphan-list\">\n @for (item of group.items; track trackOrphanByRtId($index, item)) {\n <ng-container *ngTemplateOutlet=\"orphanRowTpl; context: { $implicit: item }\"></ng-container>\n }\n </ul>\n </div>\n }\n } @else {\n <ul class=\"orphan-list\">\n @for (item of orphanVisibleList(); track trackOrphanByRtId($index, item)) {\n <ng-container *ngTemplateOutlet=\"orphanRowTpl; context: { $implicit: item }\"></ng-container>\n }\n </ul>\n }\n\n <ng-template #orphanRowTpl let-item>\n <li class=\"orphan-row\" [class.orphan-mapped]=\"item.mappingCount > 0\">\n <div class=\"orphan-line\">\n <input type=\"checkbox\" class=\"orphan-check\"\n [checked]=\"isOrphanSelected(item.rtId)\"\n (change)=\"toggleOrphanSelected(item.rtId)\"\n [attr.aria-label]=\"'Select ' + item.name\" />\n <span class=\"orphan-name\">{{ item.name }}</span>\n @if (item.mappingCount > 0) {\n <span class=\"orphan-badge orphan-badge-mapped\">\n {{ item.mappingCount }} mapping{{ item.mappingCount === 1 ? '' : 's' }}\n </span>\n } @else {\n <span class=\"orphan-badge orphan-badge-unmapped\">unmapped</span>\n }\n </div>\n @if (item.parentPath.length > 0) {\n <div class=\"orphan-breadcrumb\" [attr.title]=\"'Parent chain (root-first)'\">\n @for (parent of breadcrumbFor(item); track parent.rtId; let last = $last) {\n <span class=\"crumb\">{{ parent.name }}</span>\n @if (!last) { <span class=\"crumb-sep\">\u203A</span> }\n }\n </div>\n }\n <div class=\"orphan-meta\">\n <span class=\"kv-val\">{{ item.ckTypeId }}@{{ item.rtId }}</span>\n </div>\n @if (item.description) {\n <div class=\"orphan-description\">{{ item.description }}</div>\n }\n <div class=\"orphan-actions\">\n <button kendoButton themeColor=\"primary\" fillMode=\"flat\" size=\"small\"\n [svgIcon]=\"icons.plus\"\n (click)=\"createMappingFromOrphan(item)\"\n title=\"Create mapping pre-linked to this source\">\n Map\u2026\n </button>\n </div>\n </li>\n </ng-template>\n </div>\n }\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0}.coverage-root{display:flex;flex-direction:column;flex:1;min-height:0;gap:12px}.coverage-toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 12px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface-alt, #f8f9fa)) 70%,transparent)}.coverage-toolbar .toolbar-label{flex:0 0 96px;font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.coverage-toolbar .root-select{flex:0 0 280px;min-width:0;padding:4px 8px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:4px;background:var(--theme-bg-elevated, var(--kendo-color-surface, #fff));color:var(--theme-text-primary, inherit);font-size:.9rem;height:30px}.coverage-toolbar .orphan-search-wrap{display:inline-flex;align-items:center;gap:2px}.coverage-toolbar .orphan-search-wrap .orphan-search{flex:1 1 220px;min-width:140px}.coverage-toolbar .orphan-group-filter{flex:0 1 320px;min-width:160px}.coverage-toolbar .toolbar-spacer{flex:1}.coverage-toolbar .toolbar-meta{display:flex;flex-direction:column;align-items:flex-end;line-height:1.1}.coverage-toolbar .toolbar-meta .meta-name{font-size:.85rem;font-weight:600}.coverage-toolbar .toolbar-meta .meta-type{font-size:.7rem;font-family:monospace;color:var(--kendo-color-subtle, #6c757d)}.coverage-body{flex:1;display:flex;gap:12px;min-height:0}@media(max-width:900px){.coverage-body{flex-direction:column}.coverage-tree-pane{flex:0 0 38vh;min-width:0;min-height:180px}.coverage-detail-pane{min-height:180px}.coverage-toolbar .toolbar-label{flex:0 0 auto}.coverage-toolbar .root-select{flex:1 1 200px;max-width:100%}}.coverage-tree-pane{flex:0 0 40%;min-width:240px;display:flex;flex-direction:column;min-height:0;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);color:var(--theme-text-primary, inherit);overflow:auto}.coverage-detail-pane{flex:1;min-width:0;display:flex;flex-direction:column;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);color:var(--theme-text-primary, inherit);padding:12px 14px;gap:12px;overflow:auto}.detail-header{display:flex;align-items:flex-start;gap:8px}.detail-header .detail-titles{flex:1;min-width:0}.detail-header .detail-name{margin:0;font-size:1.05rem;font-weight:600;word-break:break-word}.detail-header .detail-subtitle{font-size:.72rem;font-family:monospace;color:var(--kendo-color-subtle, #6c757d);word-break:break-all}.detail-section-title{display:flex;align-items:center;gap:10px;font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--kendo-color-subtle, #6c757d)}.detail-section-title .toolbar-spacer{flex:1}.detail-section-title .detail-summary{text-transform:none;letter-spacing:0;font-weight:500;color:var(--kendo-color-on-app-surface, inherit);font-size:.78rem}.mapping-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.mapping-row{border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;padding:8px 10px;display:flex;flex-direction:column;gap:6px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.mapping-row.mapping-disabled{opacity:.55}.mapping-line{display:flex;align-items:center;gap:8px}.mapping-line .mapping-name{font-weight:600;font-size:.9rem}.mapping-badge{font-size:.65rem;text-transform:uppercase;letter-spacing:.5px;padding:1px 6px;border-radius:8px;border:1px solid var(--kendo-color-border, #dee2e6)}.mapping-badge.mapping-badge-off{color:var(--kendo-color-subtle, #6c757d)}.mapping-details{display:flex;flex-wrap:wrap;gap:10px;font-size:.8rem}.mapping-details .kv{display:inline-flex;align-items:baseline;gap:4px}.mapping-details .kv-key{font-weight:600;color:var(--kendo-color-subtle, #6c757d)}.mapping-details code.kv-val{font-family:monospace;background:var(--kendo-color-surface, transparent);padding:1px 4px;border-radius:3px}.mapping-actions{display:flex;gap:6px;justify-content:flex-end}.empty-hint,.error-hint{padding:12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d);text-align:center}.error-hint{color:var(--kendo-color-error, #dc3545)}.coverage-tabs{display:flex;gap:0;border-bottom:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6))}.coverage-tab{padding:8px 16px;border:none;background:transparent;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-size:.85rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;display:inline-flex;align-items:center;gap:6px}.coverage-tab:hover{color:var(--theme-text-primary, inherit)}.coverage-tab.active{color:var(--theme-text-accent, var(--kendo-color-primary, #ff6358));border-bottom-color:var(--theme-text-accent, var(--kendo-color-primary, #ff6358))}.coverage-tab .tab-badge{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 22%,transparent);color:var(--kendo-color-error, #dc3545);border-radius:10px;padding:1px 8px;font-size:.7rem;font-weight:700}.orphan-toggle{display:inline-flex;align-items:center;gap:6px;font-size:.8rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));cursor:pointer}.orphan-body{flex:1;min-height:0;overflow:auto;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);padding:8px}.orphan-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.orphan-row{display:flex;flex-direction:column;gap:4px;padding:8px 10px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-left-width:3px;border-left-color:var(--kendo-color-error, #dc3545);border-radius:6px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.orphan-row.orphan-mapped{border-left-color:var(--kendo-color-success, #28a745);opacity:.7}.orphan-row .orphan-line{display:flex;align-items:center;gap:8px}.orphan-row .orphan-line .orphan-check{flex-shrink:0;margin:0;cursor:pointer;accent-color:var(--kendo-color-primary, #ff6358)}.orphan-row .orphan-line .orphan-name{flex:1;font-weight:600;font-size:.9rem}.orphan-row .orphan-badge{font-size:.7rem;padding:1px 8px;border-radius:10px;text-transform:uppercase;letter-spacing:.5px;font-weight:600}.orphan-row .orphan-badge-unmapped{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 22%,transparent);color:var(--kendo-color-error, #dc3545);border:1px solid var(--kendo-color-error, #dc3545)}.orphan-row .orphan-badge-mapped{background:color-mix(in srgb,var(--kendo-color-success, #28a745) 18%,transparent);color:var(--kendo-color-success, #28a745);border:1px solid var(--kendo-color-success, #28a745)}.orphan-row .orphan-meta{font-family:monospace;font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));word-break:break-all}.orphan-row .orphan-breadcrumb{display:flex;flex-wrap:wrap;align-items:center;gap:4px;font-size:.75rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.orphan-row .orphan-breadcrumb .crumb{line-height:1.3}.orphan-row .orphan-breadcrumb .crumb-sep{opacity:.55;font-weight:600}.orphan-row .orphan-description{font-size:.78rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-style:italic}.orphan-row .orphan-actions{display:flex;gap:6px;justify-content:flex-end}.orphan-group{display:flex;flex-direction:column;gap:6px}.orphan-group+.orphan-group{margin-top:14px}.orphan-group .orphan-group-header{display:flex;align-items:baseline;gap:8px;padding:4px 8px;border-bottom:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));font-size:.85rem;font-weight:600;color:var(--theme-text-primary, inherit)}.orphan-group .orphan-group-header .orphan-group-label{flex:1}.orphan-group .orphan-group-header .orphan-group-count{font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f1f3f5)) 80%,transparent);border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:10px;padding:0 8px}.validation-summary{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}.badge{font-size:.7rem;padding:2px 8px;border-radius:10px;background:var(--kendo-color-surface, #f1f3f5);border:1px solid var(--kendo-color-border, #dee2e6)}.badge-error{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 18%,transparent);border-color:var(--kendo-color-error, #dc3545);color:var(--kendo-color-error, #dc3545);font-weight:600}.badge-warning{background:color-mix(in srgb,var(--kendo-color-warning, #ffc107) 22%,transparent);border-color:var(--kendo-color-warning, #ffc107);color:var(--kendo-color-warning-on, #6b5500);font-weight:600}.badge-ok{background:color-mix(in srgb,var(--kendo-color-success, #28a745) 18%,transparent);border-color:var(--kendo-color-success, #28a745);color:var(--kendo-color-success, #28a745);font-weight:600}.badge-info{background:color-mix(in srgb,var(--kendo-color-info, #0dcaf0) 18%,transparent);border-color:var(--kendo-color-info, #0dcaf0);color:var(--kendo-color-info, #0dcaf0)}.validation-error-text{color:var(--kendo-color-error, #dc3545);font-size:.8rem}.validation-timestamp{font-size:.7rem;color:var(--kendo-color-subtle, #6c757d);margin-left:4px}\n"] }]
|
|
21425
|
+
], providers: [MappingCoverageTreeDataSource], template: "<div class=\"coverage-root\">\n @if (config.sourceCandidateCkTypeIds.length > 0) {\n <div class=\"coverage-tabs\" role=\"tablist\">\n <button class=\"coverage-tab\"\n [class.active]=\"activeTab() === 'coverage'\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === 'coverage'\"\n (click)=\"selectTab('coverage')\">Coverage Tree</button>\n <button class=\"coverage-tab\"\n [class.active]=\"activeTab() === 'orphans'\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab() === 'orphans'\"\n (click)=\"selectTab('orphans')\">\n Orphan Sources\n @if (orphanStats(); as s) {\n @if (s.unmapped > 0) { <span class=\"tab-badge\">{{ s.unmapped }}</span> }\n }\n </button>\n </div>\n }\n\n @if (activeTab() === 'coverage') {\n <div class=\"coverage-toolbar\">\n <mm-perspective-switcher\n [perspectives]=\"perspectives()\"\n [activeKey]=\"activePerspectiveKey()\"\n (perspectiveChange)=\"onPerspectiveChange($event)\"></mm-perspective-switcher>\n <label class=\"toolbar-label\">Tree:</label>\n <select class=\"root-select\"\n [value]=\"selectedRoot()?.rtId ?? ''\"\n (change)=\"onRootSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a {{ activeRootCkTypeId() }} \u2014</option>\n @for (root of rootCandidates(); track root.rtId) {\n <option [value]=\"root.rtId\" [title]=\"root.description\">{{ root.name }}</option>\n }\n </select>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n (click)=\"refreshRoots()\" title=\"Refresh tree list\" aria-label=\"Refresh tree list\"></button>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.folderOpen\"\n (click)=\"pickRoot()\" title=\"Browse for entity\">Browse...</button>\n\n @if (selectedRoot(); as root) {\n <div class=\"toolbar-spacer\"></div>\n <span class=\"toolbar-meta\">\n <span class=\"meta-name\">{{ root.name }}</span>\n <span class=\"meta-type\">{{ root.ckTypeId }}</span>\n </span>\n }\n </div>\n\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Validation:</label>\n <select class=\"root-select\"\n [value]=\"selectedPipeline()?.rtId ?? ''\"\n (change)=\"onPipelineSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a {{ config.validationPipelineCkTypeId }} \u2014</option>\n @for (p of validationPipelines(); track p.rtId) {\n <option [value]=\"p.rtId\">{{ p.name }}</option>\n }\n </select>\n @if (tenantId) {\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"!selectedPipeline() || validationRunning() || validationLoading()\"\n (click)=\"runValidation()\"\n [title]=\"validationRunning() ? 'Validation running\u2026' : 'Run pipeline + load report'\">\n @if (validationRunning()) { Running\u2026 } @else { Run }\n </button>\n }\n <button kendoButton fillMode=\"solid\" size=\"small\" [svgIcon]=\"icons.refresh\"\n [disabled]=\"!selectedPipeline() || validationLoading() || validationRunning()\"\n (click)=\"refreshValidation()\">Load Report</button>\n @if (validationSummary()) {\n <button kendoButton fillMode=\"flat\" size=\"small\"\n (click)=\"clearValidation()\">Clear</button>\n }\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (validationLoading()) {\n <span class=\"toolbar-meta\">Loading\u2026</span>\n } @else if (validationError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (validationSummary(); as s) {\n <span class=\"validation-summary\">\n <span class=\"badge badge-error\" title=\"error\">{{ s.error }} err</span>\n <span class=\"badge badge-warning\" title=\"warning\">{{ s.warning }} warn</span>\n <span class=\"badge badge-ok\" title=\"ok\">{{ s.ok }} ok</span>\n <span class=\"badge badge-info\" title=\"info / unscoped\">{{ s.info }} info</span>\n <span class=\"badge\">{{ s.total }} total</span>\n @if (validationExecutedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n }\n </div>\n\n @if (tenantId) {\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Generation:</label>\n <select class=\"root-select\"\n [value]=\"selectedGenerationPipeline()?.rtId ?? ''\"\n (change)=\"onGenerationSelectChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick an auto-mapping pipeline \u2014</option>\n @for (p of validationPipelines(); track p.rtId) {\n <option [value]=\"p.rtId\">{{ p.name }}</option>\n }\n </select>\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"!selectedGenerationPipeline() || generationRunning()\"\n (click)=\"runGeneration()\"\n [title]=\"generationRunning() ? 'Generation running\u2026' : 'Run the auto-mapping pipeline and reload counts'\">\n @if (generationRunning()) { Running\u2026 } @else { Generate }\n </button>\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (generationRunning()) {\n <span class=\"toolbar-meta\">Generating mappings\u2026</span>\n } @else if (generationError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (generationStats(); as s) {\n <span class=\"validation-summary\">\n @if (s.totalSuggestions !== undefined) {\n <span class=\"badge badge-ok\" title=\"mapping suggestions produced\">{{ s.totalSuggestions }} mappings</span>\n }\n @if (s.matchedContainers !== undefined && s.totalContainers !== undefined) {\n <span class=\"badge\" title=\"containers (e.g. rooms) matched to a target\">\n {{ s.matchedContainers }}/{{ s.totalContainers }} matched\n </span>\n }\n @if (s.unmatchedContainers) {\n <span class=\"badge badge-warning\"\n [attr.title]=\"'Unmatched: ' + (s.unmatchedContainerNames ?? []).join(', ')\">\n {{ s.unmatchedContainers }} unmatched\n </span>\n }\n @if (generationCompletedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n } @else if (generationCompletedAt(); as ts) {\n <span class=\"toolbar-meta\">Completed {{ ts }} (no statistics in OutputData)</span>\n }\n </div>\n }\n\n @if (tenantId && (exportBackupPipeline() || importBackupPipeline())) {\n <div class=\"coverage-toolbar coverage-toolbar-validation\">\n <label class=\"toolbar-label\">Backup:</label>\n <button kendoButton size=\"small\" [svgIcon]=\"icons.download\"\n [disabled]=\"!exportBackupPipeline() || backupRunning() !== null\"\n (click)=\"exportMappings()\"\n title=\"Run the export pipeline and download the mapping document as JSON\">\n @if (backupRunning() === 'export') { Exporting\u2026 } @else { Export }\n </button>\n <button kendoButton size=\"small\" [svgIcon]=\"icons.upload\"\n [disabled]=\"!importBackupPipeline() || backupRunning() !== null\"\n (click)=\"importFileInput.click()\"\n title=\"Import a previously exported mapping document (JSON)\">\n @if (backupRunning() === 'import') { Importing\u2026 } @else { Import\u2026 }\n </button>\n <input #importFileInput type=\"file\" accept=\".json,application/json\" hidden\n (change)=\"onImportFileSelected($event)\" />\n\n <div class=\"toolbar-spacer\"></div>\n\n @if (backupRunning() === 'export') {\n <span class=\"toolbar-meta\">Exporting mappings\u2026</span>\n } @else if (backupRunning() === 'import') {\n <span class=\"toolbar-meta\">Importing mappings\u2026</span>\n } @else if (backupError(); as err) {\n <span class=\"toolbar-meta validation-error-text\">{{ err }}</span>\n } @else if (importStats(); as s) {\n <span class=\"validation-summary\">\n @if (s.resolved !== undefined) {\n <span class=\"badge badge-ok\" title=\"mappings resolved and imported\">{{ s.resolved }} imported</span>\n }\n @if (s.unresolved) {\n <span class=\"badge badge-warning\"\n [attr.title]=\"'Unresolved: ' + unresolvedImportNames()\">\n {{ s.unresolved }} unresolved\n </span>\n }\n @if (s.total !== undefined) {\n <span class=\"badge\">{{ s.total }} total</span>\n }\n @if (importCompletedAt(); as ts) {\n <span class=\"validation-timestamp\">{{ ts }}</span>\n }\n </span>\n } @else if (importCompletedAt(); as ts) {\n <span class=\"toolbar-meta\">Import completed {{ ts }} (no statistics in OutputData)</span>\n }\n </div>\n }\n\n <div class=\"coverage-body\">\n <div class=\"coverage-tree-pane\">\n @if (selectedRoot()) {\n <mm-tree-view\n [dataSource]=\"dataSource\"\n (nodeSelected)=\"onNodeSelected($event)\">\n </mm-tree-view>\n } @else {\n <div class=\"empty-hint\">\n Select a tree to start. Counts in brackets show how many mappings\n point to that node.\n </div>\n }\n </div>\n\n <div class=\"coverage-detail-pane\">\n @if (selectedNode(); as node) {\n <div class=\"detail-header\">\n <div class=\"detail-titles\">\n <h3 class=\"detail-name\">{{ node.name }}</h3>\n <div class=\"detail-subtitle\">{{ node.ckTypeId }}@{{ node.rtId }}</div>\n </div>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n (click)=\"refreshSelected()\" title=\"Refresh\" aria-label=\"Refresh mappings\"></button>\n </div>\n\n <div class=\"detail-section-title\">\n <span>Mappings</span>\n @if (summaryLine(); as s) {\n <span class=\"detail-summary\">{{ s }}</span>\n }\n <span class=\"toolbar-spacer\"></span>\n <button kendoButton themeColor=\"primary\" size=\"small\" [svgIcon]=\"icons.plus\"\n (click)=\"addMapping()\">Add</button>\n </div>\n\n @if (mappingsLoading()) {\n <div class=\"empty-hint\">Loading mappings\u2026</div>\n } @else if (mappingsError(); as err) {\n <div class=\"error-hint\">{{ err }}</div>\n } @else if (mappings().length === 0) {\n <div class=\"empty-hint\">\n No mappings reference this node yet. Add one using the button above.\n </div>\n } @else {\n <ul class=\"mapping-list\">\n @for (mapping of mappings(); track trackByRtId($index, mapping)) {\n <li class=\"mapping-row\" [class.mapping-disabled]=\"!mapping.enabled\">\n <div class=\"mapping-line\">\n <span class=\"mapping-name\">\n {{ mapping.name || 'Mapping ' + ($index + 1) }}\n </span>\n @if (!mapping.enabled) {\n <span class=\"mapping-badge mapping-badge-off\">disabled</span>\n }\n </div>\n <div class=\"mapping-details\">\n <span class=\"kv\">\n <span class=\"kv-key\">Source:</span>\n <span class=\"kv-val\">\n {{ mapping.sourceName || mapping.sourceRtId || '\u2014 not linked \u2014' }}\n </span>\n </span>\n @if (mapping.sourceAttributePath) {\n <span class=\"kv\">\n <span class=\"kv-key\">Attr:</span>\n <span class=\"kv-val\">{{ mapping.sourceAttributePath }}</span>\n </span>\n }\n @if (mapping.mappingExpression) {\n <span class=\"kv\">\n <span class=\"kv-key\">Expr:</span>\n <code class=\"kv-val\">{{ mapping.mappingExpression }}</code>\n </span>\n }\n @if (mapping.targetAttributePath) {\n <span class=\"kv\">\n <span class=\"kv-key\">\u2192</span>\n <span class=\"kv-val\">{{ mapping.targetAttributePath }}</span>\n </span>\n }\n </div>\n <div class=\"mapping-actions\">\n <button kendoButton fillMode=\"flat\" size=\"small\"\n [svgIcon]=\"icons.pencil\"\n (click)=\"editMapping(mapping)\"\n title=\"Edit mapping\" [attr.aria-label]=\"'Edit mapping ' + (mapping.name || mapping.rtId)\"></button>\n <button kendoButton fillMode=\"flat\" size=\"small\" themeColor=\"error\" [svgIcon]=\"icons.trash\"\n (click)=\"deleteMapping(mapping)\" data-action=\"delete\"\n title=\"Delete mapping\" [attr.aria-label]=\"'Delete mapping ' + (mapping.name || mapping.rtId)\"></button>\n </div>\n </li>\n }\n </ul>\n }\n } @else {\n <div class=\"empty-hint\">\n Select a node from the tree to view and edit its mappings.\n </div>\n }\n </div>\n </div>\n }\n\n @if (activeTab() === 'orphans') {\n <div class=\"coverage-toolbar\">\n <label class=\"toolbar-label\">Source type:</label>\n <select class=\"root-select\"\n [value]=\"orphanCkType() ?? ''\"\n (change)=\"onOrphanCkTypeChange($any($event.target).value)\">\n <option value=\"\" disabled>\u2014 Pick a source type \u2014</option>\n @for (ckType of config.sourceCandidateCkTypeIds; track ckType) {\n <option [value]=\"ckType\">{{ ckType }}</option>\n }\n </select>\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.refresh\"\n [disabled]=\"!orphanCkType() || orphanLoading()\"\n (click)=\"refreshOrphans()\" title=\"Reload\" aria-label=\"Reload orphans\"></button>\n <span class=\"orphan-search-wrap\">\n <input type=\"text\" class=\"root-select orphan-search\"\n placeholder=\"Search name, room, description\u2026\"\n [value]=\"orphanSearchText()\"\n (input)=\"orphanSearchText.set($any($event.target).value)\" />\n @if (orphanSearchText()) {\n <button kendoButton fillMode=\"flat\" size=\"small\" [svgIcon]=\"icons.x\"\n class=\"orphan-search-clear\"\n (click)=\"orphanSearchText.set('')\"\n title=\"Clear search\" aria-label=\"Clear search\"></button>\n }\n </span>\n <label class=\"orphan-toggle\">\n <input type=\"checkbox\" [checked]=\"orphanHideMapped()\" (change)=\"toggleOrphanHideMapped()\" />\n Hide already-mapped\n </label>\n <label class=\"toolbar-label\">Group by:</label>\n <select class=\"root-select\"\n [value]=\"orphanGroupParentType() ?? ''\"\n (change)=\"onOrphanGroupParentTypeChange($any($event.target).value)\">\n <option value=\"\">(no grouping)</option>\n @for (t of orphanAvailableParentTypes(); track t) {\n <option [value]=\"t\">{{ t }}</option>\n }\n </select>\n @if (orphanGroupParentType()) {\n <kendo-multiselect class=\"orphan-group-filter\"\n [data]=\"orphanAvailableGroupNames()\"\n [value]=\"orphanSelectedGroupNames()\"\n (valueChange)=\"onOrphanGroupNamesChange($event)\"\n [autoClose]=\"false\"\n [clearButton]=\"true\"\n size=\"small\"\n placeholder=\"Filter groups\u2026\"\n title=\"Show only the selected groups (e.g. specific categories)\">\n </kendo-multiselect>\n }\n\n <div class=\"toolbar-spacer\"></div>\n\n <button kendoButton size=\"small\" fillMode=\"flat\"\n [disabled]=\"orphanVisibleList().length === 0\"\n (click)=\"selectAllVisibleOrphans()\"\n title=\"Select every row visible under the current filter\">Select all</button>\n <button kendoButton size=\"small\" fillMode=\"flat\"\n [disabled]=\"orphanSelectedCount() === 0\"\n (click)=\"clearOrphanSelection()\">Clear</button>\n <button kendoButton themeColor=\"primary\" size=\"small\"\n [disabled]=\"orphanSelectedCount() === 0\"\n (click)=\"bulkMapSelected()\"\n title=\"Create one mapping per selected source (shared target + paths)\">\n Map {{ orphanSelectedCount() }} selected\u2026\n </button>\n\n @if (orphanStats(); as s) {\n <span class=\"validation-summary\">\n @if (orphanSearchText().trim() || orphanSelectedGroupNames().length > 0) {\n <span class=\"badge badge-info\" title=\"rows matching search + group filter\">{{ orphanVisibleList().length }} shown</span>\n }\n <span class=\"badge badge-error\" title=\"unmapped \u2014 no DataPointMapping yet\">{{ s.unmapped }} unmapped</span>\n <span class=\"badge badge-ok\" title=\"already covered by at least one mapping\">{{ s.mapped }} mapped</span>\n <span class=\"badge\">{{ s.total }} total</span>\n </span>\n }\n </div>\n\n <div class=\"orphan-body\">\n @if (orphanLoading()) {\n <div class=\"empty-hint\">Loading source candidates\u2026</div>\n } @else if (orphanError(); as err) {\n <div class=\"error-hint\">{{ err }}</div>\n } @else if (orphanVisibleList().length === 0) {\n <div class=\"empty-hint\">\n @if (orphanSelectedGroupNames().length > 0) {\n No entries in the selected group(s) match the current filters.\n } @else if (orphanSearchText().trim()) {\n No entries match \"{{ orphanSearchText() }}\".\n } @else if (orphanHideMapped()) {\n All {{ orphanCkType() }} entities are mapped at least once. \uD83C\uDF89\n } @else {\n No entities of type {{ orphanCkType() }} found.\n }\n </div>\n } @else if (orphanGroupParentType()) {\n @for (group of orphanGroupedList(); track group.key) {\n <div class=\"orphan-group\">\n <div class=\"orphan-group-header\">\n <span class=\"orphan-group-label\">{{ group.label }}</span>\n <span class=\"orphan-group-count\">{{ group.items.length }}</span>\n </div>\n <ul class=\"orphan-list\">\n @for (item of group.items; track trackOrphanByRtId($index, item)) {\n <ng-container *ngTemplateOutlet=\"orphanRowTpl; context: { $implicit: item }\"></ng-container>\n }\n </ul>\n </div>\n }\n } @else {\n <ul class=\"orphan-list\">\n @for (item of orphanVisibleList(); track trackOrphanByRtId($index, item)) {\n <ng-container *ngTemplateOutlet=\"orphanRowTpl; context: { $implicit: item }\"></ng-container>\n }\n </ul>\n }\n\n <ng-template #orphanRowTpl let-item>\n <li class=\"orphan-row\" [class.orphan-mapped]=\"item.mappingCount > 0\">\n <div class=\"orphan-line\">\n <input type=\"checkbox\" class=\"orphan-check\"\n [checked]=\"isOrphanSelected(item.rtId)\"\n (change)=\"toggleOrphanSelected(item.rtId)\"\n [attr.aria-label]=\"'Select ' + item.name\" />\n <span class=\"orphan-name\">{{ item.name }}</span>\n @if (item.mappingCount > 0) {\n <span class=\"orphan-badge orphan-badge-mapped\">\n {{ item.mappingCount }} mapping{{ item.mappingCount === 1 ? '' : 's' }}\n </span>\n } @else {\n <span class=\"orphan-badge orphan-badge-unmapped\">unmapped</span>\n }\n </div>\n @if (item.parentPath.length > 0) {\n <div class=\"orphan-breadcrumb\" [attr.title]=\"'Parent chain (root-first)'\">\n @for (parent of breadcrumbFor(item); track parent.rtId; let last = $last) {\n <span class=\"crumb\">{{ parent.name }}</span>\n @if (!last) { <span class=\"crumb-sep\">\u203A</span> }\n }\n </div>\n }\n <div class=\"orphan-meta\">\n <span class=\"kv-val\">{{ item.ckTypeId }}@{{ item.rtId }}</span>\n </div>\n @if (item.description) {\n <div class=\"orphan-description\">{{ item.description }}</div>\n }\n <div class=\"orphan-actions\">\n <button kendoButton themeColor=\"primary\" fillMode=\"flat\" size=\"small\"\n [svgIcon]=\"icons.plus\"\n (click)=\"createMappingFromOrphan(item)\"\n title=\"Create mapping pre-linked to this source\">\n Map\u2026\n </button>\n </div>\n </li>\n </ng-template>\n </div>\n }\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0}.coverage-root{display:flex;flex-direction:column;flex:1;min-height:0;gap:12px}.coverage-toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 12px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface-alt, #f8f9fa)) 70%,transparent)}.coverage-toolbar .toolbar-label{flex:0 0 96px;font-size:.75rem;font-weight:600;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.coverage-toolbar .root-select{flex:0 0 280px;min-width:0;padding:4px 8px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:4px;background:var(--theme-bg-elevated, var(--kendo-color-surface, #fff));color:var(--theme-text-primary, inherit);font-size:.9rem;height:30px}.coverage-toolbar .orphan-search-wrap{display:inline-flex;align-items:center;gap:2px}.coverage-toolbar .orphan-search-wrap .orphan-search{flex:1 1 220px;min-width:140px}.coverage-toolbar .orphan-group-filter{flex:0 1 320px;min-width:160px}.coverage-toolbar .toolbar-spacer{flex:1}.coverage-toolbar .toolbar-meta{display:flex;flex-direction:column;align-items:flex-end;line-height:1.1}.coverage-toolbar .toolbar-meta .meta-name{font-size:.85rem;font-weight:600}.coverage-toolbar .toolbar-meta .meta-type{font-size:.7rem;font-family:monospace;color:var(--kendo-color-subtle, #6c757d)}.coverage-body{flex:1;display:flex;gap:12px;min-height:0}@media(max-width:900px){.coverage-body{flex-direction:column}.coverage-tree-pane{flex:0 0 38vh;min-width:0;min-height:180px}.coverage-detail-pane{min-height:180px}.coverage-toolbar .toolbar-label{flex:0 0 auto}.coverage-toolbar .root-select{flex:1 1 200px;max-width:100%}}.coverage-tree-pane{flex:0 0 40%;min-width:240px;display:flex;flex-direction:column;min-height:0;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);color:var(--theme-text-primary, inherit);overflow:auto}.coverage-detail-pane{flex:1;min-width:0;display:flex;flex-direction:column;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);color:var(--theme-text-primary, inherit);padding:12px 14px;gap:12px;overflow:auto}.detail-header{display:flex;align-items:flex-start;gap:8px}.detail-header .detail-titles{flex:1;min-width:0}.detail-header .detail-name{margin:0;font-size:1.05rem;font-weight:600;word-break:break-word}.detail-header .detail-subtitle{font-size:.72rem;font-family:monospace;color:var(--kendo-color-subtle, #6c757d);word-break:break-all}.detail-section-title{display:flex;align-items:center;gap:10px;font-size:.78rem;font-weight:700;color:var(--kendo-color-subtle, #6c757d)}.detail-section-title .toolbar-spacer{flex:1}.detail-section-title .detail-summary{text-transform:none;font-weight:500;color:var(--kendo-color-on-app-surface, inherit);font-size:.78rem}.mapping-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.mapping-row{border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;padding:8px 10px;display:flex;flex-direction:column;gap:6px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.mapping-row.mapping-disabled{opacity:.55}.mapping-line{display:flex;align-items:center;gap:8px}.mapping-line .mapping-name{font-weight:600;font-size:.9rem}.mapping-badge{font-size:.65rem;padding:1px 6px;border-radius:8px;border:1px solid var(--kendo-color-border, #dee2e6)}.mapping-badge.mapping-badge-off{color:var(--kendo-color-subtle, #6c757d)}.mapping-details{display:flex;flex-wrap:wrap;gap:10px;font-size:.8rem}.mapping-details .kv{display:inline-flex;align-items:baseline;gap:4px}.mapping-details .kv-key{font-weight:600;color:var(--kendo-color-subtle, #6c757d)}.mapping-details code.kv-val{font-family:monospace;background:var(--kendo-color-surface, transparent);padding:1px 4px;border-radius:3px}.mapping-actions{display:flex;gap:6px;justify-content:flex-end}.empty-hint,.error-hint{padding:12px;font-size:.85rem;color:var(--kendo-color-subtle, #6c757d);text-align:center}.error-hint{color:var(--kendo-color-error, #dc3545)}.coverage-tabs{display:flex;gap:0;border-bottom:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6))}.coverage-tab{padding:8px 16px;border:none;background:transparent;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-size:.85rem;font-weight:600;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;display:inline-flex;align-items:center;gap:6px}.coverage-tab:hover{color:var(--theme-text-primary, inherit)}.coverage-tab.active{color:var(--theme-text-accent, var(--kendo-color-primary, #ff6358));border-bottom-color:var(--theme-text-accent, var(--kendo-color-primary, #ff6358))}.coverage-tab .tab-badge{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 22%,transparent);color:var(--kendo-color-error, #dc3545);border-radius:10px;padding:1px 8px;font-size:.7rem;font-weight:700}.orphan-toggle{display:inline-flex;align-items:center;gap:6px;font-size:.8rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));cursor:pointer}.orphan-body{flex:1;min-height:0;overflow:auto;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:6px;background:color-mix(in srgb,var(--theme-bg-surface, var(--kendo-color-surface, #fff)) 60%,transparent);padding:8px}.orphan-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.orphan-row{display:flex;flex-direction:column;gap:4px;padding:8px 10px;border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-left-width:3px;border-left-color:var(--kendo-color-error, #dc3545);border-radius:6px;background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f8f9fa)) 65%,transparent)}.orphan-row.orphan-mapped{border-left-color:var(--kendo-color-success, #28a745);opacity:.7}.orphan-row .orphan-line{display:flex;align-items:center;gap:8px}.orphan-row .orphan-line .orphan-check{flex-shrink:0;margin:0;cursor:pointer;accent-color:var(--kendo-color-primary, #ff6358)}.orphan-row .orphan-line .orphan-name{flex:1;font-weight:600;font-size:.9rem}.orphan-row .orphan-badge{font-size:.7rem;padding:1px 8px;border-radius:10px;font-weight:600}.orphan-row .orphan-badge-unmapped{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 22%,transparent);color:var(--kendo-color-error, #dc3545);border:1px solid var(--kendo-color-error, #dc3545)}.orphan-row .orphan-badge-mapped{background:color-mix(in srgb,var(--kendo-color-success, #28a745) 18%,transparent);color:var(--kendo-color-success, #28a745);border:1px solid var(--kendo-color-success, #28a745)}.orphan-row .orphan-meta{font-family:monospace;font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));word-break:break-all}.orphan-row .orphan-breadcrumb{display:flex;flex-wrap:wrap;align-items:center;gap:4px;font-size:.75rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d))}.orphan-row .orphan-breadcrumb .crumb{line-height:1.3}.orphan-row .orphan-breadcrumb .crumb-sep{opacity:.55;font-weight:600}.orphan-row .orphan-description{font-size:.78rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));font-style:italic}.orphan-row .orphan-actions{display:flex;gap:6px;justify-content:flex-end}.orphan-group{display:flex;flex-direction:column;gap:6px}.orphan-group+.orphan-group{margin-top:14px}.orphan-group .orphan-group-header{display:flex;align-items:baseline;gap:8px;padding:4px 8px;border-bottom:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));font-size:.85rem;font-weight:600;color:var(--theme-text-primary, inherit)}.orphan-group .orphan-group-header .orphan-group-label{flex:1}.orphan-group .orphan-group-header .orphan-group-count{font-size:.7rem;color:var(--theme-text-secondary, var(--kendo-color-subtle, #6c757d));background:color-mix(in srgb,var(--theme-bg-elevated, var(--kendo-color-surface-alt, #f1f3f5)) 80%,transparent);border:1px solid var(--theme-border-subtle, var(--kendo-color-border, #dee2e6));border-radius:10px;padding:0 8px}.validation-summary{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}.badge{font-size:.7rem;padding:2px 8px;border-radius:10px;background:var(--kendo-color-surface, #f1f3f5);border:1px solid var(--kendo-color-border, #dee2e6)}.badge-error{background:color-mix(in srgb,var(--kendo-color-error, #dc3545) 18%,transparent);border-color:var(--kendo-color-error, #dc3545);color:var(--kendo-color-error, #dc3545);font-weight:600}.badge-warning{background:color-mix(in srgb,var(--kendo-color-warning, #ffc107) 22%,transparent);border-color:var(--kendo-color-warning, #ffc107);color:var(--kendo-color-warning-on, #6b5500);font-weight:600}.badge-ok{background:color-mix(in srgb,var(--kendo-color-success, #28a745) 18%,transparent);border-color:var(--kendo-color-success, #28a745);color:var(--kendo-color-success, #28a745);font-weight:600}.badge-info{background:color-mix(in srgb,var(--kendo-color-info, #0dcaf0) 18%,transparent);border-color:var(--kendo-color-info, #0dcaf0);color:var(--kendo-color-info, #0dcaf0)}.validation-error-text{color:var(--kendo-color-error, #dc3545);font-size:.8rem}.validation-timestamp{font-size:.7rem;color:var(--kendo-color-subtle, #6c757d);margin-left:4px}\n"] }]
|
|
20843
21426
|
}], ctorParameters: () => [], propDecorators: { treeView: [{
|
|
20844
21427
|
type: ViewChild,
|
|
20845
21428
|
args: [TreeComponent, { static: false }]
|
|
@@ -21114,7 +21697,7 @@ class TenantSwitcherComponent {
|
|
|
21114
21697
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: TenantSwitcherComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
21115
21698
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: TenantSwitcherComponent, isStandalone: true, selector: "mm-tenant-switcher", inputs: { currentTenantId: "currentTenantId", allowedTenants: "allowedTenants", isDenied: "isDenied" }, outputs: { tenantSelected: "tenantSelected", refreshRequested: "refreshRequested" }, host: { listeners: { "document:keydown": "onKeydown($event)", "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "anchor", first: true, predicate: ["badgeEl"], descendants: true, read: ElementRef }, { propertyName: "popup", first: true, predicate: ["popupContent"], descendants: true, read: ElementRef }], ngImport: i0, template: `
|
|
21116
21699
|
@if (currentTenantId) {
|
|
21117
|
-
<div #badgeEl class="tenant-badge" [class.denied]="isDenied" (click)="onToggle()">
|
|
21700
|
+
<div #badgeEl class="tenant-badge" [class.denied]="isDenied" [title]="currentTenantId" (click)="onToggle()">
|
|
21118
21701
|
<span class="tenant-icon">{{ isDenied ? '\u26A0' : '\u25C6' }}</span>
|
|
21119
21702
|
<span class="tenant-name">{{ currentTenantId }}</span>
|
|
21120
21703
|
@if (isDenied) {
|
|
@@ -21130,7 +21713,7 @@ class TenantSwitcherComponent {
|
|
|
21130
21713
|
<span>Switch Tenant</span>
|
|
21131
21714
|
<button kendoButton fillMode="flat" size="small" class="refresh-btn"
|
|
21132
21715
|
[disabled]="isRefreshing"
|
|
21133
|
-
title="Refresh tenant list"
|
|
21716
|
+
title="Refresh tenant list" aria-label="Refresh tenant list"
|
|
21134
21717
|
(click)="onRefresh($event)">
|
|
21135
21718
|
<kendo-svgicon [icon]="refreshIcon" size="small"
|
|
21136
21719
|
[class.spinning]="isRefreshing"></kendo-svgicon>
|
|
@@ -21149,7 +21732,7 @@ class TenantSwitcherComponent {
|
|
|
21149
21732
|
</kendo-popup>
|
|
21150
21733
|
}
|
|
21151
21734
|
}
|
|
21152
|
-
`, isInline: true, styles: [":host{display:inline-flex;align-items:center}.tenant-badge{display:flex;align-items:center;gap:8px;padding:6px 14px;background:var(--mm-tenant-switcher-bg, var(--kendo-color-surface, transparent));border:1px solid var(--mm-tenant-switcher-border, var(--kendo-color-border, #dee2e6));border-radius:var(--mm-tenant-switcher-radius, 4px 16px 16px 4px);box-shadow:var(--mm-tenant-switcher-shadow, none);cursor:pointer;transition:all .2s ease}.tenant-badge:hover{background:var(--mm-tenant-switcher-bg-hover, var(--kendo-color-base-hover, rgba(0, 0, 0, .04)));box-shadow:var(--mm-tenant-switcher-shadow-hover, var(--mm-tenant-switcher-shadow, none))}.tenant-icon{font-size:.7rem;color:var(--mm-tenant-switcher-accent, var(--kendo-color-primary, #ff6358));animation:var(--mm-tenant-switcher-icon-animation, none)}.tenant-name{font-family:var(--mm-tenant-switcher-font, inherit);font-size:.85rem;font-weight:600;
|
|
21735
|
+
`, isInline: true, styles: [":host{display:inline-flex;align-items:center;min-width:0;max-width:100%}.tenant-badge{display:flex;align-items:center;gap:8px;min-width:0;padding:var(--mm-tenant-switcher-padding, 6px 14px);background:var(--mm-tenant-switcher-bg, var(--kendo-color-surface, transparent));border:1px solid var(--mm-tenant-switcher-border, var(--kendo-color-border, #dee2e6));border-radius:var(--mm-tenant-switcher-radius, 4px 16px 16px 4px);box-shadow:var(--mm-tenant-switcher-shadow, none);cursor:pointer;transition:all .2s ease}.tenant-badge:hover{background:var(--mm-tenant-switcher-bg-hover, var(--kendo-color-base-hover, rgba(0, 0, 0, .04)));box-shadow:var(--mm-tenant-switcher-shadow-hover, var(--mm-tenant-switcher-shadow, none))}.tenant-icon{flex:none;font-size:.7rem;color:var(--mm-tenant-switcher-accent, var(--kendo-color-primary, #ff6358));animation:var(--mm-tenant-switcher-icon-animation, none)}.tenant-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mm-tenant-switcher-font, inherit);font-size:.85rem;font-weight:600;color:var(--mm-tenant-switcher-accent, var(--kendo-color-primary, #ff6358));text-shadow:var(--mm-tenant-switcher-text-shadow, none)}.denied{background:var(--mm-tenant-switcher-denied-bg, var(--mm-tenant-switcher-bg, var(--kendo-color-surface, transparent)));border-color:var(--mm-tenant-switcher-denied-border, var(--kendo-color-error, #d9534f));box-shadow:var(--mm-tenant-switcher-denied-shadow, none)}.denied .tenant-icon,.denied .tenant-name{color:var(--mm-tenant-switcher-denied-accent, var(--kendo-color-error, #d9534f));text-shadow:var(--mm-tenant-switcher-denied-text-shadow, none)}.denied-label{font-family:var(--mm-tenant-switcher-font, inherit);font-size:.55rem;font-weight:700;color:var(--mm-tenant-switcher-denied-accent, var(--kendo-color-error, #d9534f));background:var(--mm-tenant-switcher-denied-label-bg, color-mix(in srgb, var(--kendo-color-error, #d9534f) 15%, transparent));padding:2px 6px;border-radius:3px}.tenant-popup{min-width:220px;padding:8px 0;background:var(--kendo-color-surface, #fff);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.tenant-popup-header{display:flex;align-items:center;justify-content:space-between;padding:8px 16px;font-size:.75rem;font-weight:600;color:var(--kendo-color-subtle, #666);border-bottom:1px solid var(--kendo-color-border, #dee2e6);margin-bottom:4px}.refresh-btn{padding:2px;min-width:unset}.spinning{animation:spin .8s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.tenant-list{list-style:none;margin:0;padding:0}.tenant-list-item{display:flex;align-items:center;gap:10px;padding:8px 16px;cursor:pointer;font-size:.85rem;transition:background .15s ease}.tenant-list-item:hover{background:var(--kendo-color-base-hover, rgba(0, 0, 0, .04))}.tenant-list-item.active{color:var(--kendo-color-primary, #ff6358);font-weight:600}.tenant-list-icon{font-size:.5rem;color:var(--kendo-color-subtle, #666)}.tenant-list-item.active .tenant-list-icon{color:var(--kendo-color-primary, #ff6358)}@keyframes mm-icon-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.7;transform:scale(1.1)}}\n"], dependencies: [{ kind: "component", type: PopupComponent, selector: "kendo-popup", inputs: ["animate", "anchor", "anchorAlign", "collision", "popupAlign", "copyAnchorStyles", "popupClass", "positionMode", "offset", "margin"], outputs: ["anchorViewportLeave", "close", "open", "positionChange"], exportAs: ["kendo-popup"] }, { kind: "component", type: 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: "component", type: SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon", "variant"], exportAs: ["kendoSVGIcon"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
21153
21736
|
}
|
|
21154
21737
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: TenantSwitcherComponent, decorators: [{
|
|
21155
21738
|
type: Component,
|
|
@@ -21159,7 +21742,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
21159
21742
|
SVGIconComponent
|
|
21160
21743
|
], template: `
|
|
21161
21744
|
@if (currentTenantId) {
|
|
21162
|
-
<div #badgeEl class="tenant-badge" [class.denied]="isDenied" (click)="onToggle()">
|
|
21745
|
+
<div #badgeEl class="tenant-badge" [class.denied]="isDenied" [title]="currentTenantId" (click)="onToggle()">
|
|
21163
21746
|
<span class="tenant-icon">{{ isDenied ? '\u26A0' : '\u25C6' }}</span>
|
|
21164
21747
|
<span class="tenant-name">{{ currentTenantId }}</span>
|
|
21165
21748
|
@if (isDenied) {
|
|
@@ -21175,7 +21758,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
21175
21758
|
<span>Switch Tenant</span>
|
|
21176
21759
|
<button kendoButton fillMode="flat" size="small" class="refresh-btn"
|
|
21177
21760
|
[disabled]="isRefreshing"
|
|
21178
|
-
title="Refresh tenant list"
|
|
21761
|
+
title="Refresh tenant list" aria-label="Refresh tenant list"
|
|
21179
21762
|
(click)="onRefresh($event)">
|
|
21180
21763
|
<kendo-svgicon [icon]="refreshIcon" size="small"
|
|
21181
21764
|
[class.spinning]="isRefreshing"></kendo-svgicon>
|
|
@@ -21194,7 +21777,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
|
|
|
21194
21777
|
</kendo-popup>
|
|
21195
21778
|
}
|
|
21196
21779
|
}
|
|
21197
|
-
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:inline-flex;align-items:center}.tenant-badge{display:flex;align-items:center;gap:8px;padding:6px 14px;background:var(--mm-tenant-switcher-bg, var(--kendo-color-surface, transparent));border:1px solid var(--mm-tenant-switcher-border, var(--kendo-color-border, #dee2e6));border-radius:var(--mm-tenant-switcher-radius, 4px 16px 16px 4px);box-shadow:var(--mm-tenant-switcher-shadow, none);cursor:pointer;transition:all .2s ease}.tenant-badge:hover{background:var(--mm-tenant-switcher-bg-hover, var(--kendo-color-base-hover, rgba(0, 0, 0, .04)));box-shadow:var(--mm-tenant-switcher-shadow-hover, var(--mm-tenant-switcher-shadow, none))}.tenant-icon{font-size:.7rem;color:var(--mm-tenant-switcher-accent, var(--kendo-color-primary, #ff6358));animation:var(--mm-tenant-switcher-icon-animation, none)}.tenant-name{font-family:var(--mm-tenant-switcher-font, inherit);font-size:.85rem;font-weight:600;
|
|
21780
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:inline-flex;align-items:center;min-width:0;max-width:100%}.tenant-badge{display:flex;align-items:center;gap:8px;min-width:0;padding:var(--mm-tenant-switcher-padding, 6px 14px);background:var(--mm-tenant-switcher-bg, var(--kendo-color-surface, transparent));border:1px solid var(--mm-tenant-switcher-border, var(--kendo-color-border, #dee2e6));border-radius:var(--mm-tenant-switcher-radius, 4px 16px 16px 4px);box-shadow:var(--mm-tenant-switcher-shadow, none);cursor:pointer;transition:all .2s ease}.tenant-badge:hover{background:var(--mm-tenant-switcher-bg-hover, var(--kendo-color-base-hover, rgba(0, 0, 0, .04)));box-shadow:var(--mm-tenant-switcher-shadow-hover, var(--mm-tenant-switcher-shadow, none))}.tenant-icon{flex:none;font-size:.7rem;color:var(--mm-tenant-switcher-accent, var(--kendo-color-primary, #ff6358));animation:var(--mm-tenant-switcher-icon-animation, none)}.tenant-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mm-tenant-switcher-font, inherit);font-size:.85rem;font-weight:600;color:var(--mm-tenant-switcher-accent, var(--kendo-color-primary, #ff6358));text-shadow:var(--mm-tenant-switcher-text-shadow, none)}.denied{background:var(--mm-tenant-switcher-denied-bg, var(--mm-tenant-switcher-bg, var(--kendo-color-surface, transparent)));border-color:var(--mm-tenant-switcher-denied-border, var(--kendo-color-error, #d9534f));box-shadow:var(--mm-tenant-switcher-denied-shadow, none)}.denied .tenant-icon,.denied .tenant-name{color:var(--mm-tenant-switcher-denied-accent, var(--kendo-color-error, #d9534f));text-shadow:var(--mm-tenant-switcher-denied-text-shadow, none)}.denied-label{font-family:var(--mm-tenant-switcher-font, inherit);font-size:.55rem;font-weight:700;color:var(--mm-tenant-switcher-denied-accent, var(--kendo-color-error, #d9534f));background:var(--mm-tenant-switcher-denied-label-bg, color-mix(in srgb, var(--kendo-color-error, #d9534f) 15%, transparent));padding:2px 6px;border-radius:3px}.tenant-popup{min-width:220px;padding:8px 0;background:var(--kendo-color-surface, #fff);border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px}.tenant-popup-header{display:flex;align-items:center;justify-content:space-between;padding:8px 16px;font-size:.75rem;font-weight:600;color:var(--kendo-color-subtle, #666);border-bottom:1px solid var(--kendo-color-border, #dee2e6);margin-bottom:4px}.refresh-btn{padding:2px;min-width:unset}.spinning{animation:spin .8s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.tenant-list{list-style:none;margin:0;padding:0}.tenant-list-item{display:flex;align-items:center;gap:10px;padding:8px 16px;cursor:pointer;font-size:.85rem;transition:background .15s ease}.tenant-list-item:hover{background:var(--kendo-color-base-hover, rgba(0, 0, 0, .04))}.tenant-list-item.active{color:var(--kendo-color-primary, #ff6358);font-weight:600}.tenant-list-icon{font-size:.5rem;color:var(--kendo-color-subtle, #666)}.tenant-list-item.active .tenant-list-icon{color:var(--kendo-color-primary, #ff6358)}@keyframes mm-icon-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.7;transform:scale(1.1)}}\n"] }]
|
|
21198
21781
|
}], propDecorators: { currentTenantId: [{
|
|
21199
21782
|
type: Input
|
|
21200
21783
|
}], allowedTenants: [{
|
|
@@ -21371,5 +21954,5 @@ function provideOctoUi() {
|
|
|
21371
21954
|
* Generated bundle index. Do not edit.
|
|
21372
21955
|
*/
|
|
21373
21956
|
|
|
21374
|
-
export { AssociationValidationService, AttributeSelectorDialogComponent, AttributeSelectorDialogService, AttributeSortSelectorDialogComponent, AttributeSortSelectorDialogService, AttributeValueTypeDto, BulkMappingDialogComponent, BulkMappingDialogService, CkTypeSelectorDialogComponent, CkTypeSelectorDialogService, CkTypeSelectorInputComponent, DEFAULT_CK_TYPE_SELECTOR_DIALOG_MESSAGES, DEFAULT_CK_TYPE_SELECTOR_INPUT_MESSAGES, DEFAULT_DATA_POINT, DEFAULT_MAPPING_COVERAGE_TREE_CONFIG, DEFAULT_PROPERTY_GRID_MESSAGES, DEFAULT_RUNTIME_BROWSER_MESSAGES, DataMappingOverviewComponent, DataPointPickerComponent, DataPointResolverService, DefaultPropertyCategory, EntityDetailComponent, EntityIdInfoComponent, EntitySelectorDialogComponent, EntitySelectorDialogService, FieldFilterEditorComponent, MAPPING_COVERAGE_CONFIG_CONSTANTS, MappingCoverageConfigService, MappingCoverageTreeComponent, MappingCoverageTreeDataSource, MappingEditDialogComponent, MappingEditDialogService, OctoGraphQlDataSource, OctoGraphQlHierarchyDataSource, OctoLoaderComponent, PropertyConverterService, PropertyDisplayMode, PropertyGridComponent, PropertyValueDisplayComponent, RUNTIME_BROWSER_MESSAGES, RecordDetailDialogComponent, RtEntityIdHelper, RuntimeBrowserComponent, RuntimeBrowserOutletComponent, RuntimeBrowserPageComponent, RuntimeBrowserStateService, RuntimeEntityVariableDialogComponent, RuntimeEntityVariableDialogService, TREE_NAVIGATION_CONFIG_CONSTANTS, TenantSwitcherComponent, ThemeModeService, ThemeModeToggleComponent, TreeNavigationConfigService, account_tree, add, analytics, app_registration, article, botService, category, chat, checklist, code, coerceDataPointValue, component_exchange, computeExpressionPreview, computer, createRuntimeBrowserRoutes, customer, dashboard, event_list, extractDataPointNames, extractDataPoints, graphic_eq, group, identityService, insert_link, manage_accounts, more_time, notifications, page_info, pages, person_search, playlist_add_check, pool, power, provideOctoUi, publicIcon, query_builder, schedule_send, settings, sort, storage, swagger, swagger_asset, swagger_bot, swagger_communication, swagger_identity, team_dashboard, tenancy, text_snippet, travel_explore, user_diagnostics, webhook, work };
|
|
21957
|
+
export { AssociationValidationService, AttributeSelectorDialogComponent, AttributeSelectorDialogService, AttributeSortSelectorDialogComponent, AttributeSortSelectorDialogService, AttributeValueTypeDto, BulkMappingDialogComponent, BulkMappingDialogService, CkTypeSelectorDialogComponent, CkTypeSelectorDialogService, CkTypeSelectorInputComponent, DATA_POINT_MAPPING_ATTRIBUTE_NAMES, DEFAULT_CK_TYPE_SELECTOR_DIALOG_MESSAGES, DEFAULT_CK_TYPE_SELECTOR_INPUT_MESSAGES, DEFAULT_DATA_POINT, DEFAULT_MAPPING_COVERAGE_TREE_CONFIG, DEFAULT_PROPERTY_GRID_MESSAGES, DEFAULT_RUNTIME_BROWSER_MESSAGES, DataMappingOverviewComponent, DataPointPickerComponent, DataPointResolverService, DefaultPropertyCategory, EntityDetailComponent, EntityIdInfoComponent, EntitySelectorDialogComponent, EntitySelectorDialogService, FieldFilterEditorComponent, MAPPING_COVERAGE_CONFIG_CONSTANTS, MM_PAGE, MappingCoverageConfigService, MappingCoverageTreeComponent, MappingCoverageTreeDataSource, MappingEditDialogComponent, MappingEditDialogService, OctoGraphQlDataSource, OctoGraphQlHierarchyDataSource, OctoLoaderComponent, PageActionsDirective, PageComponent, PageSubtitleDirective, PageTitleDirective, PropertyConverterService, PropertyDisplayMode, PropertyGridComponent, PropertyValueDisplayComponent, RUNTIME_BROWSER_MESSAGES, RecordDetailDialogComponent, RtEntityIdHelper, RuntimeBrowserComponent, RuntimeBrowserOutletComponent, RuntimeBrowserPageComponent, RuntimeBrowserStateService, RuntimeEntityVariableDialogComponent, RuntimeEntityVariableDialogService, SecretSafeAttributeNamesService, TREE_NAVIGATION_CONFIG_CONSTANTS, TenantSwitcherComponent, ThemeModeService, ThemeModeToggleComponent, TreeNavigationConfigService, account_tree, add, analytics, app_registration, article, botService, category, chat, checklist, code, coerceDataPointValue, component_exchange, computeExpressionPreview, computer, createRuntimeBrowserRoutes, customer, dashboard, event_list, extractDataPointNames, extractDataPoints, graphic_eq, group, identityService, insert_link, isSecretMarker, manage_accounts, more_time, notifications, page_info, pages, person_search, playlist_add_check, pool, power, provideOctoUi, publicIcon, query_builder, schedule_send, settings, sort, storage, swagger, swagger_asset, swagger_bot, swagger_communication, swagger_identity, team_dashboard, tenancy, text_snippet, travel_explore, user_diagnostics, webhook, work };
|
|
21375
21958
|
//# sourceMappingURL=meshmakers-octo-ui.mjs.map
|