@meshmakers/octo-ui 3.4.290 → 3.4.310
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/fesm2022/meshmakers-octo-ui-tree-navigation-settings.mjs +77 -4
- package/fesm2022/meshmakers-octo-ui-tree-navigation-settings.mjs.map +1 -1
- package/fesm2022/meshmakers-octo-ui.mjs +495 -18
- package/fesm2022/meshmakers-octo-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/meshmakers-octo-ui-tree-navigation-settings.d.ts +25 -0
- package/types/meshmakers-octo-ui.d.ts +224 -95
|
@@ -53,6 +53,19 @@ const DEFAULT_TREE_NAVIGATION_SETTINGS_MESSAGES = {
|
|
|
53
53
|
exportError: 'Failed to export the tree navigation configuration.',
|
|
54
54
|
importSuccess: 'Import completed successfully.',
|
|
55
55
|
importError: 'Failed to import the tree navigation configuration.',
|
|
56
|
+
perspectivesTitle: 'Tree perspectives',
|
|
57
|
+
perspectivesDescription: 'Switchable tree roots offered next to the built-in Spatial perspective. A Type perspective roots on all instances of a CK type and, at the root level, shows only its primary and secondary roles (deeper levels use auto-discovery).',
|
|
58
|
+
columnKey: 'Key',
|
|
59
|
+
columnPerspectiveName: 'Label',
|
|
60
|
+
columnRootMode: 'Root',
|
|
61
|
+
columnRootType: 'Root CK type',
|
|
62
|
+
columnPrimaryRole: 'Primary role',
|
|
63
|
+
columnSecondaryRoles: 'Secondary roles',
|
|
64
|
+
rootModeSpatial: 'Spatial',
|
|
65
|
+
rootModeType: 'Type',
|
|
66
|
+
secondaryRolesHint: 'comma-separated role ids',
|
|
67
|
+
addPerspective: 'Add perspective',
|
|
68
|
+
perspectivesEmpty: 'No extra perspectives — only the built-in Spatial view.',
|
|
56
69
|
};
|
|
57
70
|
|
|
58
71
|
/** Matches every source CK type. */
|
|
@@ -83,6 +96,12 @@ class TreeNavigationSettingsComponent {
|
|
|
83
96
|
...(ngDevMode ? [{ debugName: "typePresent" }] : /* istanbul ignore next */ []));
|
|
84
97
|
rtId = null;
|
|
85
98
|
rules = this.fb.array([]);
|
|
99
|
+
perspectiveRows = this.fb.array([]);
|
|
100
|
+
rootModeOptions = computed(() => [
|
|
101
|
+
{ text: this.messages().rootModeSpatial, value: 'Spatial' },
|
|
102
|
+
{ text: this.messages().rootModeType, value: 'Type' },
|
|
103
|
+
], /* @ts-ignore */
|
|
104
|
+
...(ngDevMode ? [{ debugName: "rootModeOptions" }] : /* istanbul ignore next */ []));
|
|
86
105
|
// Shared suggestion pools — only one combobox dropdown is open at a time, so a
|
|
87
106
|
// single signal per kind is enough (loaded on open / filter).
|
|
88
107
|
ckTypeSuggestions = signal([WILDCARD], /* @ts-ignore */
|
|
@@ -120,6 +139,10 @@ class TreeNavigationSettingsComponent {
|
|
|
120
139
|
for (const role of config.roles) {
|
|
121
140
|
this.rules.push(this.createRow(role));
|
|
122
141
|
}
|
|
142
|
+
this.perspectiveRows.clear();
|
|
143
|
+
for (const perspective of config.perspectives) {
|
|
144
|
+
this.perspectiveRows.push(this.createPerspectiveRow(perspective));
|
|
145
|
+
}
|
|
123
146
|
}
|
|
124
147
|
catch (error) {
|
|
125
148
|
console.error('[TreeNavigationSettingsComponent] Failed to load config', error);
|
|
@@ -137,16 +160,26 @@ class TreeNavigationSettingsComponent {
|
|
|
137
160
|
this.rules.removeAt(index);
|
|
138
161
|
this.rules.markAsDirty();
|
|
139
162
|
}
|
|
163
|
+
addPerspective() {
|
|
164
|
+
this.perspectiveRows.push(this.createPerspectiveRow());
|
|
165
|
+
this.perspectiveRows.markAsDirty();
|
|
166
|
+
}
|
|
167
|
+
removePerspective(index) {
|
|
168
|
+
this.perspectiveRows.removeAt(index);
|
|
169
|
+
this.perspectiveRows.markAsDirty();
|
|
170
|
+
}
|
|
140
171
|
async onSave() {
|
|
141
|
-
if (this.rules.invalid) {
|
|
172
|
+
if (this.rules.invalid || this.perspectiveRows.invalid) {
|
|
142
173
|
this.rules.markAllAsTouched();
|
|
174
|
+
this.perspectiveRows.markAllAsTouched();
|
|
143
175
|
return;
|
|
144
176
|
}
|
|
145
177
|
this.saving.set(true);
|
|
146
178
|
try {
|
|
147
|
-
this.rtId = await this.config.saveConfig(this.rtId, this.collectRoles());
|
|
179
|
+
this.rtId = await this.config.saveConfig(this.rtId, this.collectRoles(), this.collectPerspectives());
|
|
148
180
|
this.messageService.showInformation(this.messages().saveSuccess);
|
|
149
181
|
this.rules.markAsPristine();
|
|
182
|
+
this.perspectiveRows.markAsPristine();
|
|
150
183
|
}
|
|
151
184
|
catch (error) {
|
|
152
185
|
console.error('[TreeNavigationSettingsComponent] Failed to save config', error);
|
|
@@ -178,6 +211,11 @@ class TreeNavigationSettingsComponent {
|
|
|
178
211
|
const ckTypeId = row.get('sourceCkTypeId')?.value ?? '';
|
|
179
212
|
this.roleSuggestions.set(await this.config.getRoleSuggestions(ckTypeId));
|
|
180
213
|
}
|
|
214
|
+
/** Loads role suggestions for the root CK type of a perspective row. */
|
|
215
|
+
async loadRoleSuggestionsForType(row) {
|
|
216
|
+
const ckTypeId = row.get('rootCkTypeId')?.value ?? '';
|
|
217
|
+
this.roleSuggestions.set(await this.config.getRoleSuggestions(ckTypeId));
|
|
218
|
+
}
|
|
181
219
|
/**
|
|
182
220
|
* Exports the saved configuration singleton as a deep-graph runtime model ZIP,
|
|
183
221
|
* via the standard asset-repo export job (same mechanism as pools / adapters /
|
|
@@ -261,6 +299,41 @@ class TreeNavigationSettingsComponent {
|
|
|
261
299
|
.map((group) => this.toRoleConfig(group))
|
|
262
300
|
.filter((r) => r.sourceCkTypeId && r.roleId);
|
|
263
301
|
}
|
|
302
|
+
collectPerspectives() {
|
|
303
|
+
return this.perspectiveRows.controls
|
|
304
|
+
.map((group) => this.toPerspectiveConfig(group))
|
|
305
|
+
.filter((p) => p.key);
|
|
306
|
+
}
|
|
307
|
+
createPerspectiveRow(p) {
|
|
308
|
+
return this.fb.group({
|
|
309
|
+
key: [p?.key ?? '', [Validators.required]],
|
|
310
|
+
displayName: [p?.displayName ?? ''],
|
|
311
|
+
rootMode: [p?.rootMode ?? 'Type'],
|
|
312
|
+
rootCkTypeId: [p?.rootCkTypeId ?? ''],
|
|
313
|
+
primaryRoleId: [p?.primaryRoleId ?? ''],
|
|
314
|
+
secondaryRoleIds: [(p?.secondaryRoleIds ?? []).join(', ')],
|
|
315
|
+
sortIndex: [p?.sortIndex ?? null],
|
|
316
|
+
icon: [p?.icon ?? ''],
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
toPerspectiveConfig(group) {
|
|
320
|
+
const value = group.getRawValue();
|
|
321
|
+
const secondary = (value.secondaryRoleIds ?? '')
|
|
322
|
+
.split(/[\n,]/)
|
|
323
|
+
.map((r) => r.trim())
|
|
324
|
+
.filter((r) => r.length > 0);
|
|
325
|
+
const key = (value.key ?? '').trim();
|
|
326
|
+
return {
|
|
327
|
+
key,
|
|
328
|
+
displayName: value.displayName?.trim() || key,
|
|
329
|
+
rootMode: value.rootMode === 'Spatial' ? 'Spatial' : 'Type',
|
|
330
|
+
rootCkTypeId: value.rootCkTypeId?.trim() || undefined,
|
|
331
|
+
primaryRoleId: value.primaryRoleId?.trim() || undefined,
|
|
332
|
+
secondaryRoleIds: secondary.length > 0 ? secondary : undefined,
|
|
333
|
+
sortIndex: value.sortIndex ?? undefined,
|
|
334
|
+
icon: value.icon?.trim() || undefined,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
264
337
|
createRow(role) {
|
|
265
338
|
return this.fb.group({
|
|
266
339
|
sourceCkTypeId: [role?.sourceCkTypeId ?? '*', [Validators.required]],
|
|
@@ -295,7 +368,7 @@ class TreeNavigationSettingsComponent {
|
|
|
295
368
|
return grouped ? 'group' : 'flatten';
|
|
296
369
|
}
|
|
297
370
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: TreeNavigationSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
298
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: TreeNavigationSettingsComponent, isStandalone: true, selector: "mm-tree-navigation-settings", inputs: { messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"tree-nav-settings\">\n <header class=\"header\">\n <h2 class=\"title\">{{ messages().title }}</h2>\n <p class=\"description\">{{ messages().description }}</p>\n </header>\n\n @if (loading()) {\n <div class=\"state\">\u2026</div>\n } @else if (!typePresent()) {\n <div class=\"hint not-installed\">{{ messages().notInstalled }}</div>\n } @else {\n <div class=\"toolbar mm-toolbar-actions\">\n <button kendoButton [svgIcon]=\"plusIcon\" (click)=\"addRule()\">\n {{ messages().addRule }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"exportIcon\"\n fillMode=\"flat\"\n (click)=\"export()\"\n >\n {{ messages().export }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"importIcon\"\n fillMode=\"flat\"\n (click)=\"fileInput.click()\"\n >\n {{ messages().import }}\n </button>\n <input\n #fileInput\n type=\"file\"\n accept=\".zip\"\n hidden\n (change)=\"onFileSelected($event)\"\n />\n <span class=\"toolbar-spacer\"></span>\n <button\n kendoButton\n [svgIcon]=\"reloadIcon\"\n fillMode=\"flat\"\n [disabled]=\"saving()\"\n (click)=\"reload()\"\n >\n {{ messages().reload }}\n </button>\n <button\n kendoButton\n themeColor=\"primary\"\n [svgIcon]=\"saveIcon\"\n [disabled]=\"saving()\"\n (click)=\"onSave()\"\n >\n {{ messages().save }}\n </button>\n </div>\n\n @if (rules.length === 0) {\n <div class=\"empty\">{{ messages().empty }}</div>\n } @else {\n <div class=\"table-wrap\">\n <table class=\"rules\">\n <thead>\n <tr>\n <th>{{ messages().columnSourceType }}</th>\n <th>{{ messages().columnRole }}</th>\n <th>{{ messages().columnDisplayName }}</th>\n <th class=\"narrow\">{{ messages().columnSortIndex }}</th>\n <th class=\"narrow\">{{ messages().columnVisible }}</th>\n <th class=\"narrow\">{{ messages().columnGrouped }}</th>\n <th>{{ messages().columnIcon }}</th>\n <th class=\"actions\">{{ messages().columnActions }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rules.controls; track $index) {\n <tr [formGroup]=\"row\">\n <td>\n <kendo-combobox\n [data]=\"ckTypeSuggestions()\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().sourceTypeHint\"\n formControlName=\"sourceCkTypeId\"\n (open)=\"searchCkTypes('')\"\n (filterChange)=\"searchCkTypes($event)\"\n ></kendo-combobox>\n </td>\n <td>\n <kendo-combobox\n [data]=\"roleSuggestions()\"\n textField=\"label\"\n valueField=\"roleId\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().roleHint\"\n formControlName=\"roleId\"\n (open)=\"loadRoleSuggestions(row)\"\n ></kendo-combobox>\n </td>\n <td><input kendoTextBox formControlName=\"displayName\" /></td>\n <td class=\"narrow\">\n <kendo-numerictextbox\n formControlName=\"sortIndex\"\n [decimals]=\"0\"\n format=\"n0\"\n [spinners]=\"false\"\n ></kendo-numerictextbox>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"visibleOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"visible\"\n ></kendo-dropdownlist>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"groupedOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"grouped\"\n ></kendo-dropdownlist>\n </td>\n <td><input kendoTextBox formControlName=\"icon\" /></td>\n <td class=\"actions\">\n <button\n kendoButton\n fillMode=\"flat\"\n [svgIcon]=\"removeIcon\"\n [title]=\"messages().removeRule\"\n (click)=\"removeRule($index)\"\n ></button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n</div>\n", styles: [":host{display:block;padding:16px 20px}.header{margin-bottom:16px}.header .title{margin:0 0 4px;font-size:1.1rem;font-weight:600}.header .description{margin:0;max-width:70ch;color:var(--kendo-color-subtle, #6c757d);font-size:.85rem}.toolbar{display:flex;align-items:center;gap:8px;margin-bottom:12px}.toolbar .toolbar-spacer{flex:1}.hint,.empty{padding:12px 14px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;background:var(--kendo-color-surface-alt, #f8f9fa);color:var(--kendo-color-subtle, #6c757d);font-size:.9rem}.table-wrap{overflow-x:auto}.rules{width:100%;border-collapse:collapse}.rules th,.rules td{padding:6px 8px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--kendo-color-border, #dee2e6)}.rules th{font-size:.75rem;text-transform:uppercase;letter-spacing:.03em;color:var(--kendo-color-subtle, #6c757d);font-weight:600}.rules td input,.rules td kendo-numerictextbox,.rules td kendo-dropdownlist{width:100%}.rules .narrow{width:120px}.rules .actions{width:48px;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "directive", type: i3.TextBoxDirective, selector: "input[kendoTextBox]", inputs: ["value"] }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "ngmodule", type: LabelModule }, { kind: "ngmodule", type: DropDownsModule }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
371
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: TreeNavigationSettingsComponent, isStandalone: true, selector: "mm-tree-navigation-settings", inputs: { messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"tree-nav-settings\">\n <header class=\"header\">\n <h2 class=\"title\">{{ messages().title }}</h2>\n <p class=\"description\">{{ messages().description }}</p>\n </header>\n\n @if (loading()) {\n <div class=\"state\">\u2026</div>\n } @else if (!typePresent()) {\n <div class=\"hint not-installed\">{{ messages().notInstalled }}</div>\n } @else {\n <div class=\"toolbar mm-toolbar-actions\">\n <button kendoButton [svgIcon]=\"plusIcon\" (click)=\"addRule()\">\n {{ messages().addRule }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"exportIcon\"\n fillMode=\"flat\"\n (click)=\"export()\"\n >\n {{ messages().export }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"importIcon\"\n fillMode=\"flat\"\n (click)=\"fileInput.click()\"\n >\n {{ messages().import }}\n </button>\n <input\n #fileInput\n type=\"file\"\n accept=\".zip\"\n hidden\n (change)=\"onFileSelected($event)\"\n />\n <span class=\"toolbar-spacer\"></span>\n <button\n kendoButton\n [svgIcon]=\"reloadIcon\"\n fillMode=\"flat\"\n [disabled]=\"saving()\"\n (click)=\"reload()\"\n >\n {{ messages().reload }}\n </button>\n <button\n kendoButton\n themeColor=\"primary\"\n [svgIcon]=\"saveIcon\"\n [disabled]=\"saving()\"\n (click)=\"onSave()\"\n >\n {{ messages().save }}\n </button>\n </div>\n\n @if (rules.length === 0) {\n <div class=\"empty\">{{ messages().empty }}</div>\n } @else {\n <div class=\"table-wrap\">\n <table class=\"rules\">\n <thead>\n <tr>\n <th>{{ messages().columnSourceType }}</th>\n <th>{{ messages().columnRole }}</th>\n <th>{{ messages().columnDisplayName }}</th>\n <th class=\"narrow\">{{ messages().columnSortIndex }}</th>\n <th class=\"narrow\">{{ messages().columnVisible }}</th>\n <th class=\"narrow\">{{ messages().columnGrouped }}</th>\n <th>{{ messages().columnIcon }}</th>\n <th class=\"actions\">{{ messages().columnActions }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rules.controls; track $index) {\n <tr [formGroup]=\"row\">\n <td>\n <kendo-combobox\n [data]=\"ckTypeSuggestions()\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().sourceTypeHint\"\n formControlName=\"sourceCkTypeId\"\n (open)=\"searchCkTypes('')\"\n (filterChange)=\"searchCkTypes($event)\"\n ></kendo-combobox>\n </td>\n <td>\n <kendo-combobox\n [data]=\"roleSuggestions()\"\n textField=\"label\"\n valueField=\"roleId\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().roleHint\"\n formControlName=\"roleId\"\n (open)=\"loadRoleSuggestions(row)\"\n ></kendo-combobox>\n </td>\n <td><input kendoTextBox formControlName=\"displayName\" /></td>\n <td class=\"narrow\">\n <kendo-numerictextbox\n formControlName=\"sortIndex\"\n [decimals]=\"0\"\n format=\"n0\"\n [spinners]=\"false\"\n ></kendo-numerictextbox>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"visibleOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"visible\"\n ></kendo-dropdownlist>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"groupedOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"grouped\"\n ></kendo-dropdownlist>\n </td>\n <td><input kendoTextBox formControlName=\"icon\" /></td>\n <td class=\"actions\">\n <button\n kendoButton\n fillMode=\"flat\"\n [svgIcon]=\"removeIcon\"\n [title]=\"messages().removeRule\"\n (click)=\"removeRule($index)\"\n ></button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n <header class=\"header perspectives-header\">\n <h2 class=\"title\">{{ messages().perspectivesTitle }}</h2>\n <p class=\"description\">{{ messages().perspectivesDescription }}</p>\n </header>\n\n <div class=\"toolbar mm-toolbar-actions\">\n <button kendoButton [svgIcon]=\"plusIcon\" (click)=\"addPerspective()\">\n {{ messages().addPerspective }}\n </button>\n </div>\n\n @if (perspectiveRows.length === 0) {\n <div class=\"empty\">{{ messages().perspectivesEmpty }}</div>\n } @else {\n <div class=\"table-wrap\">\n <table class=\"rules\">\n <thead>\n <tr>\n <th>{{ messages().columnKey }}</th>\n <th>{{ messages().columnPerspectiveName }}</th>\n <th class=\"narrow\">{{ messages().columnRootMode }}</th>\n <th>{{ messages().columnRootType }}</th>\n <th>{{ messages().columnPrimaryRole }}</th>\n <th>{{ messages().columnSecondaryRoles }}</th>\n <th class=\"narrow\">{{ messages().columnSortIndex }}</th>\n <th>{{ messages().columnIcon }}</th>\n <th class=\"actions\">{{ messages().columnActions }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of perspectiveRows.controls; track $index) {\n <tr [formGroup]=\"row\">\n <td><input kendoTextBox formControlName=\"key\" /></td>\n <td><input kendoTextBox formControlName=\"displayName\" /></td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"rootModeOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"rootMode\"\n ></kendo-dropdownlist>\n </td>\n <td>\n <kendo-combobox\n [data]=\"ckTypeSuggestions()\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n formControlName=\"rootCkTypeId\"\n (open)=\"searchCkTypes('')\"\n (filterChange)=\"searchCkTypes($event)\"\n ></kendo-combobox>\n </td>\n <td>\n <kendo-combobox\n [data]=\"roleSuggestions()\"\n textField=\"label\"\n valueField=\"roleId\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n formControlName=\"primaryRoleId\"\n (open)=\"loadRoleSuggestionsForType(row)\"\n ></kendo-combobox>\n </td>\n <td>\n <input\n kendoTextBox\n formControlName=\"secondaryRoleIds\"\n [placeholder]=\"messages().secondaryRolesHint\"\n />\n </td>\n <td class=\"narrow\">\n <kendo-numerictextbox\n formControlName=\"sortIndex\"\n [decimals]=\"0\"\n format=\"n0\"\n [spinners]=\"false\"\n ></kendo-numerictextbox>\n </td>\n <td><input kendoTextBox formControlName=\"icon\" /></td>\n <td class=\"actions\">\n <button\n kendoButton\n fillMode=\"flat\"\n [svgIcon]=\"removeIcon\"\n [title]=\"messages().removeRule\"\n (click)=\"removePerspective($index)\"\n ></button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n</div>\n", styles: [":host{display:block;padding:16px 20px}.header{margin-bottom:16px}.header .title{margin:0 0 4px;font-size:1.1rem;font-weight:600}.header .description{margin:0;max-width:70ch;color:var(--kendo-color-subtle, #6c757d);font-size:.85rem}.toolbar{display:flex;align-items:center;gap:8px;margin-bottom:12px}.toolbar .toolbar-spacer{flex:1}.hint,.empty{padding:12px 14px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;background:var(--kendo-color-surface-alt, #f8f9fa);color:var(--kendo-color-subtle, #6c757d);font-size:.9rem}.table-wrap{overflow-x:auto}.rules{width:100%;border-collapse:collapse}.rules th,.rules td{padding:6px 8px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--kendo-color-border, #dee2e6)}.rules th{font-size:.75rem;text-transform:uppercase;letter-spacing:.03em;color:var(--kendo-color-subtle, #6c757d);font-weight:600}.rules td input,.rules td kendo-numerictextbox,.rules td kendo-dropdownlist{width:100%}.rules .narrow{width:120px}.rules .actions{width:48px;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i2.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconPosition", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: InputsModule }, { kind: "directive", type: i3.TextBoxDirective, selector: "input[kendoTextBox]", inputs: ["value"] }, { kind: "component", type: i3.NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "ngmodule", type: LabelModule }, { kind: "ngmodule", type: DropDownsModule }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
299
372
|
}
|
|
300
373
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: TreeNavigationSettingsComponent, decorators: [{
|
|
301
374
|
type: Component,
|
|
@@ -306,7 +379,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
306
379
|
InputsModule,
|
|
307
380
|
LabelModule,
|
|
308
381
|
DropDownsModule,
|
|
309
|
-
], changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"tree-nav-settings\">\n <header class=\"header\">\n <h2 class=\"title\">{{ messages().title }}</h2>\n <p class=\"description\">{{ messages().description }}</p>\n </header>\n\n @if (loading()) {\n <div class=\"state\">\u2026</div>\n } @else if (!typePresent()) {\n <div class=\"hint not-installed\">{{ messages().notInstalled }}</div>\n } @else {\n <div class=\"toolbar mm-toolbar-actions\">\n <button kendoButton [svgIcon]=\"plusIcon\" (click)=\"addRule()\">\n {{ messages().addRule }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"exportIcon\"\n fillMode=\"flat\"\n (click)=\"export()\"\n >\n {{ messages().export }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"importIcon\"\n fillMode=\"flat\"\n (click)=\"fileInput.click()\"\n >\n {{ messages().import }}\n </button>\n <input\n #fileInput\n type=\"file\"\n accept=\".zip\"\n hidden\n (change)=\"onFileSelected($event)\"\n />\n <span class=\"toolbar-spacer\"></span>\n <button\n kendoButton\n [svgIcon]=\"reloadIcon\"\n fillMode=\"flat\"\n [disabled]=\"saving()\"\n (click)=\"reload()\"\n >\n {{ messages().reload }}\n </button>\n <button\n kendoButton\n themeColor=\"primary\"\n [svgIcon]=\"saveIcon\"\n [disabled]=\"saving()\"\n (click)=\"onSave()\"\n >\n {{ messages().save }}\n </button>\n </div>\n\n @if (rules.length === 0) {\n <div class=\"empty\">{{ messages().empty }}</div>\n } @else {\n <div class=\"table-wrap\">\n <table class=\"rules\">\n <thead>\n <tr>\n <th>{{ messages().columnSourceType }}</th>\n <th>{{ messages().columnRole }}</th>\n <th>{{ messages().columnDisplayName }}</th>\n <th class=\"narrow\">{{ messages().columnSortIndex }}</th>\n <th class=\"narrow\">{{ messages().columnVisible }}</th>\n <th class=\"narrow\">{{ messages().columnGrouped }}</th>\n <th>{{ messages().columnIcon }}</th>\n <th class=\"actions\">{{ messages().columnActions }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rules.controls; track $index) {\n <tr [formGroup]=\"row\">\n <td>\n <kendo-combobox\n [data]=\"ckTypeSuggestions()\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().sourceTypeHint\"\n formControlName=\"sourceCkTypeId\"\n (open)=\"searchCkTypes('')\"\n (filterChange)=\"searchCkTypes($event)\"\n ></kendo-combobox>\n </td>\n <td>\n <kendo-combobox\n [data]=\"roleSuggestions()\"\n textField=\"label\"\n valueField=\"roleId\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().roleHint\"\n formControlName=\"roleId\"\n (open)=\"loadRoleSuggestions(row)\"\n ></kendo-combobox>\n </td>\n <td><input kendoTextBox formControlName=\"displayName\" /></td>\n <td class=\"narrow\">\n <kendo-numerictextbox\n formControlName=\"sortIndex\"\n [decimals]=\"0\"\n format=\"n0\"\n [spinners]=\"false\"\n ></kendo-numerictextbox>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"visibleOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"visible\"\n ></kendo-dropdownlist>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"groupedOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"grouped\"\n ></kendo-dropdownlist>\n </td>\n <td><input kendoTextBox formControlName=\"icon\" /></td>\n <td class=\"actions\">\n <button\n kendoButton\n fillMode=\"flat\"\n [svgIcon]=\"removeIcon\"\n [title]=\"messages().removeRule\"\n (click)=\"removeRule($index)\"\n ></button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n</div>\n", styles: [":host{display:block;padding:16px 20px}.header{margin-bottom:16px}.header .title{margin:0 0 4px;font-size:1.1rem;font-weight:600}.header .description{margin:0;max-width:70ch;color:var(--kendo-color-subtle, #6c757d);font-size:.85rem}.toolbar{display:flex;align-items:center;gap:8px;margin-bottom:12px}.toolbar .toolbar-spacer{flex:1}.hint,.empty{padding:12px 14px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;background:var(--kendo-color-surface-alt, #f8f9fa);color:var(--kendo-color-subtle, #6c757d);font-size:.9rem}.table-wrap{overflow-x:auto}.rules{width:100%;border-collapse:collapse}.rules th,.rules td{padding:6px 8px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--kendo-color-border, #dee2e6)}.rules th{font-size:.75rem;text-transform:uppercase;letter-spacing:.03em;color:var(--kendo-color-subtle, #6c757d);font-weight:600}.rules td input,.rules td kendo-numerictextbox,.rules td kendo-dropdownlist{width:100%}.rules .narrow{width:120px}.rules .actions{width:48px;text-align:center}\n"] }]
|
|
382
|
+
], changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"tree-nav-settings\">\n <header class=\"header\">\n <h2 class=\"title\">{{ messages().title }}</h2>\n <p class=\"description\">{{ messages().description }}</p>\n </header>\n\n @if (loading()) {\n <div class=\"state\">\u2026</div>\n } @else if (!typePresent()) {\n <div class=\"hint not-installed\">{{ messages().notInstalled }}</div>\n } @else {\n <div class=\"toolbar mm-toolbar-actions\">\n <button kendoButton [svgIcon]=\"plusIcon\" (click)=\"addRule()\">\n {{ messages().addRule }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"exportIcon\"\n fillMode=\"flat\"\n (click)=\"export()\"\n >\n {{ messages().export }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"importIcon\"\n fillMode=\"flat\"\n (click)=\"fileInput.click()\"\n >\n {{ messages().import }}\n </button>\n <input\n #fileInput\n type=\"file\"\n accept=\".zip\"\n hidden\n (change)=\"onFileSelected($event)\"\n />\n <span class=\"toolbar-spacer\"></span>\n <button\n kendoButton\n [svgIcon]=\"reloadIcon\"\n fillMode=\"flat\"\n [disabled]=\"saving()\"\n (click)=\"reload()\"\n >\n {{ messages().reload }}\n </button>\n <button\n kendoButton\n themeColor=\"primary\"\n [svgIcon]=\"saveIcon\"\n [disabled]=\"saving()\"\n (click)=\"onSave()\"\n >\n {{ messages().save }}\n </button>\n </div>\n\n @if (rules.length === 0) {\n <div class=\"empty\">{{ messages().empty }}</div>\n } @else {\n <div class=\"table-wrap\">\n <table class=\"rules\">\n <thead>\n <tr>\n <th>{{ messages().columnSourceType }}</th>\n <th>{{ messages().columnRole }}</th>\n <th>{{ messages().columnDisplayName }}</th>\n <th class=\"narrow\">{{ messages().columnSortIndex }}</th>\n <th class=\"narrow\">{{ messages().columnVisible }}</th>\n <th class=\"narrow\">{{ messages().columnGrouped }}</th>\n <th>{{ messages().columnIcon }}</th>\n <th class=\"actions\">{{ messages().columnActions }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rules.controls; track $index) {\n <tr [formGroup]=\"row\">\n <td>\n <kendo-combobox\n [data]=\"ckTypeSuggestions()\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().sourceTypeHint\"\n formControlName=\"sourceCkTypeId\"\n (open)=\"searchCkTypes('')\"\n (filterChange)=\"searchCkTypes($event)\"\n ></kendo-combobox>\n </td>\n <td>\n <kendo-combobox\n [data]=\"roleSuggestions()\"\n textField=\"label\"\n valueField=\"roleId\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().roleHint\"\n formControlName=\"roleId\"\n (open)=\"loadRoleSuggestions(row)\"\n ></kendo-combobox>\n </td>\n <td><input kendoTextBox formControlName=\"displayName\" /></td>\n <td class=\"narrow\">\n <kendo-numerictextbox\n formControlName=\"sortIndex\"\n [decimals]=\"0\"\n format=\"n0\"\n [spinners]=\"false\"\n ></kendo-numerictextbox>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"visibleOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"visible\"\n ></kendo-dropdownlist>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"groupedOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"grouped\"\n ></kendo-dropdownlist>\n </td>\n <td><input kendoTextBox formControlName=\"icon\" /></td>\n <td class=\"actions\">\n <button\n kendoButton\n fillMode=\"flat\"\n [svgIcon]=\"removeIcon\"\n [title]=\"messages().removeRule\"\n (click)=\"removeRule($index)\"\n ></button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n <header class=\"header perspectives-header\">\n <h2 class=\"title\">{{ messages().perspectivesTitle }}</h2>\n <p class=\"description\">{{ messages().perspectivesDescription }}</p>\n </header>\n\n <div class=\"toolbar mm-toolbar-actions\">\n <button kendoButton [svgIcon]=\"plusIcon\" (click)=\"addPerspective()\">\n {{ messages().addPerspective }}\n </button>\n </div>\n\n @if (perspectiveRows.length === 0) {\n <div class=\"empty\">{{ messages().perspectivesEmpty }}</div>\n } @else {\n <div class=\"table-wrap\">\n <table class=\"rules\">\n <thead>\n <tr>\n <th>{{ messages().columnKey }}</th>\n <th>{{ messages().columnPerspectiveName }}</th>\n <th class=\"narrow\">{{ messages().columnRootMode }}</th>\n <th>{{ messages().columnRootType }}</th>\n <th>{{ messages().columnPrimaryRole }}</th>\n <th>{{ messages().columnSecondaryRoles }}</th>\n <th class=\"narrow\">{{ messages().columnSortIndex }}</th>\n <th>{{ messages().columnIcon }}</th>\n <th class=\"actions\">{{ messages().columnActions }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of perspectiveRows.controls; track $index) {\n <tr [formGroup]=\"row\">\n <td><input kendoTextBox formControlName=\"key\" /></td>\n <td><input kendoTextBox formControlName=\"displayName\" /></td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"rootModeOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"rootMode\"\n ></kendo-dropdownlist>\n </td>\n <td>\n <kendo-combobox\n [data]=\"ckTypeSuggestions()\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n formControlName=\"rootCkTypeId\"\n (open)=\"searchCkTypes('')\"\n (filterChange)=\"searchCkTypes($event)\"\n ></kendo-combobox>\n </td>\n <td>\n <kendo-combobox\n [data]=\"roleSuggestions()\"\n textField=\"label\"\n valueField=\"roleId\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n formControlName=\"primaryRoleId\"\n (open)=\"loadRoleSuggestionsForType(row)\"\n ></kendo-combobox>\n </td>\n <td>\n <input\n kendoTextBox\n formControlName=\"secondaryRoleIds\"\n [placeholder]=\"messages().secondaryRolesHint\"\n />\n </td>\n <td class=\"narrow\">\n <kendo-numerictextbox\n formControlName=\"sortIndex\"\n [decimals]=\"0\"\n format=\"n0\"\n [spinners]=\"false\"\n ></kendo-numerictextbox>\n </td>\n <td><input kendoTextBox formControlName=\"icon\" /></td>\n <td class=\"actions\">\n <button\n kendoButton\n fillMode=\"flat\"\n [svgIcon]=\"removeIcon\"\n [title]=\"messages().removeRule\"\n (click)=\"removePerspective($index)\"\n ></button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n</div>\n", styles: [":host{display:block;padding:16px 20px}.header{margin-bottom:16px}.header .title{margin:0 0 4px;font-size:1.1rem;font-weight:600}.header .description{margin:0;max-width:70ch;color:var(--kendo-color-subtle, #6c757d);font-size:.85rem}.toolbar{display:flex;align-items:center;gap:8px;margin-bottom:12px}.toolbar .toolbar-spacer{flex:1}.hint,.empty{padding:12px 14px;border:1px solid var(--kendo-color-border, #dee2e6);border-radius:4px;background:var(--kendo-color-surface-alt, #f8f9fa);color:var(--kendo-color-subtle, #6c757d);font-size:.9rem}.table-wrap{overflow-x:auto}.rules{width:100%;border-collapse:collapse}.rules th,.rules td{padding:6px 8px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--kendo-color-border, #dee2e6)}.rules th{font-size:.75rem;text-transform:uppercase;letter-spacing:.03em;color:var(--kendo-color-subtle, #6c757d);font-weight:600}.rules td input,.rules td kendo-numerictextbox,.rules td kendo-dropdownlist{width:100%}.rules .narrow{width:120px}.rules .actions{width:48px;text-align:center}\n"] }]
|
|
310
383
|
}], propDecorators: { messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: false }] }] } });
|
|
311
384
|
|
|
312
385
|
var treeNavigationSettings_component = /*#__PURE__*/Object.freeze({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meshmakers-octo-ui-tree-navigation-settings.mjs","sources":["../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/tree-navigation-settings.messages.ts","../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/tree-navigation-settings.component.ts","../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/tree-navigation-settings.component.html","../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/tree-navigation-settings.routes.ts","../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/public-api.ts","../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/meshmakers-octo-ui-tree-navigation-settings.ts"],"sourcesContent":["/** UI strings for the tree navigation settings editor. */\nexport interface TreeNavigationSettingsMessages {\n title: string;\n description: string;\n /** Shown when System.UI < 2.2.0 (the CK type is not installed on the tenant). */\n notInstalled: string;\n columnSourceType: string;\n columnRole: string;\n columnDisplayName: string;\n columnSortIndex: string;\n columnVisible: string;\n columnGrouped: string;\n columnIcon: string;\n columnActions: string;\n visibleAuto: string;\n visibleShow: string;\n visibleHide: string;\n groupedAuto: string;\n groupedGroup: string;\n groupedFlatten: string;\n sourceTypeHint: string;\n roleHint: string;\n addRule: string;\n removeRule: string;\n save: string;\n reload: string;\n export: string;\n import: string;\n empty: string;\n saveSuccess: string;\n saveError: string;\n loadError: string;\n exportNothing: string;\n exportError: string;\n importSuccess: string;\n importError: string;\n}\n\n/** English defaults; hosts may override via the `messages` input. */\nexport const DEFAULT_TREE_NAVIGATION_SETTINGS_MESSAGES: TreeNavigationSettingsMessages =\n {\n title: 'Tree Navigation',\n description:\n 'Per-tenant overrides for the entity trees (repository browser and data-mappings). Rules are applied on top of auto-discovered associations. Without any rule a role is shown with its default name, grouped (except System/ParentChild which is flattened).',\n notInstalled:\n 'The System.UI construction kit model (>= 2.2.0) is not installed on this tenant, so tree navigation cannot be configured yet.',\n columnSourceType: 'Source type',\n columnRole: 'Role id',\n columnDisplayName: 'Label',\n columnSortIndex: 'Order',\n columnVisible: 'Visibility',\n columnGrouped: 'Grouping',\n columnIcon: 'Icon',\n columnActions: '',\n visibleAuto: 'Auto',\n visibleShow: 'Show',\n visibleHide: 'Hide',\n groupedAuto: 'Auto',\n groupedGroup: 'Group',\n groupedFlatten: 'Flatten',\n sourceTypeHint: '* matches every type',\n roleHint: 'e.g. EnergyIQ/SpaceSensors',\n addRule: 'Add rule',\n removeRule: 'Remove',\n save: 'Save',\n reload: 'Reload',\n export: 'Export',\n import: 'Import',\n empty: 'No rules yet — every association uses its defaults.',\n saveSuccess: 'Tree navigation configuration saved.',\n saveError: 'Failed to save the tree navigation configuration.',\n loadError: 'Failed to load the tree navigation configuration.',\n exportNothing: 'Save the configuration before exporting it.',\n exportError: 'Failed to export the tree navigation configuration.',\n importSuccess: 'Import completed successfully.',\n importError: 'Failed to import the tree navigation configuration.',\n };\n","import { CommonModule } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n inject,\n input,\n OnInit,\n signal,\n} from '@angular/core';\nimport {\n FormBuilder,\n FormGroup,\n ReactiveFormsModule,\n Validators,\n} from '@angular/forms';\nimport { ActivatedRoute } from '@angular/router';\nimport {\n TreeNavigationConfigService,\n TreeNavigationRoleConfig,\n TREE_NAVIGATION_CONFIG_CONSTANTS,\n} from '@meshmakers/octo-ui';\nimport {\n AssetRepoService,\n CkTypeSelectorService,\n ImportStrategyDto,\n JobManagementService,\n} from '@meshmakers/octo-services';\nimport { ImportStrategyDialogService } from '@meshmakers/shared-ui';\nimport { MessageService } from '@meshmakers/shared-services';\nimport { ButtonsModule } from '@progress/kendo-angular-buttons';\nimport { DropDownsModule } from '@progress/kendo-angular-dropdowns';\nimport { InputsModule } from '@progress/kendo-angular-inputs';\nimport { LabelModule } from '@progress/kendo-angular-label';\nimport {\n plusIcon,\n saveIcon,\n arrowRotateCwIcon,\n xIcon,\n downloadIcon,\n uploadIcon,\n} from '@progress/kendo-svg-icons';\nimport { firstValueFrom } from 'rxjs';\nimport {\n DEFAULT_TREE_NAVIGATION_SETTINGS_MESSAGES,\n TreeNavigationSettingsMessages,\n} from './tree-navigation-settings.messages';\n\n/** Tri-state form value for the visibility/grouping dropdowns. */\ntype TriState = 'auto' | string;\n\n/** Matches every source CK type. */\nconst WILDCARD = '*';\n\n/**\n * Admin editor for the per-tenant `System.UI/TreeNavigationConfiguration`.\n * Each row is one override rule matched by (source type, role id); `*` as the\n * source type matches every type. Empty dropdown value = auto (default\n * behavior). Source type and role id offer autocomplete suggestions but also\n * accept custom values (so orphan roles remain configurable).\n */\n@Component({\n selector: 'mm-tree-navigation-settings',\n standalone: true,\n imports: [\n CommonModule,\n ReactiveFormsModule,\n ButtonsModule,\n InputsModule,\n LabelModule,\n DropDownsModule,\n ],\n templateUrl: './tree-navigation-settings.component.html',\n styleUrl: './tree-navigation-settings.component.scss',\n changeDetection: ChangeDetectionStrategy.Eager,\n})\nexport class TreeNavigationSettingsComponent implements OnInit {\n readonly messages = input<TreeNavigationSettingsMessages>(\n DEFAULT_TREE_NAVIGATION_SETTINGS_MESSAGES,\n );\n\n private readonly fb = inject(FormBuilder);\n private readonly config = inject(TreeNavigationConfigService);\n private readonly ckTypeSelector = inject(CkTypeSelectorService);\n private readonly assetRepo = inject(AssetRepoService);\n private readonly jobs = inject(JobManagementService);\n private readonly importStrategyDialog = inject(ImportStrategyDialogService);\n private readonly route = inject(ActivatedRoute);\n private readonly messageService = inject(MessageService);\n\n protected readonly loading = signal(true);\n protected readonly saving = signal(false);\n protected readonly typePresent = signal(true);\n private rtId: string | null = null;\n\n protected readonly rules = this.fb.array<FormGroup>([]);\n\n // Shared suggestion pools — only one combobox dropdown is open at a time, so a\n // single signal per kind is enough (loaded on open / filter).\n protected readonly ckTypeSuggestions = signal<string[]>([WILDCARD]);\n protected readonly roleSuggestions = signal<{ roleId: string; label: string }[]>(\n [],\n );\n\n protected readonly saveIcon = saveIcon;\n protected readonly plusIcon = plusIcon;\n protected readonly reloadIcon = arrowRotateCwIcon;\n protected readonly removeIcon = xIcon;\n protected readonly exportIcon = downloadIcon;\n protected readonly importIcon = uploadIcon;\n\n protected readonly visibleOptions = computed(() => [\n { text: this.messages().visibleAuto, value: 'auto' },\n { text: this.messages().visibleShow, value: 'show' },\n { text: this.messages().visibleHide, value: 'hide' },\n ]);\n protected readonly groupedOptions = computed(() => [\n { text: this.messages().groupedAuto, value: 'auto' },\n { text: this.messages().groupedGroup, value: 'group' },\n { text: this.messages().groupedFlatten, value: 'flatten' },\n ]);\n\n async ngOnInit(): Promise<void> {\n await this.reload();\n }\n\n protected async reload(): Promise<void> {\n this.loading.set(true);\n try {\n const config = await this.config.loadConfig();\n this.typePresent.set(config.typePresent);\n this.rtId = config.rtId;\n this.rules.clear();\n for (const role of config.roles) {\n this.rules.push(this.createRow(role));\n }\n } catch (error) {\n console.error(\n '[TreeNavigationSettingsComponent] Failed to load config',\n error,\n );\n this.messageService.showError(this.messages().loadError);\n } finally {\n this.loading.set(false);\n }\n }\n\n protected addRule(): void {\n this.rules.push(this.createRow());\n this.rules.markAsDirty();\n }\n\n protected removeRule(index: number): void {\n this.rules.removeAt(index);\n this.rules.markAsDirty();\n }\n\n protected async onSave(): Promise<void> {\n if (this.rules.invalid) {\n this.rules.markAllAsTouched();\n return;\n }\n this.saving.set(true);\n try {\n this.rtId = await this.config.saveConfig(this.rtId, this.collectRoles());\n this.messageService.showInformation(this.messages().saveSuccess);\n this.rules.markAsPristine();\n } catch (error) {\n console.error(\n '[TreeNavigationSettingsComponent] Failed to save config',\n error,\n );\n this.messageService.showError(this.messages().saveError);\n } finally {\n this.saving.set(false);\n }\n }\n\n /** Loads CK type suggestions for the source-type combobox (server filter). */\n protected async searchCkTypes(term: string): Promise<void> {\n try {\n const result = await firstValueFrom(\n this.ckTypeSelector.getCkTypes({\n searchText: term?.trim() || undefined,\n first: 30,\n }),\n );\n const ids = result.items\n .map((i) => i.rtCkTypeId)\n .filter((id): id is string => !!id && id !== WILDCARD);\n this.ckTypeSuggestions.set([WILDCARD, ...ids]);\n } catch (error) {\n console.error('Error loading CK type suggestions', error);\n this.ckTypeSuggestions.set([WILDCARD]);\n }\n }\n\n /** Loads role suggestions for the source type of the opened row's combobox. */\n protected async loadRoleSuggestions(row: FormGroup): Promise<void> {\n const ckTypeId = (row.get('sourceCkTypeId')?.value as string) ?? '';\n this.roleSuggestions.set(await this.config.getRoleSuggestions(ckTypeId));\n }\n\n /**\n * Exports the saved configuration singleton as a deep-graph runtime model ZIP,\n * via the standard asset-repo export job (same mechanism as pools / adapters /\n * data flows). Requires the config to have been saved first.\n */\n protected async export(): Promise<void> {\n if (!this.rtId) {\n this.messageService.showInformation(this.messages().exportNothing);\n return;\n }\n const tenantId = this.getTenantId();\n if (!tenantId) {\n this.messageService.showError(this.messages().exportError);\n return;\n }\n try {\n const jobId = await this.assetRepo.exportRtModelDeepGraph(\n tenantId,\n [this.rtId],\n TREE_NAVIGATION_CONFIG_CONSTANTS.CONFIG_CK_TYPE_ID,\n );\n if (!jobId) {\n throw new Error('export job not started');\n }\n const ok = await this.jobs.waitForJob(\n jobId,\n this.messages().export,\n this.messages().title,\n );\n if (ok) {\n await this.jobs.downloadJobResult(\n tenantId,\n jobId,\n 'tree-navigation-config.zip',\n );\n }\n } catch (error) {\n console.error('[TreeNavigationSettingsComponent] Export failed', error);\n this.messageService.showError(this.messages().exportError);\n }\n }\n\n /**\n * Imports a configuration from a deep-graph runtime model ZIP via the standard\n * import-strategy dialog + asset-repo import job, then reloads the editor.\n */\n protected async onFileSelected(event: Event): Promise<void> {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0];\n input.value = '';\n if (!file) {\n return;\n }\n const tenantId = this.getTenantId();\n if (!tenantId) {\n this.messageService.showError(this.messages().importError);\n return;\n }\n const strategy = await this.importStrategyDialog.showImportStrategyDialog(\n this.messages().import,\n );\n if (strategy === null) {\n return;\n }\n try {\n const jobId = await this.assetRepo.importRtModel(\n tenantId,\n file,\n strategy as ImportStrategyDto,\n );\n if (!jobId) {\n throw new Error('import job not started');\n }\n const ok = await this.jobs.waitForJob(\n jobId,\n this.messages().import,\n file.name,\n );\n if (ok) {\n this.messageService.showInformation(this.messages().importSuccess);\n await this.reload();\n }\n } catch (error) {\n console.error('[TreeNavigationSettingsComponent] Import failed', error);\n this.messageService.showError(this.messages().importError);\n }\n }\n\n /** Resolves the tenant id from the route hierarchy (route is /:tenantId/...). */\n private getTenantId(): string | null {\n let route: ActivatedRoute | null = this.route;\n while (route) {\n const tenantId = route.snapshot.paramMap.get('tenantId');\n if (tenantId) {\n return tenantId;\n }\n route = route.parent;\n }\n return null;\n }\n\n private collectRoles(): TreeNavigationRoleConfig[] {\n return this.rules.controls\n .map((group) => this.toRoleConfig(group as FormGroup))\n .filter((r) => r.sourceCkTypeId && r.roleId);\n }\n\n private createRow(role?: TreeNavigationRoleConfig): FormGroup {\n return this.fb.group({\n sourceCkTypeId: [role?.sourceCkTypeId ?? '*', [Validators.required]],\n roleId: [role?.roleId ?? '', [Validators.required]],\n displayName: [role?.displayName ?? ''],\n sortIndex: [role?.sortIndex ?? null],\n visible: [this.toVisibleValue(role?.visible)],\n grouped: [this.toGroupedValue(role?.grouped)],\n icon: [role?.icon ?? ''],\n });\n }\n\n private toRoleConfig(group: FormGroup): TreeNavigationRoleConfig {\n const value = group.getRawValue() as {\n sourceCkTypeId: string;\n roleId: string;\n displayName: string;\n sortIndex: number | null;\n visible: TriState;\n grouped: TriState;\n icon: string;\n };\n return {\n sourceCkTypeId: (value.sourceCkTypeId ?? '').trim(),\n roleId: (value.roleId ?? '').trim(),\n displayName: value.displayName?.trim() || undefined,\n sortIndex: value.sortIndex ?? undefined,\n visible: value.visible === 'auto' ? undefined : value.visible === 'show',\n grouped: value.grouped === 'auto' ? undefined : value.grouped === 'group',\n icon: value.icon?.trim() || undefined,\n };\n }\n\n private toVisibleValue(visible: boolean | undefined): TriState {\n if (visible === undefined) return 'auto';\n return visible ? 'show' : 'hide';\n }\n\n private toGroupedValue(grouped: boolean | undefined): TriState {\n if (grouped === undefined) return 'auto';\n return grouped ? 'group' : 'flatten';\n }\n}\n","<div class=\"tree-nav-settings\">\n <header class=\"header\">\n <h2 class=\"title\">{{ messages().title }}</h2>\n <p class=\"description\">{{ messages().description }}</p>\n </header>\n\n @if (loading()) {\n <div class=\"state\">…</div>\n } @else if (!typePresent()) {\n <div class=\"hint not-installed\">{{ messages().notInstalled }}</div>\n } @else {\n <div class=\"toolbar mm-toolbar-actions\">\n <button kendoButton [svgIcon]=\"plusIcon\" (click)=\"addRule()\">\n {{ messages().addRule }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"exportIcon\"\n fillMode=\"flat\"\n (click)=\"export()\"\n >\n {{ messages().export }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"importIcon\"\n fillMode=\"flat\"\n (click)=\"fileInput.click()\"\n >\n {{ messages().import }}\n </button>\n <input\n #fileInput\n type=\"file\"\n accept=\".zip\"\n hidden\n (change)=\"onFileSelected($event)\"\n />\n <span class=\"toolbar-spacer\"></span>\n <button\n kendoButton\n [svgIcon]=\"reloadIcon\"\n fillMode=\"flat\"\n [disabled]=\"saving()\"\n (click)=\"reload()\"\n >\n {{ messages().reload }}\n </button>\n <button\n kendoButton\n themeColor=\"primary\"\n [svgIcon]=\"saveIcon\"\n [disabled]=\"saving()\"\n (click)=\"onSave()\"\n >\n {{ messages().save }}\n </button>\n </div>\n\n @if (rules.length === 0) {\n <div class=\"empty\">{{ messages().empty }}</div>\n } @else {\n <div class=\"table-wrap\">\n <table class=\"rules\">\n <thead>\n <tr>\n <th>{{ messages().columnSourceType }}</th>\n <th>{{ messages().columnRole }}</th>\n <th>{{ messages().columnDisplayName }}</th>\n <th class=\"narrow\">{{ messages().columnSortIndex }}</th>\n <th class=\"narrow\">{{ messages().columnVisible }}</th>\n <th class=\"narrow\">{{ messages().columnGrouped }}</th>\n <th>{{ messages().columnIcon }}</th>\n <th class=\"actions\">{{ messages().columnActions }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rules.controls; track $index) {\n <tr [formGroup]=\"row\">\n <td>\n <kendo-combobox\n [data]=\"ckTypeSuggestions()\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().sourceTypeHint\"\n formControlName=\"sourceCkTypeId\"\n (open)=\"searchCkTypes('')\"\n (filterChange)=\"searchCkTypes($event)\"\n ></kendo-combobox>\n </td>\n <td>\n <kendo-combobox\n [data]=\"roleSuggestions()\"\n textField=\"label\"\n valueField=\"roleId\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().roleHint\"\n formControlName=\"roleId\"\n (open)=\"loadRoleSuggestions(row)\"\n ></kendo-combobox>\n </td>\n <td><input kendoTextBox formControlName=\"displayName\" /></td>\n <td class=\"narrow\">\n <kendo-numerictextbox\n formControlName=\"sortIndex\"\n [decimals]=\"0\"\n format=\"n0\"\n [spinners]=\"false\"\n ></kendo-numerictextbox>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"visibleOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"visible\"\n ></kendo-dropdownlist>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"groupedOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"grouped\"\n ></kendo-dropdownlist>\n </td>\n <td><input kendoTextBox formControlName=\"icon\" /></td>\n <td class=\"actions\">\n <button\n kendoButton\n fillMode=\"flat\"\n [svgIcon]=\"removeIcon\"\n [title]=\"messages().removeRule\"\n (click)=\"removeRule($index)\"\n ></button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n</div>\n","import { Routes } from '@angular/router';\n\n/**\n * Routes for the tree navigation settings UI. Mount under any path, e.g.:\n *\n * ```ts\n * { path: 'tree-navigation', canActivate: [adminGuard], children: TREE_NAVIGATION_SETTINGS_ROUTES }\n * ```\n *\n * The component is lazy-loaded on first navigation (`loadComponent`).\n */\nexport const TREE_NAVIGATION_SETTINGS_ROUTES: Routes = [\n {\n path: '',\n loadComponent: () =>\n import('./tree-navigation-settings.component').then(\n (m) => m.TreeNavigationSettingsComponent,\n ),\n },\n];\n","/*\n * Public API Surface of @meshmakers/octo-ui/tree-navigation-settings\n *\n * Admin-only editor for the per-tenant System.UI/TreeNavigationConfiguration.\n * Lives in its own secondary entry point so host applications that only need\n * the runtime browser / data-mappings trees (primary `@meshmakers/octo-ui`\n * entry) do not pay for the reactive-form / Kendo modules this editor pulls in.\n */\nexport * from './tree-navigation-settings.component';\nexport * from './tree-navigation-settings.messages';\nexport * from './tree-navigation-settings.routes';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"meshmakers-octo-ui-tree-navigation-settings.mjs","sources":["../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/tree-navigation-settings.messages.ts","../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/tree-navigation-settings.component.ts","../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/tree-navigation-settings.component.html","../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/tree-navigation-settings.routes.ts","../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/public-api.ts","../../../../projects/meshmakers/octo-ui/tree-navigation-settings/src/meshmakers-octo-ui-tree-navigation-settings.ts"],"sourcesContent":["/** UI strings for the tree navigation settings editor. */\nexport interface TreeNavigationSettingsMessages {\n title: string;\n description: string;\n /** Shown when System.UI < 2.2.0 (the CK type is not installed on the tenant). */\n notInstalled: string;\n columnSourceType: string;\n columnRole: string;\n columnDisplayName: string;\n columnSortIndex: string;\n columnVisible: string;\n columnGrouped: string;\n columnIcon: string;\n columnActions: string;\n visibleAuto: string;\n visibleShow: string;\n visibleHide: string;\n groupedAuto: string;\n groupedGroup: string;\n groupedFlatten: string;\n sourceTypeHint: string;\n roleHint: string;\n addRule: string;\n removeRule: string;\n save: string;\n reload: string;\n export: string;\n import: string;\n empty: string;\n saveSuccess: string;\n saveError: string;\n loadError: string;\n exportNothing: string;\n exportError: string;\n importSuccess: string;\n importError: string;\n\n // --- Perspectives editor (AB#4263) ---\n perspectivesTitle: string;\n perspectivesDescription: string;\n columnKey: string;\n columnPerspectiveName: string;\n columnRootMode: string;\n columnRootType: string;\n columnPrimaryRole: string;\n columnSecondaryRoles: string;\n rootModeSpatial: string;\n rootModeType: string;\n secondaryRolesHint: string;\n addPerspective: string;\n perspectivesEmpty: string;\n}\n\n/** English defaults; hosts may override via the `messages` input. */\nexport const DEFAULT_TREE_NAVIGATION_SETTINGS_MESSAGES: TreeNavigationSettingsMessages =\n {\n title: 'Tree Navigation',\n description:\n 'Per-tenant overrides for the entity trees (repository browser and data-mappings). Rules are applied on top of auto-discovered associations. Without any rule a role is shown with its default name, grouped (except System/ParentChild which is flattened).',\n notInstalled:\n 'The System.UI construction kit model (>= 2.2.0) is not installed on this tenant, so tree navigation cannot be configured yet.',\n columnSourceType: 'Source type',\n columnRole: 'Role id',\n columnDisplayName: 'Label',\n columnSortIndex: 'Order',\n columnVisible: 'Visibility',\n columnGrouped: 'Grouping',\n columnIcon: 'Icon',\n columnActions: '',\n visibleAuto: 'Auto',\n visibleShow: 'Show',\n visibleHide: 'Hide',\n groupedAuto: 'Auto',\n groupedGroup: 'Group',\n groupedFlatten: 'Flatten',\n sourceTypeHint: '* matches every type',\n roleHint: 'e.g. EnergyIQ/SpaceSensors',\n addRule: 'Add rule',\n removeRule: 'Remove',\n save: 'Save',\n reload: 'Reload',\n export: 'Export',\n import: 'Import',\n empty: 'No rules yet — every association uses its defaults.',\n saveSuccess: 'Tree navigation configuration saved.',\n saveError: 'Failed to save the tree navigation configuration.',\n loadError: 'Failed to load the tree navigation configuration.',\n exportNothing: 'Save the configuration before exporting it.',\n exportError: 'Failed to export the tree navigation configuration.',\n importSuccess: 'Import completed successfully.',\n importError: 'Failed to import the tree navigation configuration.',\n perspectivesTitle: 'Tree perspectives',\n perspectivesDescription:\n 'Switchable tree roots offered next to the built-in Spatial perspective. A Type perspective roots on all instances of a CK type and, at the root level, shows only its primary and secondary roles (deeper levels use auto-discovery).',\n columnKey: 'Key',\n columnPerspectiveName: 'Label',\n columnRootMode: 'Root',\n columnRootType: 'Root CK type',\n columnPrimaryRole: 'Primary role',\n columnSecondaryRoles: 'Secondary roles',\n rootModeSpatial: 'Spatial',\n rootModeType: 'Type',\n secondaryRolesHint: 'comma-separated role ids',\n addPerspective: 'Add perspective',\n perspectivesEmpty: 'No extra perspectives — only the built-in Spatial view.',\n };\n","import { CommonModule } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n inject,\n input,\n OnInit,\n signal,\n} from '@angular/core';\nimport {\n FormBuilder,\n FormGroup,\n ReactiveFormsModule,\n Validators,\n} from '@angular/forms';\nimport { ActivatedRoute } from '@angular/router';\nimport {\n PerspectiveDefinition,\n TreeNavigationConfigService,\n TreeNavigationRoleConfig,\n TREE_NAVIGATION_CONFIG_CONSTANTS,\n} from '@meshmakers/octo-ui';\nimport {\n AssetRepoService,\n CkTypeSelectorService,\n ImportStrategyDto,\n JobManagementService,\n} from '@meshmakers/octo-services';\nimport { ImportStrategyDialogService } from '@meshmakers/shared-ui';\nimport { MessageService } from '@meshmakers/shared-services';\nimport { ButtonsModule } from '@progress/kendo-angular-buttons';\nimport { DropDownsModule } from '@progress/kendo-angular-dropdowns';\nimport { InputsModule } from '@progress/kendo-angular-inputs';\nimport { LabelModule } from '@progress/kendo-angular-label';\nimport {\n plusIcon,\n saveIcon,\n arrowRotateCwIcon,\n xIcon,\n downloadIcon,\n uploadIcon,\n} from '@progress/kendo-svg-icons';\nimport { firstValueFrom } from 'rxjs';\nimport {\n DEFAULT_TREE_NAVIGATION_SETTINGS_MESSAGES,\n TreeNavigationSettingsMessages,\n} from './tree-navigation-settings.messages';\n\n/** Tri-state form value for the visibility/grouping dropdowns. */\ntype TriState = 'auto' | string;\n\n/** Matches every source CK type. */\nconst WILDCARD = '*';\n\n/**\n * Admin editor for the per-tenant `System.UI/TreeNavigationConfiguration`.\n * Each row is one override rule matched by (source type, role id); `*` as the\n * source type matches every type. Empty dropdown value = auto (default\n * behavior). Source type and role id offer autocomplete suggestions but also\n * accept custom values (so orphan roles remain configurable).\n */\n@Component({\n selector: 'mm-tree-navigation-settings',\n standalone: true,\n imports: [\n CommonModule,\n ReactiveFormsModule,\n ButtonsModule,\n InputsModule,\n LabelModule,\n DropDownsModule,\n ],\n templateUrl: './tree-navigation-settings.component.html',\n styleUrl: './tree-navigation-settings.component.scss',\n changeDetection: ChangeDetectionStrategy.Eager,\n})\nexport class TreeNavigationSettingsComponent implements OnInit {\n readonly messages = input<TreeNavigationSettingsMessages>(\n DEFAULT_TREE_NAVIGATION_SETTINGS_MESSAGES,\n );\n\n private readonly fb = inject(FormBuilder);\n private readonly config = inject(TreeNavigationConfigService);\n private readonly ckTypeSelector = inject(CkTypeSelectorService);\n private readonly assetRepo = inject(AssetRepoService);\n private readonly jobs = inject(JobManagementService);\n private readonly importStrategyDialog = inject(ImportStrategyDialogService);\n private readonly route = inject(ActivatedRoute);\n private readonly messageService = inject(MessageService);\n\n protected readonly loading = signal(true);\n protected readonly saving = signal(false);\n protected readonly typePresent = signal(true);\n private rtId: string | null = null;\n\n protected readonly rules = this.fb.array<FormGroup>([]);\n protected readonly perspectiveRows = this.fb.array<FormGroup>([]);\n\n protected readonly rootModeOptions = computed(() => [\n { text: this.messages().rootModeSpatial, value: 'Spatial' },\n { text: this.messages().rootModeType, value: 'Type' },\n ]);\n\n // Shared suggestion pools — only one combobox dropdown is open at a time, so a\n // single signal per kind is enough (loaded on open / filter).\n protected readonly ckTypeSuggestions = signal<string[]>([WILDCARD]);\n protected readonly roleSuggestions = signal<{ roleId: string; label: string }[]>(\n [],\n );\n\n protected readonly saveIcon = saveIcon;\n protected readonly plusIcon = plusIcon;\n protected readonly reloadIcon = arrowRotateCwIcon;\n protected readonly removeIcon = xIcon;\n protected readonly exportIcon = downloadIcon;\n protected readonly importIcon = uploadIcon;\n\n protected readonly visibleOptions = computed(() => [\n { text: this.messages().visibleAuto, value: 'auto' },\n { text: this.messages().visibleShow, value: 'show' },\n { text: this.messages().visibleHide, value: 'hide' },\n ]);\n protected readonly groupedOptions = computed(() => [\n { text: this.messages().groupedAuto, value: 'auto' },\n { text: this.messages().groupedGroup, value: 'group' },\n { text: this.messages().groupedFlatten, value: 'flatten' },\n ]);\n\n async ngOnInit(): Promise<void> {\n await this.reload();\n }\n\n protected async reload(): Promise<void> {\n this.loading.set(true);\n try {\n const config = await this.config.loadConfig();\n this.typePresent.set(config.typePresent);\n this.rtId = config.rtId;\n this.rules.clear();\n for (const role of config.roles) {\n this.rules.push(this.createRow(role));\n }\n this.perspectiveRows.clear();\n for (const perspective of config.perspectives) {\n this.perspectiveRows.push(this.createPerspectiveRow(perspective));\n }\n } catch (error) {\n console.error(\n '[TreeNavigationSettingsComponent] Failed to load config',\n error,\n );\n this.messageService.showError(this.messages().loadError);\n } finally {\n this.loading.set(false);\n }\n }\n\n protected addRule(): void {\n this.rules.push(this.createRow());\n this.rules.markAsDirty();\n }\n\n protected removeRule(index: number): void {\n this.rules.removeAt(index);\n this.rules.markAsDirty();\n }\n\n protected addPerspective(): void {\n this.perspectiveRows.push(this.createPerspectiveRow());\n this.perspectiveRows.markAsDirty();\n }\n\n protected removePerspective(index: number): void {\n this.perspectiveRows.removeAt(index);\n this.perspectiveRows.markAsDirty();\n }\n\n protected async onSave(): Promise<void> {\n if (this.rules.invalid || this.perspectiveRows.invalid) {\n this.rules.markAllAsTouched();\n this.perspectiveRows.markAllAsTouched();\n return;\n }\n this.saving.set(true);\n try {\n this.rtId = await this.config.saveConfig(\n this.rtId,\n this.collectRoles(),\n this.collectPerspectives(),\n );\n this.messageService.showInformation(this.messages().saveSuccess);\n this.rules.markAsPristine();\n this.perspectiveRows.markAsPristine();\n } catch (error) {\n console.error(\n '[TreeNavigationSettingsComponent] Failed to save config',\n error,\n );\n this.messageService.showError(this.messages().saveError);\n } finally {\n this.saving.set(false);\n }\n }\n\n /** Loads CK type suggestions for the source-type combobox (server filter). */\n protected async searchCkTypes(term: string): Promise<void> {\n try {\n const result = await firstValueFrom(\n this.ckTypeSelector.getCkTypes({\n searchText: term?.trim() || undefined,\n first: 30,\n }),\n );\n const ids = result.items\n .map((i) => i.rtCkTypeId)\n .filter((id): id is string => !!id && id !== WILDCARD);\n this.ckTypeSuggestions.set([WILDCARD, ...ids]);\n } catch (error) {\n console.error('Error loading CK type suggestions', error);\n this.ckTypeSuggestions.set([WILDCARD]);\n }\n }\n\n /** Loads role suggestions for the source type of the opened row's combobox. */\n protected async loadRoleSuggestions(row: FormGroup): Promise<void> {\n const ckTypeId = (row.get('sourceCkTypeId')?.value as string) ?? '';\n this.roleSuggestions.set(await this.config.getRoleSuggestions(ckTypeId));\n }\n\n /** Loads role suggestions for the root CK type of a perspective row. */\n protected async loadRoleSuggestionsForType(row: FormGroup): Promise<void> {\n const ckTypeId = (row.get('rootCkTypeId')?.value as string) ?? '';\n this.roleSuggestions.set(await this.config.getRoleSuggestions(ckTypeId));\n }\n\n /**\n * Exports the saved configuration singleton as a deep-graph runtime model ZIP,\n * via the standard asset-repo export job (same mechanism as pools / adapters /\n * data flows). Requires the config to have been saved first.\n */\n protected async export(): Promise<void> {\n if (!this.rtId) {\n this.messageService.showInformation(this.messages().exportNothing);\n return;\n }\n const tenantId = this.getTenantId();\n if (!tenantId) {\n this.messageService.showError(this.messages().exportError);\n return;\n }\n try {\n const jobId = await this.assetRepo.exportRtModelDeepGraph(\n tenantId,\n [this.rtId],\n TREE_NAVIGATION_CONFIG_CONSTANTS.CONFIG_CK_TYPE_ID,\n );\n if (!jobId) {\n throw new Error('export job not started');\n }\n const ok = await this.jobs.waitForJob(\n jobId,\n this.messages().export,\n this.messages().title,\n );\n if (ok) {\n await this.jobs.downloadJobResult(\n tenantId,\n jobId,\n 'tree-navigation-config.zip',\n );\n }\n } catch (error) {\n console.error('[TreeNavigationSettingsComponent] Export failed', error);\n this.messageService.showError(this.messages().exportError);\n }\n }\n\n /**\n * Imports a configuration from a deep-graph runtime model ZIP via the standard\n * import-strategy dialog + asset-repo import job, then reloads the editor.\n */\n protected async onFileSelected(event: Event): Promise<void> {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0];\n input.value = '';\n if (!file) {\n return;\n }\n const tenantId = this.getTenantId();\n if (!tenantId) {\n this.messageService.showError(this.messages().importError);\n return;\n }\n const strategy = await this.importStrategyDialog.showImportStrategyDialog(\n this.messages().import,\n );\n if (strategy === null) {\n return;\n }\n try {\n const jobId = await this.assetRepo.importRtModel(\n tenantId,\n file,\n strategy as ImportStrategyDto,\n );\n if (!jobId) {\n throw new Error('import job not started');\n }\n const ok = await this.jobs.waitForJob(\n jobId,\n this.messages().import,\n file.name,\n );\n if (ok) {\n this.messageService.showInformation(this.messages().importSuccess);\n await this.reload();\n }\n } catch (error) {\n console.error('[TreeNavigationSettingsComponent] Import failed', error);\n this.messageService.showError(this.messages().importError);\n }\n }\n\n /** Resolves the tenant id from the route hierarchy (route is /:tenantId/...). */\n private getTenantId(): string | null {\n let route: ActivatedRoute | null = this.route;\n while (route) {\n const tenantId = route.snapshot.paramMap.get('tenantId');\n if (tenantId) {\n return tenantId;\n }\n route = route.parent;\n }\n return null;\n }\n\n private collectRoles(): TreeNavigationRoleConfig[] {\n return this.rules.controls\n .map((group) => this.toRoleConfig(group as FormGroup))\n .filter((r) => r.sourceCkTypeId && r.roleId);\n }\n\n private collectPerspectives(): PerspectiveDefinition[] {\n return this.perspectiveRows.controls\n .map((group) => this.toPerspectiveConfig(group as FormGroup))\n .filter((p) => p.key);\n }\n\n private createPerspectiveRow(p?: PerspectiveDefinition): FormGroup {\n return this.fb.group({\n key: [p?.key ?? '', [Validators.required]],\n displayName: [p?.displayName ?? ''],\n rootMode: [p?.rootMode ?? 'Type'],\n rootCkTypeId: [p?.rootCkTypeId ?? ''],\n primaryRoleId: [p?.primaryRoleId ?? ''],\n secondaryRoleIds: [(p?.secondaryRoleIds ?? []).join(', ')],\n sortIndex: [p?.sortIndex ?? null],\n icon: [p?.icon ?? ''],\n });\n }\n\n private toPerspectiveConfig(group: FormGroup): PerspectiveDefinition {\n const value = group.getRawValue() as {\n key: string;\n displayName: string;\n rootMode: 'Spatial' | 'Type';\n rootCkTypeId: string;\n primaryRoleId: string;\n secondaryRoleIds: string;\n sortIndex: number | null;\n icon: string;\n };\n const secondary = (value.secondaryRoleIds ?? '')\n .split(/[\\n,]/)\n .map((r) => r.trim())\n .filter((r) => r.length > 0);\n const key = (value.key ?? '').trim();\n return {\n key,\n displayName: value.displayName?.trim() || key,\n rootMode: value.rootMode === 'Spatial' ? 'Spatial' : 'Type',\n rootCkTypeId: value.rootCkTypeId?.trim() || undefined,\n primaryRoleId: value.primaryRoleId?.trim() || undefined,\n secondaryRoleIds: secondary.length > 0 ? secondary : undefined,\n sortIndex: value.sortIndex ?? undefined,\n icon: value.icon?.trim() || undefined,\n };\n }\n\n private createRow(role?: TreeNavigationRoleConfig): FormGroup {\n return this.fb.group({\n sourceCkTypeId: [role?.sourceCkTypeId ?? '*', [Validators.required]],\n roleId: [role?.roleId ?? '', [Validators.required]],\n displayName: [role?.displayName ?? ''],\n sortIndex: [role?.sortIndex ?? null],\n visible: [this.toVisibleValue(role?.visible)],\n grouped: [this.toGroupedValue(role?.grouped)],\n icon: [role?.icon ?? ''],\n });\n }\n\n private toRoleConfig(group: FormGroup): TreeNavigationRoleConfig {\n const value = group.getRawValue() as {\n sourceCkTypeId: string;\n roleId: string;\n displayName: string;\n sortIndex: number | null;\n visible: TriState;\n grouped: TriState;\n icon: string;\n };\n return {\n sourceCkTypeId: (value.sourceCkTypeId ?? '').trim(),\n roleId: (value.roleId ?? '').trim(),\n displayName: value.displayName?.trim() || undefined,\n sortIndex: value.sortIndex ?? undefined,\n visible: value.visible === 'auto' ? undefined : value.visible === 'show',\n grouped: value.grouped === 'auto' ? undefined : value.grouped === 'group',\n icon: value.icon?.trim() || undefined,\n };\n }\n\n private toVisibleValue(visible: boolean | undefined): TriState {\n if (visible === undefined) return 'auto';\n return visible ? 'show' : 'hide';\n }\n\n private toGroupedValue(grouped: boolean | undefined): TriState {\n if (grouped === undefined) return 'auto';\n return grouped ? 'group' : 'flatten';\n }\n}\n","<div class=\"tree-nav-settings\">\n <header class=\"header\">\n <h2 class=\"title\">{{ messages().title }}</h2>\n <p class=\"description\">{{ messages().description }}</p>\n </header>\n\n @if (loading()) {\n <div class=\"state\">…</div>\n } @else if (!typePresent()) {\n <div class=\"hint not-installed\">{{ messages().notInstalled }}</div>\n } @else {\n <div class=\"toolbar mm-toolbar-actions\">\n <button kendoButton [svgIcon]=\"plusIcon\" (click)=\"addRule()\">\n {{ messages().addRule }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"exportIcon\"\n fillMode=\"flat\"\n (click)=\"export()\"\n >\n {{ messages().export }}\n </button>\n <button\n kendoButton\n [svgIcon]=\"importIcon\"\n fillMode=\"flat\"\n (click)=\"fileInput.click()\"\n >\n {{ messages().import }}\n </button>\n <input\n #fileInput\n type=\"file\"\n accept=\".zip\"\n hidden\n (change)=\"onFileSelected($event)\"\n />\n <span class=\"toolbar-spacer\"></span>\n <button\n kendoButton\n [svgIcon]=\"reloadIcon\"\n fillMode=\"flat\"\n [disabled]=\"saving()\"\n (click)=\"reload()\"\n >\n {{ messages().reload }}\n </button>\n <button\n kendoButton\n themeColor=\"primary\"\n [svgIcon]=\"saveIcon\"\n [disabled]=\"saving()\"\n (click)=\"onSave()\"\n >\n {{ messages().save }}\n </button>\n </div>\n\n @if (rules.length === 0) {\n <div class=\"empty\">{{ messages().empty }}</div>\n } @else {\n <div class=\"table-wrap\">\n <table class=\"rules\">\n <thead>\n <tr>\n <th>{{ messages().columnSourceType }}</th>\n <th>{{ messages().columnRole }}</th>\n <th>{{ messages().columnDisplayName }}</th>\n <th class=\"narrow\">{{ messages().columnSortIndex }}</th>\n <th class=\"narrow\">{{ messages().columnVisible }}</th>\n <th class=\"narrow\">{{ messages().columnGrouped }}</th>\n <th>{{ messages().columnIcon }}</th>\n <th class=\"actions\">{{ messages().columnActions }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rules.controls; track $index) {\n <tr [formGroup]=\"row\">\n <td>\n <kendo-combobox\n [data]=\"ckTypeSuggestions()\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().sourceTypeHint\"\n formControlName=\"sourceCkTypeId\"\n (open)=\"searchCkTypes('')\"\n (filterChange)=\"searchCkTypes($event)\"\n ></kendo-combobox>\n </td>\n <td>\n <kendo-combobox\n [data]=\"roleSuggestions()\"\n textField=\"label\"\n valueField=\"roleId\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n [placeholder]=\"messages().roleHint\"\n formControlName=\"roleId\"\n (open)=\"loadRoleSuggestions(row)\"\n ></kendo-combobox>\n </td>\n <td><input kendoTextBox formControlName=\"displayName\" /></td>\n <td class=\"narrow\">\n <kendo-numerictextbox\n formControlName=\"sortIndex\"\n [decimals]=\"0\"\n format=\"n0\"\n [spinners]=\"false\"\n ></kendo-numerictextbox>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"visibleOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"visible\"\n ></kendo-dropdownlist>\n </td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"groupedOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"grouped\"\n ></kendo-dropdownlist>\n </td>\n <td><input kendoTextBox formControlName=\"icon\" /></td>\n <td class=\"actions\">\n <button\n kendoButton\n fillMode=\"flat\"\n [svgIcon]=\"removeIcon\"\n [title]=\"messages().removeRule\"\n (click)=\"removeRule($index)\"\n ></button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n <header class=\"header perspectives-header\">\n <h2 class=\"title\">{{ messages().perspectivesTitle }}</h2>\n <p class=\"description\">{{ messages().perspectivesDescription }}</p>\n </header>\n\n <div class=\"toolbar mm-toolbar-actions\">\n <button kendoButton [svgIcon]=\"plusIcon\" (click)=\"addPerspective()\">\n {{ messages().addPerspective }}\n </button>\n </div>\n\n @if (perspectiveRows.length === 0) {\n <div class=\"empty\">{{ messages().perspectivesEmpty }}</div>\n } @else {\n <div class=\"table-wrap\">\n <table class=\"rules\">\n <thead>\n <tr>\n <th>{{ messages().columnKey }}</th>\n <th>{{ messages().columnPerspectiveName }}</th>\n <th class=\"narrow\">{{ messages().columnRootMode }}</th>\n <th>{{ messages().columnRootType }}</th>\n <th>{{ messages().columnPrimaryRole }}</th>\n <th>{{ messages().columnSecondaryRoles }}</th>\n <th class=\"narrow\">{{ messages().columnSortIndex }}</th>\n <th>{{ messages().columnIcon }}</th>\n <th class=\"actions\">{{ messages().columnActions }}</th>\n </tr>\n </thead>\n <tbody>\n @for (row of perspectiveRows.controls; track $index) {\n <tr [formGroup]=\"row\">\n <td><input kendoTextBox formControlName=\"key\" /></td>\n <td><input kendoTextBox formControlName=\"displayName\" /></td>\n <td class=\"narrow\">\n <kendo-dropdownlist\n [data]=\"rootModeOptions()\"\n textField=\"text\"\n valueField=\"value\"\n [valuePrimitive]=\"true\"\n formControlName=\"rootMode\"\n ></kendo-dropdownlist>\n </td>\n <td>\n <kendo-combobox\n [data]=\"ckTypeSuggestions()\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n formControlName=\"rootCkTypeId\"\n (open)=\"searchCkTypes('')\"\n (filterChange)=\"searchCkTypes($event)\"\n ></kendo-combobox>\n </td>\n <td>\n <kendo-combobox\n [data]=\"roleSuggestions()\"\n textField=\"label\"\n valueField=\"roleId\"\n [allowCustom]=\"true\"\n [filterable]=\"true\"\n [valuePrimitive]=\"true\"\n formControlName=\"primaryRoleId\"\n (open)=\"loadRoleSuggestionsForType(row)\"\n ></kendo-combobox>\n </td>\n <td>\n <input\n kendoTextBox\n formControlName=\"secondaryRoleIds\"\n [placeholder]=\"messages().secondaryRolesHint\"\n />\n </td>\n <td class=\"narrow\">\n <kendo-numerictextbox\n formControlName=\"sortIndex\"\n [decimals]=\"0\"\n format=\"n0\"\n [spinners]=\"false\"\n ></kendo-numerictextbox>\n </td>\n <td><input kendoTextBox formControlName=\"icon\" /></td>\n <td class=\"actions\">\n <button\n kendoButton\n fillMode=\"flat\"\n [svgIcon]=\"removeIcon\"\n [title]=\"messages().removeRule\"\n (click)=\"removePerspective($index)\"\n ></button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n</div>\n","import { Routes } from '@angular/router';\n\n/**\n * Routes for the tree navigation settings UI. Mount under any path, e.g.:\n *\n * ```ts\n * { path: 'tree-navigation', canActivate: [adminGuard], children: TREE_NAVIGATION_SETTINGS_ROUTES }\n * ```\n *\n * The component is lazy-loaded on first navigation (`loadComponent`).\n */\nexport const TREE_NAVIGATION_SETTINGS_ROUTES: Routes = [\n {\n path: '',\n loadComponent: () =>\n import('./tree-navigation-settings.component').then(\n (m) => m.TreeNavigationSettingsComponent,\n ),\n },\n];\n","/*\n * Public API Surface of @meshmakers/octo-ui/tree-navigation-settings\n *\n * Admin-only editor for the per-tenant System.UI/TreeNavigationConfiguration.\n * Lives in its own secondary entry point so host applications that only need\n * the runtime browser / data-mappings trees (primary `@meshmakers/octo-ui`\n * entry) do not pay for the reactive-form / Kendo modules this editor pulls in.\n */\nexport * from './tree-navigation-settings.component';\nexport * from './tree-navigation-settings.messages';\nexport * from './tree-navigation-settings.routes';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|