@meshmakers/octo-ui 3.3.560 → 3.3.580
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.mjs +1132 -757
- package/fesm2022/meshmakers-octo-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/meshmakers-octo-ui.d.ts +104 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Component, Injectable, EventEmitter, Output, Input, ElementRef, forwardRef, ViewChild, makeEnvironmentProviders } from '@angular/core';
|
|
3
|
-
import { AttributeSelectorService, AttributeValueTypeDto as AttributeValueTypeDto$1, CkTypeAttributeService, CkTypeSelectorService, SearchFilterTypesDto, SortOrdersDto, FieldFilterOperatorsDto, provideOctoServices } from '@meshmakers/octo-services';
|
|
4
|
-
import { DataSourceTyped, HierarchyDataSourceBase, NotificationDisplayService, provideMmSharedUi } from '@meshmakers/shared-ui';
|
|
2
|
+
import { inject, Component, Injectable, EventEmitter, Output, Input, ElementRef, forwardRef, ViewChild, signal, computed, makeEnvironmentProviders } from '@angular/core';
|
|
3
|
+
import { AttributeSelectorService, AttributeValueTypeDto as AttributeValueTypeDto$1, CkTypeAttributeService, CkTypeSelectorService, GetEntitiesByCkTypeDtoGQL, RuntimeEntitySelectDataSource, RuntimeEntityDialogDataSource, SearchFilterTypesDto, SortOrdersDto, FieldFilterOperatorsDto, provideOctoServices } from '@meshmakers/octo-services';
|
|
4
|
+
import { WindowStateService, EntitySelectInputComponent, DataSourceTyped, HierarchyDataSourceBase, NotificationDisplayService, provideMmSharedUi } from '@meshmakers/shared-ui';
|
|
5
5
|
import { provideMmSharedAuth } from '@meshmakers/shared-auth';
|
|
6
6
|
import * as i1 from '@angular/common';
|
|
7
7
|
import { CommonModule } from '@angular/common';
|
|
@@ -17,7 +17,7 @@ import * as i3$1 from '@progress/kendo-angular-dropdowns';
|
|
|
17
17
|
import { DropDownListModule, DropDownsModule, AutoCompleteModule } from '@progress/kendo-angular-dropdowns';
|
|
18
18
|
import * as i5$1 from '@progress/kendo-angular-icons';
|
|
19
19
|
import { IconsModule, SVGIconModule } from '@progress/kendo-angular-icons';
|
|
20
|
-
import { searchIcon, sortAscSmallIcon, sortDescSmallIcon, chevronRightIcon, chevronDownIcon, downloadIcon, fileIcon, folderIcon, calendarIcon, checkboxCheckedIcon, listUnorderedIcon, filterClearIcon, arrowRightIcon, arrowLeftIcon, chevronDoubleRightIcon, chevronDoubleLeftIcon, arrowUpIcon, arrowDownIcon, plusIcon, minusIcon,
|
|
20
|
+
import { searchIcon, sortAscSmallIcon, sortDescSmallIcon, chevronRightIcon, chevronDownIcon, downloadIcon, fileIcon, folderIcon, calendarIcon, checkboxCheckedIcon, listUnorderedIcon, filterClearIcon, arrowRightIcon, arrowLeftIcon, chevronDoubleRightIcon, chevronDoubleLeftIcon, arrowUpIcon, arrowDownIcon, pencilIcon, trashIcon, plusIcon, minusIcon, dollarIcon, copyIcon } from '@progress/kendo-svg-icons';
|
|
21
21
|
import { WindowRef, WindowModule, WindowService, WindowCloseResult } from '@progress/kendo-angular-dialog';
|
|
22
22
|
import { Subject, firstValueFrom, of, forkJoin, Subscription } from 'rxjs';
|
|
23
23
|
import { debounceTime, distinctUntilChanged, switchMap, map, tap, catchError } from 'rxjs/operators';
|
|
@@ -493,6 +493,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
493
493
|
|
|
494
494
|
class AttributeSortSelectorDialogService {
|
|
495
495
|
windowService = inject(WindowService);
|
|
496
|
+
windowStateService = inject(WindowStateService);
|
|
496
497
|
/**
|
|
497
498
|
* Opens the attribute sort selector dialog
|
|
498
499
|
* @param ckTypeId The CkType ID to fetch attributes for
|
|
@@ -506,15 +507,17 @@ class AttributeSortSelectorDialogService {
|
|
|
506
507
|
selectedAttributes,
|
|
507
508
|
dialogTitle
|
|
508
509
|
};
|
|
510
|
+
const size = this.windowStateService.resolveWindowSize('attribute-sort-selector', { width: 1200, height: 750 });
|
|
509
511
|
const windowRef = this.windowService.open({
|
|
510
512
|
content: AttributeSortSelectorDialogComponent,
|
|
511
|
-
width:
|
|
512
|
-
height:
|
|
513
|
+
width: size.width,
|
|
514
|
+
height: size.height,
|
|
513
515
|
minWidth: 1050,
|
|
514
516
|
minHeight: 700,
|
|
515
517
|
resizable: true,
|
|
516
518
|
title: dialogTitle || 'Select Attributes with Sort Order'
|
|
517
519
|
});
|
|
520
|
+
this.windowStateService.applyModalBehavior('attribute-sort-selector', windowRef);
|
|
518
521
|
// Pass data to the component
|
|
519
522
|
const contentRef = windowRef.content;
|
|
520
523
|
if (contentRef?.instance) {
|
|
@@ -523,14 +526,12 @@ class AttributeSortSelectorDialogService {
|
|
|
523
526
|
try {
|
|
524
527
|
const result = await firstValueFrom(windowRef.result);
|
|
525
528
|
if (result instanceof WindowCloseResult) {
|
|
526
|
-
// User closed the window via X button
|
|
527
529
|
return {
|
|
528
530
|
confirmed: false,
|
|
529
531
|
selectedAttributes: []
|
|
530
532
|
};
|
|
531
533
|
}
|
|
532
534
|
if (result && typeof result === 'object' && 'selectedAttributes' in result) {
|
|
533
|
-
// User clicked OK
|
|
534
535
|
const dialogResult = result;
|
|
535
536
|
return {
|
|
536
537
|
confirmed: true,
|
|
@@ -538,7 +539,6 @@ class AttributeSortSelectorDialogService {
|
|
|
538
539
|
};
|
|
539
540
|
}
|
|
540
541
|
else {
|
|
541
|
-
// User clicked Cancel or closed dialog (result is undefined)
|
|
542
542
|
return {
|
|
543
543
|
confirmed: false,
|
|
544
544
|
selectedAttributes: []
|
|
@@ -546,7 +546,6 @@ class AttributeSortSelectorDialogService {
|
|
|
546
546
|
}
|
|
547
547
|
}
|
|
548
548
|
catch {
|
|
549
|
-
// Dialog was closed without result (e.g., ESC key, X button)
|
|
550
549
|
return {
|
|
551
550
|
confirmed: false,
|
|
552
551
|
selectedAttributes: []
|
|
@@ -1898,7 +1897,7 @@ class CkTypeSelectorDialogComponent {
|
|
|
1898
1897
|
searchIcon = searchIcon;
|
|
1899
1898
|
filterClearIcon = filterClearIcon;
|
|
1900
1899
|
dialogTitle = 'Select Construction Kit Type';
|
|
1901
|
-
allowAbstract =
|
|
1900
|
+
allowAbstract = true;
|
|
1902
1901
|
searchText = '';
|
|
1903
1902
|
selectedModel = null;
|
|
1904
1903
|
availableModels = [];
|
|
@@ -1919,7 +1918,7 @@ class CkTypeSelectorDialogComponent {
|
|
|
1919
1918
|
ngOnInit() {
|
|
1920
1919
|
if (this.data) {
|
|
1921
1920
|
this.dialogTitle = this.data.dialogTitle || 'Select Construction Kit Type';
|
|
1922
|
-
this.allowAbstract = this.data.allowAbstract ??
|
|
1921
|
+
this.allowAbstract = this.data.allowAbstract ?? true;
|
|
1923
1922
|
this.initialCkModelIds = this.data.ckModelIds;
|
|
1924
1923
|
this.derivedFromRtCkTypeId = this.data.derivedFromRtCkTypeId;
|
|
1925
1924
|
if (this.data.selectedCkTypeId) {
|
|
@@ -2220,6 +2219,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2220
2219
|
|
|
2221
2220
|
class CkTypeSelectorDialogService {
|
|
2222
2221
|
windowService = inject(WindowService);
|
|
2222
|
+
windowStateService = inject(WindowStateService);
|
|
2223
2223
|
/**
|
|
2224
2224
|
* Opens the CkType selector dialog
|
|
2225
2225
|
* @param options Dialog options
|
|
@@ -2233,15 +2233,17 @@ class CkTypeSelectorDialogService {
|
|
|
2233
2233
|
allowAbstract: options.allowAbstract,
|
|
2234
2234
|
derivedFromRtCkTypeId: options.derivedFromRtCkTypeId
|
|
2235
2235
|
};
|
|
2236
|
+
const size = this.windowStateService.resolveWindowSize('ck-type-selector', { width: 900, height: 650 });
|
|
2236
2237
|
const windowRef = this.windowService.open({
|
|
2237
2238
|
content: CkTypeSelectorDialogComponent,
|
|
2238
|
-
width:
|
|
2239
|
-
height:
|
|
2239
|
+
width: size.width,
|
|
2240
|
+
height: size.height,
|
|
2240
2241
|
minWidth: 750,
|
|
2241
2242
|
minHeight: 550,
|
|
2242
2243
|
resizable: true,
|
|
2243
2244
|
title: options.dialogTitle || 'Select Construction Kit Type'
|
|
2244
2245
|
});
|
|
2246
|
+
this.windowStateService.applyModalBehavior('ck-type-selector', windowRef);
|
|
2245
2247
|
// Pass data to the component
|
|
2246
2248
|
const contentRef = windowRef.content;
|
|
2247
2249
|
if (contentRef?.instance) {
|
|
@@ -2256,7 +2258,6 @@ class CkTypeSelectorDialogService {
|
|
|
2256
2258
|
};
|
|
2257
2259
|
}
|
|
2258
2260
|
if (result && typeof result === 'object' && 'selectedCkType' in result) {
|
|
2259
|
-
// User clicked OK and we have a result
|
|
2260
2261
|
const dialogResult = result;
|
|
2261
2262
|
return {
|
|
2262
2263
|
confirmed: true,
|
|
@@ -2264,7 +2265,6 @@ class CkTypeSelectorDialogService {
|
|
|
2264
2265
|
};
|
|
2265
2266
|
}
|
|
2266
2267
|
else {
|
|
2267
|
-
// User clicked Cancel or closed dialog
|
|
2268
2268
|
return {
|
|
2269
2269
|
confirmed: false,
|
|
2270
2270
|
selectedCkType: null
|
|
@@ -2272,7 +2272,6 @@ class CkTypeSelectorDialogService {
|
|
|
2272
2272
|
}
|
|
2273
2273
|
}
|
|
2274
2274
|
catch {
|
|
2275
|
-
// Dialog was closed without result (e.g., ESC key, X button)
|
|
2276
2275
|
return {
|
|
2277
2276
|
confirmed: false,
|
|
2278
2277
|
selectedCkType: null
|
|
@@ -2286,363 +2285,652 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2286
2285
|
type: Injectable
|
|
2287
2286
|
}] });
|
|
2288
2287
|
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2288
|
+
class CkTypeSelectorInputComponent {
|
|
2289
|
+
autocomplete;
|
|
2290
|
+
placeholder = 'Select a CK type...';
|
|
2291
|
+
minSearchLength = 2;
|
|
2292
|
+
maxResults = 50;
|
|
2293
|
+
debounceMs = 300;
|
|
2294
|
+
ckModelIds;
|
|
2295
|
+
allowAbstract = true;
|
|
2296
|
+
dialogTitle = 'Select Construction Kit Type';
|
|
2297
|
+
advancedSearchLabel = 'Advanced Search...';
|
|
2298
|
+
derivedFromRtCkTypeId;
|
|
2299
|
+
_disabled = false;
|
|
2300
|
+
get disabled() {
|
|
2301
|
+
return this._disabled;
|
|
2301
2302
|
}
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
fieldFilters = state.filter.filters.map((f) => {
|
|
2307
|
-
if (isCompositeFilterDescriptor(f)) {
|
|
2308
|
-
throw new Error('Composite filter descriptor not supported');
|
|
2309
|
-
}
|
|
2310
|
-
const { operator, value } = OctoGraphQlDataSource.getOperatorAndValue(f.operator, f.value);
|
|
2311
|
-
return {
|
|
2312
|
-
attributePath: f.field,
|
|
2313
|
-
operator: operator,
|
|
2314
|
-
comparisonValue: value
|
|
2315
|
-
};
|
|
2316
|
-
});
|
|
2303
|
+
set disabled(value) {
|
|
2304
|
+
this._disabled = !!value;
|
|
2305
|
+
if (this._disabled) {
|
|
2306
|
+
this.searchFormControl.disable();
|
|
2317
2307
|
}
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
// noinspection JSUnusedGlobalSymbols
|
|
2321
|
-
getSearchFilterDefinitions(textSearchValue) {
|
|
2322
|
-
let searchFilterDto = null;
|
|
2323
|
-
if (textSearchValue) {
|
|
2324
|
-
searchFilterDto = {
|
|
2325
|
-
type: SearchFilterTypesDto.AttributeFilterDto,
|
|
2326
|
-
attributePaths: this.searchFilterAttributePaths,
|
|
2327
|
-
searchTerm: textSearchValue,
|
|
2328
|
-
};
|
|
2308
|
+
else {
|
|
2309
|
+
this.searchFormControl.enable();
|
|
2329
2310
|
}
|
|
2330
|
-
return searchFilterDto;
|
|
2331
2311
|
}
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
if (state.sort) {
|
|
2336
|
-
sort = new Array();
|
|
2337
|
-
state.sort.forEach((s) => {
|
|
2338
|
-
switch (s.dir) {
|
|
2339
|
-
case 'asc':
|
|
2340
|
-
sort?.push({
|
|
2341
|
-
attributePath: s.field,
|
|
2342
|
-
sortOrder: SortOrdersDto.AscendingDto
|
|
2343
|
-
});
|
|
2344
|
-
break;
|
|
2345
|
-
case 'desc':
|
|
2346
|
-
sort?.push({
|
|
2347
|
-
attributePath: s.field,
|
|
2348
|
-
sortOrder: SortOrdersDto.DescendingDto,
|
|
2349
|
-
});
|
|
2350
|
-
break;
|
|
2351
|
-
default:
|
|
2352
|
-
sort?.push({
|
|
2353
|
-
attributePath: s.field,
|
|
2354
|
-
sortOrder: SortOrdersDto.DefaultDto,
|
|
2355
|
-
});
|
|
2356
|
-
break;
|
|
2357
|
-
}
|
|
2358
|
-
});
|
|
2359
|
-
}
|
|
2360
|
-
return sort;
|
|
2312
|
+
_required = false;
|
|
2313
|
+
get required() {
|
|
2314
|
+
return this._required;
|
|
2361
2315
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
case 'eq':
|
|
2365
|
-
return { operator: FieldFilterOperatorsDto.EqualsDto, value: value };
|
|
2366
|
-
case 'neq':
|
|
2367
|
-
return { operator: FieldFilterOperatorsDto.NotEqualsDto, value: value };
|
|
2368
|
-
case 'lt':
|
|
2369
|
-
return { operator: FieldFilterOperatorsDto.LessThanDto, value: value };
|
|
2370
|
-
case 'lte':
|
|
2371
|
-
return { operator: FieldFilterOperatorsDto.LessEqualThanDto, value: value };
|
|
2372
|
-
case 'gt':
|
|
2373
|
-
return { operator: FieldFilterOperatorsDto.GreaterThanDto, value: value };
|
|
2374
|
-
case 'gte':
|
|
2375
|
-
return { operator: FieldFilterOperatorsDto.GreaterEqualThanDto, value: value };
|
|
2376
|
-
case 'contains':
|
|
2377
|
-
return { operator: FieldFilterOperatorsDto.LikeDto, value: value };
|
|
2378
|
-
case 'doesnotcontain':
|
|
2379
|
-
return { operator: FieldFilterOperatorsDto.MatchRegExDto, value: `^(?!.*${value}).*$` };
|
|
2380
|
-
case 'startswith':
|
|
2381
|
-
return { operator: FieldFilterOperatorsDto.MatchRegExDto, value: value + '.*' };
|
|
2382
|
-
case 'endswith':
|
|
2383
|
-
return { operator: FieldFilterOperatorsDto.MatchRegExDto, value: '.*' + value };
|
|
2384
|
-
case 'isnull':
|
|
2385
|
-
return { operator: FieldFilterOperatorsDto.EqualsDto, value: null };
|
|
2386
|
-
case 'isnotnull':
|
|
2387
|
-
return { operator: FieldFilterOperatorsDto.NotEqualsDto, value: null };
|
|
2388
|
-
case 'isempty':
|
|
2389
|
-
return { operator: FieldFilterOperatorsDto.EqualsDto, value: "" };
|
|
2390
|
-
case 'isnotempty':
|
|
2391
|
-
return { operator: FieldFilterOperatorsDto.NotEqualsDto, value: "" };
|
|
2392
|
-
default:
|
|
2393
|
-
throw new Error('The filter operator is not supported');
|
|
2394
|
-
}
|
|
2316
|
+
set required(value) {
|
|
2317
|
+
this._required = !!value;
|
|
2395
2318
|
}
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
attributeService = inject(AttributeSelectorService);
|
|
2319
|
+
ckTypeSelected = new EventEmitter();
|
|
2320
|
+
ckTypeCleared = new EventEmitter();
|
|
2321
|
+
searchFormControl = new FormControl();
|
|
2322
|
+
filteredTypes = [];
|
|
2323
|
+
selectedCkType = null;
|
|
2324
|
+
isLoading = false;
|
|
2325
|
+
typeMap = new Map();
|
|
2404
2326
|
searchSubject = new Subject();
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
chevronDoubleLeftIcon = chevronDoubleLeftIcon;
|
|
2327
|
+
subscriptions = new Subscription();
|
|
2328
|
+
onChange = () => { };
|
|
2329
|
+
onTouched = () => { };
|
|
2409
2330
|
searchIcon = searchIcon;
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
singleSelect = false;
|
|
2416
|
-
searchText = '';
|
|
2417
|
-
selectedSingleKey = [];
|
|
2418
|
-
selectedValueTypeFilter = null;
|
|
2419
|
-
includeNavigationProperties = true;
|
|
2420
|
-
maxDepth = null;
|
|
2421
|
-
availableAttributes = [];
|
|
2422
|
-
selectedAttributes = [];
|
|
2423
|
-
availableGridData = { data: [], total: 0 };
|
|
2424
|
-
selectedGridData = { data: [], total: 0 };
|
|
2425
|
-
selectedAvailableKeys = [];
|
|
2426
|
-
selectedChosenKeys = [];
|
|
2427
|
-
valueTypeOptions = [
|
|
2428
|
-
{ text: 'All Types', value: null },
|
|
2429
|
-
{ text: 'String', value: AttributeValueTypeDto$1.StringDto },
|
|
2430
|
-
{ text: 'Integer', value: AttributeValueTypeDto$1.IntegerDto },
|
|
2431
|
-
{ text: 'Double', value: AttributeValueTypeDto$1.DoubleDto },
|
|
2432
|
-
{ text: 'Boolean', value: AttributeValueTypeDto$1.BooleanDto },
|
|
2433
|
-
{ text: 'DateTime', value: AttributeValueTypeDto$1.DateTimeDto },
|
|
2434
|
-
{ text: 'DateTimeOffset', value: AttributeValueTypeDto$1.DateTimeOffsetDto },
|
|
2435
|
-
{ text: 'Enum', value: AttributeValueTypeDto$1.EnumDto },
|
|
2436
|
-
{ text: 'TimeSpan', value: AttributeValueTypeDto$1.TimeSpanDto }
|
|
2437
|
-
];
|
|
2438
|
-
// Double-click tracking
|
|
2439
|
-
lastClickTime = 0;
|
|
2440
|
-
lastClickedItem = null;
|
|
2441
|
-
doubleClickDelay = 300; // milliseconds
|
|
2331
|
+
popupSettings = { appendTo: 'root', popupClass: 'mm-ck-type-popup' };
|
|
2332
|
+
static popupStyleInjected = false;
|
|
2333
|
+
ckTypeSelectorService = inject(CkTypeSelectorService);
|
|
2334
|
+
dialogService = inject(CkTypeSelectorDialogService, { optional: true });
|
|
2335
|
+
elementRef = inject(ElementRef);
|
|
2442
2336
|
ngOnInit() {
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2337
|
+
this.setupSearch();
|
|
2338
|
+
this.injectPopupStyles();
|
|
2339
|
+
}
|
|
2340
|
+
ngOnDestroy() {
|
|
2341
|
+
this.subscriptions.unsubscribe();
|
|
2342
|
+
this.searchSubject.complete();
|
|
2343
|
+
}
|
|
2344
|
+
// ControlValueAccessor implementation
|
|
2345
|
+
writeValue(value) {
|
|
2346
|
+
if (value !== this.selectedCkType) {
|
|
2347
|
+
this.selectedCkType = value;
|
|
2348
|
+
if (value) {
|
|
2349
|
+
// Ensure the value is in the data list so the autocomplete can display it
|
|
2350
|
+
if (!this.typeMap.has(value.rtCkTypeId)) {
|
|
2351
|
+
this.typeMap.set(value.rtCkTypeId, value);
|
|
2352
|
+
this.filteredTypes = [value.rtCkTypeId];
|
|
2456
2353
|
}
|
|
2354
|
+
this.searchFormControl.setValue(value.rtCkTypeId, { emitEvent: false });
|
|
2355
|
+
}
|
|
2356
|
+
else {
|
|
2357
|
+
this.searchFormControl.setValue('', { emitEvent: false });
|
|
2457
2358
|
}
|
|
2458
2359
|
}
|
|
2459
|
-
// Set up search debouncing
|
|
2460
|
-
this.searchSubject.pipe(debounceTime(300), distinctUntilChanged()).subscribe(searchText => {
|
|
2461
|
-
this.loadAvailableAttributes(searchText);
|
|
2462
|
-
});
|
|
2463
|
-
// Load initial attributes
|
|
2464
|
-
this.loadAvailableAttributes();
|
|
2465
|
-
}
|
|
2466
|
-
loadAvailableAttributes(searchTerm) {
|
|
2467
|
-
this.attributeService.getAvailableAttributes(this.rtCkTypeId, undefined, undefined, undefined, this.selectedValueTypeFilter || undefined, searchTerm || undefined, this.includeNavigationProperties, this.maxDepth ?? undefined).subscribe(result => {
|
|
2468
|
-
// Filter out already selected attributes
|
|
2469
|
-
const selectedPaths = new Set(this.selectedAttributes.map(a => a.attributePath));
|
|
2470
|
-
this.availableAttributes = result.items.filter(item => !selectedPaths.has(item.attributePath));
|
|
2471
|
-
this.updateAvailableGrid();
|
|
2472
|
-
});
|
|
2473
2360
|
}
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
this.attributeService.getAvailableAttributes(this.rtCkTypeId).subscribe(result => {
|
|
2477
|
-
// Create a map for quick lookup
|
|
2478
|
-
const attributeMap = new Map(result.items.map(item => [item.attributePath, item]));
|
|
2479
|
-
// Preserve the order from attributePaths
|
|
2480
|
-
this.selectedAttributes = attributePaths
|
|
2481
|
-
.map(path => attributeMap.get(path))
|
|
2482
|
-
.filter((item) => item !== undefined);
|
|
2483
|
-
this.updateSelectedGrid();
|
|
2484
|
-
// Filter out selected from available
|
|
2485
|
-
const selectedPaths = new Set(this.selectedAttributes.map(a => a.attributePath));
|
|
2486
|
-
this.availableAttributes = result.items.filter(item => !selectedPaths.has(item.attributePath));
|
|
2487
|
-
this.updateAvailableGrid();
|
|
2488
|
-
});
|
|
2361
|
+
registerOnChange(fn) {
|
|
2362
|
+
this.onChange = fn;
|
|
2489
2363
|
}
|
|
2490
|
-
|
|
2491
|
-
this.
|
|
2364
|
+
registerOnTouched(fn) {
|
|
2365
|
+
this.onTouched = fn;
|
|
2492
2366
|
}
|
|
2493
|
-
|
|
2494
|
-
this.
|
|
2367
|
+
setDisabledState(isDisabled) {
|
|
2368
|
+
this.disabled = isDisabled;
|
|
2495
2369
|
}
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2370
|
+
// Validator implementation
|
|
2371
|
+
validate(control) {
|
|
2372
|
+
if (this.required && !this.selectedCkType) {
|
|
2373
|
+
return { required: true };
|
|
2374
|
+
}
|
|
2375
|
+
const value = control.value;
|
|
2376
|
+
if (value && typeof value === 'string') {
|
|
2377
|
+
return { invalidCkType: true };
|
|
2378
|
+
}
|
|
2379
|
+
return null;
|
|
2505
2380
|
}
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
this.
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2381
|
+
// Event handlers
|
|
2382
|
+
onFilterChange(filter) {
|
|
2383
|
+
if (!filter || filter.length < this.minSearchLength) {
|
|
2384
|
+
this.filteredTypes = [];
|
|
2385
|
+
return;
|
|
2386
|
+
}
|
|
2387
|
+
this.searchSubject.next(filter);
|
|
2512
2388
|
}
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2389
|
+
onSelectionChange(value) {
|
|
2390
|
+
if (value && typeof value === 'string') {
|
|
2391
|
+
const ckType = this.typeMap.get(value);
|
|
2392
|
+
if (ckType) {
|
|
2393
|
+
this.selectCkType(ckType);
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2520
2396
|
}
|
|
2521
|
-
|
|
2522
|
-
this.
|
|
2523
|
-
this.
|
|
2524
|
-
|
|
2525
|
-
|
|
2397
|
+
onFocus() {
|
|
2398
|
+
const currentValue = this.searchFormControl.value;
|
|
2399
|
+
if (currentValue && currentValue.length >= this.minSearchLength && this.filteredTypes.length === 0) {
|
|
2400
|
+
this.searchSubject.next(currentValue);
|
|
2401
|
+
}
|
|
2526
2402
|
}
|
|
2527
|
-
|
|
2528
|
-
this.
|
|
2529
|
-
this.
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2403
|
+
onBlur() {
|
|
2404
|
+
this.onTouched();
|
|
2405
|
+
if (this.filteredTypes.length === 1 && !this.selectedCkType) {
|
|
2406
|
+
const displayText = this.filteredTypes[0];
|
|
2407
|
+
const ckType = this.typeMap.get(displayText);
|
|
2408
|
+
if (ckType) {
|
|
2409
|
+
this.selectCkType(ckType);
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2533
2412
|
}
|
|
2534
|
-
|
|
2535
|
-
|
|
2413
|
+
// Public methods
|
|
2414
|
+
clear() {
|
|
2415
|
+
this.selectedCkType = null;
|
|
2416
|
+
this.filteredTypes = [];
|
|
2417
|
+
this.typeMap.clear();
|
|
2418
|
+
this.searchFormControl.setValue('', { emitEvent: false });
|
|
2419
|
+
this.onChange(null);
|
|
2420
|
+
this.ckTypeCleared.emit();
|
|
2421
|
+
this.autocomplete.focus();
|
|
2536
2422
|
}
|
|
2537
|
-
|
|
2538
|
-
if (this.
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
return index > 0;
|
|
2423
|
+
focus() {
|
|
2424
|
+
if (this.autocomplete) {
|
|
2425
|
+
this.autocomplete.focus();
|
|
2426
|
+
}
|
|
2542
2427
|
}
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
return false;
|
|
2546
|
-
const index = this.selectedAttributes.findIndex(a => a.attributePath === this.selectedChosenKeys[0]);
|
|
2547
|
-
return index >= 0 && index < this.selectedAttributes.length - 1;
|
|
2428
|
+
reset() {
|
|
2429
|
+
this.clear();
|
|
2548
2430
|
}
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2431
|
+
// Private methods
|
|
2432
|
+
setupSearch() {
|
|
2433
|
+
this.subscriptions.add(this.searchSubject.pipe(debounceTime(this.debounceMs), distinctUntilChanged(), tap(() => {
|
|
2434
|
+
this.isLoading = true;
|
|
2435
|
+
this.filteredTypes = [];
|
|
2436
|
+
}), switchMap(filter => {
|
|
2437
|
+
const source$ = this.derivedFromRtCkTypeId
|
|
2438
|
+
? this.ckTypeSelectorService.getDerivedCkTypes(this.derivedFromRtCkTypeId, {
|
|
2439
|
+
searchText: filter
|
|
2440
|
+
})
|
|
2441
|
+
: this.ckTypeSelectorService.getCkTypes({
|
|
2442
|
+
ckModelIds: this.ckModelIds,
|
|
2443
|
+
searchText: filter,
|
|
2444
|
+
first: this.maxResults
|
|
2445
|
+
});
|
|
2446
|
+
return source$.pipe(catchError(error => {
|
|
2447
|
+
console.error('CK type search error:', error);
|
|
2448
|
+
return of({ items: [], totalCount: 0 });
|
|
2449
|
+
}));
|
|
2450
|
+
})).subscribe(result => {
|
|
2451
|
+
this.isLoading = false;
|
|
2452
|
+
// Filter out abstract types if not allowed
|
|
2453
|
+
let items = result.items;
|
|
2454
|
+
if (!this.allowAbstract) {
|
|
2455
|
+
items = items.filter(item => !item.isAbstract);
|
|
2456
|
+
}
|
|
2457
|
+
this.filteredTypes = items.map(item => item.rtCkTypeId);
|
|
2458
|
+
this.typeMap = new Map(items.map(item => [item.rtCkTypeId, item]));
|
|
2459
|
+
}));
|
|
2556
2460
|
}
|
|
2557
|
-
|
|
2558
|
-
if (
|
|
2461
|
+
injectPopupStyles() {
|
|
2462
|
+
if (CkTypeSelectorInputComponent.popupStyleInjected)
|
|
2559
2463
|
return;
|
|
2560
|
-
const
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
};
|
|
2580
|
-
}
|
|
2581
|
-
onCancel() {
|
|
2582
|
-
this.windowRef.close();
|
|
2464
|
+
const style = document.createElement('style');
|
|
2465
|
+
style.setAttribute('data-mm-ck-type-popup', '');
|
|
2466
|
+
style.textContent = `
|
|
2467
|
+
.mm-ck-type-popup {
|
|
2468
|
+
max-width: 500px !important;
|
|
2469
|
+
min-width: 0 !important;
|
|
2470
|
+
}
|
|
2471
|
+
.mm-ck-type-popup .k-child-animation-container {
|
|
2472
|
+
max-width: 500px !important;
|
|
2473
|
+
}
|
|
2474
|
+
.mm-ck-type-popup .k-list-item {
|
|
2475
|
+
padding: 4px 12px !important;
|
|
2476
|
+
min-height: 0 !important;
|
|
2477
|
+
font-size: 13px !important;
|
|
2478
|
+
line-height: 20px !important;
|
|
2479
|
+
}
|
|
2480
|
+
`;
|
|
2481
|
+
document.head.appendChild(style);
|
|
2482
|
+
CkTypeSelectorInputComponent.popupStyleInjected = true;
|
|
2583
2483
|
}
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
}
|
|
2592
|
-
else {
|
|
2593
|
-
const result = {
|
|
2594
|
-
selectedAttributes: this.selectedAttributes
|
|
2595
|
-
};
|
|
2596
|
-
this.windowRef.close(result);
|
|
2597
|
-
}
|
|
2484
|
+
selectCkType(ckType) {
|
|
2485
|
+
this.selectedCkType = ckType;
|
|
2486
|
+
this.searchFormControl.setValue(ckType.rtCkTypeId, { emitEvent: false });
|
|
2487
|
+
this.filteredTypes = [];
|
|
2488
|
+
this.onChange(ckType);
|
|
2489
|
+
this.ckTypeSelected.emit(ckType);
|
|
2490
|
+
this.autocomplete.toggle(false);
|
|
2598
2491
|
}
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
if (!dataItem)
|
|
2605
|
-
return;
|
|
2606
|
-
const currentTime = Date.now();
|
|
2607
|
-
const attributePath = dataItem.attributePath;
|
|
2608
|
-
if (this.lastClickedItem === attributePath &&
|
|
2609
|
-
currentTime - this.lastClickTime <= this.doubleClickDelay) {
|
|
2610
|
-
// Double-click detected - move attribute to selected
|
|
2611
|
-
this.moveAttributeToSelected(dataItem);
|
|
2612
|
-
// Reset to prevent triple-click
|
|
2613
|
-
this.lastClickTime = 0;
|
|
2614
|
-
this.lastClickedItem = null;
|
|
2615
|
-
}
|
|
2616
|
-
else {
|
|
2617
|
-
// Single click - just update tracking
|
|
2618
|
-
this.lastClickTime = currentTime;
|
|
2619
|
-
this.lastClickedItem = attributePath;
|
|
2492
|
+
// Dialog
|
|
2493
|
+
async openDialog(event) {
|
|
2494
|
+
if (event) {
|
|
2495
|
+
event.preventDefault();
|
|
2496
|
+
event.stopPropagation();
|
|
2620
2497
|
}
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
* Handle cell click on selected attributes grid to detect double-click
|
|
2624
|
-
*/
|
|
2625
|
-
onSelectedCellClick(event) {
|
|
2626
|
-
const dataItem = event.dataItem;
|
|
2627
|
-
if (!dataItem)
|
|
2498
|
+
if (!this.dialogService) {
|
|
2499
|
+
console.warn('CkTypeSelectorDialogService not available');
|
|
2628
2500
|
return;
|
|
2629
|
-
const currentTime = Date.now();
|
|
2630
|
-
const attributePath = dataItem.attributePath;
|
|
2631
|
-
if (this.lastClickedItem === attributePath &&
|
|
2632
|
-
currentTime - this.lastClickTime <= this.doubleClickDelay) {
|
|
2633
|
-
// Double-click detected - move attribute to available
|
|
2634
|
-
this.moveAttributeToAvailable(dataItem);
|
|
2635
|
-
// Reset to prevent triple-click
|
|
2636
|
-
this.lastClickTime = 0;
|
|
2637
|
-
this.lastClickedItem = null;
|
|
2638
2501
|
}
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
this.
|
|
2642
|
-
this.
|
|
2502
|
+
this.autocomplete.toggle(false);
|
|
2503
|
+
const result = await this.dialogService.openCkTypeSelector({
|
|
2504
|
+
selectedCkTypeId: this.selectedCkType?.fullName,
|
|
2505
|
+
ckModelIds: this.ckModelIds,
|
|
2506
|
+
dialogTitle: this.dialogTitle,
|
|
2507
|
+
allowAbstract: this.allowAbstract,
|
|
2508
|
+
derivedFromRtCkTypeId: this.derivedFromRtCkTypeId
|
|
2509
|
+
});
|
|
2510
|
+
if (result.confirmed && result.selectedCkType) {
|
|
2511
|
+
this.selectCkType(result.selectedCkType);
|
|
2643
2512
|
}
|
|
2644
2513
|
}
|
|
2645
|
-
|
|
2514
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CkTypeSelectorInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2515
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.0", type: CkTypeSelectorInputComponent, isStandalone: true, selector: "mm-ck-type-selector-input", inputs: { placeholder: "placeholder", minSearchLength: "minSearchLength", maxResults: "maxResults", debounceMs: "debounceMs", ckModelIds: "ckModelIds", allowAbstract: "allowAbstract", dialogTitle: "dialogTitle", advancedSearchLabel: "advancedSearchLabel", derivedFromRtCkTypeId: "derivedFromRtCkTypeId", disabled: "disabled", required: "required" }, outputs: { ckTypeSelected: "ckTypeSelected", ckTypeCleared: "ckTypeCleared" }, providers: [
|
|
2516
|
+
{
|
|
2517
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2518
|
+
useExisting: forwardRef(() => CkTypeSelectorInputComponent),
|
|
2519
|
+
multi: true
|
|
2520
|
+
},
|
|
2521
|
+
{
|
|
2522
|
+
provide: NG_VALIDATORS,
|
|
2523
|
+
useExisting: forwardRef(() => CkTypeSelectorInputComponent),
|
|
2524
|
+
multi: true
|
|
2525
|
+
}
|
|
2526
|
+
], viewQueries: [{ propertyName: "autocomplete", first: true, predicate: ["autocomplete"], descendants: true, static: true }], ngImport: i0, template: `
|
|
2527
|
+
<div class="ck-type-select-wrapper" [class.disabled]="disabled">
|
|
2528
|
+
<kendo-autocomplete
|
|
2529
|
+
#autocomplete
|
|
2530
|
+
[formControl]="searchFormControl"
|
|
2531
|
+
[data]="filteredTypes"
|
|
2532
|
+
[loading]="isLoading"
|
|
2533
|
+
[placeholder]="placeholder"
|
|
2534
|
+
[suggest]="true"
|
|
2535
|
+
[clearButton]="true"
|
|
2536
|
+
[filterable]="true"
|
|
2537
|
+
[popupSettings]="popupSettings"
|
|
2538
|
+
(filterChange)="onFilterChange($event)"
|
|
2539
|
+
(valueChange)="onSelectionChange($event)"
|
|
2540
|
+
(blur)="onBlur()"
|
|
2541
|
+
(focus)="onFocus()"
|
|
2542
|
+
class="ck-type-autocomplete">
|
|
2543
|
+
|
|
2544
|
+
<ng-template kendoAutoCompleteItemTemplate let-dataItem>
|
|
2545
|
+
<div class="ck-type-item">
|
|
2546
|
+
{{ dataItem }}
|
|
2547
|
+
</div>
|
|
2548
|
+
</ng-template>
|
|
2549
|
+
|
|
2550
|
+
<ng-template kendoAutoCompleteNoDataTemplate>
|
|
2551
|
+
<div class="no-data-message">
|
|
2552
|
+
<span *ngIf="!isLoading && searchFormControl.value && searchFormControl.value.length >= minSearchLength">
|
|
2553
|
+
No types found for "{{ searchFormControl.value }}"
|
|
2554
|
+
</span>
|
|
2555
|
+
<span *ngIf="!isLoading && (!searchFormControl.value || searchFormControl.value.length < minSearchLength)">
|
|
2556
|
+
Type at least {{ minSearchLength }} characters to search...
|
|
2557
|
+
</span>
|
|
2558
|
+
</div>
|
|
2559
|
+
</ng-template>
|
|
2560
|
+
|
|
2561
|
+
<ng-template kendoAutoCompleteFooterTemplate>
|
|
2562
|
+
<div class="advanced-search-footer" (click)="openDialog($event)">
|
|
2563
|
+
<kendo-svg-icon [icon]="searchIcon" size="small"></kendo-svg-icon>
|
|
2564
|
+
<span>{{ advancedSearchLabel }}</span>
|
|
2565
|
+
</div>
|
|
2566
|
+
</ng-template>
|
|
2567
|
+
|
|
2568
|
+
</kendo-autocomplete>
|
|
2569
|
+
|
|
2570
|
+
<button
|
|
2571
|
+
kendoButton
|
|
2572
|
+
type="button"
|
|
2573
|
+
[svgIcon]="searchIcon"
|
|
2574
|
+
[disabled]="disabled"
|
|
2575
|
+
[title]="advancedSearchLabel"
|
|
2576
|
+
class="dialog-button"
|
|
2577
|
+
(click)="openDialog()">
|
|
2578
|
+
</button>
|
|
2579
|
+
</div>
|
|
2580
|
+
`, isInline: true, styles: [":host{display:block;width:100%}.ck-type-select-wrapper{position:relative;display:flex;align-items:center;width:100%;gap:4px}.ck-type-select-wrapper.disabled{opacity:.6;pointer-events:none}.ck-type-autocomplete{flex:1;min-width:0}.dialog-button{flex-shrink:0;height:30px;width:30px;padding:0;display:flex;align-items:center;justify-content:center}.ck-type-item{padding:4px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.no-data-message{padding:8px 12px;color:var(--kendo-color-subtle);font-style:italic;text-align:center}.advanced-search-footer{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;color:var(--kendo-color-primary);border-top:1px solid var(--kendo-color-border);background:var(--kendo-color-surface-alt);transition:background-color .2s}.advanced-search-footer:hover{background:var(--kendo-color-base-hover)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: AutoCompleteModule }, { kind: "component", type: i3$1.AutoCompleteComponent, selector: "kendo-autocomplete", inputs: ["highlightFirst", "showStickyHeader", "focusableId", "data", "value", "valueField", "placeholder", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "loading", "clearButton", "suggest", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoAutoComplete"] }, { kind: "directive", type: i3$1.FooterTemplateDirective, selector: "[kendoDropDownListFooterTemplate],[kendoComboBoxFooterTemplate],[kendoDropDownTreeFooterTemplate],[kendoMultiColumnComboBoxFooterTemplate],[kendoAutoCompleteFooterTemplate],[kendoMultiSelectFooterTemplate],[kendoMultiSelectTreeFooterTemplate]" }, { kind: "directive", type: i3$1.ItemTemplateDirective, selector: "[kendoDropDownListItemTemplate],[kendoComboBoxItemTemplate],[kendoAutoCompleteItemTemplate],[kendoMultiSelectItemTemplate]" }, { kind: "directive", type: i3$1.NoDataTemplateDirective, selector: "[kendoDropDownListNoDataTemplate],[kendoDropDownTreeNoDataTemplate],[kendoComboBoxNoDataTemplate],[kendoMultiColumnComboBoxNoDataTemplate],[kendoAutoCompleteNoDataTemplate],[kendoMultiSelectNoDataTemplate],[kendoMultiSelectTreeNoDataTemplate]" }, { kind: "ngmodule", type: LoaderModule }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i4.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "ngmodule", type: IconsModule }, { kind: "component", type: i5$1.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon"], exportAs: ["kendoSVGIcon"] }, { kind: "ngmodule", type: SVGIconModule }] });
|
|
2581
|
+
}
|
|
2582
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CkTypeSelectorInputComponent, decorators: [{
|
|
2583
|
+
type: Component,
|
|
2584
|
+
args: [{ selector: 'mm-ck-type-selector-input', standalone: true, imports: [
|
|
2585
|
+
CommonModule,
|
|
2586
|
+
ReactiveFormsModule,
|
|
2587
|
+
AutoCompleteModule,
|
|
2588
|
+
LoaderModule,
|
|
2589
|
+
ButtonsModule,
|
|
2590
|
+
IconsModule,
|
|
2591
|
+
SVGIconModule
|
|
2592
|
+
], providers: [
|
|
2593
|
+
{
|
|
2594
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2595
|
+
useExisting: forwardRef(() => CkTypeSelectorInputComponent),
|
|
2596
|
+
multi: true
|
|
2597
|
+
},
|
|
2598
|
+
{
|
|
2599
|
+
provide: NG_VALIDATORS,
|
|
2600
|
+
useExisting: forwardRef(() => CkTypeSelectorInputComponent),
|
|
2601
|
+
multi: true
|
|
2602
|
+
}
|
|
2603
|
+
], template: `
|
|
2604
|
+
<div class="ck-type-select-wrapper" [class.disabled]="disabled">
|
|
2605
|
+
<kendo-autocomplete
|
|
2606
|
+
#autocomplete
|
|
2607
|
+
[formControl]="searchFormControl"
|
|
2608
|
+
[data]="filteredTypes"
|
|
2609
|
+
[loading]="isLoading"
|
|
2610
|
+
[placeholder]="placeholder"
|
|
2611
|
+
[suggest]="true"
|
|
2612
|
+
[clearButton]="true"
|
|
2613
|
+
[filterable]="true"
|
|
2614
|
+
[popupSettings]="popupSettings"
|
|
2615
|
+
(filterChange)="onFilterChange($event)"
|
|
2616
|
+
(valueChange)="onSelectionChange($event)"
|
|
2617
|
+
(blur)="onBlur()"
|
|
2618
|
+
(focus)="onFocus()"
|
|
2619
|
+
class="ck-type-autocomplete">
|
|
2620
|
+
|
|
2621
|
+
<ng-template kendoAutoCompleteItemTemplate let-dataItem>
|
|
2622
|
+
<div class="ck-type-item">
|
|
2623
|
+
{{ dataItem }}
|
|
2624
|
+
</div>
|
|
2625
|
+
</ng-template>
|
|
2626
|
+
|
|
2627
|
+
<ng-template kendoAutoCompleteNoDataTemplate>
|
|
2628
|
+
<div class="no-data-message">
|
|
2629
|
+
<span *ngIf="!isLoading && searchFormControl.value && searchFormControl.value.length >= minSearchLength">
|
|
2630
|
+
No types found for "{{ searchFormControl.value }}"
|
|
2631
|
+
</span>
|
|
2632
|
+
<span *ngIf="!isLoading && (!searchFormControl.value || searchFormControl.value.length < minSearchLength)">
|
|
2633
|
+
Type at least {{ minSearchLength }} characters to search...
|
|
2634
|
+
</span>
|
|
2635
|
+
</div>
|
|
2636
|
+
</ng-template>
|
|
2637
|
+
|
|
2638
|
+
<ng-template kendoAutoCompleteFooterTemplate>
|
|
2639
|
+
<div class="advanced-search-footer" (click)="openDialog($event)">
|
|
2640
|
+
<kendo-svg-icon [icon]="searchIcon" size="small"></kendo-svg-icon>
|
|
2641
|
+
<span>{{ advancedSearchLabel }}</span>
|
|
2642
|
+
</div>
|
|
2643
|
+
</ng-template>
|
|
2644
|
+
|
|
2645
|
+
</kendo-autocomplete>
|
|
2646
|
+
|
|
2647
|
+
<button
|
|
2648
|
+
kendoButton
|
|
2649
|
+
type="button"
|
|
2650
|
+
[svgIcon]="searchIcon"
|
|
2651
|
+
[disabled]="disabled"
|
|
2652
|
+
[title]="advancedSearchLabel"
|
|
2653
|
+
class="dialog-button"
|
|
2654
|
+
(click)="openDialog()">
|
|
2655
|
+
</button>
|
|
2656
|
+
</div>
|
|
2657
|
+
`, styles: [":host{display:block;width:100%}.ck-type-select-wrapper{position:relative;display:flex;align-items:center;width:100%;gap:4px}.ck-type-select-wrapper.disabled{opacity:.6;pointer-events:none}.ck-type-autocomplete{flex:1;min-width:0}.dialog-button{flex-shrink:0;height:30px;width:30px;padding:0;display:flex;align-items:center;justify-content:center}.ck-type-item{padding:4px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.no-data-message{padding:8px 12px;color:var(--kendo-color-subtle);font-style:italic;text-align:center}.advanced-search-footer{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;color:var(--kendo-color-primary);border-top:1px solid var(--kendo-color-border);background:var(--kendo-color-surface-alt);transition:background-color .2s}.advanced-search-footer:hover{background:var(--kendo-color-base-hover)}\n"] }]
|
|
2658
|
+
}], propDecorators: { autocomplete: [{
|
|
2659
|
+
type: ViewChild,
|
|
2660
|
+
args: ['autocomplete', { static: true }]
|
|
2661
|
+
}], placeholder: [{
|
|
2662
|
+
type: Input
|
|
2663
|
+
}], minSearchLength: [{
|
|
2664
|
+
type: Input
|
|
2665
|
+
}], maxResults: [{
|
|
2666
|
+
type: Input
|
|
2667
|
+
}], debounceMs: [{
|
|
2668
|
+
type: Input
|
|
2669
|
+
}], ckModelIds: [{
|
|
2670
|
+
type: Input
|
|
2671
|
+
}], allowAbstract: [{
|
|
2672
|
+
type: Input
|
|
2673
|
+
}], dialogTitle: [{
|
|
2674
|
+
type: Input
|
|
2675
|
+
}], advancedSearchLabel: [{
|
|
2676
|
+
type: Input
|
|
2677
|
+
}], derivedFromRtCkTypeId: [{
|
|
2678
|
+
type: Input
|
|
2679
|
+
}], disabled: [{
|
|
2680
|
+
type: Input
|
|
2681
|
+
}], required: [{
|
|
2682
|
+
type: Input
|
|
2683
|
+
}], ckTypeSelected: [{
|
|
2684
|
+
type: Output
|
|
2685
|
+
}], ckTypeCleared: [{
|
|
2686
|
+
type: Output
|
|
2687
|
+
}] } });
|
|
2688
|
+
|
|
2689
|
+
class AttributeSelectorDialogComponent {
|
|
2690
|
+
windowRef = inject(WindowRef);
|
|
2691
|
+
attributeService = inject(AttributeSelectorService);
|
|
2692
|
+
searchSubject = new Subject();
|
|
2693
|
+
arrowRightIcon = arrowRightIcon;
|
|
2694
|
+
arrowLeftIcon = arrowLeftIcon;
|
|
2695
|
+
chevronDoubleRightIcon = chevronDoubleRightIcon;
|
|
2696
|
+
chevronDoubleLeftIcon = chevronDoubleLeftIcon;
|
|
2697
|
+
searchIcon = searchIcon;
|
|
2698
|
+
arrowUpIcon = arrowUpIcon;
|
|
2699
|
+
arrowDownIcon = arrowDownIcon;
|
|
2700
|
+
data;
|
|
2701
|
+
dialogTitle = 'Select Attributes';
|
|
2702
|
+
rtCkTypeId;
|
|
2703
|
+
singleSelect = false;
|
|
2704
|
+
searchText = '';
|
|
2705
|
+
selectedSingleKey = [];
|
|
2706
|
+
selectedValueTypeFilter = null;
|
|
2707
|
+
includeNavigationProperties = true;
|
|
2708
|
+
maxDepth = null;
|
|
2709
|
+
availableAttributes = [];
|
|
2710
|
+
selectedAttributes = [];
|
|
2711
|
+
availableGridData = { data: [], total: 0 };
|
|
2712
|
+
selectedGridData = { data: [], total: 0 };
|
|
2713
|
+
selectedAvailableKeys = [];
|
|
2714
|
+
selectedChosenKeys = [];
|
|
2715
|
+
valueTypeOptions = [
|
|
2716
|
+
{ text: 'All Types', value: null },
|
|
2717
|
+
{ text: 'String', value: AttributeValueTypeDto$1.StringDto },
|
|
2718
|
+
{ text: 'Integer', value: AttributeValueTypeDto$1.IntegerDto },
|
|
2719
|
+
{ text: 'Double', value: AttributeValueTypeDto$1.DoubleDto },
|
|
2720
|
+
{ text: 'Boolean', value: AttributeValueTypeDto$1.BooleanDto },
|
|
2721
|
+
{ text: 'DateTime', value: AttributeValueTypeDto$1.DateTimeDto },
|
|
2722
|
+
{ text: 'DateTimeOffset', value: AttributeValueTypeDto$1.DateTimeOffsetDto },
|
|
2723
|
+
{ text: 'Enum', value: AttributeValueTypeDto$1.EnumDto },
|
|
2724
|
+
{ text: 'TimeSpan', value: AttributeValueTypeDto$1.TimeSpanDto }
|
|
2725
|
+
];
|
|
2726
|
+
// Double-click tracking
|
|
2727
|
+
lastClickTime = 0;
|
|
2728
|
+
lastClickedItem = null;
|
|
2729
|
+
doubleClickDelay = 300; // milliseconds
|
|
2730
|
+
ngOnInit() {
|
|
2731
|
+
if (this.data) {
|
|
2732
|
+
this.rtCkTypeId = this.data.rtCkTypeId;
|
|
2733
|
+
this.dialogTitle = this.data.dialogTitle || 'Select Attributes';
|
|
2734
|
+
this.singleSelect = this.data.singleSelect ?? false;
|
|
2735
|
+
this.includeNavigationProperties = this.data.includeNavigationProperties ?? true;
|
|
2736
|
+
this.maxDepth = this.data.maxDepth ?? null;
|
|
2737
|
+
if (this.data.selectedAttributes && this.data.selectedAttributes.length > 0) {
|
|
2738
|
+
if (this.singleSelect) {
|
|
2739
|
+
this.selectedSingleKey = [this.data.selectedAttributes[0]];
|
|
2740
|
+
}
|
|
2741
|
+
else {
|
|
2742
|
+
// Pre-populate selected attributes if provided
|
|
2743
|
+
this.loadInitialSelectedAttributes(this.data.selectedAttributes);
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
// Set up search debouncing
|
|
2748
|
+
this.searchSubject.pipe(debounceTime(300), distinctUntilChanged()).subscribe(searchText => {
|
|
2749
|
+
this.loadAvailableAttributes(searchText);
|
|
2750
|
+
});
|
|
2751
|
+
// Load initial attributes
|
|
2752
|
+
this.loadAvailableAttributes();
|
|
2753
|
+
}
|
|
2754
|
+
loadAvailableAttributes(searchTerm) {
|
|
2755
|
+
this.attributeService.getAvailableAttributes(this.rtCkTypeId, undefined, undefined, undefined, this.selectedValueTypeFilter || undefined, searchTerm || undefined, this.includeNavigationProperties, this.maxDepth ?? undefined).subscribe(result => {
|
|
2756
|
+
// Filter out already selected attributes
|
|
2757
|
+
const selectedPaths = new Set(this.selectedAttributes.map(a => a.attributePath));
|
|
2758
|
+
this.availableAttributes = result.items.filter(item => !selectedPaths.has(item.attributePath));
|
|
2759
|
+
this.updateAvailableGrid();
|
|
2760
|
+
});
|
|
2761
|
+
}
|
|
2762
|
+
loadInitialSelectedAttributes(attributePaths) {
|
|
2763
|
+
// Load all attributes to get the details for selected ones
|
|
2764
|
+
this.attributeService.getAvailableAttributes(this.rtCkTypeId).subscribe(result => {
|
|
2765
|
+
// Create a map for quick lookup
|
|
2766
|
+
const attributeMap = new Map(result.items.map(item => [item.attributePath, item]));
|
|
2767
|
+
// Preserve the order from attributePaths
|
|
2768
|
+
this.selectedAttributes = attributePaths
|
|
2769
|
+
.map(path => attributeMap.get(path))
|
|
2770
|
+
.filter((item) => item !== undefined);
|
|
2771
|
+
this.updateSelectedGrid();
|
|
2772
|
+
// Filter out selected from available
|
|
2773
|
+
const selectedPaths = new Set(this.selectedAttributes.map(a => a.attributePath));
|
|
2774
|
+
this.availableAttributes = result.items.filter(item => !selectedPaths.has(item.attributePath));
|
|
2775
|
+
this.updateAvailableGrid();
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
onSearchChange(value) {
|
|
2779
|
+
this.searchSubject.next(value);
|
|
2780
|
+
}
|
|
2781
|
+
onValueTypeFilterChange(_value) {
|
|
2782
|
+
this.loadAvailableAttributes(this.searchText || undefined);
|
|
2783
|
+
}
|
|
2784
|
+
onNavigationPropertiesChange() {
|
|
2785
|
+
if (!this.includeNavigationProperties) {
|
|
2786
|
+
this.maxDepth = null;
|
|
2787
|
+
}
|
|
2788
|
+
this.loadAvailableAttributes(this.searchText || undefined);
|
|
2789
|
+
}
|
|
2790
|
+
onMaxDepthChange(value) {
|
|
2791
|
+
this.maxDepth = value;
|
|
2792
|
+
this.loadAvailableAttributes(this.searchText || undefined);
|
|
2793
|
+
}
|
|
2794
|
+
addSelected() {
|
|
2795
|
+
const itemsToAdd = this.availableAttributes.filter(item => this.selectedAvailableKeys.includes(item.attributePath));
|
|
2796
|
+
this.selectedAttributes.push(...itemsToAdd);
|
|
2797
|
+
this.availableAttributes = this.availableAttributes.filter(item => !this.selectedAvailableKeys.includes(item.attributePath));
|
|
2798
|
+
this.selectedAvailableKeys = [];
|
|
2799
|
+
this.updateGrids();
|
|
2800
|
+
}
|
|
2801
|
+
removeSelected() {
|
|
2802
|
+
const itemsToRemove = this.selectedAttributes.filter(item => this.selectedChosenKeys.includes(item.attributePath));
|
|
2803
|
+
this.availableAttributes.push(...itemsToRemove);
|
|
2804
|
+
this.selectedAttributes = this.selectedAttributes.filter(item => !this.selectedChosenKeys.includes(item.attributePath));
|
|
2805
|
+
this.selectedChosenKeys = [];
|
|
2806
|
+
this.sortAvailableAttributes();
|
|
2807
|
+
this.updateGrids();
|
|
2808
|
+
}
|
|
2809
|
+
addAll() {
|
|
2810
|
+
this.selectedAttributes.push(...this.availableAttributes);
|
|
2811
|
+
this.availableAttributes = [];
|
|
2812
|
+
this.selectedAvailableKeys = [];
|
|
2813
|
+
this.updateGrids();
|
|
2814
|
+
}
|
|
2815
|
+
removeAll() {
|
|
2816
|
+
this.availableAttributes.push(...this.selectedAttributes);
|
|
2817
|
+
this.selectedAttributes = [];
|
|
2818
|
+
this.selectedChosenKeys = [];
|
|
2819
|
+
this.sortAvailableAttributes();
|
|
2820
|
+
this.updateGrids();
|
|
2821
|
+
}
|
|
2822
|
+
sortAvailableAttributes() {
|
|
2823
|
+
this.availableAttributes.sort((a, b) => a.attributePath.localeCompare(b.attributePath));
|
|
2824
|
+
}
|
|
2825
|
+
canMoveUp() {
|
|
2826
|
+
if (this.selectedChosenKeys.length !== 1)
|
|
2827
|
+
return false;
|
|
2828
|
+
const index = this.selectedAttributes.findIndex(a => a.attributePath === this.selectedChosenKeys[0]);
|
|
2829
|
+
return index > 0;
|
|
2830
|
+
}
|
|
2831
|
+
canMoveDown() {
|
|
2832
|
+
if (this.selectedChosenKeys.length !== 1)
|
|
2833
|
+
return false;
|
|
2834
|
+
const index = this.selectedAttributes.findIndex(a => a.attributePath === this.selectedChosenKeys[0]);
|
|
2835
|
+
return index >= 0 && index < this.selectedAttributes.length - 1;
|
|
2836
|
+
}
|
|
2837
|
+
moveUp() {
|
|
2838
|
+
if (!this.canMoveUp())
|
|
2839
|
+
return;
|
|
2840
|
+
const index = this.selectedAttributes.findIndex(a => a.attributePath === this.selectedChosenKeys[0]);
|
|
2841
|
+
[this.selectedAttributes[index - 1], this.selectedAttributes[index]] =
|
|
2842
|
+
[this.selectedAttributes[index], this.selectedAttributes[index - 1]];
|
|
2843
|
+
this.updateSelectedGrid();
|
|
2844
|
+
}
|
|
2845
|
+
moveDown() {
|
|
2846
|
+
if (!this.canMoveDown())
|
|
2847
|
+
return;
|
|
2848
|
+
const index = this.selectedAttributes.findIndex(a => a.attributePath === this.selectedChosenKeys[0]);
|
|
2849
|
+
[this.selectedAttributes[index], this.selectedAttributes[index + 1]] =
|
|
2850
|
+
[this.selectedAttributes[index + 1], this.selectedAttributes[index]];
|
|
2851
|
+
this.updateSelectedGrid();
|
|
2852
|
+
}
|
|
2853
|
+
updateGrids() {
|
|
2854
|
+
this.updateAvailableGrid();
|
|
2855
|
+
this.updateSelectedGrid();
|
|
2856
|
+
}
|
|
2857
|
+
updateAvailableGrid() {
|
|
2858
|
+
this.availableGridData = {
|
|
2859
|
+
data: this.availableAttributes,
|
|
2860
|
+
total: this.availableAttributes.length
|
|
2861
|
+
};
|
|
2862
|
+
}
|
|
2863
|
+
updateSelectedGrid() {
|
|
2864
|
+
this.selectedGridData = {
|
|
2865
|
+
data: this.selectedAttributes,
|
|
2866
|
+
total: this.selectedAttributes.length
|
|
2867
|
+
};
|
|
2868
|
+
}
|
|
2869
|
+
onCancel() {
|
|
2870
|
+
this.windowRef.close();
|
|
2871
|
+
}
|
|
2872
|
+
onConfirm() {
|
|
2873
|
+
if (this.singleSelect) {
|
|
2874
|
+
const selected = this.availableAttributes.find(a => a.attributePath === this.selectedSingleKey[0]);
|
|
2875
|
+
const result = {
|
|
2876
|
+
selectedAttributes: selected ? [selected] : []
|
|
2877
|
+
};
|
|
2878
|
+
this.windowRef.close(result);
|
|
2879
|
+
}
|
|
2880
|
+
else {
|
|
2881
|
+
const result = {
|
|
2882
|
+
selectedAttributes: this.selectedAttributes
|
|
2883
|
+
};
|
|
2884
|
+
this.windowRef.close(result);
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2887
|
+
/**
|
|
2888
|
+
* Handle cell click on available attributes grid to detect double-click
|
|
2889
|
+
*/
|
|
2890
|
+
onAvailableCellClick(event) {
|
|
2891
|
+
const dataItem = event.dataItem;
|
|
2892
|
+
if (!dataItem)
|
|
2893
|
+
return;
|
|
2894
|
+
const currentTime = Date.now();
|
|
2895
|
+
const attributePath = dataItem.attributePath;
|
|
2896
|
+
if (this.lastClickedItem === attributePath &&
|
|
2897
|
+
currentTime - this.lastClickTime <= this.doubleClickDelay) {
|
|
2898
|
+
// Double-click detected - move attribute to selected
|
|
2899
|
+
this.moveAttributeToSelected(dataItem);
|
|
2900
|
+
// Reset to prevent triple-click
|
|
2901
|
+
this.lastClickTime = 0;
|
|
2902
|
+
this.lastClickedItem = null;
|
|
2903
|
+
}
|
|
2904
|
+
else {
|
|
2905
|
+
// Single click - just update tracking
|
|
2906
|
+
this.lastClickTime = currentTime;
|
|
2907
|
+
this.lastClickedItem = attributePath;
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2910
|
+
/**
|
|
2911
|
+
* Handle cell click on selected attributes grid to detect double-click
|
|
2912
|
+
*/
|
|
2913
|
+
onSelectedCellClick(event) {
|
|
2914
|
+
const dataItem = event.dataItem;
|
|
2915
|
+
if (!dataItem)
|
|
2916
|
+
return;
|
|
2917
|
+
const currentTime = Date.now();
|
|
2918
|
+
const attributePath = dataItem.attributePath;
|
|
2919
|
+
if (this.lastClickedItem === attributePath &&
|
|
2920
|
+
currentTime - this.lastClickTime <= this.doubleClickDelay) {
|
|
2921
|
+
// Double-click detected - move attribute to available
|
|
2922
|
+
this.moveAttributeToAvailable(dataItem);
|
|
2923
|
+
// Reset to prevent triple-click
|
|
2924
|
+
this.lastClickTime = 0;
|
|
2925
|
+
this.lastClickedItem = null;
|
|
2926
|
+
}
|
|
2927
|
+
else {
|
|
2928
|
+
// Single click - just update tracking
|
|
2929
|
+
this.lastClickTime = currentTime;
|
|
2930
|
+
this.lastClickedItem = attributePath;
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
/**
|
|
2646
2934
|
* Handle cell click on single-select grid to detect double-click (confirm immediately)
|
|
2647
2935
|
*/
|
|
2648
2936
|
onSingleSelectCellClick(event) {
|
|
@@ -3011,6 +3299,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
3011
3299
|
|
|
3012
3300
|
class AttributeSelectorDialogService {
|
|
3013
3301
|
windowService = inject(WindowService);
|
|
3302
|
+
windowStateService = inject(WindowStateService);
|
|
3014
3303
|
/**
|
|
3015
3304
|
* Opens the attribute selector dialog
|
|
3016
3305
|
* @param rtCkTypeId The RtCkType ID to fetch attributes for
|
|
@@ -3026,455 +3315,540 @@ class AttributeSelectorDialogService {
|
|
|
3026
3315
|
dialogTitle,
|
|
3027
3316
|
singleSelect
|
|
3028
3317
|
};
|
|
3318
|
+
const dialogKey = singleSelect ? 'attribute-selector-single' : 'attribute-selector';
|
|
3319
|
+
const defaultWidth = singleSelect ? 550 : 1000;
|
|
3320
|
+
const defaultHeight = singleSelect ? 650 : 700;
|
|
3321
|
+
const size = this.windowStateService.resolveWindowSize(dialogKey, { width: defaultWidth, height: defaultHeight });
|
|
3029
3322
|
const windowRef = this.windowService.open({
|
|
3030
3323
|
content: AttributeSelectorDialogComponent,
|
|
3031
|
-
width:
|
|
3032
|
-
height:
|
|
3324
|
+
width: size.width,
|
|
3325
|
+
height: size.height,
|
|
3033
3326
|
minWidth: singleSelect ? 450 : 850,
|
|
3034
3327
|
minHeight: singleSelect ? 550 : 650,
|
|
3035
3328
|
resizable: true,
|
|
3036
3329
|
title: dialogTitle || 'Select Attributes'
|
|
3037
3330
|
});
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
try {
|
|
3044
|
-
const result = await firstValueFrom(windowRef.result);
|
|
3045
|
-
if (result instanceof WindowCloseResult) {
|
|
3046
|
-
// User closed the window via X button
|
|
3047
|
-
return {
|
|
3048
|
-
confirmed: false,
|
|
3049
|
-
selectedAttributes: []
|
|
3050
|
-
};
|
|
3051
|
-
}
|
|
3052
|
-
if (result && typeof result === 'object' && 'selectedAttributes' in result) {
|
|
3053
|
-
// User clicked OK and we have a result
|
|
3054
|
-
const dialogResult = result;
|
|
3055
|
-
return {
|
|
3056
|
-
confirmed: true,
|
|
3057
|
-
selectedAttributes: dialogResult.selectedAttributes
|
|
3058
|
-
};
|
|
3059
|
-
}
|
|
3060
|
-
else {
|
|
3061
|
-
// User clicked Cancel or closed dialog
|
|
3062
|
-
return {
|
|
3063
|
-
confirmed: false,
|
|
3064
|
-
selectedAttributes: []
|
|
3065
|
-
};
|
|
3066
|
-
}
|
|
3067
|
-
}
|
|
3068
|
-
catch {
|
|
3069
|
-
// Dialog was closed without result (e.g., ESC key, X button)
|
|
3070
|
-
return {
|
|
3071
|
-
confirmed: false,
|
|
3072
|
-
selectedAttributes: []
|
|
3073
|
-
};
|
|
3074
|
-
}
|
|
3075
|
-
}
|
|
3076
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AttributeSelectorDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3077
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AttributeSelectorDialogService });
|
|
3078
|
-
}
|
|
3079
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AttributeSelectorDialogService, decorators: [{
|
|
3080
|
-
type: Injectable
|
|
3081
|
-
}] });
|
|
3082
|
-
|
|
3083
|
-
class CkTypeSelectorInputComponent {
|
|
3084
|
-
autocomplete;
|
|
3085
|
-
placeholder = 'Select a CK type...';
|
|
3086
|
-
minSearchLength = 2;
|
|
3087
|
-
maxResults = 50;
|
|
3088
|
-
debounceMs = 300;
|
|
3089
|
-
ckModelIds;
|
|
3090
|
-
allowAbstract = false;
|
|
3091
|
-
dialogTitle = 'Select Construction Kit Type';
|
|
3092
|
-
advancedSearchLabel = 'Advanced Search...';
|
|
3093
|
-
derivedFromRtCkTypeId;
|
|
3094
|
-
_disabled = false;
|
|
3095
|
-
get disabled() {
|
|
3096
|
-
return this._disabled;
|
|
3097
|
-
}
|
|
3098
|
-
set disabled(value) {
|
|
3099
|
-
this._disabled = !!value;
|
|
3100
|
-
if (this._disabled) {
|
|
3101
|
-
this.searchFormControl.disable();
|
|
3102
|
-
}
|
|
3103
|
-
else {
|
|
3104
|
-
this.searchFormControl.enable();
|
|
3105
|
-
}
|
|
3106
|
-
}
|
|
3107
|
-
_required = false;
|
|
3108
|
-
get required() {
|
|
3109
|
-
return this._required;
|
|
3110
|
-
}
|
|
3111
|
-
set required(value) {
|
|
3112
|
-
this._required = !!value;
|
|
3113
|
-
}
|
|
3114
|
-
ckTypeSelected = new EventEmitter();
|
|
3115
|
-
ckTypeCleared = new EventEmitter();
|
|
3116
|
-
searchFormControl = new FormControl();
|
|
3117
|
-
filteredTypes = [];
|
|
3118
|
-
selectedCkType = null;
|
|
3119
|
-
isLoading = false;
|
|
3120
|
-
typeMap = new Map();
|
|
3121
|
-
searchSubject = new Subject();
|
|
3122
|
-
subscriptions = new Subscription();
|
|
3123
|
-
onChange = () => { };
|
|
3124
|
-
onTouched = () => { };
|
|
3125
|
-
searchIcon = searchIcon;
|
|
3126
|
-
popupSettings = { appendTo: 'root', popupClass: 'mm-ck-type-popup' };
|
|
3127
|
-
static popupStyleInjected = false;
|
|
3128
|
-
ckTypeSelectorService = inject(CkTypeSelectorService);
|
|
3129
|
-
dialogService = inject(CkTypeSelectorDialogService, { optional: true });
|
|
3130
|
-
elementRef = inject(ElementRef);
|
|
3131
|
-
ngOnInit() {
|
|
3132
|
-
this.setupSearch();
|
|
3133
|
-
this.injectPopupStyles();
|
|
3134
|
-
}
|
|
3135
|
-
ngOnDestroy() {
|
|
3136
|
-
this.subscriptions.unsubscribe();
|
|
3137
|
-
this.searchSubject.complete();
|
|
3138
|
-
}
|
|
3139
|
-
// ControlValueAccessor implementation
|
|
3140
|
-
writeValue(value) {
|
|
3141
|
-
if (value !== this.selectedCkType) {
|
|
3142
|
-
this.selectedCkType = value;
|
|
3143
|
-
if (value) {
|
|
3144
|
-
this.searchFormControl.setValue(value.rtCkTypeId, { emitEvent: false });
|
|
3145
|
-
}
|
|
3146
|
-
else {
|
|
3147
|
-
this.searchFormControl.setValue('', { emitEvent: false });
|
|
3148
|
-
}
|
|
3149
|
-
}
|
|
3150
|
-
}
|
|
3151
|
-
registerOnChange(fn) {
|
|
3152
|
-
this.onChange = fn;
|
|
3153
|
-
}
|
|
3154
|
-
registerOnTouched(fn) {
|
|
3155
|
-
this.onTouched = fn;
|
|
3156
|
-
}
|
|
3157
|
-
setDisabledState(isDisabled) {
|
|
3158
|
-
this.disabled = isDisabled;
|
|
3159
|
-
}
|
|
3160
|
-
// Validator implementation
|
|
3161
|
-
validate(control) {
|
|
3162
|
-
if (this.required && !this.selectedCkType) {
|
|
3163
|
-
return { required: true };
|
|
3164
|
-
}
|
|
3165
|
-
const value = control.value;
|
|
3166
|
-
if (value && typeof value === 'string') {
|
|
3167
|
-
return { invalidCkType: true };
|
|
3168
|
-
}
|
|
3169
|
-
return null;
|
|
3170
|
-
}
|
|
3171
|
-
// Event handlers
|
|
3172
|
-
onFilterChange(filter) {
|
|
3173
|
-
if (!filter || filter.length < this.minSearchLength) {
|
|
3174
|
-
this.filteredTypes = [];
|
|
3175
|
-
return;
|
|
3331
|
+
this.windowStateService.applyModalBehavior(dialogKey, windowRef);
|
|
3332
|
+
// Pass data to the component
|
|
3333
|
+
const contentRef = windowRef.content;
|
|
3334
|
+
if (contentRef?.instance) {
|
|
3335
|
+
contentRef.instance.data = data;
|
|
3176
3336
|
}
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3337
|
+
try {
|
|
3338
|
+
const result = await firstValueFrom(windowRef.result);
|
|
3339
|
+
if (result instanceof WindowCloseResult) {
|
|
3340
|
+
return {
|
|
3341
|
+
confirmed: false,
|
|
3342
|
+
selectedAttributes: []
|
|
3343
|
+
};
|
|
3184
3344
|
}
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
const ckType = this.typeMap.get(displayText);
|
|
3198
|
-
if (ckType) {
|
|
3199
|
-
this.selectCkType(ckType);
|
|
3345
|
+
if (result && typeof result === 'object' && 'selectedAttributes' in result) {
|
|
3346
|
+
const dialogResult = result;
|
|
3347
|
+
return {
|
|
3348
|
+
confirmed: true,
|
|
3349
|
+
selectedAttributes: dialogResult.selectedAttributes
|
|
3350
|
+
};
|
|
3351
|
+
}
|
|
3352
|
+
else {
|
|
3353
|
+
return {
|
|
3354
|
+
confirmed: false,
|
|
3355
|
+
selectedAttributes: []
|
|
3356
|
+
};
|
|
3200
3357
|
}
|
|
3201
3358
|
}
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
this.typeMap.clear();
|
|
3208
|
-
this.searchFormControl.setValue('', { emitEvent: false });
|
|
3209
|
-
this.onChange(null);
|
|
3210
|
-
this.ckTypeCleared.emit();
|
|
3211
|
-
this.autocomplete.focus();
|
|
3212
|
-
}
|
|
3213
|
-
focus() {
|
|
3214
|
-
if (this.autocomplete) {
|
|
3215
|
-
this.autocomplete.focus();
|
|
3359
|
+
catch {
|
|
3360
|
+
return {
|
|
3361
|
+
confirmed: false,
|
|
3362
|
+
selectedAttributes: []
|
|
3363
|
+
};
|
|
3216
3364
|
}
|
|
3217
3365
|
}
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
})
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3366
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AttributeSelectorDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3367
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AttributeSelectorDialogService, providedIn: 'root' });
|
|
3368
|
+
}
|
|
3369
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AttributeSelectorDialogService, decorators: [{
|
|
3370
|
+
type: Injectable,
|
|
3371
|
+
args: [{
|
|
3372
|
+
providedIn: 'root'
|
|
3373
|
+
}]
|
|
3374
|
+
}] });
|
|
3375
|
+
|
|
3376
|
+
class RuntimeEntityVariableDialogComponent {
|
|
3377
|
+
windowRef = inject(WindowRef);
|
|
3378
|
+
getEntitiesByCkTypeGQL = inject(GetEntitiesByCkTypeDtoGQL);
|
|
3379
|
+
attributeSelectorDialogService = inject(AttributeSelectorDialogService);
|
|
3380
|
+
pencilIcon = pencilIcon;
|
|
3381
|
+
trashIcon = trashIcon;
|
|
3382
|
+
/** Data passed to the dialog (set by service) */
|
|
3383
|
+
data = {};
|
|
3384
|
+
// Signals
|
|
3385
|
+
selectedCkType = signal(null, ...(ngDevMode ? [{ debugName: "selectedCkType" }] : []));
|
|
3386
|
+
selectedEntity = signal(null, ...(ngDevMode ? [{ debugName: "selectedEntity" }] : []));
|
|
3387
|
+
variableMappings = signal([], ...(ngDevMode ? [{ debugName: "variableMappings" }] : []));
|
|
3388
|
+
entityDataSource = computed(() => {
|
|
3389
|
+
const ckType = this.selectedCkType();
|
|
3390
|
+
if (!ckType)
|
|
3391
|
+
return null;
|
|
3392
|
+
return new RuntimeEntitySelectDataSource(this.getEntitiesByCkTypeGQL, ckType.rtCkTypeId);
|
|
3393
|
+
}, ...(ngDevMode ? [{ debugName: "entityDataSource" }] : []));
|
|
3394
|
+
entityDialogDataSource = computed(() => {
|
|
3395
|
+
const ckType = this.selectedCkType();
|
|
3396
|
+
if (!ckType)
|
|
3397
|
+
return null;
|
|
3398
|
+
return new RuntimeEntityDialogDataSource(this.getEntitiesByCkTypeGQL, ckType.rtCkTypeId);
|
|
3399
|
+
}, ...(ngDevMode ? [{ debugName: "entityDialogDataSource" }] : []));
|
|
3400
|
+
VALID_NAME_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
3401
|
+
onCkTypeSelected(ckType) {
|
|
3402
|
+
this.selectedCkType.set(ckType);
|
|
3403
|
+
this.selectedEntity.set(null);
|
|
3404
|
+
// Don't clear mappings — keep them if user is just switching type
|
|
3405
|
+
}
|
|
3406
|
+
onCkTypeCleared() {
|
|
3407
|
+
this.selectedCkType.set(null);
|
|
3408
|
+
this.selectedEntity.set(null);
|
|
3409
|
+
}
|
|
3410
|
+
onEntitySelected(entity) {
|
|
3411
|
+
this.selectedEntity.set(entity);
|
|
3412
|
+
}
|
|
3413
|
+
onEntityCleared() {
|
|
3414
|
+
this.selectedEntity.set(null);
|
|
3415
|
+
}
|
|
3416
|
+
async openAttributeSelector() {
|
|
3417
|
+
const ckType = this.selectedCkType();
|
|
3418
|
+
if (!ckType)
|
|
3253
3419
|
return;
|
|
3254
|
-
const
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3420
|
+
const existingPaths = this.variableMappings().map(m => m.attributePath);
|
|
3421
|
+
const result = await this.attributeSelectorDialogService.openAttributeSelector(ckType.rtCkTypeId, existingPaths, 'Select Attributes');
|
|
3422
|
+
if (result.confirmed && result.selectedAttributes.length > 0) {
|
|
3423
|
+
this.addAttributeMappings(result.selectedAttributes);
|
|
3424
|
+
}
|
|
3425
|
+
}
|
|
3426
|
+
onNameChange(index, name) {
|
|
3427
|
+
const sanitized = name.replace(/[^a-zA-Z0-9_]/g, '');
|
|
3428
|
+
const mappings = [...this.variableMappings()];
|
|
3429
|
+
mappings[index] = { ...mappings[index], name: sanitized };
|
|
3430
|
+
this.variableMappings.set(mappings);
|
|
3431
|
+
}
|
|
3432
|
+
removeMapping(index) {
|
|
3433
|
+
const mappings = this.variableMappings().filter((_, i) => i !== index);
|
|
3434
|
+
this.variableMappings.set(mappings);
|
|
3435
|
+
}
|
|
3436
|
+
getNameError(name, index) {
|
|
3437
|
+
if (!name)
|
|
3438
|
+
return 'Name required';
|
|
3439
|
+
if (!this.VALID_NAME_REGEX.test(name))
|
|
3440
|
+
return 'Invalid name';
|
|
3441
|
+
if (this.isDuplicateName(name, index))
|
|
3442
|
+
return 'Duplicate';
|
|
3443
|
+
return null;
|
|
3273
3444
|
}
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
this.
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3445
|
+
isValid() {
|
|
3446
|
+
const entity = this.selectedEntity();
|
|
3447
|
+
const mappings = this.variableMappings();
|
|
3448
|
+
if (!entity || mappings.length === 0)
|
|
3449
|
+
return false;
|
|
3450
|
+
return mappings.every((m, i) => m.name &&
|
|
3451
|
+
this.VALID_NAME_REGEX.test(m.name) &&
|
|
3452
|
+
!this.isDuplicateName(m.name, i));
|
|
3281
3453
|
}
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
event.stopPropagation();
|
|
3287
|
-
}
|
|
3288
|
-
if (!this.dialogService) {
|
|
3289
|
-
console.warn('CkTypeSelectorDialogService not available');
|
|
3454
|
+
onOk() {
|
|
3455
|
+
const ckType = this.selectedCkType();
|
|
3456
|
+
const entity = this.selectedEntity();
|
|
3457
|
+
if (!ckType || !entity)
|
|
3290
3458
|
return;
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
derivedFromRtCkTypeId: this.derivedFromRtCkTypeId
|
|
3299
|
-
});
|
|
3300
|
-
if (result.confirmed && result.selectedCkType) {
|
|
3301
|
-
this.selectCkType(result.selectedCkType);
|
|
3302
|
-
}
|
|
3459
|
+
const result = {
|
|
3460
|
+
entityCkTypeId: ckType.rtCkTypeId,
|
|
3461
|
+
entityRtId: entity.rtId,
|
|
3462
|
+
entityDisplayName: entity.displayName,
|
|
3463
|
+
variables: this.variableMappings()
|
|
3464
|
+
};
|
|
3465
|
+
this.windowRef.close(result);
|
|
3303
3466
|
}
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3467
|
+
onCancel() {
|
|
3468
|
+
this.windowRef.close();
|
|
3469
|
+
}
|
|
3470
|
+
addAttributeMappings(attributes) {
|
|
3471
|
+
const existingMappings = this.variableMappings();
|
|
3472
|
+
const existingPaths = new Set(existingMappings.map(m => m.attributePath));
|
|
3473
|
+
const allNames = new Set([
|
|
3474
|
+
...existingMappings.map(m => m.name),
|
|
3475
|
+
...(this.data.existingVariableNames ?? [])
|
|
3476
|
+
]);
|
|
3477
|
+
const newMappings = [];
|
|
3478
|
+
for (const attr of attributes) {
|
|
3479
|
+
if (existingPaths.has(attr.attributePath))
|
|
3480
|
+
continue;
|
|
3481
|
+
let name = this.attributePathToVariableName(attr.attributePath);
|
|
3482
|
+
let counter = 1;
|
|
3483
|
+
while (allNames.has(name)) {
|
|
3484
|
+
name = `${this.attributePathToVariableName(attr.attributePath)}${counter}`;
|
|
3485
|
+
counter++;
|
|
3315
3486
|
}
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
[
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3487
|
+
allNames.add(name);
|
|
3488
|
+
newMappings.push({
|
|
3489
|
+
name,
|
|
3490
|
+
attributePath: attr.attributePath,
|
|
3491
|
+
attributeValueType: attr.attributeValueType
|
|
3492
|
+
});
|
|
3493
|
+
}
|
|
3494
|
+
this.variableMappings.set([...existingMappings, ...newMappings]);
|
|
3495
|
+
}
|
|
3496
|
+
attributePathToVariableName(attributePath) {
|
|
3497
|
+
const parts = attributePath.split('.');
|
|
3498
|
+
return parts
|
|
3499
|
+
.map((part, index) => index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1))
|
|
3500
|
+
.join('');
|
|
3501
|
+
}
|
|
3502
|
+
isDuplicateName(name, currentIndex) {
|
|
3503
|
+
const mappings = this.variableMappings();
|
|
3504
|
+
const existingNames = this.data.existingVariableNames ?? [];
|
|
3505
|
+
// Check within dialog mappings
|
|
3506
|
+
if (mappings.some((m, i) => i !== currentIndex && m.name === name))
|
|
3507
|
+
return true;
|
|
3508
|
+
// Check against existing external variable names
|
|
3509
|
+
if (existingNames.includes(name))
|
|
3510
|
+
return true;
|
|
3511
|
+
return false;
|
|
3512
|
+
}
|
|
3513
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: RuntimeEntityVariableDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3514
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: RuntimeEntityVariableDialogComponent, isStandalone: true, selector: "mm-runtime-entity-variable-dialog", ngImport: i0, template: `
|
|
3515
|
+
<div class="dialog-content">
|
|
3516
|
+
<div class="form-row">
|
|
3517
|
+
<label class="form-label">CK Type</label>
|
|
3518
|
+
<mm-ck-type-selector-input
|
|
3519
|
+
[placeholder]="'Select CK Type...'"
|
|
3520
|
+
[minSearchLength]="2"
|
|
3521
|
+
(ckTypeSelected)="onCkTypeSelected($event)"
|
|
3522
|
+
(ckTypeCleared)="onCkTypeCleared()">
|
|
3523
|
+
</mm-ck-type-selector-input>
|
|
3524
|
+
</div>
|
|
3333
3525
|
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3526
|
+
<div class="form-row">
|
|
3527
|
+
<label class="form-label">Entity</label>
|
|
3528
|
+
<mm-entity-select-input
|
|
3529
|
+
[dataSource]="entityDataSource()!"
|
|
3530
|
+
[dialogDataSource]="entityDialogDataSource()!"
|
|
3531
|
+
[placeholder]="'Select Entity...'"
|
|
3532
|
+
[disabled]="!selectedCkType()"
|
|
3533
|
+
[minSearchLength]="1"
|
|
3534
|
+
dialogTitle="Select Entity"
|
|
3535
|
+
(entitySelected)="onEntitySelected($event)"
|
|
3536
|
+
(entityCleared)="onEntityCleared()">
|
|
3537
|
+
</mm-entity-select-input>
|
|
3538
|
+
</div>
|
|
3339
3539
|
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
</
|
|
3540
|
+
<div class="form-row">
|
|
3541
|
+
<label class="form-label">Attributes</label>
|
|
3542
|
+
<button
|
|
3543
|
+
kendoButton
|
|
3544
|
+
(click)="openAttributeSelector()"
|
|
3545
|
+
[disabled]="!selectedCkType()"
|
|
3546
|
+
themeColor="primary"
|
|
3547
|
+
fillMode="outline">
|
|
3548
|
+
Select Attributes...
|
|
3549
|
+
</button>
|
|
3550
|
+
</div>
|
|
3350
3551
|
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
<span>
|
|
3552
|
+
@if (variableMappings().length > 0) {
|
|
3553
|
+
<div class="mappings-grid">
|
|
3554
|
+
<div class="grid-header">
|
|
3555
|
+
<span class="col-name">Variable Name</span>
|
|
3556
|
+
<span class="col-path">Attribute Path</span>
|
|
3557
|
+
<span class="col-type">Type</span>
|
|
3558
|
+
<span class="col-actions"></span>
|
|
3355
3559
|
</div>
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3560
|
+
@for (mapping of variableMappings(); track mapping.attributePath; let i = $index) {
|
|
3561
|
+
<div class="grid-row">
|
|
3562
|
+
<div class="col-name">
|
|
3563
|
+
<kendo-textbox
|
|
3564
|
+
[value]="mapping.name"
|
|
3565
|
+
(valueChange)="onNameChange(i, $event)"
|
|
3566
|
+
[style.width.%]="100">
|
|
3567
|
+
</kendo-textbox>
|
|
3568
|
+
@if (getNameError(mapping.name, i); as error) {
|
|
3569
|
+
<span class="error-text">{{ error }}</span>
|
|
3570
|
+
}
|
|
3571
|
+
</div>
|
|
3572
|
+
<div class="col-path">{{ mapping.attributePath }}</div>
|
|
3573
|
+
<div class="col-type">{{ mapping.attributeValueType }}</div>
|
|
3574
|
+
<div class="col-actions">
|
|
3575
|
+
<button
|
|
3576
|
+
kendoButton
|
|
3577
|
+
(click)="removeMapping(i)"
|
|
3578
|
+
[svgIcon]="trashIcon"
|
|
3579
|
+
fillMode="flat"
|
|
3580
|
+
themeColor="error"
|
|
3581
|
+
title="Remove">
|
|
3582
|
+
</button>
|
|
3583
|
+
</div>
|
|
3584
|
+
</div>
|
|
3585
|
+
}
|
|
3586
|
+
</div>
|
|
3587
|
+
}
|
|
3359
3588
|
|
|
3360
|
-
<
|
|
3361
|
-
kendoButton
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
[disabled]="disabled"
|
|
3365
|
-
[title]="advancedSearchLabel"
|
|
3366
|
-
class="dialog-button"
|
|
3367
|
-
(click)="openDialog()">
|
|
3368
|
-
</button>
|
|
3589
|
+
<div class="dialog-actions">
|
|
3590
|
+
<button kendoButton (click)="onCancel()" fillMode="outline">Cancel</button>
|
|
3591
|
+
<button kendoButton (click)="onOk()" themeColor="primary" [disabled]="!isValid()">OK</button>
|
|
3592
|
+
</div>
|
|
3369
3593
|
</div>
|
|
3370
|
-
`, isInline: true, styles: ["
|
|
3594
|
+
`, isInline: true, styles: [".dialog-content{display:flex;flex-direction:column;gap:16px;padding:16px 20px}.form-row{display:flex;flex-direction:column;gap:4px}.form-label{font-size:12px;font-weight:600;color:var(--kendo-color-subtle, #666)}.mappings-grid{border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px;background:var(--kendo-color-surface-alt, #fafafa)}.grid-header{display:grid;grid-template-columns:1fr 1fr 100px 40px;gap:.5rem;padding:.5rem .75rem;background:var(--kendo-color-surface, #f5f5f5);border-bottom:1px solid var(--kendo-color-border, #e0e0e0);font-size:12px;font-weight:600;color:var(--kendo-color-subtle, #666)}.grid-row{display:grid;grid-template-columns:1fr 1fr 100px 40px;gap:.5rem;padding:.5rem .75rem;align-items:start;border-bottom:1px solid var(--kendo-color-border, #e0e0e0)}.grid-row:last-child{border-bottom:none}.col-name{display:flex;flex-direction:column;gap:2px}.col-path,.col-type{font-size:13px;padding-top:6px;color:var(--kendo-color-on-app-surface, #424242)}.col-actions{display:flex;justify-content:center;padding-top:2px}.error-text{font-size:11px;color:var(--kendo-color-error, #f44336)}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;padding-top:8px;border-top:1px solid var(--kendo-color-border, #e0e0e0)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ButtonsModule }, { kind: "component", type: i4.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], 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: "ngmodule", type: GridModule }, { kind: "ngmodule", type: IconsModule }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: EntitySelectInputComponent, selector: "mm-entity-select-input", inputs: ["dataSource", "placeholder", "minSearchLength", "maxResults", "debounceMs", "prefix", "initialDisplayValue", "dialogDataSource", "dialogTitle", "multiSelect", "advancedSearchLabel", "dialogMessages", "messages", "disabled", "required"], outputs: ["entitySelected", "entityCleared", "entitiesSelected"] }] });
|
|
3371
3595
|
}
|
|
3372
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type:
|
|
3373
|
-
type: Component,
|
|
3374
|
-
args: [{ selector: 'mm-
|
|
3375
|
-
CommonModule,
|
|
3376
|
-
|
|
3377
|
-
AutoCompleteModule,
|
|
3378
|
-
LoaderModule,
|
|
3596
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: RuntimeEntityVariableDialogComponent, decorators: [{
|
|
3597
|
+
type: Component,
|
|
3598
|
+
args: [{ selector: 'mm-runtime-entity-variable-dialog', standalone: true, imports: [
|
|
3599
|
+
CommonModule,
|
|
3600
|
+
FormsModule,
|
|
3379
3601
|
ButtonsModule,
|
|
3602
|
+
InputsModule,
|
|
3603
|
+
GridModule,
|
|
3380
3604
|
IconsModule,
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
{
|
|
3384
|
-
provide: NG_VALUE_ACCESSOR,
|
|
3385
|
-
useExisting: forwardRef(() => CkTypeSelectorInputComponent),
|
|
3386
|
-
multi: true
|
|
3387
|
-
},
|
|
3388
|
-
{
|
|
3389
|
-
provide: NG_VALIDATORS,
|
|
3390
|
-
useExisting: forwardRef(() => CkTypeSelectorInputComponent),
|
|
3391
|
-
multi: true
|
|
3392
|
-
}
|
|
3605
|
+
CkTypeSelectorInputComponent,
|
|
3606
|
+
EntitySelectInputComponent
|
|
3393
3607
|
], template: `
|
|
3394
|
-
<div class="
|
|
3395
|
-
<
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
[popupSettings]="popupSettings"
|
|
3405
|
-
(filterChange)="onFilterChange($event)"
|
|
3406
|
-
(valueChange)="onSelectionChange($event)"
|
|
3407
|
-
(blur)="onBlur()"
|
|
3408
|
-
(focus)="onFocus()"
|
|
3409
|
-
class="ck-type-autocomplete">
|
|
3608
|
+
<div class="dialog-content">
|
|
3609
|
+
<div class="form-row">
|
|
3610
|
+
<label class="form-label">CK Type</label>
|
|
3611
|
+
<mm-ck-type-selector-input
|
|
3612
|
+
[placeholder]="'Select CK Type...'"
|
|
3613
|
+
[minSearchLength]="2"
|
|
3614
|
+
(ckTypeSelected)="onCkTypeSelected($event)"
|
|
3615
|
+
(ckTypeCleared)="onCkTypeCleared()">
|
|
3616
|
+
</mm-ck-type-selector-input>
|
|
3617
|
+
</div>
|
|
3410
3618
|
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3619
|
+
<div class="form-row">
|
|
3620
|
+
<label class="form-label">Entity</label>
|
|
3621
|
+
<mm-entity-select-input
|
|
3622
|
+
[dataSource]="entityDataSource()!"
|
|
3623
|
+
[dialogDataSource]="entityDialogDataSource()!"
|
|
3624
|
+
[placeholder]="'Select Entity...'"
|
|
3625
|
+
[disabled]="!selectedCkType()"
|
|
3626
|
+
[minSearchLength]="1"
|
|
3627
|
+
dialogTitle="Select Entity"
|
|
3628
|
+
(entitySelected)="onEntitySelected($event)"
|
|
3629
|
+
(entityCleared)="onEntityCleared()">
|
|
3630
|
+
</mm-entity-select-input>
|
|
3631
|
+
</div>
|
|
3416
3632
|
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
</
|
|
3633
|
+
<div class="form-row">
|
|
3634
|
+
<label class="form-label">Attributes</label>
|
|
3635
|
+
<button
|
|
3636
|
+
kendoButton
|
|
3637
|
+
(click)="openAttributeSelector()"
|
|
3638
|
+
[disabled]="!selectedCkType()"
|
|
3639
|
+
themeColor="primary"
|
|
3640
|
+
fillMode="outline">
|
|
3641
|
+
Select Attributes...
|
|
3642
|
+
</button>
|
|
3643
|
+
</div>
|
|
3427
3644
|
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
<span>
|
|
3645
|
+
@if (variableMappings().length > 0) {
|
|
3646
|
+
<div class="mappings-grid">
|
|
3647
|
+
<div class="grid-header">
|
|
3648
|
+
<span class="col-name">Variable Name</span>
|
|
3649
|
+
<span class="col-path">Attribute Path</span>
|
|
3650
|
+
<span class="col-type">Type</span>
|
|
3651
|
+
<span class="col-actions"></span>
|
|
3432
3652
|
</div>
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3653
|
+
@for (mapping of variableMappings(); track mapping.attributePath; let i = $index) {
|
|
3654
|
+
<div class="grid-row">
|
|
3655
|
+
<div class="col-name">
|
|
3656
|
+
<kendo-textbox
|
|
3657
|
+
[value]="mapping.name"
|
|
3658
|
+
(valueChange)="onNameChange(i, $event)"
|
|
3659
|
+
[style.width.%]="100">
|
|
3660
|
+
</kendo-textbox>
|
|
3661
|
+
@if (getNameError(mapping.name, i); as error) {
|
|
3662
|
+
<span class="error-text">{{ error }}</span>
|
|
3663
|
+
}
|
|
3664
|
+
</div>
|
|
3665
|
+
<div class="col-path">{{ mapping.attributePath }}</div>
|
|
3666
|
+
<div class="col-type">{{ mapping.attributeValueType }}</div>
|
|
3667
|
+
<div class="col-actions">
|
|
3668
|
+
<button
|
|
3669
|
+
kendoButton
|
|
3670
|
+
(click)="removeMapping(i)"
|
|
3671
|
+
[svgIcon]="trashIcon"
|
|
3672
|
+
fillMode="flat"
|
|
3673
|
+
themeColor="error"
|
|
3674
|
+
title="Remove">
|
|
3675
|
+
</button>
|
|
3676
|
+
</div>
|
|
3677
|
+
</div>
|
|
3678
|
+
}
|
|
3679
|
+
</div>
|
|
3680
|
+
}
|
|
3436
3681
|
|
|
3437
|
-
<
|
|
3438
|
-
kendoButton
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
[disabled]="disabled"
|
|
3442
|
-
[title]="advancedSearchLabel"
|
|
3443
|
-
class="dialog-button"
|
|
3444
|
-
(click)="openDialog()">
|
|
3445
|
-
</button>
|
|
3682
|
+
<div class="dialog-actions">
|
|
3683
|
+
<button kendoButton (click)="onCancel()" fillMode="outline">Cancel</button>
|
|
3684
|
+
<button kendoButton (click)="onOk()" themeColor="primary" [disabled]="!isValid()">OK</button>
|
|
3685
|
+
</div>
|
|
3446
3686
|
</div>
|
|
3447
|
-
`, styles: ["
|
|
3448
|
-
}]
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3687
|
+
`, styles: [".dialog-content{display:flex;flex-direction:column;gap:16px;padding:16px 20px}.form-row{display:flex;flex-direction:column;gap:4px}.form-label{font-size:12px;font-weight:600;color:var(--kendo-color-subtle, #666)}.mappings-grid{border:1px solid var(--kendo-color-border, #e0e0e0);border-radius:4px;background:var(--kendo-color-surface-alt, #fafafa)}.grid-header{display:grid;grid-template-columns:1fr 1fr 100px 40px;gap:.5rem;padding:.5rem .75rem;background:var(--kendo-color-surface, #f5f5f5);border-bottom:1px solid var(--kendo-color-border, #e0e0e0);font-size:12px;font-weight:600;color:var(--kendo-color-subtle, #666)}.grid-row{display:grid;grid-template-columns:1fr 1fr 100px 40px;gap:.5rem;padding:.5rem .75rem;align-items:start;border-bottom:1px solid var(--kendo-color-border, #e0e0e0)}.grid-row:last-child{border-bottom:none}.col-name{display:flex;flex-direction:column;gap:2px}.col-path,.col-type{font-size:13px;padding-top:6px;color:var(--kendo-color-on-app-surface, #424242)}.col-actions{display:flex;justify-content:center;padding-top:2px}.error-text{font-size:11px;color:var(--kendo-color-error, #f44336)}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;padding-top:8px;border-top:1px solid var(--kendo-color-border, #e0e0e0)}\n"] }]
|
|
3688
|
+
}] });
|
|
3689
|
+
|
|
3690
|
+
class RuntimeEntityVariableDialogService {
|
|
3691
|
+
windowService = inject(WindowService);
|
|
3692
|
+
windowStateService = inject(WindowStateService);
|
|
3693
|
+
/**
|
|
3694
|
+
* Opens the runtime entity variable dialog.
|
|
3695
|
+
* @param data Optional pre-populated data for editing
|
|
3696
|
+
* @returns Promise with confirmation status and dialog result
|
|
3697
|
+
*/
|
|
3698
|
+
async openRuntimeEntityVariableDialog(data) {
|
|
3699
|
+
const size = this.windowStateService.resolveWindowSize('runtime-entity-variable', { width: 800, height: 600 });
|
|
3700
|
+
const windowRef = this.windowService.open({
|
|
3701
|
+
content: RuntimeEntityVariableDialogComponent,
|
|
3702
|
+
width: size.width,
|
|
3703
|
+
height: size.height,
|
|
3704
|
+
minWidth: 650,
|
|
3705
|
+
minHeight: 500,
|
|
3706
|
+
resizable: true,
|
|
3707
|
+
title: 'Runtime Entity Variables'
|
|
3708
|
+
});
|
|
3709
|
+
this.windowStateService.applyModalBehavior('runtime-entity-variable', windowRef);
|
|
3710
|
+
const contentRef = windowRef.content;
|
|
3711
|
+
if (contentRef?.instance && data) {
|
|
3712
|
+
contentRef.instance.data = data;
|
|
3713
|
+
}
|
|
3714
|
+
try {
|
|
3715
|
+
const result = await firstValueFrom(windowRef.result);
|
|
3716
|
+
if (result instanceof WindowCloseResult) {
|
|
3717
|
+
return { confirmed: false };
|
|
3718
|
+
}
|
|
3719
|
+
if (result && typeof result === 'object' && 'variables' in result) {
|
|
3720
|
+
return {
|
|
3721
|
+
confirmed: true,
|
|
3722
|
+
result: result
|
|
3723
|
+
};
|
|
3724
|
+
}
|
|
3725
|
+
return { confirmed: false };
|
|
3726
|
+
}
|
|
3727
|
+
catch {
|
|
3728
|
+
return { confirmed: false };
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: RuntimeEntityVariableDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3732
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: RuntimeEntityVariableDialogService, providedIn: 'root' });
|
|
3733
|
+
}
|
|
3734
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: RuntimeEntityVariableDialogService, decorators: [{
|
|
3735
|
+
type: Injectable,
|
|
3736
|
+
args: [{
|
|
3737
|
+
providedIn: 'root'
|
|
3738
|
+
}]
|
|
3739
|
+
}] });
|
|
3740
|
+
|
|
3741
|
+
// noinspection JSUnusedGlobalSymbols
|
|
3742
|
+
class OctoGraphQlDataSource extends DataSourceTyped {
|
|
3743
|
+
_searchFilterAttributePaths = [];
|
|
3744
|
+
// noinspection JSUnusedGlobalSymbols
|
|
3745
|
+
constructor(listViewComponent) {
|
|
3746
|
+
super(listViewComponent);
|
|
3747
|
+
}
|
|
3748
|
+
get searchFilterAttributePaths() {
|
|
3749
|
+
return this._searchFilterAttributePaths;
|
|
3750
|
+
}
|
|
3751
|
+
set searchFilterAttributePaths(value) {
|
|
3752
|
+
this._searchFilterAttributePaths = value;
|
|
3753
|
+
}
|
|
3754
|
+
// noinspection JSUnusedGlobalSymbols
|
|
3755
|
+
getFieldFilterDefinitions(state) {
|
|
3756
|
+
let fieldFilters = null;
|
|
3757
|
+
if (state.filter?.filters) {
|
|
3758
|
+
fieldFilters = state.filter.filters.map((f) => {
|
|
3759
|
+
if (isCompositeFilterDescriptor(f)) {
|
|
3760
|
+
throw new Error('Composite filter descriptor not supported');
|
|
3761
|
+
}
|
|
3762
|
+
const { operator, value } = OctoGraphQlDataSource.getOperatorAndValue(f.operator, f.value);
|
|
3763
|
+
return {
|
|
3764
|
+
attributePath: f.field,
|
|
3765
|
+
operator: operator,
|
|
3766
|
+
comparisonValue: value
|
|
3767
|
+
};
|
|
3768
|
+
});
|
|
3769
|
+
}
|
|
3770
|
+
return fieldFilters;
|
|
3771
|
+
}
|
|
3772
|
+
// noinspection JSUnusedGlobalSymbols
|
|
3773
|
+
getSearchFilterDefinitions(textSearchValue) {
|
|
3774
|
+
let searchFilterDto = null;
|
|
3775
|
+
if (textSearchValue) {
|
|
3776
|
+
searchFilterDto = {
|
|
3777
|
+
type: SearchFilterTypesDto.AttributeFilterDto,
|
|
3778
|
+
attributePaths: this.searchFilterAttributePaths,
|
|
3779
|
+
searchTerm: textSearchValue,
|
|
3780
|
+
};
|
|
3781
|
+
}
|
|
3782
|
+
return searchFilterDto;
|
|
3783
|
+
}
|
|
3784
|
+
// noinspection JSUnusedGlobalSymbols
|
|
3785
|
+
getSortDefinitions(state) {
|
|
3786
|
+
let sort = null;
|
|
3787
|
+
if (state.sort) {
|
|
3788
|
+
sort = new Array();
|
|
3789
|
+
state.sort.forEach((s) => {
|
|
3790
|
+
switch (s.dir) {
|
|
3791
|
+
case 'asc':
|
|
3792
|
+
sort?.push({
|
|
3793
|
+
attributePath: s.field,
|
|
3794
|
+
sortOrder: SortOrdersDto.AscendingDto
|
|
3795
|
+
});
|
|
3796
|
+
break;
|
|
3797
|
+
case 'desc':
|
|
3798
|
+
sort?.push({
|
|
3799
|
+
attributePath: s.field,
|
|
3800
|
+
sortOrder: SortOrdersDto.DescendingDto,
|
|
3801
|
+
});
|
|
3802
|
+
break;
|
|
3803
|
+
default:
|
|
3804
|
+
sort?.push({
|
|
3805
|
+
attributePath: s.field,
|
|
3806
|
+
sortOrder: SortOrdersDto.DefaultDto,
|
|
3807
|
+
});
|
|
3808
|
+
break;
|
|
3809
|
+
}
|
|
3810
|
+
});
|
|
3811
|
+
}
|
|
3812
|
+
return sort;
|
|
3813
|
+
}
|
|
3814
|
+
static getOperatorAndValue(operator, value) {
|
|
3815
|
+
switch (operator) {
|
|
3816
|
+
case 'eq':
|
|
3817
|
+
return { operator: FieldFilterOperatorsDto.EqualsDto, value: value };
|
|
3818
|
+
case 'neq':
|
|
3819
|
+
return { operator: FieldFilterOperatorsDto.NotEqualsDto, value: value };
|
|
3820
|
+
case 'lt':
|
|
3821
|
+
return { operator: FieldFilterOperatorsDto.LessThanDto, value: value };
|
|
3822
|
+
case 'lte':
|
|
3823
|
+
return { operator: FieldFilterOperatorsDto.LessEqualThanDto, value: value };
|
|
3824
|
+
case 'gt':
|
|
3825
|
+
return { operator: FieldFilterOperatorsDto.GreaterThanDto, value: value };
|
|
3826
|
+
case 'gte':
|
|
3827
|
+
return { operator: FieldFilterOperatorsDto.GreaterEqualThanDto, value: value };
|
|
3828
|
+
case 'contains':
|
|
3829
|
+
return { operator: FieldFilterOperatorsDto.LikeDto, value: value };
|
|
3830
|
+
case 'doesnotcontain':
|
|
3831
|
+
return { operator: FieldFilterOperatorsDto.MatchRegExDto, value: `^(?!.*${value}).*$` };
|
|
3832
|
+
case 'startswith':
|
|
3833
|
+
return { operator: FieldFilterOperatorsDto.MatchRegExDto, value: value + '.*' };
|
|
3834
|
+
case 'endswith':
|
|
3835
|
+
return { operator: FieldFilterOperatorsDto.MatchRegExDto, value: '.*' + value };
|
|
3836
|
+
case 'isnull':
|
|
3837
|
+
return { operator: FieldFilterOperatorsDto.EqualsDto, value: null };
|
|
3838
|
+
case 'isnotnull':
|
|
3839
|
+
return { operator: FieldFilterOperatorsDto.NotEqualsDto, value: null };
|
|
3840
|
+
case 'isempty':
|
|
3841
|
+
return { operator: FieldFilterOperatorsDto.EqualsDto, value: "" };
|
|
3842
|
+
case 'isnotempty':
|
|
3843
|
+
return { operator: FieldFilterOperatorsDto.NotEqualsDto, value: "" };
|
|
3844
|
+
default:
|
|
3845
|
+
throw new Error('The filter operator is not supported');
|
|
3846
|
+
}
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
|
|
3850
|
+
class OctoGraphQlHierarchyDataSource extends HierarchyDataSourceBase {
|
|
3851
|
+
}
|
|
3478
3852
|
|
|
3479
3853
|
class FieldFilterEditorComponent {
|
|
3480
3854
|
attributeService = inject(AttributeSelectorService, { optional: true });
|
|
@@ -4795,7 +5169,8 @@ function provideOctoUi() {
|
|
|
4795
5169
|
provideMmSharedAuth(),
|
|
4796
5170
|
AttributeSortSelectorDialogService,
|
|
4797
5171
|
PropertyConverterService,
|
|
4798
|
-
CkTypeSelectorDialogService
|
|
5172
|
+
CkTypeSelectorDialogService,
|
|
5173
|
+
RuntimeEntityVariableDialogService
|
|
4799
5174
|
]);
|
|
4800
5175
|
}
|
|
4801
5176
|
|
|
@@ -4803,5 +5178,5 @@ function provideOctoUi() {
|
|
|
4803
5178
|
* Generated bundle index. Do not edit.
|
|
4804
5179
|
*/
|
|
4805
5180
|
|
|
4806
|
-
export { AttributeSelectorDialogComponent, AttributeSelectorDialogService, AttributeSortSelectorDialogComponent, AttributeSortSelectorDialogService, AttributeValueTypeDto, CkTypeSelectorDialogComponent, CkTypeSelectorDialogService, CkTypeSelectorInputComponent, DefaultPropertyCategory, EntityIdInfoComponent, FieldFilterEditorComponent, OctoGraphQlDataSource, OctoGraphQlHierarchyDataSource, OctoLoaderComponent, PropertyConverterService, PropertyDisplayMode, PropertyGridComponent, PropertyValueDisplayComponent, provideOctoUi };
|
|
5181
|
+
export { AttributeSelectorDialogComponent, AttributeSelectorDialogService, AttributeSortSelectorDialogComponent, AttributeSortSelectorDialogService, AttributeValueTypeDto, CkTypeSelectorDialogComponent, CkTypeSelectorDialogService, CkTypeSelectorInputComponent, DefaultPropertyCategory, EntityIdInfoComponent, FieldFilterEditorComponent, OctoGraphQlDataSource, OctoGraphQlHierarchyDataSource, OctoLoaderComponent, PropertyConverterService, PropertyDisplayMode, PropertyGridComponent, PropertyValueDisplayComponent, RuntimeEntityVariableDialogComponent, RuntimeEntityVariableDialogService, provideOctoUi };
|
|
4807
5182
|
//# sourceMappingURL=meshmakers-octo-ui.mjs.map
|