@messaia/cdk 22.0.0 → 22.0.1-rc.10

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.
@@ -1383,6 +1383,17 @@ class BaseComponent {
1383
1383
  this.router.navigateByUrl(urlTree.toString());
1384
1384
  }
1385
1385
  }
1386
+ /**
1387
+ * Navigates to the previous page in browser history.
1388
+ */
1389
+ navigateBack() {
1390
+ /* If history is unavailable or too short, fallback to configured return URL */
1391
+ if (typeof window === 'undefined' || (window.history?.length ?? 0) <= 1) {
1392
+ this.navigateToReturnUrl();
1393
+ return;
1394
+ }
1395
+ this.location.back();
1396
+ }
1386
1397
  /**
1387
1398
  * Expands the specified expansion panel path (supporting nested IDs) and collapses others.
1388
1399
  * @param panelPath - The dot-separated ID path (e.g., 'warehouse.orders.details').
@@ -1672,7 +1683,7 @@ class BaseComponent {
1672
1683
  * @param playSound A flag indicating whether to play a warning sound when the message type is Warning or Error. Defaults to false.
1673
1684
  * @returns An observable that emits when the action button is clicked.
1674
1685
  */
1675
- showMessage(message, type = MessageType.Success, duration, actionLabel = $localize `:@@ok:OK`, playSound = false) {
1686
+ showMessage(message, type = MessageType.Success, duration, actionLabel = $localize `:@@ok:Ok`, playSound = false) {
1676
1687
  /* Default snack bar class to 'primary' (for success messages) */
1677
1688
  let snackBarClass = 'primary';
1678
1689
  /* If duration is not provided, calculate it based on message length */
@@ -12406,6 +12417,26 @@ function mixinDisabled(base) {
12406
12417
  };
12407
12418
  }
12408
12419
 
12420
+ class MsaSelectionLabelComponent {
12421
+ /**
12422
+ * Label value used by the i18n select expression.
12423
+ */
12424
+ label;
12425
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MsaSelectionLabelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12426
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: MsaSelectionLabelComponent, isStandalone: true, selector: "msa-selection-label", inputs: { label: "label" }, ngImport: i0, template: '<span i18n="@@selection">{ label, select, option {option} other{ {{ label }} } }</span>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.Eager });
12427
+ }
12428
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MsaSelectionLabelComponent, decorators: [{
12429
+ type: Component,
12430
+ args: [{
12431
+ selector: 'msa-selection-label',
12432
+ template: '<span i18n="@@selection">{ label, select, option {option} other{ {{ label }} } }</span>',
12433
+ standalone: true,
12434
+ changeDetection: ChangeDetectionStrategy.Eager
12435
+ }]
12436
+ }], propDecorators: { label: [{
12437
+ type: Input
12438
+ }] } });
12439
+
12409
12440
  class MsaEnumDisplayComponent {
12410
12441
  /**
12411
12442
  * The numeric value of the enum to convert.
@@ -12528,11 +12559,13 @@ class MsaEnumDisplayComponent {
12528
12559
  </mat-icon>
12529
12560
  }
12530
12561
  @let text = resolvedText();
12531
- <span class="enum-text" i18n="@@selection">{ text, select, type {type} other { {{text}}} }</span>`, isInline: true, styles: [".enum-icon{margin-right:.2rem;vertical-align:middle}.enum-text{vertical-align:middle}\n"], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
12562
+ <span class="enum-text">
12563
+ <msa-selection-label [label]="text"></msa-selection-label>
12564
+ </span>`, isInline: true, styles: [".enum-icon{margin-right:.2rem;vertical-align:middle}.enum-text{vertical-align:middle}\n"], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MsaSelectionLabelComponent, selector: "msa-selection-label", inputs: ["label"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
12532
12565
  }
12533
12566
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MsaEnumDisplayComponent, decorators: [{
12534
12567
  type: Component,
12535
- args: [{ selector: 'msa-enum-display', standalone: true, imports: [MatIcon, NgClass], template: `
12568
+ args: [{ selector: 'msa-enum-display', standalone: true, imports: [MatIcon, NgClass, MsaSelectionLabelComponent], template: `
12536
12569
  @if (resolvedIcon(); as iconConfig) {
12537
12570
  <mat-icon
12538
12571
  [svgIcon]="iconConfig.svgIcon"
@@ -12545,7 +12578,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
12545
12578
  </mat-icon>
12546
12579
  }
12547
12580
  @let text = resolvedText();
12548
- <span class="enum-text" i18n="@@selection">{ text, select, type {type} other { {{text}}} }</span>`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".enum-icon{margin-right:.2rem;vertical-align:middle}.enum-text{vertical-align:middle}\n"] }]
12581
+ <span class="enum-text">
12582
+ <msa-selection-label [label]="text"></msa-selection-label>
12583
+ </span>`, changeDetection: ChangeDetectionStrategy.Eager, styles: [".enum-icon{margin-right:.2rem;vertical-align:middle}.enum-text{vertical-align:middle}\n"] }]
12549
12584
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], enumType: [{ type: i0.Input, args: [{ isSignal: true, alias: "enumType", required: false }] }], metadata: [{ type: i0.Input, args: [{ isSignal: true, alias: "metadata", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], entity: [{ type: i0.Input, args: [{ isSignal: true, alias: "entity", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }] } });
12550
12585
 
12551
12586
  const headerMetadataKey = 'customer:vdHeader';
@@ -12853,15 +12888,16 @@ function getEndpoint(origin) {
12853
12888
  /* Retrieve and return the endpoint metadata associated with the given class */
12854
12889
  return Reflect.getMetadata(endpointMetadataKey, origin);
12855
12890
  }
12891
+
12856
12892
  /**
12857
- * Gets the display header metadata from a class.
12858
- *
12859
- * @param origin - The class from which to retrieve the header metadata.
12860
- * @returns The display header as a string.
12893
+ * Retrieves the display name for a given property of an instance using metadata.
12894
+ * @template T - The type of the instance.
12895
+ * @param {T} instance - The instance from which to retrieve the display name.
12896
+ * @param {string | symbol} propertyKey - The property key for which to retrieve the display name.
12897
+ * @returns {string | undefined} - The display name if found; otherwise, undefined.
12861
12898
  */
12862
- function getDisplay(origin) {
12863
- /* Retrieve and return the display header metadata associated with the given class */
12864
- return Reflect.getMetadata(headerMetadataKey, origin);
12899
+ function getDisplay(instance, propertyKey) {
12900
+ return Reflect.getMetadata(headerMetadataKey, instance, propertyKey);
12865
12901
  }
12866
12902
 
12867
12903
  /**
@@ -12978,6 +13014,9 @@ class AppEvent {
12978
13014
  }
12979
13015
  }
12980
13016
 
13017
+ const TABLE_DEFINITION_METADATA_KEY = Symbol('msa-ng-cdk:table-definition');
13018
+ const TABLE_COLUMNS_METADATA_KEY = Symbol('msa-ng-cdk:table-columns');
13019
+
12981
13020
  var Grid;
12982
13021
  (function (Grid) {
12983
13022
  Grid[Grid["All"] = 0] = "All";
@@ -12990,9 +13029,6 @@ var Grid;
12990
13029
  Grid[Grid["None"] = 7] = "None";
12991
13030
  })(Grid || (Grid = {}));
12992
13031
 
12993
- const tableDefinitionMetadataKey = 'custom:vdTableDefinition';
12994
- const tableColumnsMetadataKey = 'custom:vdTableColumns';
12995
-
12996
13032
  var TableColumnType;
12997
13033
  (function (TableColumnType) {
12998
13034
  TableColumnType[TableColumnType["None"] = 0] = "None";
@@ -13056,6 +13092,11 @@ class TableColumn {
13056
13092
  * @property
13057
13093
  */
13058
13094
  display;
13095
+ /**
13096
+ * Cached classes for responsive display visibility.
13097
+ * @property
13098
+ */
13099
+ displayNgClass;
13059
13100
  /**
13060
13101
  * Endpoint for additional data retrieval.
13061
13102
  * @property
@@ -13201,6 +13242,11 @@ class TableColumn {
13201
13242
  * @property
13202
13243
  */
13203
13244
  multiple = false;
13245
+ /**
13246
+ * The property of the entity that this column represents.
13247
+ * @property
13248
+ */
13249
+ property;
13204
13250
  /**
13205
13251
  * The name of the column.
13206
13252
  * @property
@@ -13287,491 +13333,280 @@ class TableColumn {
13287
13333
  }
13288
13334
 
13289
13335
  /**
13290
- * Class representing the structure and behavior of a table definition.
13291
- * It defines various configurations such as column settings, actions,
13292
- * and callbacks for rows and data handling.
13293
- *
13336
+ * Manual creator function to define a column in a table programmatically.
13337
+ * It sets various properties and behaviors for the column without using decorators.
13294
13338
  * @template T - The type of data represented in the table rows.
13339
+ * @param {string} propertyKey - The property key to bind the column to.
13340
+ * @param {Partial<TableColumn<T>>} [args] - Partial configuration for the table column.
13341
+ * @param {string} [propertyType] - Optional explicit type (e.g., 'string', 'number', 'date', 'boolean', 'array') to drive defaults.
13342
+ * @param {any} [target] - Optional target prototype object for custom display text extraction.
13343
+ * @returns {TableColumn<T>} - The fully constructed and initialized TableColumn instance.
13295
13344
  */
13296
- class TableDefinition {
13345
+ function buildColumn(propertyKey, args, propertyType, target) {
13346
+ /* Create a new instance of TableColumn with the provided arguments */
13347
+ let tableColumn = new TableColumn(args);
13348
+ /* Set default values for the table column properties */
13349
+ tableColumn.property = propertyKey;
13350
+ tableColumn.name ||= propertyKey;
13351
+ tableColumn.header ||= (target ? getDisplay(target, propertyKey) : null) || tableColumn.name;
13352
+ tableColumn.filter ||= tableColumn.name;
13353
+ tableColumn.sortBy ||= tableColumn.name;
13354
+ tableColumn.content ||= (row) => {
13355
+ /* Get content using property name */
13356
+ var content = Utils.getPropertyValue(row, tableColumn.name);
13357
+ /* Truncate the text if content length is specified */
13358
+ if ((tableColumn?.contentLength ?? 0) > 0) {
13359
+ return Utils.truncateText(content, tableColumn.contentLength);
13360
+ }
13361
+ return content;
13362
+ };
13363
+ tableColumn.configurable = args?.configurable === undefined ? true : args.configurable;
13364
+ tableColumn.display ||= Grid.All;
13365
+ /* Set type to 'Menu' if menu is specified */
13366
+ if (tableColumn.menu) {
13367
+ tableColumn.type ||= TableColumnType.Menu;
13368
+ }
13369
+ /* Set type to 'Icon' if icon is specified */
13370
+ else if (tableColumn.icon) {
13371
+ tableColumn.type ||= TableColumnType.Icon;
13372
+ }
13373
+ /* Set type to 'IconButton' if iconButton is specified */
13374
+ else if (tableColumn.iconButton) {
13375
+ tableColumn.type ||= TableColumnType.IconButton;
13376
+ }
13377
+ /* Set type to enum, if enum type is specified */
13378
+ else if (tableColumn.enumType) {
13379
+ tableColumn.type ||= TableColumnType.Enum;
13380
+ tableColumn.multiple = propertyType?.trim()?.toLowerCase() == 'array';
13381
+ }
13382
+ /* Otherwise, set type depending on property type */
13383
+ else {
13384
+ switch (propertyType?.toLowerCase()) {
13385
+ case 'number':
13386
+ tableColumn.inputType ||= 'number';
13387
+ tableColumn.type ||= TableColumnType.Number;
13388
+ tableColumn.filterOperator = tableColumn.filterOperator != undefined
13389
+ ? tableColumn.filterOperator
13390
+ : FilterOperator.Contains;
13391
+ break;
13392
+ case 'date':
13393
+ tableColumn.inputType ||= 'date';
13394
+ tableColumn.type ||= TableColumnType.Date;
13395
+ tableColumn.maxWidth ||= 115;
13396
+ tableColumn.arrowBefore = tableColumn.arrowBefore !== undefined ? tableColumn.arrowBefore : true;
13397
+ break;
13398
+ case 'boolean':
13399
+ tableColumn.type ||= TableColumnType.Toggle;
13400
+ tableColumn.options ||= [{ id: false, name: $localize `:@@no:No` }, { id: true, name: $localize `:@@yes:Yes` }];
13401
+ tableColumn.maxWidth ||= 70;
13402
+ if (tableColumn.type == TableColumnType.Text) {
13403
+ tableColumn.content = (row) => {
13404
+ /* Get content using property name */
13405
+ var content = Utils.getPropertyValue(row, tableColumn.name);
13406
+ if (content != null) {
13407
+ return content ? $localize `:@@yes:Yes` : $localize `:@@no:No`;
13408
+ }
13409
+ return null;
13410
+ };
13411
+ }
13412
+ break;
13413
+ /* Default to text type for all other property types */
13414
+ default:
13415
+ tableColumn.type ||= TableColumnType.Text;
13416
+ break;
13417
+ }
13418
+ }
13419
+ if (tableColumn.maxWidth) {
13420
+ tableColumn.width ||= tableColumn.maxWidth;
13421
+ }
13422
+ /* Set width to minWidth if width is not specified */
13423
+ return tableColumn;
13424
+ }
13425
+
13426
+ /**
13427
+ * Property decorator to define a column in a table.
13428
+ * It sets various properties and behaviors for the column,
13429
+ * including its name, type, display settings, and associated actions.
13430
+ * @template T - The type of data represented in the table rows.
13431
+ * @param {Partial<TableColumn<T>>} args - Partial configuration for the table column.
13432
+ * @returns {Function} - A decorator function that modifies the target property.
13433
+ */
13434
+ function Column(args) {
13435
+ return function (target, propertyKey) {
13436
+ /* Resolve the design:type metadata from the decorator target */
13437
+ const designType = Reflect.getMetadata("design:type", target, propertyKey)?.name;
13438
+ /* Get old table columns */
13439
+ let previousTableColumns = Reflect.getMetadata(TABLE_COLUMNS_METADATA_KEY, target);
13440
+ /* Override the field with the args, if exists */
13441
+ const previousTableColumn = previousTableColumns?.find(x => x.property == propertyKey);
13442
+ const tableColumnArgs = previousTableColumn
13443
+ ? Object.assign({}, previousTableColumn, args)
13444
+ : args;
13445
+ /* Build the structural column using the factory method */
13446
+ let tableColumn = buildColumn(propertyKey, tableColumnArgs, designType, target);
13447
+ /* Override the field, if exists */
13448
+ previousTableColumns = previousTableColumns?.filter(x => x.property != tableColumn.property);
13449
+ /* Create a copy of the result */
13450
+ let tableColumns = previousTableColumns ? previousTableColumns.concat([tableColumn]) : [tableColumn];
13451
+ /* Set column index */
13452
+ tableColumns.forEach((x, i) => x.index ??= i);
13453
+ /* Sort the columns by index */
13454
+ Utils.sortArray(tableColumns, 'index');
13455
+ /* Override the result in the metadata */
13456
+ Reflect.defineMetadata(TABLE_COLUMNS_METADATA_KEY, tableColumns, target);
13457
+ };
13458
+ }
13459
+
13460
+ /**
13461
+ * Abstract class representing a base entity with common properties and functionality.
13462
+ */
13463
+ class BaseEntity {
13297
13464
  /**
13298
- * @property endpoint
13299
- * @description API endpoint from which table data will be fetched.
13300
- * @type {string}
13465
+ * @property ID
13466
+ * @description Represents the unique identifier of the entity.
13467
+ * @type {number}
13301
13468
  */
13302
- endpoint = '';
13469
+ id;
13303
13470
  /**
13304
- * @property projection
13305
- * @description Optional projection for specifying which fields should be included
13306
- * in the fetched data. Can be a single string or an array of field names.
13307
- * @type {string | string[]}
13471
+ * @property Version
13472
+ * @description Represents the version number of the entity for concurrency control.
13473
+ * @type {number}
13308
13474
  */
13309
- projection;
13475
+ version;
13310
13476
  /**
13311
- * @property includes
13312
- * @description Optional array of related data entities (includes) to be retrieved along
13313
- * with the main data set.
13314
- * @type {string[]}
13477
+ * Constructor to initialize properties of the base entity.
13478
+ * @param init Partial object containing initial property values.
13315
13479
  */
13316
- includes;
13480
+ constructor(init) {
13481
+ Object.assign(this, init);
13482
+ }
13483
+ }
13484
+ __decorate([
13485
+ Column({
13486
+ filterOperator: FilterOperator.Contains,
13487
+ index: 1100,
13488
+ columnSets: ['base', 'common'],
13489
+ header: $localize `:@@id:ID`,
13490
+ arrowBefore: true
13491
+ }),
13492
+ prop(),
13493
+ __metadata("design:type", Number)
13494
+ ], BaseEntity.prototype, "id", void 0);
13495
+
13496
+ /**
13497
+ * Abstract class extending the base entity with audit-related properties.
13498
+ * Includes information about entity creation and updates.
13499
+ */
13500
+ class AuditEntity extends BaseEntity {
13317
13501
  /**
13318
- * @property showAction
13319
- * @description Flag to indicate if action columns (e.g., edit, delete buttons)
13320
- * should be displayed in the table. Defaults to `true`.
13321
- * @type {boolean}
13502
+ * @property Created By
13503
+ * @description Specifies the username or identifier of the user who created the entity.
13504
+ * @type {string}
13322
13505
  */
13323
- showAction = true;
13506
+ createdBy;
13324
13507
  /**
13325
- * @property selectable
13326
- * @description Flag to indicate if rows can be selected (e.g., with checkboxes).
13327
- * Defaults to `true`.
13328
- * @type {boolean}
13508
+ * @property Created Date
13509
+ * @description Specifies the date and time when the entity was created.
13510
+ * @type {Date}
13329
13511
  */
13330
- selectable = true;
13512
+ createdDate;
13331
13513
  /**
13332
- * @property addable
13333
- * @description Flag to indicate if new items can be added to the table.
13334
- * Defaults to `true`.
13335
- * @type {boolean}
13514
+ * @property Updated By
13515
+ * @description Specifies the username or identifier of the user who last updated the entity.
13516
+ * @type {string}
13336
13517
  */
13337
- addable = true;
13518
+ updatedBy;
13338
13519
  /**
13339
- * @property editable
13340
- * @description Flag to indicate if rows can be edited. Defaults to `true`.
13341
- * @type {boolean}
13520
+ * @property Updated Date
13521
+ * @description Specifies the date and time when the entity was last updated.
13522
+ * @type {Date}
13342
13523
  */
13343
- editable = true;
13524
+ updatedDate;
13344
13525
  /**
13345
- * @property deletable
13346
- * @description Flag to indicate if rows can be deleted. Defaults to `true`.
13347
- * @type {boolean}
13526
+ * Constructor to initialize properties of the audit entity.
13527
+ * @param init Partial object containing initial property values.
13348
13528
  */
13349
- deletable = true;
13529
+ constructor(init) {
13530
+ super(init);
13531
+ Object.assign(this, init);
13532
+ }
13533
+ }
13534
+ __decorate([
13535
+ Column({
13536
+ index: 1000,
13537
+ columnSets: ['audit', 'common'],
13538
+ header: $localize `:@@createdDate:Created date`,
13539
+ arrowBefore: true,
13540
+ display: Grid.Sm
13541
+ }),
13542
+ __metadata("design:type", Date)
13543
+ ], AuditEntity.prototype, "createdDate", void 0);
13544
+
13545
+ /**
13546
+ * Represents a user entity with audit-related information such as display name, email, and letter.
13547
+ */
13548
+ class AuditUser {
13350
13549
  /**
13351
- * @property downloadable
13352
- * @description Flag to indicate if table data can be downloaded (e.g., as CSV or Excel).
13353
- * @type {boolean}
13550
+ * @property Display Name
13551
+ * @description The full name or preferred display name of the user.
13552
+ * @type {string}
13354
13553
  */
13355
- downloadable;
13554
+ displayName;
13356
13555
  /**
13357
- * @property duplicable
13358
- * @description Flag to indicate if rows can be duplicated.
13359
- * @type {boolean}
13556
+ * @property Email
13557
+ * @description The email address of the user.
13558
+ * @type {string}
13360
13559
  */
13361
- duplicable;
13560
+ email;
13362
13561
  /**
13363
- * @property exportable
13364
- * @description Determines if the table is exportable.
13365
- * @type {boolean}
13562
+ * @property Letter
13563
+ * @description The first letter or an abbreviation associated with the user.
13564
+ * @type {string}
13366
13565
  */
13367
- exportable = true;
13566
+ letter;
13567
+ }
13568
+
13569
+ /**
13570
+ * Represents a common error with a code and description.
13571
+ * Typically used to encapsulate error details for consistent error handling.
13572
+ */
13573
+ class CommonError {
13368
13574
  /**
13369
- * @property exportFileName
13370
- * @description The name of the file to export.
13575
+ * @property Code
13576
+ * @description The unique code identifying the type of error.
13371
13577
  * @type {string}
13372
13578
  */
13373
- exportFileName;
13579
+ code;
13374
13580
  /**
13375
- * @property sticky
13376
- * @description Flag to indicate whether the table headers or columns should stick
13377
- * to the viewport during scrolling. Defaults to `false`.
13378
- * @type {boolean}
13581
+ * @property Description
13582
+ * @description A human-readable message providing details about the error.
13583
+ * @type {string}
13379
13584
  */
13380
- sticky = false;
13585
+ description;
13381
13586
  /**
13382
- * @property columns
13383
- * @description Array of table columns that define the structure and data types
13384
- * of each column in the table.
13385
- * @type {TableColumn<T>[]}
13587
+ * Constructs a new instance of the `CommonError` class.
13588
+ *
13589
+ * @param code The unique error code.
13590
+ * @param description A descriptive message explaining the error.
13386
13591
  */
13387
- columns = [];
13592
+ constructor(code, description) {
13593
+ this.code = code;
13594
+ this.description = description;
13595
+ }
13596
+ }
13597
+
13598
+ /**
13599
+ * Represents the context of a handler operation, including the operation result, success status, and associated errors.
13600
+ *
13601
+ * @typeparam TResult The type of the result encapsulated by the context.
13602
+ */
13603
+ class CommonHandlerContext {
13388
13604
  /**
13389
- * @property hideColumns
13390
- * @description Optional array of column keys that should be hidden from view.
13391
- * @type {string[]}
13605
+ * @property Errors
13606
+ * @description A collection of errors that occurred during the operation. Empty if the operation succeeded.
13607
+ * @type {CommonError[]}
13392
13608
  */
13393
- hideColumns;
13394
- /**
13395
- * @property rowNgClass
13396
- * @description Function to dynamically assign CSS classes to rows based on the row data
13397
- * and context. Can be used for conditional row styling.
13398
- * @type {(x?: T, ctx?: IGenericListComponent<T>) => any}
13399
- */
13400
- rowNgClass;
13401
- /**
13402
- * @property rowClick
13403
- * @description Callback function for handling row click events.
13404
- * Invoked when a row is clicked.
13405
- * @type {(x?: T, ctx?: IGenericListComponent<T>) => any}
13406
- */
13407
- rowClick;
13408
- /**
13409
- * @property onEdit
13410
- * @description Callback function for handling edit actions.
13411
- * Invoked when the edit button is clicked for a row.
13412
- * @type {(x?: T, ctx?: IGenericListComponent<T>) => any}
13413
- */
13414
- onEdit;
13415
- /**
13416
- * @property detailsTemplate
13417
- * @description Name of the template to use for displaying additional row details.
13418
- * @type {string}
13419
- */
13420
- detailsTemplate;
13421
- /**
13422
- * @property actions
13423
- * @description Array of action items (e.g., custom buttons) available for each row in the table.
13424
- * Actions can be context-sensitive based on the row data and table context.
13425
- * @type {ActionItem<T, IGenericListComponent<T>>[]}
13426
- */
13427
- actions = [];
13428
- /**
13429
- * @property columnSets
13430
- * @description Used to display specific columns in the table.
13431
- * This array defines sets of columns that can be shown
13432
- * based on the active configuration, allowing for dynamic table
13433
- * column customization.
13434
- * @type {string[]}
13435
- */
13436
- columnSets = [];
13437
- /**
13438
- * Constructor for initializing the table definition with optional values.
13439
- * Merges the provided initialization object with default properties.
13440
- *
13441
- * @param init - Optional partial table definition to initialize values.
13442
- */
13443
- constructor(init) {
13444
- Object.assign(this, init);
13445
- }
13446
- }
13447
-
13448
- /**
13449
- * Gets classes decoarated with @Table
13450
- * @param origin
13451
- * @returns
13452
- */
13453
- function getTableDefinition(origin) {
13454
- /* Save the table defintion in the metadata */
13455
- var tableDefinition = Reflect.getMetadata(tableDefinitionMetadataKey, origin) ?? new TableDefinition({});
13456
- if (tableDefinition) {
13457
- /* Set column in the table definition */
13458
- tableDefinition.columns = Reflect.getMetadata(tableColumnsMetadataKey, Reflect.construct(origin, []))
13459
- ?.filter((x) => !x.hidden && !tableDefinition.hideColumns?.some(y => y.trim() == x.name.trim()));
13460
- /* Sort the columns by index */
13461
- Utils.sortArray(tableDefinition.columns || [], 'index');
13462
- /* Set endpoint from the decorator @Api, if any */
13463
- var endpoint = Reflect.getMetadata(endpointMetadataKey, origin);
13464
- if (endpoint) {
13465
- tableDefinition.endpoint = endpoint;
13466
- }
13467
- }
13468
- return tableDefinition;
13469
- }
13470
-
13471
- /**
13472
- * Class decorator to create a mat-table
13473
- * @param tableDefinition
13474
- * @returns
13475
- */
13476
- function Table(tableDefinition) {
13477
- return function (target) {
13478
- if (tableDefinition?.columns) {
13479
- /* Add action menus from table definition, if any */
13480
- var actionColmun = tableDefinition.columns?.find(x => x.name == 'action');
13481
- if (!actionColmun) {
13482
- actionColmun = new TableColumn({
13483
- index: 2000,
13484
- name: 'action',
13485
- columnSets: ['action', 'common'],
13486
- type: TableColumnType.Action,
13487
- disabled: true,
13488
- rowMenuItems: actions,
13489
- configurable: false,
13490
- stickyEnd: true
13491
- });
13492
- /* Add the action column into the table columns */
13493
- tableDefinition.columns.push(actionColmun);
13494
- }
13495
- /* Get custom action, if any */
13496
- var actions = tableDefinition?.actions;
13497
- if (actions != null && actionColmun != null) {
13498
- actionColmun.rowMenuItems ??= [];
13499
- actions.forEach(y => actionColmun.rowMenuItems.push(y));
13500
- }
13501
- }
13502
- /* Save the table defintion in the metadata */
13503
- Reflect.defineMetadata(tableDefinitionMetadataKey, tableDefinition, target);
13504
- };
13505
- }
13506
- /**
13507
- * Property decorator to create table columns
13508
- * @param args
13509
- * @returns
13510
- */
13511
- function Column(args) {
13512
- return function (target, propertyKey) {
13513
- let tableColumn = new TableColumn(args);
13514
- tableColumn.name ||= propertyKey;
13515
- tableColumn.header ||= Reflect.getMetadata(headerMetadataKey, target, propertyKey) || tableColumn.name;
13516
- tableColumn.filter ||= tableColumn.name;
13517
- tableColumn.sortBy ||= tableColumn.name;
13518
- tableColumn.content ||= (row) => {
13519
- /* Get content using property name */
13520
- var content = Utils.getPropertyValue(row, tableColumn.name);
13521
- /* Truncate the text if content length is specified */
13522
- if ((tableColumn?.contentLength ?? 0) > 0) {
13523
- return Utils.truncateText(content, tableColumn.contentLength);
13524
- }
13525
- return content;
13526
- };
13527
- tableColumn.configurable = args?.configurable === undefined ? true : args.configurable;
13528
- tableColumn.display ||= Grid.All;
13529
- /* Set type to 'Menu' if menu is specified */
13530
- if (tableColumn.menu) {
13531
- tableColumn.type ||= TableColumnType.Menu;
13532
- }
13533
- /* Set type to 'Icon' if icon is specified */
13534
- else if (tableColumn.icon) {
13535
- tableColumn.type ||= TableColumnType.Icon;
13536
- }
13537
- /* Set type to 'IconButton' if iconButton is specified */
13538
- else if (tableColumn.iconButton) {
13539
- tableColumn.type ||= TableColumnType.IconButton;
13540
- }
13541
- /* Set type to enum, if enum type is specified */
13542
- else if (tableColumn.enumType) {
13543
- tableColumn.type ||= TableColumnType.Enum;
13544
- tableColumn.multiple = Reflect.getMetadata("design:type", target, propertyKey)?.name?.trim()?.toLowerCase() == 'array';
13545
- }
13546
- /* Otherwiese, set type depending on property type */
13547
- else {
13548
- /* Get property type */
13549
- var propertyType = Reflect.getMetadata("design:type", target, propertyKey)?.name;
13550
- switch (propertyType?.toLowerCase()) {
13551
- case 'number':
13552
- tableColumn.inputType ||= 'number';
13553
- tableColumn.type ||= TableColumnType.Number;
13554
- tableColumn.filterOperator = tableColumn.filterOperator != undefined ? tableColumn.filterOperator : FilterOperator.Contains;
13555
- break;
13556
- case 'date':
13557
- tableColumn.inputType ||= 'date';
13558
- tableColumn.type ||= TableColumnType.Date;
13559
- tableColumn.maxWidth ||= 115;
13560
- tableColumn.arrowBefore = tableColumn.arrowBefore !== undefined ? tableColumn.arrowBefore : true;
13561
- break;
13562
- case 'boolean':
13563
- tableColumn.type ||= TableColumnType.Toggle;
13564
- tableColumn.options ||= [{ id: false, name: $localize `:@@no:No` }, { id: true, name: $localize `:@@yes:Yes` }];
13565
- tableColumn.maxWidth ||= 70;
13566
- if (tableColumn.type == TableColumnType.Text) {
13567
- tableColumn.content = (row) => {
13568
- /* Get content using property name */
13569
- var content = Utils.getPropertyValue(row, tableColumn.name);
13570
- if (content != null) {
13571
- return content ? $localize `:@@yes:Yes` : $localize `:@@no:No`;
13572
- }
13573
- return null;
13574
- };
13575
- }
13576
- break;
13577
- default:
13578
- tableColumn.type ||= TableColumnType.Text;
13579
- break;
13580
- }
13581
- }
13582
- if (tableColumn.maxWidth) {
13583
- tableColumn.width ||= tableColumn.maxWidth;
13584
- }
13585
- /* Get old table columns */
13586
- let previousTableColumns = Reflect.getMetadata(tableColumnsMetadataKey, target);
13587
- /* Override the field, if exists */
13588
- previousTableColumns = previousTableColumns?.filter(x => x.name != tableColumn.name);
13589
- /* Create a copy of the result */
13590
- let tableColumns = previousTableColumns ? previousTableColumns.concat([tableColumn]) : [tableColumn];
13591
- /* Set column index */
13592
- tableColumns.forEach((x, i) => x.index ??= i);
13593
- /* Sort the columns by index */
13594
- Utils.sortArray(tableColumns, 'index');
13595
- /* Override the result in the metadata */
13596
- Reflect.defineMetadata(tableColumnsMetadataKey, tableColumns, target);
13597
- };
13598
- }
13599
- /**
13600
- * Decorator function to define columns for a table object.
13601
- * @param type The constructor function of the table object.
13602
- * @returns A decorator function.
13603
- */
13604
- function ColumnObject(type) {
13605
- return function (target, propertyKey) {
13606
- /* Retrieve table definition */
13607
- var tableDef = getTableDefinition(type);
13608
- /* Retrieve columns from the table definition */
13609
- var columns = tableDef.columns;
13610
- /* Update column names with property key prefix */
13611
- columns?.forEach(x => x.name = `${propertyKey}.${x.name}`);
13612
- /* Get existing table columns from metadata */
13613
- let previousTableColumns = Reflect.getMetadata(tableColumnsMetadataKey, target);
13614
- /* Create a copy of the existing columns array and append new columns */
13615
- let tableColumns = previousTableColumns ? previousTableColumns.concat(columns ?? []) : [];
13616
- /* Set column index if not already set */
13617
- tableColumns.forEach((x, i) => x.index ??= i);
13618
- /* Sort the columns by index */
13619
- Utils.sortArray(tableColumns, 'index');
13620
- /* Override the table columns in the metadata */
13621
- Reflect.defineMetadata(tableColumnsMetadataKey, tableColumns, target);
13622
- };
13623
- }
13624
-
13625
- /**
13626
- * Abstract class representing a base entity with common properties and functionality.
13627
- */
13628
- class BaseEntity {
13629
- /**
13630
- * @property ID
13631
- * @description Represents the unique identifier of the entity.
13632
- * @type {number}
13633
- */
13634
- id;
13635
- /**
13636
- * @property Version
13637
- * @description Represents the version number of the entity for concurrency control.
13638
- * @type {number}
13639
- */
13640
- version;
13641
- /**
13642
- * Constructor to initialize properties of the base entity.
13643
- * @param init Partial object containing initial property values.
13644
- */
13645
- constructor(init) {
13646
- Object.assign(this, init);
13647
- }
13648
- }
13649
- __decorate([
13650
- Column({
13651
- filterOperator: FilterOperator.Contains,
13652
- index: 1100,
13653
- columnSets: ['base', 'common'],
13654
- header: $localize `:@@id:ID`,
13655
- arrowBefore: true
13656
- }),
13657
- prop(),
13658
- __metadata("design:type", Number)
13659
- ], BaseEntity.prototype, "id", void 0);
13660
-
13661
- /**
13662
- * Abstract class extending the base entity with audit-related properties.
13663
- * Includes information about entity creation and updates.
13664
- */
13665
- class AuditEntity extends BaseEntity {
13666
- /**
13667
- * @property Created By
13668
- * @description Specifies the username or identifier of the user who created the entity.
13669
- * @type {string}
13670
- */
13671
- createdBy;
13672
- /**
13673
- * @property Created Date
13674
- * @description Specifies the date and time when the entity was created.
13675
- * @type {Date}
13676
- */
13677
- createdDate;
13678
- /**
13679
- * @property Updated By
13680
- * @description Specifies the username or identifier of the user who last updated the entity.
13681
- * @type {string}
13682
- */
13683
- updatedBy;
13684
- /**
13685
- * @property Updated Date
13686
- * @description Specifies the date and time when the entity was last updated.
13687
- * @type {Date}
13688
- */
13689
- updatedDate;
13690
- /**
13691
- * Constructor to initialize properties of the audit entity.
13692
- * @param init Partial object containing initial property values.
13693
- */
13694
- constructor(init) {
13695
- super(init);
13696
- Object.assign(this, init);
13697
- }
13698
- }
13699
- __decorate([
13700
- Column({
13701
- index: 1000,
13702
- columnSets: ['audit', 'common'],
13703
- header: $localize `:@@createdDate:Created date`,
13704
- arrowBefore: true,
13705
- display: Grid.Sm
13706
- }),
13707
- __metadata("design:type", Date)
13708
- ], AuditEntity.prototype, "createdDate", void 0);
13709
-
13710
- /**
13711
- * Represents a user entity with audit-related information such as display name, email, and letter.
13712
- */
13713
- class AuditUser {
13714
- /**
13715
- * @property Display Name
13716
- * @description The full name or preferred display name of the user.
13717
- * @type {string}
13718
- */
13719
- displayName;
13720
- /**
13721
- * @property Email
13722
- * @description The email address of the user.
13723
- * @type {string}
13724
- */
13725
- email;
13726
- /**
13727
- * @property Letter
13728
- * @description The first letter or an abbreviation associated with the user.
13729
- * @type {string}
13730
- */
13731
- letter;
13732
- }
13733
-
13734
- /**
13735
- * Represents a common error with a code and description.
13736
- * Typically used to encapsulate error details for consistent error handling.
13737
- */
13738
- class CommonError {
13739
- /**
13740
- * @property Code
13741
- * @description The unique code identifying the type of error.
13742
- * @type {string}
13743
- */
13744
- code;
13745
- /**
13746
- * @property Description
13747
- * @description A human-readable message providing details about the error.
13748
- * @type {string}
13749
- */
13750
- description;
13751
- /**
13752
- * Constructs a new instance of the `CommonError` class.
13753
- *
13754
- * @param code The unique error code.
13755
- * @param description A descriptive message explaining the error.
13756
- */
13757
- constructor(code, description) {
13758
- this.code = code;
13759
- this.description = description;
13760
- }
13761
- }
13762
-
13763
- /**
13764
- * Represents the context of a handler operation, including the operation result, success status, and associated errors.
13765
- *
13766
- * @typeparam TResult The type of the result encapsulated by the context.
13767
- */
13768
- class CommonHandlerContext {
13769
- /**
13770
- * @property Errors
13771
- * @description A collection of errors that occurred during the operation. Empty if the operation succeeded.
13772
- * @type {CommonError[]}
13773
- */
13774
- errors = [];
13609
+ errors = [];
13775
13610
  /**
13776
13611
  * @property Result
13777
13612
  * @description The result of the operation. Its value depends on the success or failure of the operation.
@@ -15074,8 +14909,15 @@ class GenericService {
15074
14909
  * @param observeResponse Whether to observe the full response (default: false)
15075
14910
  */
15076
14911
  get(id, params, headers, handleError = true, observeResponse = false) {
14912
+ /* Normalize the 'projection' parameter in query parameters */
14913
+ const parsedParams = this.normalizeProjectionParam(params);
14914
+ /* Make the HTTP GET request */
15077
14915
  let request = this.http
15078
- .get(`${this.endpoint}/${id}`, { observe: (observeResponse ? 'response' : 'body'), params: Utils.toHttpParams(params), headers: this.toHttpHeaders(headers) });
14916
+ .get(`${this.endpoint}/${id}`, {
14917
+ observe: (observeResponse ? 'response' : 'body'),
14918
+ params: parsedParams instanceof HttpParams ? parsedParams : Utils.toHttpParams(parsedParams),
14919
+ headers: this.toHttpHeaders(headers)
14920
+ });
15079
14921
  /* Handle error */
15080
14922
  if (handleError) {
15081
14923
  request = request.pipe(catchError(this.handleError('get')));
@@ -15099,6 +14941,7 @@ class GenericService {
15099
14941
  * @param handleError Whether to handle errors (default: true)
15100
14942
  */
15101
14943
  count(params, path, headers, handleError = true) {
14944
+ /* Make the HTTP GET request to count entities */
15102
14945
  let request = this.http
15103
14946
  .get(`${this.endpoint}${path ? path : '/count'}`, { params: Utils.toHttpParams(params), headers: this.toHttpHeaders(headers) });
15104
14947
  /* Handle error */
@@ -15124,6 +14967,7 @@ class GenericService {
15124
14967
  * @returns Observable with the response data
15125
14968
  */
15126
14969
  getList(params, path, headers) {
14970
+ /* Normalize the 'projection' parameter in query parameters */
15127
14971
  const parsedParams = this.normalizeProjectionParam(params);
15128
14972
  return this.http
15129
14973
  .get(`${this.endpoint}${path ? path : ''}`, {
@@ -15177,177 +15021,99 @@ class GenericService {
15177
15021
  getListAsObservable() {
15178
15022
  return this.list.asObservable();
15179
15023
  }
15180
- /**
15181
- * Creates a new entity
15182
- * @param entity The entity to create
15183
- * @param path Optional relative path to the action
15184
- * @param httpOptions Optional HTTP options (headers, etc.)
15185
- * @param handleError Whether to handle errors (default: true)
15186
- */
15187
- create(entity, path, httpOptions, handleError = true) {
15024
+ create(entity, path, optionsOrHttpOptions, handleError = true, showMessage = false) {
15025
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, handleError, showMessage);
15026
+ const options = this.withShowMessage(resolved.httpOptions, resolved.showMessage);
15188
15027
  let request = this.http
15189
- .post(`${this.endpoint}${path ? path : ''}`, entity, httpOptions);
15028
+ .post(`${this.endpoint}${path ? path : ''}`, entity, options);
15190
15029
  /* Handle error */
15191
- if (handleError) {
15030
+ if (resolved.handleError) {
15192
15031
  request = request.pipe(catchError(this.handleError('create')));
15193
15032
  }
15194
15033
  return request;
15195
15034
  }
15196
- /**
15197
- * Asynchronously creates a new entity
15198
- * @param entity The entity to create
15199
- * @param path Optional relative path to the action
15200
- * @param httpOptions Optional HTTP options (headers, etc.)
15201
- * @returns Promise resolving to the created entity
15202
- */
15203
- async createAsync(entity, path, httpOptions) {
15204
- return await firstValueFrom(this.create(entity, path, httpOptions));
15035
+ async createAsync(entity, path, optionsOrHttpOptions, showMessage = false) {
15036
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, true, showMessage);
15037
+ return await firstValueFrom(this.create(entity, path, resolved.httpOptions, resolved.handleError, resolved.showMessage));
15205
15038
  }
15206
- /**
15207
- * Updates an existing entity asynchronously
15208
- * @param id The ID of the entity to update
15209
- * @param entity The updated entity data
15210
- * @param path Optional relative path to the action
15211
- * @param httpOptions Optional HTTP options (headers, etc.)
15212
- * @param handleError Whether to handle errors (default: true)
15213
- */
15214
- update(id, entity, path, httpOptions, handleError = true) {
15039
+ update(id, entity, path, optionsOrHttpOptions, handleError = true, showMessage = false) {
15040
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, handleError, showMessage);
15041
+ const options = this.withShowMessage(resolved.httpOptions, resolved.showMessage);
15215
15042
  let request = this.http
15216
- .put(`${this.endpoint}${path ? path : ''}/${id}`, entity, httpOptions);
15043
+ .put(`${this.endpoint}${path ? path : ''}/${id}`, entity, options);
15217
15044
  /* Handle error */
15218
- if (handleError) {
15045
+ if (resolved.handleError) {
15219
15046
  request = request.pipe(catchError(this.handleError('update')));
15220
15047
  }
15221
15048
  return request;
15222
15049
  }
15223
- /**
15224
- * Asynchronously updates an existing entity
15225
- * @param id The ID of the entity to update
15226
- * @param entity The updated entity data
15227
- * @param path Optional relative path to the action
15228
- * @param httpOptions Optional HTTP options (headers, etc.)
15229
- * @returns Promise resolving to the updated entity
15230
- */
15231
- async updateAsync(id, entity, path, httpOptions) {
15232
- return await firstValueFrom(this.update(id, entity, path, httpOptions));
15050
+ async updateAsync(id, entity, path, optionsOrHttpOptions, showMessage = false) {
15051
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, true, showMessage);
15052
+ return await firstValueFrom(this.update(id, entity, path, resolved.httpOptions, resolved.handleError, resolved.showMessage));
15233
15053
  }
15234
- /**
15235
- * Applies a JSON Patch to an entity
15236
- * @param id The ID of the item to patch
15237
- * @param body The patch body
15238
- * @param path Optional relative path to the action
15239
- * @param httpOptions Optional HTTP options (headers, etc.)
15240
- * @param handleError Whether to handle errors (default: true)
15241
- */
15242
- patch(id, body, path, httpOptions, handleError = true) {
15054
+ patch(id, body, path, optionsOrHttpOptions, handleError = true, showMessage = false) {
15055
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, handleError, showMessage);
15056
+ const options = this.withShowMessage(resolved.httpOptions, resolved.showMessage) || {};
15243
15057
  /* Ensure correct content-type for patch */
15244
- const headers = new HttpHeaders({
15245
- 'Content-Type': 'application/json-patch+json'
15246
- });
15247
- /* Merge headers */
15248
- const options = {
15249
- ...httpOptions,
15250
- headers: httpOptions?.headers
15251
- ? httpOptions.headers.append('Content-Type', 'application/json-patch+json')
15252
- : headers
15253
- };
15058
+ const mergedHeaders = options?.headers instanceof HttpHeaders
15059
+ ? options.headers
15060
+ : this.toHttpHeaders(options?.headers);
15061
+ options.headers = mergedHeaders.set('Content-Type', 'application/json-patch+json');
15254
15062
  /* Create request */
15255
15063
  let request = this.http.patch(`${this.endpoint}${path ? path : ''}/${id}`, body, options);
15256
15064
  /* Handle error */
15257
- if (handleError) {
15065
+ if (resolved.handleError) {
15258
15066
  request = request.pipe(catchError(this.handleError('patch')));
15259
15067
  }
15260
15068
  return request;
15261
15069
  }
15262
- /**
15263
- * Asynchronously applies a JSON Patch to an entity
15264
- * @param id The ID of the item to patch
15265
- * @param body The patch body
15266
- * @param path Optional relative path to the action
15267
- * @param httpOptions Optional HTTP options (headers, etc.)
15268
- * @returns Promise resolving to the patched entity
15269
- */
15270
- async patchAsync(id, body, path, httpOptions) {
15271
- return await firstValueFrom(this.patch(id, body, path, httpOptions));
15070
+ async patchAsync(id, body, path, optionsOrHttpOptions, showMessage = false) {
15071
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, true, showMessage);
15072
+ return await firstValueFrom(this.patch(id, body, path, resolved.httpOptions, resolved.handleError, resolved.showMessage));
15272
15073
  }
15273
- /**
15274
- * Applies a JSON Patch to multiple entities
15275
- * @param ids The IDs of the items to patch
15276
- * @param body The patch body
15277
- * @param path Optional relative path to the action
15278
- * @param httpOptions Optional HTTP options (headers, etc.)
15279
- * @param handleError Whether to handle errors (default: true)
15280
- */
15281
- patchList(ids, body, path, httpOptions, handleError = true) {
15074
+ patchList(ids, body, path, optionsOrHttpOptions, handleError = true, showMessage = false) {
15075
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, handleError, showMessage);
15076
+ const options = this.withShowMessage(resolved.httpOptions, resolved.showMessage);
15282
15077
  let request = this.http
15283
- .patch(`${this.endpoint}${path ? path : ''}`, body, Object.assign(httpOptions || {}, { params: Utils.toHttpParams({ ids: ids }) }));
15078
+ .patch(`${this.endpoint}${path ? path : ''}`, body, Object.assign(options || {}, { params: Utils.toHttpParams({ ids: ids }) }));
15284
15079
  /* Handle error */
15285
- if (handleError) {
15080
+ if (resolved.handleError) {
15286
15081
  request = request.pipe(catchError(this.handleError('patch')));
15287
15082
  }
15288
15083
  return request;
15289
15084
  }
15290
- /**
15291
- * Asynchronously applies a JSON Patch to multiple entities
15292
- * @param ids The IDs of the items to patch
15293
- * @param body The patch body
15294
- * @param path Optional relative path to the action
15295
- * @param httpOptions Optional HTTP options (headers, etc.)
15296
- * @returns Promise resolving to the patched entities
15297
- */
15298
- async patchListAsync(ids, body, path, httpOptions) {
15299
- return await firstValueFrom(this.patchList(ids, body, path, httpOptions));
15085
+ async patchListAsync(ids, body, path, optionsOrHttpOptions, showMessage = false) {
15086
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, true, showMessage);
15087
+ return await firstValueFrom(this.patchList(ids, body, path, resolved.httpOptions, resolved.handleError, resolved.showMessage));
15300
15088
  }
15301
- /**
15302
- * Deletes an entity by ID
15303
- * @param id The ID of the item to delete
15304
- * @param path Optional relative path to the action
15305
- * @param httpOptions Optional HTTP options (headers, etc.)
15306
- * @param handleError Whether to handle errors (default: true)
15307
- */
15308
- delete(id, path, httpOptions, handleError = true) {
15089
+ delete(id, path, optionsOrHttpOptions, handleError = true, showMessage = false) {
15090
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, handleError, showMessage);
15091
+ const options = this.withShowMessage(resolved.httpOptions, resolved.showMessage);
15309
15092
  let request = this.http
15310
- .delete(`${this.endpoint}${path ? path : ''}/${id}`, httpOptions);
15093
+ .delete(`${this.endpoint}${path ? path : ''}/${id}`, options);
15311
15094
  /* Handle error */
15312
- if (handleError) {
15095
+ if (resolved.handleError) {
15313
15096
  request = request.pipe(catchError(this.handleError('delete')));
15314
15097
  }
15315
15098
  return request;
15316
15099
  }
15317
- /**
15318
- * Asynchronously deletes an entity by ID
15319
- * @param id The ID of the item to delete
15320
- * @param path Optional relative path to the action
15321
- * @param httpOptions Optional HTTP options (headers, etc.)
15322
- * @returns Promise resolving to the delete result
15323
- */
15324
- async deleteAsync(id, path, httpOptions) {
15325
- return await firstValueFrom(this.delete(id, path, httpOptions));
15100
+ async deleteAsync(id, path, optionsOrHttpOptions, showMessage = false) {
15101
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, true, showMessage);
15102
+ return await firstValueFrom(this.delete(id, path, resolved.httpOptions, resolved.handleError, resolved.showMessage));
15326
15103
  }
15327
- /**
15328
- * Deletes multiple entities by IDs
15329
- * @param ids The IDs of the items to delete
15330
- * @param path Optional relative path to the action
15331
- * @param httpOptions Optional HTTP options (headers, etc.)
15332
- * @param handleError Whether to handle errors (default: true)
15333
- */
15334
- deleteList(ids, path, httpOptions, handleError = true) {
15335
- let request = this.http.delete(`${this.endpoint}${path ? path : ''}`, Object.assign(httpOptions || {}, { params: Utils.toHttpParams({ ids: ids }) }));
15104
+ deleteList(ids, path, optionsOrHttpOptions, handleError = true, showMessage = false) {
15105
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, handleError, showMessage);
15106
+ const options = this.withShowMessage(resolved.httpOptions, resolved.showMessage);
15107
+ let request = this.http.delete(`${this.endpoint}${path ? path : ''}`, Object.assign(options || {}, { params: Utils.toHttpParams({ ids: ids }) }));
15336
15108
  /* Handle error */
15337
- if (handleError) {
15109
+ if (resolved.handleError) {
15338
15110
  request = request.pipe(catchError(this.handleError('deleteList')));
15339
15111
  }
15340
15112
  return request;
15341
15113
  }
15342
- /**
15343
- * Asynchronously deletes multiple entities by IDs
15344
- * @param ids The IDs of the items to delete
15345
- * @param path Optional relative path to the action
15346
- * @param httpOptions Optional HTTP options (headers, etc.)
15347
- * @returns Promise resolving to the delete result
15348
- */
15349
- async deleteListAsync(ids, path, httpOptions) {
15350
- return await firstValueFrom(this.deleteList(ids, path, httpOptions));
15114
+ async deleteListAsync(ids, path, optionsOrHttpOptions, showMessage = false) {
15115
+ const resolved = this.resolveMutationOptions(optionsOrHttpOptions, true, showMessage);
15116
+ return await firstValueFrom(this.deleteList(ids, path, resolved.httpOptions, resolved.handleError, resolved.showMessage));
15351
15117
  }
15352
15118
  /**
15353
15119
  * Downloads a file from the server
@@ -15385,16 +15151,16 @@ class GenericService {
15385
15151
  * Duplicates a record by ID
15386
15152
  * @param id The ID of the record to duplicate
15387
15153
  */
15388
- duplicate(id) {
15389
- return this.create(null, `/duplicate/${id}`);
15154
+ duplicate(id, showMessage = false) {
15155
+ return this.create(null, `/duplicate/${id}`, undefined, true, showMessage);
15390
15156
  }
15391
15157
  /**
15392
15158
  * Asynchronously duplicates a record by ID
15393
15159
  * @param id The ID of the record to duplicate
15394
15160
  * @returns Promise resolving to the duplicated record
15395
15161
  */
15396
- async duplicateAsync(id) {
15397
- return await firstValueFrom(this.duplicate(id));
15162
+ async duplicateAsync(id, showMessage = false) {
15163
+ return await firstValueFrom(this.duplicate(id, showMessage));
15398
15164
  }
15399
15165
  /**
15400
15166
  * Uploads a file to the server
@@ -15462,6 +15228,52 @@ class GenericService {
15462
15228
  .filter(key => body[key] != null && body[key] != '')
15463
15229
  .reduce((p, key) => p.set(key, body[key]), new HttpHeaders());
15464
15230
  }
15231
+ /**
15232
+ * Adds the Show-Message header to request options when enabled
15233
+ * @param httpOptions Existing HTTP options
15234
+ * @param showMessage Whether to add the Show-Message header
15235
+ * @returns HTTP options with optional Show-Message header
15236
+ */
15237
+ withShowMessage(httpOptions, showMessage = false) {
15238
+ if (!showMessage) {
15239
+ return httpOptions;
15240
+ }
15241
+ /* Create a copy of the httpOptions to avoid mutating the original object */
15242
+ const options = { ...(httpOptions || {}) };
15243
+ const headers = options.headers instanceof HttpHeaders
15244
+ ? options.headers
15245
+ : this.toHttpHeaders(options.headers);
15246
+ /* Set the Show-Message header to 'Yes' */
15247
+ options.headers = headers.set('Show-Message', 'Yes');
15248
+ return options;
15249
+ }
15250
+ /**
15251
+ * Normalizes legacy mutation arguments and options-object overload arguments
15252
+ * @param optionsOrHttpOptions Legacy httpOptions or options object
15253
+ * @param handleError Legacy handleError value
15254
+ * @param showMessage Legacy showMessage value
15255
+ * @returns Normalized mutation options
15256
+ */
15257
+ resolveMutationOptions(optionsOrHttpOptions, handleError = true, showMessage = false) {
15258
+ if (optionsOrHttpOptions && typeof optionsOrHttpOptions === 'object') {
15259
+ const options = optionsOrHttpOptions;
15260
+ /* Interpret as options-object overload only when one of its dedicated keys exists */
15261
+ if (Object.prototype.hasOwnProperty.call(options, 'httpOptions') ||
15262
+ Object.prototype.hasOwnProperty.call(options, 'handleError') ||
15263
+ Object.prototype.hasOwnProperty.call(options, 'showMessage')) {
15264
+ return {
15265
+ httpOptions: options.httpOptions ?? {},
15266
+ handleError: options.handleError ?? true,
15267
+ showMessage: options.showMessage ?? false
15268
+ };
15269
+ }
15270
+ }
15271
+ return {
15272
+ httpOptions: optionsOrHttpOptions ?? {},
15273
+ handleError,
15274
+ showMessage
15275
+ };
15276
+ }
15465
15277
  /**
15466
15278
  * Normalizes the 'projection' parameter in query parameters
15467
15279
  * @param params The query parameters (HttpParams or object)
@@ -17001,7 +16813,7 @@ class VdSelectComponent extends AbstractSelectFormField {
17001
16813
  provide: MAT_SELECT_CONFIG,
17002
16814
  useValue: { overlayPanelClass: 'vd-select-filter-overlay' }
17003
16815
  }
17004
- ], queries: [{ propertyName: "optionTemplate", first: true, predicate: VdSelectOptionDirective, descendants: true }, { propertyName: "triggerTemplate", first: true, predicate: VdSelectTriggerDirective, descendants: true }], viewQueries: [{ propertyName: "selectEl", first: true, predicate: MatSelect, descendants: true }, { propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<mat-select [placeholder]=\"placeholder\" i18n-placeholder [(ngModel)]=\"value\" #select=\"matSelect\" (selectionChange)=\"handleChange($event)\" [hidden]=\"readonly\" [multiple]=\"multiple\" [compareWith]=\"compareWith??defaultCompareWith\" [disabled]=\"disabled\" flex>\n <!-- #region Filter input -->\n <div class=\"mat-mdc-form-field mat-form-field-appearance-fill flex\">\n <div class=\"mat-mdc-text-field-wrapper mdc-text-field mdc-text-field--filled mdc-text-field--no-label\">\n <div class=\"mat-mdc-form-field-focus-overlay\"></div>\n <div class=\"mat-mdc-form-field-flex\">\n <div class=\"mat-mdc-form-field-infix\" layout=\"row\" flex>\n <input matInput #filterInput type=\"text\" placeholder=\"Filter...\" class=\"mat-mdc-input-element vd-select-filter mat-mdc-form-field-input-control mdc-text-field__input\" (keyup)=\"handleFilter($event)\" flex />\n @if (filterInput?.value) {\n <mat-icon (click)=\"filterInput!.value = ''; handleFilter($event);\" fontSet=\"material-symbols-outlined\">close</mat-icon>\n }\n </div>\n </div>\n <div class=\"mdc-line-ripple\"></div>\n </div>\n </div>\n <!-- #endregion -->\n <!-- #region Selection template -->\n <ng-template #selectionTemplate let-label=\"label\">\n <span i18n=\"@@selection\">{ label, select, option {option} other { {{ label }} } }</span>\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option template -->\n <ng-template #optionTextTemplate let-option=\"option\">\n <span layout=\"column\" class=\"option-text\" [ngClass]=\"{'option-has-hint': $safeNavigationMigration(option.hint?.length) > 0}\">\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n <span class=\"mat-caption text-secondary option-hint\" [matTooltip]=\"option.hint\">{{option.hint}}</span>\n </span>\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option icon template -->\n <ng-template #optionIconTemplate let-option=\"option\" let-isAvatar=\"isAvatar\">\n <!-- #region Property icon -->\n @if (matIconKey && !svgIconKey) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"fontSet || 'material-symbols-outlined'\">{{option[matIconKey]}}</mat-icon>\n }\n @if (svgIconKey && !matIconKey) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"option[svgIconKey]\" [fontSet]=\"fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Option icon -->\n @if (option.icon?.matIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\">{{option.icon?.matIcon}}</mat-icon>\n }\n @if (option.icon?.svgIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"$safeNavigationMigration(option.icon?.svgIcon)\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Dynamic icon -->\n @if (optionIcon; as optionIcon) {\n <ng-template #optionIconTemplate [ngTemplateOutlet]=\"optionIconTemplate\" let-optionIcon=\"optionIcon\" [ngTemplateOutletContext]=\"{ optionIcon: optionIcon(option) }\">\n @if (optionIcon.svgIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"optionIcon.svgIcon\" [fontSet]=\"optionIcon.fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n @if (optionIcon.matIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"optionIcon.fontSet || 'material-symbols-outlined'\">{{optionIcon.matIcon}}</mat-icon>\n }\n </ng-template>\n }\n <!-- #endregion -->\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option icon template -->\n <ng-template #optionIconChipAvatarTemplate let-option=\"option\">\n <!-- #region Property icon -->\n <span class=\"option-icon\" matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n <!-- #endregion -->\n </ng-template>\n <!-- #endregion -->\n <!-- #region Trigger for launch button -->\n @if (onLaunch.observed) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <span layout=\"row\" layout-align=\"start center\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n <mat-icon class=\"vd-select-launch\" (click)=\"$event.stopPropagation(); handleLaunchClicked(value)\">launch</mat-icon>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Custom trigger template -->\n @if (!onLaunch.observed && triggerTemplate && triggerTemplate.templateRef) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <ng-template [ngTemplateOutlet]=\"triggerTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ trigger: selectedOptions }\"></ng-template>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Option template as trigger -->\n @if (!onLaunch.observed && !triggerTemplate?.templateRef && optionTemplate?.templateRef) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <span layout=\"row\" layout-align=\"start center\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n @if (multiple) {\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n </mat-chip>\n }\n @else\n {\n <span layout=\"row\" layout-align=\"start center\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n </span>\n }\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Trigger for icons -->\n @if (!triggerTemplate?.templateRef && !optionTemplate?.templateRef) {\n <mat-select-trigger>\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n @if (multiple) {\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"optionTextTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </mat-chip>\n }\n @else {\n <ng-template [ngTemplateOutlet]=\"optionIconChipAvatarTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"optionTextTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n }\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Default option -->\n @if (!multiple && defaultOption) {\n <mat-option class=\"tc-grey-500\" i18n=\"@@pleaseSelect\">--- Please Select ---</mat-option>\n }\n <!-- #endregion -->\n <!-- #region Options -->\n @for (option of filteredOptions; track option; let first = $first) {\n <mat-option [value]=\"mapper ? option : option[optionValueProperty]\" [disabled]=\"$safeNavigationMigration(option?.disabled)\">\n <!-- #region Property icon -->\n @if (matIconKey && !svgIconKey) {\n <mat-icon [fontSet]=\"fontSet || 'material-symbols-outlined'\">{{option[matIconKey]}}</mat-icon>\n } @if (svgIconKey && !matIconKey) {\n <mat-icon [svgIcon]=\"option[svgIconKey]\" [fontSet]=\"fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Option icon -->\n @if (option.icon?.matIcon) {\n <mat-icon [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\">{{option.icon?.matIcon}}</mat-icon>\n }\n @if (option.icon?.svgIcon) {\n <mat-icon [svgIcon]=\"$safeNavigationMigration(option.icon?.svgIcon)\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Text -->\n <span layout=\"column\" layout-align=\"start center\" class=\"option-text\" [ngClass]=\"{'option-has-hint':$safeNavigationMigration(option.hint?.length)>0}\">\n @if (!optionTemplate?.templateRef) {\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n }\n @if (optionTemplate && optionTemplate.templateRef) {\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n }\n <!-- #endregion -->\n <span class=\"mat-caption text-secondary option-hint\" [matTooltip]=\"option.hint\">{{option.hint}}</span>\n </span>\n </mat-option>\n }\n <!-- #endregion -->\n</mat-select>\n<!-- #region Read only value -->\n@if (readonly) {\n @if (currentValue) {\n <div class=\"readonly-value\">\n @if (!optionTemplate?.templateRef && !triggerTemplate?.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"readonly-content\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n <span layout=\"row\" layout-align=\"start center\">\n @if(!this.multiple) {\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n }\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: currentValue[optionTextProperty] }\"></ng-template>\n </span>\n }\n @else if(currentValue[i]){\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue[i] }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: currentValue[i][optionTextProperty] }\"></ng-template>\n </mat-chip>\n }\n </span>\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n }\n @if (triggerTemplate && triggerTemplate.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger readonly-content\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"triggerTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ trigger: currentValue }\"></ng-template>\n </span>\n </span>\n }\n @if (optionTemplate && optionTemplate.templateRef && !triggerTemplate?.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger readonly-content\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: currentValue, text: currentValue[optionTextProperty] }\"></ng-template>\n </span>\n </span>\n }\n </div>\n @if (onLaunch.observed) {\n <mat-icon class=\"vd-select-launch-readonly\" (click)=\"$event.stopPropagation(); handleLaunchClicked(value)\">launch</mat-icon>\n }\n }\n @if (!currentValue) {\n <div>&nbsp;</div>\n }\n}\n<!-- #endregion -->", styles: [":host{display:block;width:100%;min-width:0}.vd-select-launch{position:absolute;right:30px;top:-5px;font-size:18px;cursor:pointer}.readonly-value{padding-right:24px;opacity:.6;min-height:15px;display:flex;align-items:center;width:0;flex:1 1 auto;max-width:100%;min-width:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.readonly-value>*{min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-content{display:flex;align-items:center;width:0;flex:1 1 auto;max-width:100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-ellipsis-text{display:block;flex:1 1 auto;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-content [layout=row],.readonly-value .readonly-content .option-text,.readonly-value .readonly-content .mat-mdc-chip,.readonly-value .readonly-content .mat-mdc-chip-action-label,.readonly-value .readonly-content .mat-mdc-standard-chip{min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vd-select-launch-readonly{position:absolute;right:0;top:9px;font-size:18px;cursor:pointer}.vd-select-filter-wrap{background:inherit;position:sticky;top:-8px;box-sizing:border-box;z-index:100}.vd-select-filter-wrap .vd-select-filter-inner{z-index:100;display:flex;flex-direction:row;align-items:center;background:inherit}.vd-select-filter-wrap .vd-select-filter-inner .vd-select-filter{box-shadow:none;padding:16px 16px 16px 0;box-sizing:border-box;width:100%;border:none;background-color:inherit;color:inherit}.vd-select-filter-wrap .vd-select-filter-inner .vd-select-filter:focus-visible{border:none;outline:none}.vd-select-filter-wrap .mat-divider{display:block;width:100%;border-top-width:1px;border-top-style:solid;box-sizing:border-box}::ng-deep .mat-mdc-select-trigger{display:flex!important}::ng-deep .mat-mdc-select-trigger .mat-icon{display:flex;margin-right:8px}::ng-deep .mat-mdc-form-field-type-vd-select .mat-mdc-form-field-infix{display:flex;align-items:center;min-width:0;max-width:100%;width:100%}::ng-deep .mat-mdc-form-field-type-vd-select-multiple .mat-mdc-form-field-infix{padding-top:4px!important;padding-bottom:4px!important}::ng-deep .mat-mdc-form-field-type-vd-select-multiple .mat-mdc-form-field-infix .mat-mdc-select-trigger{height:100%}.mat-mdc-select mat-select-trigger .option-text,.mat-mdc-select .mat-mdc-option .option-text{display:contents!important}.mat-mdc-select mat-select-trigger .option-text.option-has-hint,.mat-mdc-select .mat-mdc-option .option-text.option-has-hint{line-height:.92em}.mat-mdc-select mat-select-trigger .option-text .option-hint,.mat-mdc-select .mat-mdc-option .option-text .option-hint{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}.mat-mdc-select:not(.mat-mdc-select-multiple) mat-select-trigger .option-text,.mat-mdc-select:not(.mat-mdc-select-multiple) .mat-mdc-option .option-text{width:calc(100% - 36px)}.mat-mdc-select:not(.mat-mdc-select-multiple) mat-select-trigger .mat-mdc-form-field-infix{padding-top:8px;padding-bottom:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i2$2.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i7.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: i7.MatChipAvatar, selector: "mat-chip-avatar, [matChipAvatar]" }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
16816
+ ], queries: [{ propertyName: "optionTemplate", first: true, predicate: VdSelectOptionDirective, descendants: true }, { propertyName: "triggerTemplate", first: true, predicate: VdSelectTriggerDirective, descendants: true }], viewQueries: [{ propertyName: "selectEl", first: true, predicate: MatSelect, descendants: true }, { propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<mat-select [placeholder]=\"placeholder\" i18n-placeholder [(ngModel)]=\"value\" #select=\"matSelect\" (selectionChange)=\"handleChange($event)\" [hidden]=\"readonly\" [multiple]=\"multiple\" [compareWith]=\"compareWith??defaultCompareWith\" [disabled]=\"disabled\" flex>\n <!-- #region Filter input -->\n <div class=\"mat-mdc-form-field mat-form-field-appearance-fill flex\">\n <div class=\"mat-mdc-text-field-wrapper mdc-text-field mdc-text-field--filled mdc-text-field--no-label\">\n <div class=\"mat-mdc-form-field-focus-overlay\"></div>\n <div class=\"mat-mdc-form-field-flex\">\n <div class=\"mat-mdc-form-field-infix\" layout=\"row\" flex>\n <input matInput #filterInput type=\"text\" placeholder=\"Filter...\" class=\"mat-mdc-input-element vd-select-filter mat-mdc-form-field-input-control mdc-text-field__input\" (keyup)=\"handleFilter($event)\" flex />\n @if (filterInput?.value) {\n <mat-icon (click)=\"filterInput!.value = ''; handleFilter($event);\" fontSet=\"material-symbols-outlined\">close</mat-icon>\n }\n </div>\n </div>\n <div class=\"mdc-line-ripple\"></div>\n </div>\n </div>\n <!-- #endregion -->\n <!-- #region Selection template -->\n <ng-template #selectionTemplate let-label=\"label\">\n <msa-selection-label [label]=\"label\"></msa-selection-label>\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option template -->\n <ng-template #optionTextTemplate let-option=\"option\">\n <span layout=\"column\" class=\"option-text\" [ngClass]=\"{'option-has-hint': $safeNavigationMigration(option.hint?.length) > 0}\">\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n <span class=\"mat-caption text-secondary option-hint\" [matTooltip]=\"option.hint\">{{option.hint}}</span>\n </span>\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option icon template -->\n <ng-template #optionIconTemplate let-option=\"option\" let-isAvatar=\"isAvatar\">\n <!-- #region Property icon -->\n @if (matIconKey && !svgIconKey) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"fontSet || 'material-symbols-outlined'\">{{option[matIconKey]}}</mat-icon>\n }\n @if (svgIconKey && !matIconKey) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"option[svgIconKey]\" [fontSet]=\"fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Option icon -->\n @if (option.icon?.matIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\">{{option.icon?.matIcon}}</mat-icon>\n }\n @if (option.icon?.svgIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"$safeNavigationMigration(option.icon?.svgIcon)\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Dynamic icon -->\n @if (optionIcon; as optionIcon) {\n <ng-template #optionIconTemplate [ngTemplateOutlet]=\"optionIconTemplate\" let-optionIcon=\"optionIcon\" [ngTemplateOutletContext]=\"{ optionIcon: optionIcon(option) }\">\n @if (optionIcon.svgIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"optionIcon.svgIcon\" [fontSet]=\"optionIcon.fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n @if (optionIcon.matIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"optionIcon.fontSet || 'material-symbols-outlined'\">{{optionIcon.matIcon}}</mat-icon>\n }\n </ng-template>\n }\n <!-- #endregion -->\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option icon template -->\n <ng-template #optionIconChipAvatarTemplate let-option=\"option\">\n <!-- #region Property icon -->\n <span class=\"option-icon\" matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n <!-- #endregion -->\n </ng-template>\n <!-- #endregion -->\n <!-- #region Trigger for launch button -->\n @if (onLaunch.observed) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <span layout=\"row\" layout-align=\"start center\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n <mat-icon class=\"vd-select-launch\" (click)=\"$event.stopPropagation(); handleLaunchClicked(value)\">launch</mat-icon>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Custom trigger template -->\n @if (!onLaunch.observed && triggerTemplate && triggerTemplate.templateRef) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <ng-template [ngTemplateOutlet]=\"triggerTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ trigger: selectedOptions }\"></ng-template>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Option template as trigger -->\n @if (!onLaunch.observed && !triggerTemplate?.templateRef && optionTemplate?.templateRef) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <span layout=\"row\" layout-align=\"start center\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n @if (multiple) {\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n </mat-chip>\n }\n @else\n {\n <span layout=\"row\" layout-align=\"start center\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n </span>\n }\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Trigger for icons -->\n @if (!triggerTemplate?.templateRef && !optionTemplate?.templateRef) {\n <mat-select-trigger>\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n @if (multiple) {\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"optionTextTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </mat-chip>\n }\n @else {\n <ng-template [ngTemplateOutlet]=\"optionIconChipAvatarTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"optionTextTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n }\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Default option -->\n @if (!multiple && defaultOption) {\n <mat-option class=\"tc-grey-500\" i18n=\"@@pleaseSelect\">--- Please Select ---</mat-option>\n }\n <!-- #endregion -->\n <!-- #region Options -->\n @for (option of filteredOptions; track option; let first = $first) {\n <mat-option [value]=\"mapper ? option : option[optionValueProperty]\" [disabled]=\"$safeNavigationMigration(option?.disabled)\">\n <!-- #region Property icon -->\n @if (matIconKey && !svgIconKey) {\n <mat-icon [fontSet]=\"fontSet || 'material-symbols-outlined'\">{{option[matIconKey]}}</mat-icon>\n } @if (svgIconKey && !matIconKey) {\n <mat-icon [svgIcon]=\"option[svgIconKey]\" [fontSet]=\"fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Option icon -->\n @if (option.icon?.matIcon) {\n <mat-icon [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\">{{option.icon?.matIcon}}</mat-icon>\n }\n @if (option.icon?.svgIcon) {\n <mat-icon [svgIcon]=\"$safeNavigationMigration(option.icon?.svgIcon)\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Text -->\n <span layout=\"column\" layout-align=\"start center\" class=\"option-text\" [ngClass]=\"{'option-has-hint':$safeNavigationMigration(option.hint?.length)>0}\">\n @if (!optionTemplate?.templateRef) {\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n }\n @if (optionTemplate && optionTemplate.templateRef) {\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n }\n <!-- #endregion -->\n <span class=\"mat-caption text-secondary option-hint\" [matTooltip]=\"option.hint\">{{option.hint}}</span>\n </span>\n </mat-option>\n }\n <!-- #endregion -->\n</mat-select>\n<!-- #region Read only value -->\n@if (readonly) {\n @if (currentValue) {\n <div class=\"readonly-value\">\n @if (!optionTemplate?.templateRef && !triggerTemplate?.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"readonly-content\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n <span layout=\"row\" layout-align=\"start center\">\n @if(!this.multiple) {\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n }\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: currentValue[optionTextProperty] }\"></ng-template>\n </span>\n }\n @else if(currentValue[i]){\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue[i] }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: currentValue[i][optionTextProperty] }\"></ng-template>\n </mat-chip>\n }\n </span>\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n }\n @if (triggerTemplate && triggerTemplate.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger readonly-content\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"triggerTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ trigger: currentValue }\"></ng-template>\n </span>\n </span>\n }\n @if (optionTemplate && optionTemplate.templateRef && !triggerTemplate?.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger readonly-content\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: currentValue, text: currentValue[optionTextProperty] }\"></ng-template>\n </span>\n </span>\n }\n </div>\n @if (onLaunch.observed) {\n <mat-icon class=\"vd-select-launch-readonly\" (click)=\"$event.stopPropagation(); handleLaunchClicked(value)\">launch</mat-icon>\n }\n }\n @if (!currentValue) {\n <div>&nbsp;</div>\n }\n}\n<!-- #endregion -->", styles: [":host{display:block;width:100%;min-width:0}.vd-select-launch{position:absolute;right:30px;top:-5px;font-size:18px;cursor:pointer}.readonly-value{padding-right:24px;opacity:.6;min-height:15px;display:flex;align-items:center;width:0;flex:1 1 auto;max-width:100%;min-width:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.readonly-value>*{min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-content{display:flex;align-items:center;width:0;flex:1 1 auto;max-width:100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-ellipsis-text{display:block;flex:1 1 auto;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-content [layout=row],.readonly-value .readonly-content .option-text,.readonly-value .readonly-content .mat-mdc-chip,.readonly-value .readonly-content .mat-mdc-chip-action-label,.readonly-value .readonly-content .mat-mdc-standard-chip{min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vd-select-launch-readonly{position:absolute;right:0;top:9px;font-size:18px;cursor:pointer}.vd-select-filter-wrap{background:inherit;position:sticky;top:-8px;box-sizing:border-box;z-index:100}.vd-select-filter-wrap .vd-select-filter-inner{z-index:100;display:flex;flex-direction:row;align-items:center;background:inherit}.vd-select-filter-wrap .vd-select-filter-inner .vd-select-filter{box-shadow:none;padding:16px 16px 16px 0;box-sizing:border-box;width:100%;border:none;background-color:inherit;color:inherit}.vd-select-filter-wrap .vd-select-filter-inner .vd-select-filter:focus-visible{border:none;outline:none}.vd-select-filter-wrap .mat-divider{display:block;width:100%;border-top-width:1px;border-top-style:solid;box-sizing:border-box}::ng-deep .mat-mdc-select-trigger{display:flex!important}::ng-deep .mat-mdc-select-trigger .mat-icon{display:flex;margin-right:8px}::ng-deep .mat-mdc-form-field-type-vd-select .mat-mdc-form-field-infix{display:flex;align-items:center;min-width:0;max-width:100%;width:100%}::ng-deep .mat-mdc-form-field-type-vd-select-multiple .mat-mdc-form-field-infix{padding-top:4px!important;padding-bottom:4px!important}::ng-deep .mat-mdc-form-field-type-vd-select-multiple .mat-mdc-form-field-infix .mat-mdc-select-trigger{height:100%}.mat-mdc-select mat-select-trigger .option-text,.mat-mdc-select .mat-mdc-option .option-text{display:contents!important}.mat-mdc-select mat-select-trigger .option-text.option-has-hint,.mat-mdc-select .mat-mdc-option .option-text.option-has-hint{line-height:.92em}.mat-mdc-select mat-select-trigger .option-text .option-hint,.mat-mdc-select .mat-mdc-option .option-text .option-hint{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}.mat-mdc-select:not(.mat-mdc-select-multiple) mat-select-trigger .option-text,.mat-mdc-select:not(.mat-mdc-select-multiple) .mat-mdc-option .option-text{width:calc(100% - 36px)}.mat-mdc-select:not(.mat-mdc-select-multiple) mat-select-trigger .mat-mdc-form-field-infix{padding-top:8px;padding-bottom:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i2$2.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i7.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: i7.MatChipAvatar, selector: "mat-chip-avatar, [matChipAvatar]" }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MsaSelectionLabelComponent, selector: "msa-selection-label", inputs: ["label"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
17005
16817
  }
17006
16818
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: VdSelectComponent, decorators: [{
17007
16819
  type: Component,
@@ -17012,14 +16824,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
17012
16824
  MatIconModule,
17013
16825
  MatChipsModule,
17014
16826
  MatTooltip,
17015
- FormsModule
16827
+ FormsModule,
16828
+ MsaSelectionLabelComponent
17016
16829
  ], changeDetection: ChangeDetectionStrategy.Eager, providers: [
17017
16830
  { provide: MatFormFieldControl, useExisting: VdSelectComponent },
17018
16831
  {
17019
16832
  provide: MAT_SELECT_CONFIG,
17020
16833
  useValue: { overlayPanelClass: 'vd-select-filter-overlay' }
17021
16834
  }
17022
- ], template: "<mat-select [placeholder]=\"placeholder\" i18n-placeholder [(ngModel)]=\"value\" #select=\"matSelect\" (selectionChange)=\"handleChange($event)\" [hidden]=\"readonly\" [multiple]=\"multiple\" [compareWith]=\"compareWith??defaultCompareWith\" [disabled]=\"disabled\" flex>\n <!-- #region Filter input -->\n <div class=\"mat-mdc-form-field mat-form-field-appearance-fill flex\">\n <div class=\"mat-mdc-text-field-wrapper mdc-text-field mdc-text-field--filled mdc-text-field--no-label\">\n <div class=\"mat-mdc-form-field-focus-overlay\"></div>\n <div class=\"mat-mdc-form-field-flex\">\n <div class=\"mat-mdc-form-field-infix\" layout=\"row\" flex>\n <input matInput #filterInput type=\"text\" placeholder=\"Filter...\" class=\"mat-mdc-input-element vd-select-filter mat-mdc-form-field-input-control mdc-text-field__input\" (keyup)=\"handleFilter($event)\" flex />\n @if (filterInput?.value) {\n <mat-icon (click)=\"filterInput!.value = ''; handleFilter($event);\" fontSet=\"material-symbols-outlined\">close</mat-icon>\n }\n </div>\n </div>\n <div class=\"mdc-line-ripple\"></div>\n </div>\n </div>\n <!-- #endregion -->\n <!-- #region Selection template -->\n <ng-template #selectionTemplate let-label=\"label\">\n <span i18n=\"@@selection\">{ label, select, option {option} other { {{ label }} } }</span>\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option template -->\n <ng-template #optionTextTemplate let-option=\"option\">\n <span layout=\"column\" class=\"option-text\" [ngClass]=\"{'option-has-hint': $safeNavigationMigration(option.hint?.length) > 0}\">\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n <span class=\"mat-caption text-secondary option-hint\" [matTooltip]=\"option.hint\">{{option.hint}}</span>\n </span>\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option icon template -->\n <ng-template #optionIconTemplate let-option=\"option\" let-isAvatar=\"isAvatar\">\n <!-- #region Property icon -->\n @if (matIconKey && !svgIconKey) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"fontSet || 'material-symbols-outlined'\">{{option[matIconKey]}}</mat-icon>\n }\n @if (svgIconKey && !matIconKey) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"option[svgIconKey]\" [fontSet]=\"fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Option icon -->\n @if (option.icon?.matIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\">{{option.icon?.matIcon}}</mat-icon>\n }\n @if (option.icon?.svgIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"$safeNavigationMigration(option.icon?.svgIcon)\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Dynamic icon -->\n @if (optionIcon; as optionIcon) {\n <ng-template #optionIconTemplate [ngTemplateOutlet]=\"optionIconTemplate\" let-optionIcon=\"optionIcon\" [ngTemplateOutletContext]=\"{ optionIcon: optionIcon(option) }\">\n @if (optionIcon.svgIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"optionIcon.svgIcon\" [fontSet]=\"optionIcon.fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n @if (optionIcon.matIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"optionIcon.fontSet || 'material-symbols-outlined'\">{{optionIcon.matIcon}}</mat-icon>\n }\n </ng-template>\n }\n <!-- #endregion -->\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option icon template -->\n <ng-template #optionIconChipAvatarTemplate let-option=\"option\">\n <!-- #region Property icon -->\n <span class=\"option-icon\" matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n <!-- #endregion -->\n </ng-template>\n <!-- #endregion -->\n <!-- #region Trigger for launch button -->\n @if (onLaunch.observed) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <span layout=\"row\" layout-align=\"start center\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n <mat-icon class=\"vd-select-launch\" (click)=\"$event.stopPropagation(); handleLaunchClicked(value)\">launch</mat-icon>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Custom trigger template -->\n @if (!onLaunch.observed && triggerTemplate && triggerTemplate.templateRef) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <ng-template [ngTemplateOutlet]=\"triggerTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ trigger: selectedOptions }\"></ng-template>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Option template as trigger -->\n @if (!onLaunch.observed && !triggerTemplate?.templateRef && optionTemplate?.templateRef) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <span layout=\"row\" layout-align=\"start center\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n @if (multiple) {\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n </mat-chip>\n }\n @else\n {\n <span layout=\"row\" layout-align=\"start center\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n </span>\n }\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Trigger for icons -->\n @if (!triggerTemplate?.templateRef && !optionTemplate?.templateRef) {\n <mat-select-trigger>\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n @if (multiple) {\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"optionTextTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </mat-chip>\n }\n @else {\n <ng-template [ngTemplateOutlet]=\"optionIconChipAvatarTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"optionTextTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n }\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Default option -->\n @if (!multiple && defaultOption) {\n <mat-option class=\"tc-grey-500\" i18n=\"@@pleaseSelect\">--- Please Select ---</mat-option>\n }\n <!-- #endregion -->\n <!-- #region Options -->\n @for (option of filteredOptions; track option; let first = $first) {\n <mat-option [value]=\"mapper ? option : option[optionValueProperty]\" [disabled]=\"$safeNavigationMigration(option?.disabled)\">\n <!-- #region Property icon -->\n @if (matIconKey && !svgIconKey) {\n <mat-icon [fontSet]=\"fontSet || 'material-symbols-outlined'\">{{option[matIconKey]}}</mat-icon>\n } @if (svgIconKey && !matIconKey) {\n <mat-icon [svgIcon]=\"option[svgIconKey]\" [fontSet]=\"fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Option icon -->\n @if (option.icon?.matIcon) {\n <mat-icon [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\">{{option.icon?.matIcon}}</mat-icon>\n }\n @if (option.icon?.svgIcon) {\n <mat-icon [svgIcon]=\"$safeNavigationMigration(option.icon?.svgIcon)\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Text -->\n <span layout=\"column\" layout-align=\"start center\" class=\"option-text\" [ngClass]=\"{'option-has-hint':$safeNavigationMigration(option.hint?.length)>0}\">\n @if (!optionTemplate?.templateRef) {\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n }\n @if (optionTemplate && optionTemplate.templateRef) {\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n }\n <!-- #endregion -->\n <span class=\"mat-caption text-secondary option-hint\" [matTooltip]=\"option.hint\">{{option.hint}}</span>\n </span>\n </mat-option>\n }\n <!-- #endregion -->\n</mat-select>\n<!-- #region Read only value -->\n@if (readonly) {\n @if (currentValue) {\n <div class=\"readonly-value\">\n @if (!optionTemplate?.templateRef && !triggerTemplate?.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"readonly-content\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n <span layout=\"row\" layout-align=\"start center\">\n @if(!this.multiple) {\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n }\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: currentValue[optionTextProperty] }\"></ng-template>\n </span>\n }\n @else if(currentValue[i]){\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue[i] }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: currentValue[i][optionTextProperty] }\"></ng-template>\n </mat-chip>\n }\n </span>\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n }\n @if (triggerTemplate && triggerTemplate.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger readonly-content\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"triggerTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ trigger: currentValue }\"></ng-template>\n </span>\n </span>\n }\n @if (optionTemplate && optionTemplate.templateRef && !triggerTemplate?.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger readonly-content\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: currentValue, text: currentValue[optionTextProperty] }\"></ng-template>\n </span>\n </span>\n }\n </div>\n @if (onLaunch.observed) {\n <mat-icon class=\"vd-select-launch-readonly\" (click)=\"$event.stopPropagation(); handleLaunchClicked(value)\">launch</mat-icon>\n }\n }\n @if (!currentValue) {\n <div>&nbsp;</div>\n }\n}\n<!-- #endregion -->", styles: [":host{display:block;width:100%;min-width:0}.vd-select-launch{position:absolute;right:30px;top:-5px;font-size:18px;cursor:pointer}.readonly-value{padding-right:24px;opacity:.6;min-height:15px;display:flex;align-items:center;width:0;flex:1 1 auto;max-width:100%;min-width:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.readonly-value>*{min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-content{display:flex;align-items:center;width:0;flex:1 1 auto;max-width:100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-ellipsis-text{display:block;flex:1 1 auto;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-content [layout=row],.readonly-value .readonly-content .option-text,.readonly-value .readonly-content .mat-mdc-chip,.readonly-value .readonly-content .mat-mdc-chip-action-label,.readonly-value .readonly-content .mat-mdc-standard-chip{min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vd-select-launch-readonly{position:absolute;right:0;top:9px;font-size:18px;cursor:pointer}.vd-select-filter-wrap{background:inherit;position:sticky;top:-8px;box-sizing:border-box;z-index:100}.vd-select-filter-wrap .vd-select-filter-inner{z-index:100;display:flex;flex-direction:row;align-items:center;background:inherit}.vd-select-filter-wrap .vd-select-filter-inner .vd-select-filter{box-shadow:none;padding:16px 16px 16px 0;box-sizing:border-box;width:100%;border:none;background-color:inherit;color:inherit}.vd-select-filter-wrap .vd-select-filter-inner .vd-select-filter:focus-visible{border:none;outline:none}.vd-select-filter-wrap .mat-divider{display:block;width:100%;border-top-width:1px;border-top-style:solid;box-sizing:border-box}::ng-deep .mat-mdc-select-trigger{display:flex!important}::ng-deep .mat-mdc-select-trigger .mat-icon{display:flex;margin-right:8px}::ng-deep .mat-mdc-form-field-type-vd-select .mat-mdc-form-field-infix{display:flex;align-items:center;min-width:0;max-width:100%;width:100%}::ng-deep .mat-mdc-form-field-type-vd-select-multiple .mat-mdc-form-field-infix{padding-top:4px!important;padding-bottom:4px!important}::ng-deep .mat-mdc-form-field-type-vd-select-multiple .mat-mdc-form-field-infix .mat-mdc-select-trigger{height:100%}.mat-mdc-select mat-select-trigger .option-text,.mat-mdc-select .mat-mdc-option .option-text{display:contents!important}.mat-mdc-select mat-select-trigger .option-text.option-has-hint,.mat-mdc-select .mat-mdc-option .option-text.option-has-hint{line-height:.92em}.mat-mdc-select mat-select-trigger .option-text .option-hint,.mat-mdc-select .mat-mdc-option .option-text .option-hint{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}.mat-mdc-select:not(.mat-mdc-select-multiple) mat-select-trigger .option-text,.mat-mdc-select:not(.mat-mdc-select-multiple) .mat-mdc-option .option-text{width:calc(100% - 36px)}.mat-mdc-select:not(.mat-mdc-select-multiple) mat-select-trigger .mat-mdc-form-field-infix{padding-top:8px;padding-bottom:8px}\n"] }]
16835
+ ], template: "<mat-select [placeholder]=\"placeholder\" i18n-placeholder [(ngModel)]=\"value\" #select=\"matSelect\" (selectionChange)=\"handleChange($event)\" [hidden]=\"readonly\" [multiple]=\"multiple\" [compareWith]=\"compareWith??defaultCompareWith\" [disabled]=\"disabled\" flex>\n <!-- #region Filter input -->\n <div class=\"mat-mdc-form-field mat-form-field-appearance-fill flex\">\n <div class=\"mat-mdc-text-field-wrapper mdc-text-field mdc-text-field--filled mdc-text-field--no-label\">\n <div class=\"mat-mdc-form-field-focus-overlay\"></div>\n <div class=\"mat-mdc-form-field-flex\">\n <div class=\"mat-mdc-form-field-infix\" layout=\"row\" flex>\n <input matInput #filterInput type=\"text\" placeholder=\"Filter...\" class=\"mat-mdc-input-element vd-select-filter mat-mdc-form-field-input-control mdc-text-field__input\" (keyup)=\"handleFilter($event)\" flex />\n @if (filterInput?.value) {\n <mat-icon (click)=\"filterInput!.value = ''; handleFilter($event);\" fontSet=\"material-symbols-outlined\">close</mat-icon>\n }\n </div>\n </div>\n <div class=\"mdc-line-ripple\"></div>\n </div>\n </div>\n <!-- #endregion -->\n <!-- #region Selection template -->\n <ng-template #selectionTemplate let-label=\"label\">\n <msa-selection-label [label]=\"label\"></msa-selection-label>\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option template -->\n <ng-template #optionTextTemplate let-option=\"option\">\n <span layout=\"column\" class=\"option-text\" [ngClass]=\"{'option-has-hint': $safeNavigationMigration(option.hint?.length) > 0}\">\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n <span class=\"mat-caption text-secondary option-hint\" [matTooltip]=\"option.hint\">{{option.hint}}</span>\n </span>\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option icon template -->\n <ng-template #optionIconTemplate let-option=\"option\" let-isAvatar=\"isAvatar\">\n <!-- #region Property icon -->\n @if (matIconKey && !svgIconKey) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"fontSet || 'material-symbols-outlined'\">{{option[matIconKey]}}</mat-icon>\n }\n @if (svgIconKey && !matIconKey) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"option[svgIconKey]\" [fontSet]=\"fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Option icon -->\n @if (option.icon?.matIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\">{{option.icon?.matIcon}}</mat-icon>\n }\n @if (option.icon?.svgIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"$safeNavigationMigration(option.icon?.svgIcon)\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Dynamic icon -->\n @if (optionIcon; as optionIcon) {\n <ng-template #optionIconTemplate [ngTemplateOutlet]=\"optionIconTemplate\" let-optionIcon=\"optionIcon\" [ngTemplateOutletContext]=\"{ optionIcon: optionIcon(option) }\">\n @if (optionIcon.svgIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [svgIcon]=\"optionIcon.svgIcon\" [fontSet]=\"optionIcon.fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n @if (optionIcon.matIcon) {\n <mat-icon [class.mat-mdc-chip-avatar]=\"isAvatar\" [fontSet]=\"optionIcon.fontSet || 'material-symbols-outlined'\">{{optionIcon.matIcon}}</mat-icon>\n }\n </ng-template>\n }\n <!-- #endregion -->\n </ng-template>\n <!-- #endregion -->\n <!-- #region Option icon template -->\n <ng-template #optionIconChipAvatarTemplate let-option=\"option\">\n <!-- #region Property icon -->\n <span class=\"option-icon\" matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n <!-- #endregion -->\n </ng-template>\n <!-- #endregion -->\n <!-- #region Trigger for launch button -->\n @if (onLaunch.observed) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <span layout=\"row\" layout-align=\"start center\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n <mat-icon class=\"vd-select-launch\" (click)=\"$event.stopPropagation(); handleLaunchClicked(value)\">launch</mat-icon>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Custom trigger template -->\n @if (!onLaunch.observed && triggerTemplate && triggerTemplate.templateRef) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <ng-template [ngTemplateOutlet]=\"triggerTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ trigger: selectedOptions }\"></ng-template>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Option template as trigger -->\n @if (!onLaunch.observed && !triggerTemplate?.templateRef && optionTemplate?.templateRef) {\n <mat-select-trigger [class]=\"triggerCssClass\">\n <span layout=\"row\" layout-align=\"start center\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n @if (multiple) {\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n </mat-chip>\n }\n @else\n {\n <span layout=\"row\" layout-align=\"start center\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n </span>\n }\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Trigger for icons -->\n @if (!triggerTemplate?.templateRef && !optionTemplate?.templateRef) {\n <mat-select-trigger>\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n @if (multiple) {\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"optionTextTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n </mat-chip>\n }\n @else {\n <ng-template [ngTemplateOutlet]=\"optionIconChipAvatarTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n <ng-template [ngTemplateOutlet]=\"optionTextTemplate\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\n }\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n </mat-select-trigger>\n }\n <!-- #endregion -->\n <!-- #region Default option -->\n @if (!multiple && defaultOption) {\n <mat-option class=\"tc-grey-500\" i18n=\"@@pleaseSelect\">--- Please Select ---</mat-option>\n }\n <!-- #endregion -->\n <!-- #region Options -->\n @for (option of filteredOptions; track option; let first = $first) {\n <mat-option [value]=\"mapper ? option : option[optionValueProperty]\" [disabled]=\"$safeNavigationMigration(option?.disabled)\">\n <!-- #region Property icon -->\n @if (matIconKey && !svgIconKey) {\n <mat-icon [fontSet]=\"fontSet || 'material-symbols-outlined'\">{{option[matIconKey]}}</mat-icon>\n } @if (svgIconKey && !matIconKey) {\n <mat-icon [svgIcon]=\"option[svgIconKey]\" [fontSet]=\"fontSet || 'material-symbols-outlined'\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Option icon -->\n @if (option.icon?.matIcon) {\n <mat-icon [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\">{{option.icon?.matIcon}}</mat-icon>\n }\n @if (option.icon?.svgIcon) {\n <mat-icon [svgIcon]=\"$safeNavigationMigration(option.icon?.svgIcon)\" [fontSet]=\"option.icon?.fontSet || 'material-symbols-outlined'\" [ngStyle]=\"{ color: option.icon?.iconColor??'' }\"></mat-icon>\n }\n <!-- #endregion -->\n <!-- #region Text -->\n <span layout=\"column\" layout-align=\"start center\" class=\"option-text\" [ngClass]=\"{'option-has-hint':$safeNavigationMigration(option.hint?.length)>0}\">\n @if (!optionTemplate?.templateRef) {\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: option[optionTextProperty] }\"></ng-template>\n }\n @if (optionTemplate && optionTemplate.templateRef) {\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: option, text: option[optionTextProperty] }\"></ng-template>\n }\n <!-- #endregion -->\n <span class=\"mat-caption text-secondary option-hint\" [matTooltip]=\"option.hint\">{{option.hint}}</span>\n </span>\n </mat-option>\n }\n <!-- #endregion -->\n</mat-select>\n<!-- #region Read only value -->\n@if (readonly) {\n @if (currentValue) {\n <div class=\"readonly-value\">\n @if (!optionTemplate?.templateRef && !triggerTemplate?.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"readonly-content\">\n @for (option of selectedOptions; track option; let i = $index; let last = $last) {\n <span layout=\"row\" layout-align=\"start center\">\n @if(!this.multiple) {\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n }\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: currentValue[optionTextProperty] }\"></ng-template>\n </span>\n }\n @else if(currentValue[i]){\n <mat-chip>\n @if(optionIcon || matIconKey || svgIconKey || option.icon) {\n <span matChipAvatar>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue[i] }\"></ng-template>\n </span>\n }\n <ng-template [ngTemplateOutlet]=\"selectionTemplate\" [ngTemplateOutletContext]=\"{ label: currentValue[i][optionTextProperty] }\"></ng-template>\n </mat-chip>\n }\n </span>\n @if (!last) {\n <span>&nbsp;&nbsp;</span>\n }\n }\n </span>\n }\n @if (triggerTemplate && triggerTemplate.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger readonly-content\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"triggerTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ trigger: currentValue }\"></ng-template>\n </span>\n </span>\n }\n @if (optionTemplate && optionTemplate.templateRef && !triggerTemplate?.templateRef) {\n <span layout=\"row\" layout-align=\"start center\" class=\"option-trigger readonly-content\">\n <ng-template [ngTemplateOutlet]=\"optionIconTemplate\" [ngTemplateOutletContext]=\"{ option: currentValue }\"></ng-template>\n <span>&nbsp;&nbsp;</span>\n <span class=\"readonly-ellipsis-text\">\n <ng-template [ngTemplateOutlet]=\"optionTemplate.templateRef!\" [ngTemplateOutletContext]=\"{ option: currentValue, text: currentValue[optionTextProperty] }\"></ng-template>\n </span>\n </span>\n }\n </div>\n @if (onLaunch.observed) {\n <mat-icon class=\"vd-select-launch-readonly\" (click)=\"$event.stopPropagation(); handleLaunchClicked(value)\">launch</mat-icon>\n }\n }\n @if (!currentValue) {\n <div>&nbsp;</div>\n }\n}\n<!-- #endregion -->", styles: [":host{display:block;width:100%;min-width:0}.vd-select-launch{position:absolute;right:30px;top:-5px;font-size:18px;cursor:pointer}.readonly-value{padding-right:24px;opacity:.6;min-height:15px;display:flex;align-items:center;width:0;flex:1 1 auto;max-width:100%;min-width:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.readonly-value>*{min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-content{display:flex;align-items:center;width:0;flex:1 1 auto;max-width:100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-ellipsis-text{display:block;flex:1 1 auto;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.readonly-value .readonly-content [layout=row],.readonly-value .readonly-content .option-text,.readonly-value .readonly-content .mat-mdc-chip,.readonly-value .readonly-content .mat-mdc-chip-action-label,.readonly-value .readonly-content .mat-mdc-standard-chip{min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vd-select-launch-readonly{position:absolute;right:0;top:9px;font-size:18px;cursor:pointer}.vd-select-filter-wrap{background:inherit;position:sticky;top:-8px;box-sizing:border-box;z-index:100}.vd-select-filter-wrap .vd-select-filter-inner{z-index:100;display:flex;flex-direction:row;align-items:center;background:inherit}.vd-select-filter-wrap .vd-select-filter-inner .vd-select-filter{box-shadow:none;padding:16px 16px 16px 0;box-sizing:border-box;width:100%;border:none;background-color:inherit;color:inherit}.vd-select-filter-wrap .vd-select-filter-inner .vd-select-filter:focus-visible{border:none;outline:none}.vd-select-filter-wrap .mat-divider{display:block;width:100%;border-top-width:1px;border-top-style:solid;box-sizing:border-box}::ng-deep .mat-mdc-select-trigger{display:flex!important}::ng-deep .mat-mdc-select-trigger .mat-icon{display:flex;margin-right:8px}::ng-deep .mat-mdc-form-field-type-vd-select .mat-mdc-form-field-infix{display:flex;align-items:center;min-width:0;max-width:100%;width:100%}::ng-deep .mat-mdc-form-field-type-vd-select-multiple .mat-mdc-form-field-infix{padding-top:4px!important;padding-bottom:4px!important}::ng-deep .mat-mdc-form-field-type-vd-select-multiple .mat-mdc-form-field-infix .mat-mdc-select-trigger{height:100%}.mat-mdc-select mat-select-trigger .option-text,.mat-mdc-select .mat-mdc-option .option-text{display:contents!important}.mat-mdc-select mat-select-trigger .option-text.option-has-hint,.mat-mdc-select .mat-mdc-option .option-text.option-has-hint{line-height:.92em}.mat-mdc-select mat-select-trigger .option-text .option-hint,.mat-mdc-select .mat-mdc-option .option-text .option-hint{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}.mat-mdc-select:not(.mat-mdc-select-multiple) mat-select-trigger .option-text,.mat-mdc-select:not(.mat-mdc-select-multiple) .mat-mdc-option .option-text{width:calc(100% - 36px)}.mat-mdc-select:not(.mat-mdc-select-multiple) mat-select-trigger .mat-mdc-form-field-infix{padding-top:8px;padding-bottom:8px}\n"] }]
17023
16836
  }], ctorParameters: () => [], propDecorators: { optionTemplate: [{
17024
16837
  type: ContentChild,
17025
16838
  args: [VdSelectOptionDirective]
@@ -17306,101 +17119,283 @@ class TableDataSource extends DataSource {
17306
17119
  }
17307
17120
  }
17308
17121
  /**
17309
- * Clears field filters
17122
+ * Clears field filters
17123
+ */
17124
+ applyFilters(newFilters = {}) {
17125
+ this.fieldFilters = newFilters || {};
17126
+ this.reload();
17127
+ }
17128
+ /**
17129
+ * Clears field filters
17130
+ */
17131
+ clearFilters(newFilters = {}) {
17132
+ this.fieldFilters = newFilters || {};
17133
+ this.reload();
17134
+ }
17135
+ /**
17136
+ * Checks, whether all items are selected
17137
+ */
17138
+ isAllSelected() {
17139
+ if (this.selectionModel.isEmpty()) {
17140
+ return false;
17141
+ }
17142
+ return this.selectionModel.selected.length === this.total;
17143
+ }
17144
+ /**
17145
+ * Toggles selected items
17146
+ * @param checkbox
17147
+ * @param predicate
17148
+ */
17149
+ toggleSelect(checkbox, predicate) {
17150
+ if (this.selectionModel.hasValue()) {
17151
+ this.selectionModel.clear();
17152
+ checkbox.source.checked = false;
17153
+ }
17154
+ else {
17155
+ this.items.filter(predicate ? predicate : x => x)
17156
+ .filter(x => !x['locked'])
17157
+ .forEach(data => this.selectionModel.select(data));
17158
+ if (this.selectionModel.selected.length !== this.total) {
17159
+ checkbox.source.checked = false;
17160
+ }
17161
+ }
17162
+ }
17163
+ /**
17164
+ * Get selected Items
17165
+ */
17166
+ getSelected = (key) => this.selectionModel.selected.map(x => x[key]);
17167
+ /**
17168
+ * Get selected Items
17169
+ */
17170
+ getSelectedIds = () => this.getSelected('id');
17171
+ }
17172
+
17173
+ class DataSourceFilterDirective {
17174
+ /**
17175
+ * DataSource instance
17176
+ */
17177
+ dataSource;
17178
+ /**
17179
+ * Represents a value that changes over time.
17180
+ * Observers can subscribe to the subject to receive filter changes
17181
+ */
17182
+ _queryChange = new BehaviorSubject(null);
17183
+ /**
17184
+ * Sets query
17185
+ */
17186
+ set dataSourceFilter(query) { this._queryChange.next(query); }
17187
+ /**
17188
+ * Gets query
17189
+ */
17190
+ get dataSourceFilter() { return this._queryChange.value; }
17191
+ /**
17192
+ * Lifecycle hook that is called after data-bound properties of a directive are initialized.
17193
+ */
17194
+ ngOnInit() {
17195
+ this._queryChange.subscribe(() => {
17196
+ if (this.dataSource) {
17197
+ /* Update the filters */
17198
+ Object.assign(this.dataSource.staticFieldFilters || {}, this.dataSourceFilter != null ? this.dataSourceFilter : {});
17199
+ /* Reload data */
17200
+ this.dataSource.reload();
17201
+ }
17202
+ });
17203
+ }
17204
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: DataSourceFilterDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
17205
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: DataSourceFilterDirective, isStandalone: true, selector: "[dataSourceFilter]", inputs: { dataSource: "dataSource", dataSourceFilter: "dataSourceFilter" }, ngImport: i0 });
17206
+ }
17207
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: DataSourceFilterDirective, decorators: [{
17208
+ type: Directive,
17209
+ args: [{
17210
+ selector: '[dataSourceFilter]'
17211
+ }]
17212
+ }], propDecorators: { dataSource: [{
17213
+ type: Input
17214
+ }], dataSourceFilter: [{
17215
+ type: Input
17216
+ }] } });
17217
+
17218
+ /**
17219
+ * Class representing the structure and behavior of a table definition.
17220
+ * It defines various configurations such as column settings, actions,
17221
+ * and callbacks for rows and data handling.
17222
+ *
17223
+ * @template T - The type of data represented in the table rows.
17224
+ */
17225
+ class TableDefinition {
17226
+ /**
17227
+ * @property endpoint
17228
+ * @description API endpoint from which table data will be fetched.
17229
+ * @type {string}
17230
+ */
17231
+ endpoint = '';
17232
+ /**
17233
+ * @property projection
17234
+ * @description Optional projection for specifying which fields should be included
17235
+ * in the fetched data. Can be a single string or an array of field names.
17236
+ * @type {string | string[]}
17237
+ */
17238
+ projection;
17239
+ /**
17240
+ * @property includes
17241
+ * @description Optional array of related data entities (includes) to be retrieved along
17242
+ * with the main data set.
17243
+ * @type {string[]}
17244
+ */
17245
+ includes;
17246
+ /**
17247
+ * @property showAction
17248
+ * @description Flag to indicate if action columns (e.g., edit, delete buttons)
17249
+ * should be displayed in the table. Defaults to `true`.
17250
+ * @type {boolean}
17251
+ */
17252
+ showAction = true;
17253
+ /**
17254
+ * @property selectable
17255
+ * @description Flag to indicate if rows can be selected (e.g., with checkboxes).
17256
+ * Defaults to `true`.
17257
+ * @type {boolean}
17258
+ */
17259
+ selectable = true;
17260
+ /**
17261
+ * @property addable
17262
+ * @description Flag to indicate if new items can be added to the table.
17263
+ * Defaults to `true`.
17264
+ * @type {boolean}
17265
+ */
17266
+ addable = true;
17267
+ /**
17268
+ * @property editable
17269
+ * @description Flag to indicate if rows can be edited. Defaults to `true`.
17270
+ * @type {boolean}
17271
+ */
17272
+ editable = true;
17273
+ /**
17274
+ * @property deletable
17275
+ * @description Flag to indicate if rows can be deleted. Defaults to `true`.
17276
+ * @type {boolean}
17277
+ */
17278
+ deletable = true;
17279
+ /**
17280
+ * @property downloadable
17281
+ * @description Flag to indicate if table data can be downloaded (e.g., as CSV or Excel).
17282
+ * @type {boolean}
17283
+ */
17284
+ downloadable;
17285
+ /**
17286
+ * @property duplicable
17287
+ * @description Flag to indicate if rows can be duplicated.
17288
+ * @type {boolean}
17289
+ */
17290
+ duplicable;
17291
+ /**
17292
+ * @property exportable
17293
+ * @description Determines if the table is exportable.
17294
+ * @type {boolean}
17295
+ */
17296
+ exportable = true;
17297
+ /**
17298
+ * @property exportFileName
17299
+ * @description The name of the file to export.
17300
+ * @type {string}
17310
17301
  */
17311
- applyFilters(newFilters = {}) {
17312
- this.fieldFilters = newFilters || {};
17313
- this.reload();
17314
- }
17302
+ exportFileName;
17315
17303
  /**
17316
- * Clears field filters
17304
+ * @property sticky
17305
+ * @description Flag to indicate whether the table headers or columns should stick
17306
+ * to the viewport during scrolling. Defaults to `false`.
17307
+ * @type {boolean}
17317
17308
  */
17318
- clearFilters(newFilters = {}) {
17319
- this.fieldFilters = newFilters || {};
17320
- this.reload();
17321
- }
17309
+ sticky = false;
17322
17310
  /**
17323
- * Checks, whether all items are selected
17311
+ * @property columns
17312
+ * @description Array of table columns that define the structure and data types
17313
+ * of each column in the table.
17314
+ * @type {TableColumn<T>[]}
17324
17315
  */
17325
- isAllSelected() {
17326
- if (this.selectionModel.isEmpty()) {
17327
- return false;
17328
- }
17329
- return this.selectionModel.selected.length === this.total;
17330
- }
17316
+ columns = [];
17331
17317
  /**
17332
- * Toggles selected items
17333
- * @param checkbox
17334
- * @param predicate
17318
+ * @property hideColumns
17319
+ * @description Optional array of column keys that should be hidden from view.
17320
+ * @type {string[]}
17335
17321
  */
17336
- toggleSelect(checkbox, predicate) {
17337
- if (this.selectionModel.hasValue()) {
17338
- this.selectionModel.clear();
17339
- checkbox.source.checked = false;
17340
- }
17341
- else {
17342
- this.items.filter(predicate ? predicate : x => x)
17343
- .filter(x => !x['locked'])
17344
- .forEach(data => this.selectionModel.select(data));
17345
- if (this.selectionModel.selected.length !== this.total) {
17346
- checkbox.source.checked = false;
17347
- }
17348
- }
17349
- }
17322
+ hideColumns;
17350
17323
  /**
17351
- * Get selected Items
17324
+ * @property rowNgClass
17325
+ * @description Function to dynamically assign CSS classes to rows based on the row data
17326
+ * and context. Can be used for conditional row styling.
17327
+ * @type {(x?: T, ctx?: IGenericListComponent<T>) => any}
17352
17328
  */
17353
- getSelected = (key) => this.selectionModel.selected.map(x => x[key]);
17329
+ rowNgClass;
17354
17330
  /**
17355
- * Get selected Items
17331
+ * @property rowClick
17332
+ * @description Callback function for handling row click events.
17333
+ * Invoked when a row is clicked.
17334
+ * @type {(x?: T, ctx?: IGenericListComponent<T>) => any}
17356
17335
  */
17357
- getSelectedIds = () => this.getSelected('id');
17358
- }
17359
-
17360
- class DataSourceFilterDirective {
17336
+ rowClick;
17361
17337
  /**
17362
- * DataSource instance
17338
+ * @property onEdit
17339
+ * @description Callback function for handling edit actions.
17340
+ * Invoked when the edit button is clicked for a row.
17341
+ * @type {(x?: T, ctx?: IGenericListComponent<T>) => any}
17363
17342
  */
17364
- dataSource;
17343
+ onEdit;
17365
17344
  /**
17366
- * Represents a value that changes over time.
17367
- * Observers can subscribe to the subject to receive filter changes
17345
+ * @property detailsTemplate
17346
+ * @description Name of the template to use for displaying additional row details.
17347
+ * @type {string}
17368
17348
  */
17369
- _queryChange = new BehaviorSubject(null);
17349
+ detailsTemplate;
17370
17350
  /**
17371
- * Sets query
17351
+ * @property actions
17352
+ * @description Array of action items (e.g., custom buttons) available for each row in the table.
17353
+ * Actions can be context-sensitive based on the row data and table context.
17354
+ * @type {ActionItem<T, IGenericListComponent<T>>[]}
17372
17355
  */
17373
- set dataSourceFilter(query) { this._queryChange.next(query); }
17356
+ actions = [];
17374
17357
  /**
17375
- * Gets query
17358
+ * @property columnSets
17359
+ * @description Used to display specific columns in the table.
17360
+ * This array defines sets of columns that can be shown
17361
+ * based on the active configuration, allowing for dynamic table
17362
+ * column customization.
17363
+ * @type {string[]}
17376
17364
  */
17377
- get dataSourceFilter() { return this._queryChange.value; }
17365
+ columnSets = [];
17378
17366
  /**
17379
- * Lifecycle hook that is called after data-bound properties of a directive are initialized.
17367
+ * Constructor for initializing the table definition with optional values.
17368
+ * Merges the provided initialization object with default properties.
17369
+ *
17370
+ * @param init - Optional partial table definition to initialize values.
17380
17371
  */
17381
- ngOnInit() {
17382
- this._queryChange.subscribe(() => {
17383
- if (this.dataSource) {
17384
- /* Update the filters */
17385
- Object.assign(this.dataSource.staticFieldFilters || {}, this.dataSourceFilter != null ? this.dataSourceFilter : {});
17386
- /* Reload data */
17387
- this.dataSource.reload();
17388
- }
17389
- });
17372
+ constructor(init) {
17373
+ Object.assign(this, init);
17390
17374
  }
17391
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: DataSourceFilterDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
17392
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: DataSourceFilterDirective, isStandalone: true, selector: "[dataSourceFilter]", inputs: { dataSource: "dataSource", dataSourceFilter: "dataSourceFilter" }, ngImport: i0 });
17393
17375
  }
17394
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: DataSourceFilterDirective, decorators: [{
17395
- type: Directive,
17396
- args: [{
17397
- selector: '[dataSourceFilter]'
17398
- }]
17399
- }], propDecorators: { dataSource: [{
17400
- type: Input
17401
- }], dataSourceFilter: [{
17402
- type: Input
17403
- }] } });
17376
+
17377
+ /**
17378
+ * Gets classes decoarated with @Table
17379
+ * @param origin
17380
+ * @returns
17381
+ */
17382
+ function getTableDefinition(origin) {
17383
+ /* Save the table defintion in the metadata */
17384
+ var tableDefinition = Reflect.getMetadata(TABLE_DEFINITION_METADATA_KEY, origin) ?? new TableDefinition({});
17385
+ if (tableDefinition) {
17386
+ /* Set column in the table definition */
17387
+ tableDefinition.columns = Reflect.getMetadata(TABLE_COLUMNS_METADATA_KEY, Reflect.construct(origin, []))
17388
+ ?.filter((x) => !x.hidden && !tableDefinition.hideColumns?.some(y => y.trim() == x.name.trim()));
17389
+ /* Sort the columns by index */
17390
+ Utils.sortArray(tableDefinition.columns || [], 'index');
17391
+ /* Set endpoint from the decorator @Api, if any */
17392
+ var endpoint = Reflect.getMetadata(endpointMetadataKey, origin);
17393
+ if (endpoint) {
17394
+ tableDefinition.endpoint = endpoint;
17395
+ }
17396
+ }
17397
+ return tableDefinition;
17398
+ }
17404
17399
 
17405
17400
  /**
17406
17401
  * A generic datasource class for working with data-tables in Angular Material.
@@ -18246,7 +18241,7 @@ class FilterSelectComponent {
18246
18241
  provide: MAT_SELECT_CONFIG,
18247
18242
  useValue: { overlayPanelClass: 'vd-select-filter-overlay' }
18248
18243
  }
18249
- ], queries: [{ propertyName: "optionTemplate", first: true, predicate: VdFilterOptionDirective, descendants: true }], viewQueries: [{ propertyName: "selectEl", first: true, predicate: MatSelect, descendants: true }, { propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }], ngImport: i0, template: "<mat-form-field subscriptSizing=\"dynamic\" [ngClass]=\"{'filter-not-empty': value}\" dense-3 flex>\r\n\t@if (!value && value!=0 && !focused) {\r\n\t\t<span matPrefix (click)=\"$event.stopPropagation();select.open()\">\r\n\t\t\t<mat-icon fontSet=\"material-symbols-outlined\">manage_search</mat-icon>\r\n\t\t</span>\r\n\t}\r\n\t<mat-select type=\"input\" [(ngModel)]=\"value\" [multiple]=\"multiple\" flex #select>\r\n\t\t@if (filterable) {\r\n\t\t\t<mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\" dense-3 flex>\r\n\t\t\t\t<input matInput #filterInput type=\"text\" placeholder=\"Filter...\" class=\"vd-select-filter\" (click)=\"$event.stopPropagation();\" (keyup)=\"handleFilter($event)\" flex>\r\n\t\t\t\t@if (filterInput?.value) {\r\n\t\t\t\t\t<mat-icon (click)=\"$event.stopPropagation(); filterInput!.value = ''; handleFilter($event);\" fontSet=\"material-symbols-outlined\">close</mat-icon>\r\n\t\t\t\t}\r\n\t\t\t</mat-form-field>\r\n\t\t}\r\n\t\t@if (!multiple) {\r\n\t\t\t<mat-option class=\"tc-grey-500\" (click)=\"$event.stopPropagation();\"></mat-option>\r\n\t\t}\r\n\t\t@for (option of filteredOptions; track option; let first = $first) {\r\n\t\t\t<mat-option [value]=\"option[key]\" (click)=\"$event.stopPropagation();\">\r\n\t\t\t\t@if (!optionTemplate?.templateRef) {\r\n\t\t\t\t\t<span i18n=\"@@selection\">{option.name, select, option {option} other {{{option[text]}}}}</span>\r\n\t\t\t\t\t}\r\n\t\t\t\t\t@if (optionTemplate?.templateRef) {\r\n\t\t\t\t\t\t<ng-template [ngTemplateOutlet]=\"optionTemplate!.templateRef\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\r\n\t\t\t\t\t}\r\n\t\t\t</mat-option>\r\n\t\t\t}\r\n\t</mat-select>\r\n</mat-form-field>", styles: [".mat-mdc-form-field mat-icon{opacity:.7}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
18244
+ ], queries: [{ propertyName: "optionTemplate", first: true, predicate: VdFilterOptionDirective, descendants: true }], viewQueries: [{ propertyName: "selectEl", first: true, predicate: MatSelect, descendants: true }, { propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }], ngImport: i0, template: "<mat-form-field subscriptSizing=\"dynamic\" [ngClass]=\"{'filter-not-empty': value}\" dense-3 flex>\r\n @if (!value && value!=0 && !focused) {\r\n <span matPrefix (click)=\"$event.stopPropagation();select.open()\">\r\n <mat-icon fontSet=\"material-symbols-outlined\">manage_search</mat-icon>\r\n </span>\r\n }\r\n <mat-select type=\"input\" [(ngModel)]=\"value\" [multiple]=\"multiple\" flex #select>\r\n @if (filterable) {\r\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\" dense-3 flex>\r\n <input matInput #filterInput type=\"text\" placeholder=\"Filter...\" class=\"vd-select-filter\" (click)=\"$event.stopPropagation();\" (keyup)=\"handleFilter($event)\" flex>\r\n @if (filterInput?.value) {\r\n <mat-icon (click)=\"$event.stopPropagation(); filterInput!.value = ''; handleFilter($event);\" fontSet=\"material-symbols-outlined\">close</mat-icon>\r\n }\r\n </mat-form-field>\r\n }\r\n @if (!multiple) {\r\n <mat-option class=\"tc-grey-500\" (click)=\"$event.stopPropagation();\"></mat-option>\r\n }\r\n @for (option of filteredOptions; track option; let first = $first) {\r\n <mat-option [value]=\"option[key]\" (click)=\"$event.stopPropagation();\">\r\n @if (!optionTemplate?.templateRef) {\r\n <msa-selection-label [label]=\"option[text]\"></msa-selection-label>\r\n }\r\n @if (optionTemplate?.templateRef) {\r\n <ng-template [ngTemplateOutlet]=\"optionTemplate!.templateRef\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\r\n }\r\n </mat-option>\r\n }\r\n </mat-select>\r\n</mat-form-field>", styles: [".mat-mdc-form-field mat-icon{opacity:.7}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MsaSelectionLabelComponent, selector: "msa-selection-label", inputs: ["label"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
18250
18245
  }
18251
18246
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: FilterSelectComponent, decorators: [{
18252
18247
  type: Component,
@@ -18256,7 +18251,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
18256
18251
  MatFormFieldModule,
18257
18252
  MatInputModule,
18258
18253
  MatSelectModule,
18259
- MatIconModule
18254
+ MatIconModule,
18255
+ MsaSelectionLabelComponent
18260
18256
  ], changeDetection: ChangeDetectionStrategy.Eager, providers: [
18261
18257
  {
18262
18258
  provide: NG_VALUE_ACCESSOR,
@@ -18267,7 +18263,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
18267
18263
  provide: MAT_SELECT_CONFIG,
18268
18264
  useValue: { overlayPanelClass: 'vd-select-filter-overlay' }
18269
18265
  }
18270
- ], template: "<mat-form-field subscriptSizing=\"dynamic\" [ngClass]=\"{'filter-not-empty': value}\" dense-3 flex>\r\n\t@if (!value && value!=0 && !focused) {\r\n\t\t<span matPrefix (click)=\"$event.stopPropagation();select.open()\">\r\n\t\t\t<mat-icon fontSet=\"material-symbols-outlined\">manage_search</mat-icon>\r\n\t\t</span>\r\n\t}\r\n\t<mat-select type=\"input\" [(ngModel)]=\"value\" [multiple]=\"multiple\" flex #select>\r\n\t\t@if (filterable) {\r\n\t\t\t<mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\" dense-3 flex>\r\n\t\t\t\t<input matInput #filterInput type=\"text\" placeholder=\"Filter...\" class=\"vd-select-filter\" (click)=\"$event.stopPropagation();\" (keyup)=\"handleFilter($event)\" flex>\r\n\t\t\t\t@if (filterInput?.value) {\r\n\t\t\t\t\t<mat-icon (click)=\"$event.stopPropagation(); filterInput!.value = ''; handleFilter($event);\" fontSet=\"material-symbols-outlined\">close</mat-icon>\r\n\t\t\t\t}\r\n\t\t\t</mat-form-field>\r\n\t\t}\r\n\t\t@if (!multiple) {\r\n\t\t\t<mat-option class=\"tc-grey-500\" (click)=\"$event.stopPropagation();\"></mat-option>\r\n\t\t}\r\n\t\t@for (option of filteredOptions; track option; let first = $first) {\r\n\t\t\t<mat-option [value]=\"option[key]\" (click)=\"$event.stopPropagation();\">\r\n\t\t\t\t@if (!optionTemplate?.templateRef) {\r\n\t\t\t\t\t<span i18n=\"@@selection\">{option.name, select, option {option} other {{{option[text]}}}}</span>\r\n\t\t\t\t\t}\r\n\t\t\t\t\t@if (optionTemplate?.templateRef) {\r\n\t\t\t\t\t\t<ng-template [ngTemplateOutlet]=\"optionTemplate!.templateRef\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\r\n\t\t\t\t\t}\r\n\t\t\t</mat-option>\r\n\t\t\t}\r\n\t</mat-select>\r\n</mat-form-field>", styles: [".mat-mdc-form-field mat-icon{opacity:.7}\n"] }]
18266
+ ], template: "<mat-form-field subscriptSizing=\"dynamic\" [ngClass]=\"{'filter-not-empty': value}\" dense-3 flex>\r\n @if (!value && value!=0 && !focused) {\r\n <span matPrefix (click)=\"$event.stopPropagation();select.open()\">\r\n <mat-icon fontSet=\"material-symbols-outlined\">manage_search</mat-icon>\r\n </span>\r\n }\r\n <mat-select type=\"input\" [(ngModel)]=\"value\" [multiple]=\"multiple\" flex #select>\r\n @if (filterable) {\r\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\" dense-3 flex>\r\n <input matInput #filterInput type=\"text\" placeholder=\"Filter...\" class=\"vd-select-filter\" (click)=\"$event.stopPropagation();\" (keyup)=\"handleFilter($event)\" flex>\r\n @if (filterInput?.value) {\r\n <mat-icon (click)=\"$event.stopPropagation(); filterInput!.value = ''; handleFilter($event);\" fontSet=\"material-symbols-outlined\">close</mat-icon>\r\n }\r\n </mat-form-field>\r\n }\r\n @if (!multiple) {\r\n <mat-option class=\"tc-grey-500\" (click)=\"$event.stopPropagation();\"></mat-option>\r\n }\r\n @for (option of filteredOptions; track option; let first = $first) {\r\n <mat-option [value]=\"option[key]\" (click)=\"$event.stopPropagation();\">\r\n @if (!optionTemplate?.templateRef) {\r\n <msa-selection-label [label]=\"option[text]\"></msa-selection-label>\r\n }\r\n @if (optionTemplate?.templateRef) {\r\n <ng-template [ngTemplateOutlet]=\"optionTemplate!.templateRef\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\r\n }\r\n </mat-option>\r\n }\r\n </mat-select>\r\n</mat-form-field>", styles: [".mat-mdc-form-field mat-icon{opacity:.7}\n"] }]
18271
18267
  }], ctorParameters: () => [{ type: i1$5.MatTable }, { type: i2$3.CdkColumnDef }], propDecorators: { optionTemplate: [{
18272
18268
  type: ContentChild,
18273
18269
  args: [VdFilterOptionDirective]
@@ -18791,6 +18787,10 @@ class VdDynamicTableComponent {
18791
18787
  updateColumns() {
18792
18788
  /* Sort the columns by index */
18793
18789
  Utils.sortArray(this.columns || [], 'index');
18790
+ /* Cache responsive display classes once per column */
18791
+ this.columns?.forEach(column => {
18792
+ column.displayNgClass = this.getDisplayClasses(column);
18793
+ });
18794
18794
  /* Trigger changes */
18795
18795
  this.columnsSubject.next(this.columns);
18796
18796
  }
@@ -18946,20 +18946,47 @@ class VdDynamicTableComponent {
18946
18946
  keys.slice(0, -1).reduce((acc, key) => acc && acc[key], row)[keys[keys.length - 1]] = value;
18947
18947
  }
18948
18948
  /**
18949
- * Gets row classes
18950
- * @param column
18951
- * @param row
18952
- * @returns
18949
+ * Retrieves the display setting for a given column, which can be either a static value or a function.
18950
+ * If the display property is a function, it will be invoked with the current column sets and context.
18951
+ * @param column - The TableColumn object for which to retrieve the display setting.
18952
+ * @returns The display setting for the column, which can be a Grid value or undefined.
18953
+ */
18954
+ getColumnDisplay(column) {
18955
+ /* If the display property is a function, invoke it with the current column sets and context */
18956
+ if (typeof column.display === 'function') {
18957
+ return column.display(this.columnSets || [], this.context);
18958
+ }
18959
+ return column.display;
18960
+ }
18961
+ /**
18962
+ * Computes the CSS classes for a column based on its display setting.
18963
+ * It maps the display value to corresponding CSS classes that control visibility and layout.
18964
+ * @param column - The TableColumn object for which to compute the display classes.
18965
+ * @returns An object containing CSS class names as keys and boolean values indicating whether the class should be applied.
18966
+ */
18967
+ getDisplayClasses(column) {
18968
+ /* Retrieve the display setting for the column, which may be a static value or computed dynamically. */
18969
+ const display = this.getColumnDisplay(column);
18970
+ /* Return an object mapping display values to CSS classes, allowing for responsive visibility control. */
18971
+ return {
18972
+ 'gt-xs': display == Grid.Xs,
18973
+ 'gt-sm': display == Grid.Sm,
18974
+ 'gt-md': display == Grid.Md,
18975
+ 'gt-lg': display == Grid.Lg,
18976
+ 'gt-xl': display == Grid.Xl,
18977
+ 'gt-xxl': display == Grid.Xxl,
18978
+ 'hidden': display == Grid.None,
18979
+ };
18980
+ }
18981
+ /**
18982
+ * Computes the CSS classes for a specific row based on the column's display settings and any additional classes defined.
18983
+ * It combines the column's display classes, any custom classes defined in `cellNgClass`, and a 'text-right' class if `arrowBefore` is true.
18984
+ * @param column - The TableColumn object for which to compute the row classes.
18985
+ * @param row - The data object representing the current row.
18986
+ * @returns An object containing CSS class names as keys and boolean values indicating whether the class should be applied.
18953
18987
  */
18954
18988
  getRowClasses(column, row) {
18955
- return Object.assign({
18956
- 'gt-xs': column.display == Grid.Xs,
18957
- 'gt-sm': column.display == Grid.Sm,
18958
- 'gt-md': column.display == Grid.Md,
18959
- 'gt-lg': column.display == Grid.Lg,
18960
- 'gt-xl': column.display == Grid.Xl,
18961
- 'gt-xxl': column.display == Grid.Xxl,
18962
- 'hidden': column.display == Grid.None,
18989
+ return Object.assign({}, column.displayNgClass || this.getDisplayClasses(column), {
18963
18990
  'text-right': column.arrowBefore
18964
18991
  }, column.cellNgClass ? column.cellNgClass(row, this.context) : {});
18965
18992
  }
@@ -19004,7 +19031,7 @@ class VdDynamicTableComponent {
19004
19031
  this.changeDetector.detectChanges();
19005
19032
  }
19006
19033
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: VdDynamicTableComponent, deps: [{ token: DynamicBuilder }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
19007
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: VdDynamicTableComponent, isStandalone: true, selector: "vd-dynamic-table", inputs: { dataSource: "dataSource", data: "data", parentControl: "parentControl", entityObject: "entityObject", formArray: "formArray", debugValue: "debugValue", classType: "classType", context: "context", dataSourceFilter: "dataSourceFilter", static: "static", filterable: "filterable", sticky: "sticky", tableWidth: "tableWidth", useFilterOperator: "useFilterOperator", paginable: "paginable", selectable: "selectable", sortActive: "sortActive", sortDirection: "sortDirection", stickyHeader: "stickyHeader", stickyFilter: "stickyFilter", columnSets: "columnSets", rowNgClass: "rowNgClass", detailsTemplate: "detailsTemplate", readonly: "readonly", selectAllFilter: "selectAllFilter", paginatorRef: "paginatorRef", columns: "columns", rowMenuItems: "rowMenuItems", rowAction: "rowAction", excludedColumns: "excludedColumns", pageSize: "pageSize", pageSizeOptions: "pageSizeOptions" }, outputs: { rowClick: "rowClick" }, queries: [{ propertyName: "templateRef", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "table", first: true, predicate: ["table"], descendants: true }, { propertyName: "matSort", first: true, predicate: MatSort, descendants: true, static: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, static: true }, { propertyName: "detailsTemplateRef", predicate: ["detailsTemplate"], descendants: true, read: ViewContainerRef }, { propertyName: "rowContextMenuTriggers", predicate: MatMenuTrigger, descendants: true }], ngImport: i0, template: "@if (!static) {\r\n <div class=\"loading-progress\">\r\n @if (dataSource?.isLoading) {\r\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- #region Data table -->\r\n<div class=\"mat-table-container scrollbar-secondary\" [ngClass]=\"{'mat-table-sticky': sticky}\" #scrollContainer>\r\n <table mat-table #table [dataSource]=\"dataSource\" [dataSourceFilter]=\"dataSourceFilter\" [ngClass]=\"{'table-fixed': !sticky && !detailsTemplate && !templateRef, 'table-stick': sticky}\" [trackBy]=\"trackBy\" matSort matSortDisableClear [matSortActive]=\"sortActive||'id'\" [matSortDirection]=\"sortDirection\" multiTemplateDataRows>\r\n @for (column of columns$ | async; track columnsTrackBy($index, column)) {\r\n <!-- #region Column def -->\r\n <ng-container [cdkColumnDef]=\"column.name\" [sticky]=\"column.sticky\" [stickyEnd]=\"column.stickyEnd\">\r\n <ng-template #header [ngTemplateOutlet]=\"header\" let-headerText=\"headerText\" [ngTemplateOutletContext]=\"{headerText: column.header | func:context}\">\r\n <th mat-header-cell *cdkHeaderCellDef [mat-sort-header]=\"column.sortBy || column.name\" [hidden]=\"column.hidden\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\" [disabled]=\"column.type == ColumnType.Checkbox || column.disabled\" [ngClass]=\"{'gt-xs': column.display == Grid.Xs, 'gt-sm': column.display == Grid.Sm, 'gt-md': column.display == Grid.Md, 'gt-lg': column.display == Grid.Lg, 'gt-xl': column.display == Grid.Xl, 'gt-xxl': column.display == Grid.Xxl, 'hidden': column.display == Grid.None}\" [arrowPosition]=\"column.arrowBefore?'before':'after'\">\r\n @if (column.type == ColumnType.Checkbox) {\r\n <mat-checkbox (change)=\"$event ? dataSource.toggleSelect($event, selectAllFilter) : null\" [disabled]=\"!dataSource.paginator?.length\" [checked]=\"dataSource.selectionModel.hasValue() && dataSource.isAllSelected()\" [indeterminate]=\"dataSource.selectionModel.hasValue() && !dataSource.isAllSelected()\"></mat-checkbox>\r\n } @if (column.type != ColumnType.Checkbox) {\r\n <span [matTooltip]=\"headerText\">{{headerText}}</span>\r\n }\r\n </th>\r\n </ng-template>\r\n <td mat-cell *cdkCellDef=\"let row; let rowIndex = dataIndex\" [matTooltip]=\"column.tooltip?column.tooltip(row, undefined, context):null\" [matTooltipClass]=\"column.tooltipClass??''\" [hidden]=\"column.hidden\" [ngClass]=\"getRowClasses(column, row)\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\">\r\n <ng-template #rowVal [ngTemplateOutlet]=\"rowVal\" let-rowValue [ngTemplateOutletContext]=\"{$implicit: column?.content && column?.content(row, undefined, context)}\">\r\n @switch (column.type) {\r\n <!-- #region Checkbox column -->\r\n @case (ColumnType.Checkbox) {\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? dataSource.selectionModel.toggle(row) : null\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" [checked]=\"dataSource.selectionModel.isSelected(row)\"></mat-checkbox>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Enum column -->\r\n @case (ColumnType.Enum) {\r\n <span>\r\n @if (column.enumMetadata) {\r\n @if (column.multiple) {\r\n @for (item of rowValue; track item; let i = $index) {\r\n @if (i < 2) {\r\n <ng-template let-displayValue=\"displayValue\" [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"{ displayValue: column.enumMetadata[item].display }\"></ng-template>\r\n }\r\n @if (i === 1 && rowValue?.length > 2) {\r\n <small [matTooltip]=\"(rowValue | slice:2 | map:column.enumMetadata | map:'display') | join:'\\n'\" matTooltipClass=\"mat-tooltip-multiline\">...</small>\r\n }\r\n }\r\n <ng-template #template let-displayValue=\"displayValue\">\r\n <mat-chip-row disableRipple=\"true\" selectable=\"false\" [matTooltip]=\"displayValue\">\r\n <span>{{ displayValue }}</span>\r\n </mat-chip-row>\r\n </ng-template>\r\n } @else {\r\n @if (rowValue >= 0) {\r\n <span class=\"na\" [ngStyle]=\"{ color: ((column.enumMetadata[rowValue] || {}).textColor || 'inherit') }\" [innerHtml]=\"(column.enumMetadata[rowValue]||{}).display\"></span>\r\n }\r\n }\r\n } @else {\r\n @if (column.multiple) {\r\n @for (item of rowValue; track item; let i = $index; let last = $last) {\r\n <div>\r\n @if (i<2) {\r\n <small>\r\n <msa-enum-display [value]=\"item\" [enumType]=\"column.enumType\" [metadata]=\"column.enumMetadata\"></msa-enum-display>\r\n </small>\r\n } @if (i==1 && rowValue?.length > 2) {\r\n <small>, ...</small>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @if (rowValue >= 0) {\r\n <msa-enum-display [value]=\"rowValue\" [enumType]=\"column.enumType\" [metadata]=\"column.enumMetadata\"></msa-enum-display>\r\n }\r\n }\r\n }\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Toggle column -->\r\n @case (ColumnType.Toggle) {\r\n @if (!formArray) {\r\n <mat-slide-toggle [ngModel]=\"row | property:column.name\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);handleModelChange(column, row, undefined);\" (click)=\"$event.stopPropagation();\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" color=\"accent\"></mat-slide-toggle>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Date column -->\r\n @case (ColumnType.Date) {\r\n <span>{{rowValue | date:column.shortDate?'dd.MM.yyyy':'dd.MM.yyyy HH:mm:ss'}}</span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Text Input column -->\r\n @case (ColumnType.TextInput) {\r\n @if (!formArray) {\r\n <mat-form-field appearance=\"outline\" layout=\"column\" layout-align=\"center start\" subscriptSizing=\"dynamic\" dense-3 (click)=\"$event.stopPropagation();\">\r\n @if (!formArray) {\r\n <input matInput type=\"{{column.inputType}}\" autocomplete=\"none\" name=\"{{column.name}}{{rowIndex}}\" [ngModel]=\"row | property:column.name\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" [min]=\"column.inputMin?column.inputMin(row, undefined, context):null\" [max]=\"column.inputMax?column.inputMax(row, undefined, context):null\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);(column.change?column.change(row, undefined, context):patch(row, [column.name], $event, column.patchIncludes));\" [ngModelOptions]=\"{updateOn: 'blur'}\" (keydown.enter)=\"handleKeydownEnter($event)\" />\r\n }\r\n </mat-form-field>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region VD-Select column -->\r\n @case (ColumnType.Select) {\r\n @if (!formArray) {\r\n <mat-form-field appearance=\"outline\" layout=\"column\" layout-align=\"center start\" subscriptSizing=\"dynamic\" dense-3 (click)=\"$event.stopPropagation();\">\r\n @if (!formArray) {\r\n <vd-select name=\"{{column.name}}{{rowIndex}}\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"$safeNavigationMigration(column?.enumFilter) | func:row:context\" [options]=\"column.options\" [defaultOption]=\"column.defaultOption??true\" [ngModel]=\"row | property:column.name\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" (change)=\"column.change?column.change(row, undefined, context):patch(row, [column.name], $event.value, column.patchIncludes)\" (keydown.enter)=\"handleKeydownEnter($event)\"></vd-select>\r\n }\r\n </mat-form-field>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Action -->\r\n @case (ColumnType.Action) {\r\n @if (column.menu) {\r\n @if (menu?.matMenu && !row.locked && hasVisibleRowMenuItems(row, column)) {\r\n <div id=\"menu-{{row.id}}\" style=\"visibility: hidden; position: fixed\" #contextMenuTrigger=\"matMenuTrigger\" [matMenuTriggerFor]=\"menu.matMenu!\"></div>\r\n }\r\n <vd-dynamic-menu [items]=\"[column.menu]\" [data]=\"row\" [context]=\"context\" #menu></vd-dynamic-menu>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Menu -->\r\n @case (ColumnType.Menu) {\r\n @if (column.menu) {\r\n <vd-dynamic-menu [items]=\"[column.menu]\" [data]=\"row\" [context]=\"context\"></vd-dynamic-menu>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region icon -->\r\n @case (ColumnType.Icon) {\r\n <span layout=\"row\" layout-align=\"start center\">\r\n @if(column && column.icon){\r\n @if ( column.icon.matIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\">{{handleExpression($safeNavigationMigration(column.icon.matIcon)!, row)}}</mat-icon>\r\n }\r\n @if (column.icon.svgIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\" [svgIcon]=\"handleExpression($safeNavigationMigration(column.icon.svgIcon)!, row)!\"></mat-icon>\r\n }\r\n @if (column.icon.fontIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\" [fontIcon]=\"handleExpression($safeNavigationMigration(column.icon.fontIcon)!, row)!\"></mat-icon>\r\n }\r\n }\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region icon button -->\r\n @case (ColumnType.IconButton) {\r\n <a mat-icon-button (click)=\"$event.stopPropagation();column.iconButton?.event?column.iconButton.event(row, context):null\">\r\n <mat-icon fontSet=\"{{column.iconButton?.iconFontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.iconButton?.iconClass??'', row)\">{{handleExpression(column.iconButton?.icon??'radio_button_checked', row) || 'radio_button_checked'}}</mat-icon>\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Other column types -->\r\n @default {\r\n <span [innerHtml]=\"rowValue??''\"></span>\r\n }\r\n <!-- #endregion -->\r\n }\r\n <ng-template #recursiveContainer let-columnNameSegments=\"segments\" let-formGroup=\"formGroup\" let-parentFormGroup=\"parentFormGroup\">\r\n @if (formGroup) {\r\n <ng-container [formGroup]=\"formGroup\">\r\n <!-- If the columnNameSegments array is empty, we're at the leaf node -->\r\n @if (!columnNameSegments.length) {\r\n @switch (column.type) {\r\n <!-- #region Toggle column -->\r\n @case (ColumnType.Toggle) {\r\n <mat-slide-toggle [formControl]=\"formGroup\" (click)=\"$event.stopPropagation();\" (change)=\"column.change?column.change(parentFormGroup.value, parentFormGroup, context):handleModelChange(column, parentFormGroup.value, parentFormGroup)\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" color=\"accent\"></mat-slide-toggle>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Text Input column -->\r\n @case (ColumnType.TextInput) {\r\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" dense-3 layout=\"column\" layout-align=\"center start\" (click)=\"$event.stopPropagation();\">\r\n <input matInput [formControl]=\"formGroup\" type=\"{{column.inputType}}\" autocomplete=\"none\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" [min]=\"column.inputMin?column.inputMin(parentFormGroup.value, parentFormGroup, context):null\" [max]=\"column.inputMax?column.inputMax(parentFormGroup.value, parentFormGroup, context):null\" (keydown.enter)=\"handleKeydownEnter($event)\" />\r\n </mat-form-field>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region VD-Select column -->\r\n @case (ColumnType.Select) {\r\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" dense-3 layout=\"column\" layout-align=\"center start\" (click)=\"$event.stopPropagation();\">\r\n <vd-select [formControl]=\"formGroup\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"column.enumFilter | func:parentFormGroup.value:context\" [options]=\"column.options\" [defaultOption]=\"column.defaultOption??true\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" (selectionChange)=\"column.change?column.change(parentFormGroup.value, parentFormGroup, context):patch(parentFormGroup.value, [column.name], rowValue, column.patchIncludes)\" (keydown.enter)=\"handleKeydownEnter($event)\"></vd-select>\r\n </mat-form-field>\r\n }\r\n <!-- #endregion -->\r\n }\r\n } @else {\r\n <!-- If not the last segment, create a nested form group -->\r\n <ng-container [formGroupName]=\"columnNameSegments[0]\">\r\n <!-- Recursive call to handle nested segments -->\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: columnNameSegments.slice(1), parentFormGroup:formGroup, formGroup: formGroup.get(columnNameSegments[0])}\"></ng-container>\r\n </ng-container>\r\n }\r\n </ng-container>\r\n }\r\n </ng-template>\r\n </ng-template>\r\n </td>\r\n </ng-container>\r\n <!-- #endregion -->\r\n }\r\n\r\n <!-- #region Filter row -->\r\n @if (dataSource && filterable) {\r\n @for (column of columns$ | async; track column) {\r\n <ng-container cdkColumnDef=\"filter.{{column.filter || column.name}}\" [sticky]=\"column.sticky\" [stickyEnd]=\"column.stickyEnd\">\r\n <th mat-header-cell *cdkHeaderCellDef [hidden]=\"column.hidden\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\" [ngClass]=\"{'gt-xs': column.display == Grid.Xs, 'gt-sm': column.display == Grid.Sm, 'gt-md': column.display == Grid.Md, 'gt-lg': column.display == Grid.Lg, 'gt-xl': column.display == Grid.Xl, 'gt-xxl': column.display == Grid.Xxl, 'hidden': column.display == Grid.None}\">\r\n <!-- #region Select filter -->\r\n @if(column.endpoint || column.enumType || column.options){\r\n <span filter-select [endpoint]=\"column.endpoint\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"column.enumFilter | func:{}:context\" [options]=\"column.options\" [text]=\"column.filterOptionText || 'name'\"></span>\r\n }\r\n <!-- #region Text filter -->\r\n @else if(column.type == ColumnType.Text || column.type == ColumnType.TextInput || column.type == ColumnType.Number) {\r\n <span filter-input [onlyNumber]=\"column.filterInputNumber??false\" [matTooltip]=\"column.filterTooltip ? column.filterTooltip(context):null\" [matTooltipClass]=\"column.filterTooltipClass??''\" [operator]=\"!useFilterOperator ? undefined : column.filterOperator\"></span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Date filter -->\r\n @else if (column.type == ColumnType.Date) {\r\n <span filter-date></span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Action filter (clear) -->\r\n @else if (column.type == ColumnType.Action) {\r\n <span filter-clear></span>\r\n }\r\n <!-- #endregion -->\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n\r\n <!-- #region Details column -->\r\n <ng-container cdkColumnDef=\"expandedDetail\">\r\n <td mat-cell *matCellDef=\"let row; let index = index\" [attr.colspan]=\"(displayedColumns$ | async)?.length\">\r\n <div class=\"row-detail\" [@detailExpand]=\"row == expandedRow ? 'expanded' : 'collapsed'\" #detailsTemplate>\r\n @if (templateRef && row === expandedRow) {\r\n <ng-container *ngTemplateOutlet=\"templateRef; context:{row: row, index: index, context: context}\"></ng-container>\r\n }\r\n </div>\r\n </td>\r\n </ng-container>\r\n <!-- #endregion -->\r\n\r\n <!-- #region Filter header -->\r\n @if (filterable) {\r\n <tr mat-header-row *cdkHeaderRowDef=\"displayedFilterColumns$ | async\"></tr>\r\n }\r\n <!-- #endregion -->\r\n\r\n <tr mat-header-row *cdkHeaderRowDef=\"displayedColumns$ | async; sticky: stickyFilter\"></tr>\r\n <tr mat-row *cdkRowDef=\"let row; columns: displayedColumns$ | async; let index = dataIndex\" [ngClass]=\"rowNgClass?rowNgClass(row, context):null\" [class.expanded-row]=\"expandedRow === row\" (click)=\"handleRowClick(index, row)\" (contextmenu)=\"handleRowRightClick($event, row)\"></tr>\r\n\r\n <!-- #region Detrails row -->\r\n @if (detailsTemplate || templateRef) {\r\n <tr mat-row *cdkRowDef=\"let row; columns: ['expandedDetail']\" class=\"detail-row\" [ngClass]=\"rowNgClass?rowNgClass(row, context):null\"></tr>\r\n }\r\n <!-- #endregion -->\r\n </table>\r\n\r\n <!-- #region Modern No Results Message -->\r\n @if (dataSource?.filteredData?.length <= 0 && dataSource?.total <= 0) {\r\n <div class=\"no-results-overlay\">\r\n <mat-icon class=\"no-results-icon\">search_off</mat-icon>\r\n <div class=\"no-results-text mat-body-1\">\r\n <h3 i18n=\"@@noResultsFound\">No results found</h3>\r\n <p i18n=\"@@tryAdjustFilters\">\r\n Try adjusting your filters or search criteria.\r\n </p>\r\n </div>\r\n </div>\r\n }\r\n <!-- #endregion -->\r\n</div>\r\n<!-- #endregion -->\r\n\r\n<!-- #region Debug value -->\r\n@if (debugValue) {\r\n <code>\r\n <pre>{{formValue | json}}</pre>\r\n</code>\r\n}\r\n<!-- #endregion -->\r\n\r\n<div class=\"table-footer\" layout=\"row\">\r\n <ng-content select=\"[table-footer]\"></ng-content>\r\n <span flex></span>\r\n @if (paginable) {\r\n <mat-paginator [pageSize]=\"pageSize\" [pageSizeOptions]=\"pageSizeOptions\" showFirstLastButtons=\"true\"></mat-paginator>\r\n }\r\n</div>", styles: ["::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-form-field .mat-form-field-wrapper{width:100%}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip{height:24px;margin-top:2px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip .mdc-evolution-chip__action--primary{padding-left:9px;padding-right:9px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip:last-child{margin-bottom:2px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip *{font-size:.8rem}@media(max-width:389px){::ng-deep .mat-mdc-table [gt-xs],::ng-deep .mat-mdc-table .gt-xs{display:none}::ng-deep .mat-mdc-table [gt-sm],::ng-deep .mat-mdc-table .gt-sm{display:none}::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:599px){::ng-deep .mat-mdc-table [gt-sm],::ng-deep .mat-mdc-table .gt-sm{display:none}::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:959px){::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1279px){::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1919px){::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1979px){::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}.mat-table-container{width:100%;max-width:100%;overflow:auto}.mat-table-container .mat-mdc-header-cell,.mat-table-container .mat-mdc-footer-cell,.mat-table-container .mat-mdc-cell{min-width:80px;box-sizing:border-box}.mat-table-container .mat-mdc-header-row,.mat-table-container .mat-mdc-footer-row,.mat-table-container .mat-mdc-row{min-width:1920px}.mat-table-container.mat-table-sticky .mat-mdc-table-sticky-border-elem-right{box-shadow:-3px 0 5px #0000001a}.mat-table-container.mat-table-sticky .mat-mdc-table-sticky-border-elem-left{box-shadow:3px 0 5px #0000001a}\n"], dependencies: [{ kind: "ngmodule", type: CdkTableModule }, { kind: "directive", type: i2$3.CdkRowDef, selector: "[cdkRowDef]", inputs: ["cdkRowDefColumns", "cdkRowDefWhen"] }, { kind: "directive", type: i2$3.CdkCellDef, selector: "[cdkCellDef]" }, { kind: "directive", type: i2$3.CdkHeaderCellDef, selector: "[cdkHeaderCellDef]" }, { kind: "directive", type: i2$3.CdkColumnDef, selector: "[cdkColumnDef]", inputs: ["cdkColumnDef", "sticky", "stickyEnd"] }, { kind: "directive", type: i2$3.CdkHeaderRowDef, selector: "[cdkHeaderRowDef]", inputs: ["cdkHeaderRowDef", "cdkHeaderRowDefSticky"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i7.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i10.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i3.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i12.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i12.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i16.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "directive", type:
19034
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: VdDynamicTableComponent, isStandalone: true, selector: "vd-dynamic-table", inputs: { dataSource: "dataSource", data: "data", parentControl: "parentControl", entityObject: "entityObject", formArray: "formArray", debugValue: "debugValue", classType: "classType", context: "context", dataSourceFilter: "dataSourceFilter", static: "static", filterable: "filterable", sticky: "sticky", tableWidth: "tableWidth", useFilterOperator: "useFilterOperator", paginable: "paginable", selectable: "selectable", sortActive: "sortActive", sortDirection: "sortDirection", stickyHeader: "stickyHeader", stickyFilter: "stickyFilter", columnSets: "columnSets", rowNgClass: "rowNgClass", detailsTemplate: "detailsTemplate", readonly: "readonly", selectAllFilter: "selectAllFilter", paginatorRef: "paginatorRef", columns: "columns", rowMenuItems: "rowMenuItems", rowAction: "rowAction", excludedColumns: "excludedColumns", pageSize: "pageSize", pageSizeOptions: "pageSizeOptions" }, outputs: { rowClick: "rowClick" }, queries: [{ propertyName: "templateRef", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "table", first: true, predicate: ["table"], descendants: true }, { propertyName: "matSort", first: true, predicate: MatSort, descendants: true, static: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, static: true }, { propertyName: "detailsTemplateRef", predicate: ["detailsTemplate"], descendants: true, read: ViewContainerRef }, { propertyName: "rowContextMenuTriggers", predicate: MatMenuTrigger, descendants: true }], ngImport: i0, template: "@if (!static) {\r\n <div class=\"loading-progress\">\r\n @if (dataSource?.isLoading) {\r\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\r\n }\r\n </div>\r\n}\r\n<!-- #region Data table -->\r\n<div class=\"mat-table-container scrollbar-secondary\" [ngClass]=\"{'mat-table-sticky': sticky}\" #scrollContainer>\r\n <table mat-table #table [dataSource]=\"dataSource\" [dataSourceFilter]=\"dataSourceFilter\" [ngClass]=\"{'table-fixed': !sticky && !detailsTemplate && !templateRef, 'table-stick': sticky}\" [trackBy]=\"trackBy\" matSort matSortDisableClear [matSortActive]=\"sortActive||'id'\" [matSortDirection]=\"sortDirection\" multiTemplateDataRows>\r\n @for (column of columns$ | async; track columnsTrackBy($index, column)) {\r\n <!-- #region Column def -->\r\n <ng-container [cdkColumnDef]=\"column.name\" [sticky]=\"column.sticky\" [stickyEnd]=\"column.stickyEnd\">\r\n <ng-template #header [ngTemplateOutlet]=\"header\" let-headerText=\"headerText\" [ngTemplateOutletContext]=\"{headerText: column.header | func:context}\">\r\n <th mat-header-cell *cdkHeaderCellDef [mat-sort-header]=\"column.sortBy || column.name\" [hidden]=\"column.hidden\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\" [disabled]=\"column.type == ColumnType.Checkbox || column.disabled\" [ngClass]=\"column.displayNgClass\" [arrowPosition]=\"column.arrowBefore?'before':'after'\">\r\n @if (column.type == ColumnType.Checkbox) {\r\n <mat-checkbox (change)=\"$event ? dataSource.toggleSelect($event, selectAllFilter) : null\" [disabled]=\"!dataSource.paginator?.length\" [checked]=\"dataSource.selectionModel.hasValue() && dataSource.isAllSelected()\" [indeterminate]=\"dataSource.selectionModel.hasValue() && !dataSource.isAllSelected()\"></mat-checkbox>\r\n } @if (column.type != ColumnType.Checkbox) {\r\n <span [matTooltip]=\"headerText\">{{headerText}}</span>\r\n }\r\n </th>\r\n </ng-template>\r\n <td mat-cell *cdkCellDef=\"let row; let rowIndex = dataIndex\" [matTooltip]=\"column.tooltip?column.tooltip(row, undefined, context):null\" [matTooltipClass]=\"column.tooltipClass??''\" [hidden]=\"column.hidden\" [ngClass]=\"getRowClasses(column, row)\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\">\r\n <ng-template #rowVal [ngTemplateOutlet]=\"rowVal\" let-rowValue [ngTemplateOutletContext]=\"{$implicit: column?.content && column?.content(row, undefined, context)}\">\r\n @switch (column.type) {\r\n <!-- #region Checkbox column -->\r\n @case (ColumnType.Checkbox) {\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? dataSource.selectionModel.toggle(row) : null\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" [checked]=\"dataSource.selectionModel.isSelected(row)\"></mat-checkbox>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Enum column -->\r\n @case (ColumnType.Enum) {\r\n <span>\r\n @if (column.enumMetadata) {\r\n @if (column.multiple) {\r\n @for (item of rowValue; track item; let i = $index) {\r\n @if (i < 2) {\r\n <ng-template let-displayValue=\"displayValue\" [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"{ displayValue: column.enumMetadata[item].display }\"></ng-template>\r\n }\r\n @if (i === 1 && rowValue?.length > 2) {\r\n <small [matTooltip]=\"(rowValue | slice:2 | map:column.enumMetadata | map:'display') | join:'\\n'\" matTooltipClass=\"mat-tooltip-multiline\">...</small>\r\n }\r\n }\r\n <ng-template #template let-displayValue=\"displayValue\">\r\n <mat-chip-row disableRipple=\"true\" selectable=\"false\" [matTooltip]=\"displayValue\">\r\n <span>{{ displayValue }}</span>\r\n </mat-chip-row>\r\n </ng-template>\r\n } @else {\r\n @if (rowValue >= 0) {\r\n <span class=\"na\" [ngStyle]=\"{ color: ((column.enumMetadata[rowValue] || {}).textColor || 'inherit') }\" [innerHtml]=\"(column.enumMetadata[rowValue]||{}).display\"></span>\r\n }\r\n }\r\n } @else {\r\n @if (column.multiple) {\r\n @for (item of rowValue; track item; let i = $index; let last = $last) {\r\n <div>\r\n @if (i<2) {\r\n <small>\r\n <msa-enum-display [value]=\"item\" [enumType]=\"column.enumType\" [metadata]=\"column.enumMetadata\"></msa-enum-display>\r\n </small>\r\n } @if (i==1 && rowValue?.length > 2) {\r\n <small>, ...</small>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @if (rowValue >= 0) {\r\n <msa-enum-display [value]=\"rowValue\" [enumType]=\"column.enumType\" [metadata]=\"column.enumMetadata\"></msa-enum-display>\r\n }\r\n }\r\n }\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Toggle column -->\r\n @case (ColumnType.Toggle) {\r\n @if (!formArray) {\r\n <mat-slide-toggle [ngModel]=\"row | property:column.name\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);handleModelChange(column, row, undefined);\" (click)=\"$event.stopPropagation();\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" color=\"accent\"></mat-slide-toggle>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Date column -->\r\n @case (ColumnType.Date) {\r\n <span>{{rowValue | date:column.shortDate?'dd.MM.yyyy':'dd.MM.yyyy HH:mm:ss'}}</span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Text Input column -->\r\n @case (ColumnType.TextInput) {\r\n @if (!formArray) {\r\n <mat-form-field appearance=\"outline\" layout=\"column\" layout-align=\"center start\" subscriptSizing=\"dynamic\" dense-3 (click)=\"$event.stopPropagation();\">\r\n @if (!formArray) {\r\n <input matInput type=\"{{column.inputType}}\" autocomplete=\"none\" name=\"{{column.name}}{{rowIndex}}\" [ngModel]=\"row | property:column.name\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" [min]=\"column.inputMin?column.inputMin(row, undefined, context):null\" [max]=\"column.inputMax?column.inputMax(row, undefined, context):null\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);(column.change?column.change(row, undefined, context):patch(row, [column.name], $event, column.patchIncludes));\" [ngModelOptions]=\"{updateOn: 'blur'}\" (keydown.enter)=\"handleKeydownEnter($event)\" />\r\n }\r\n </mat-form-field>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region VD-Select column -->\r\n @case (ColumnType.Select) {\r\n @if (!formArray) {\r\n <mat-form-field appearance=\"outline\" layout=\"column\" layout-align=\"center start\" subscriptSizing=\"dynamic\" dense-3 (click)=\"$event.stopPropagation();\">\r\n @if (!formArray) {\r\n <vd-select name=\"{{column.name}}{{rowIndex}}\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"$safeNavigationMigration(column?.enumFilter) | func:row:context\" [options]=\"column.options\" [defaultOption]=\"column.defaultOption??true\" [ngModel]=\"row | property:column.name\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" (change)=\"column.change?column.change(row, undefined, context):patch(row, [column.name], $event.value, column.patchIncludes)\" (keydown.enter)=\"handleKeydownEnter($event)\"></vd-select>\r\n }\r\n </mat-form-field>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Action -->\r\n @case (ColumnType.Action) {\r\n @if (column.menu) {\r\n @if (menu?.matMenu && !row.locked && hasVisibleRowMenuItems(row, column)) {\r\n <div id=\"menu-{{row.id}}\" style=\"visibility: hidden; position: fixed\" #contextMenuTrigger=\"matMenuTrigger\" [matMenuTriggerFor]=\"menu.matMenu!\"></div>\r\n }\r\n <vd-dynamic-menu [items]=\"[column.menu]\" [data]=\"row\" [context]=\"context\" #menu></vd-dynamic-menu>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Menu -->\r\n @case (ColumnType.Menu) {\r\n @if (column.menu) {\r\n <vd-dynamic-menu [items]=\"[column.menu]\" [data]=\"row\" [context]=\"context\"></vd-dynamic-menu>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region icon -->\r\n @case (ColumnType.Icon) {\r\n <span layout=\"row\" layout-align=\"start center\">\r\n @if(column && column.icon){\r\n @if ( column.icon.matIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\">{{handleExpression($safeNavigationMigration(column.icon.matIcon)!, row)}}</mat-icon>\r\n }\r\n @if (column.icon.svgIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\" [svgIcon]=\"handleExpression($safeNavigationMigration(column.icon.svgIcon)!, row)!\"></mat-icon>\r\n }\r\n @if (column.icon.fontIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\" [fontIcon]=\"handleExpression($safeNavigationMigration(column.icon.fontIcon)!, row)!\"></mat-icon>\r\n }\r\n }\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region icon button -->\r\n @case (ColumnType.IconButton) {\r\n <a mat-icon-button (click)=\"$event.stopPropagation();column.iconButton?.event?column.iconButton.event(row, context):null\">\r\n <mat-icon fontSet=\"{{column.iconButton?.iconFontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.iconButton?.iconClass??'', row)\">{{handleExpression(column.iconButton?.icon??'radio_button_checked', row) || 'radio_button_checked'}}</mat-icon>\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Other column types -->\r\n @default {\r\n <span [innerHtml]=\"rowValue??''\"></span>\r\n }\r\n <!-- #endregion -->\r\n }\r\n <ng-template #recursiveContainer let-columnNameSegments=\"segments\" let-formGroup=\"formGroup\" let-parentFormGroup=\"parentFormGroup\">\r\n @if (formGroup) {\r\n <ng-container [formGroup]=\"formGroup\">\r\n <!-- If the columnNameSegments array is empty, we're at the leaf node -->\r\n @if (!columnNameSegments.length) {\r\n @switch (column.type) {\r\n <!-- #region Toggle column -->\r\n @case (ColumnType.Toggle) {\r\n <mat-slide-toggle [formControl]=\"formGroup\" (click)=\"$event.stopPropagation();\" (change)=\"column.change?column.change(parentFormGroup.value, parentFormGroup, context):handleModelChange(column, parentFormGroup.value, parentFormGroup)\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" color=\"accent\"></mat-slide-toggle>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Text Input column -->\r\n @case (ColumnType.TextInput) {\r\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" dense-3 layout=\"column\" layout-align=\"center start\" (click)=\"$event.stopPropagation();\">\r\n <input matInput [formControl]=\"formGroup\" type=\"{{column.inputType}}\" autocomplete=\"none\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" [min]=\"column.inputMin?column.inputMin(parentFormGroup.value, parentFormGroup, context):null\" [max]=\"column.inputMax?column.inputMax(parentFormGroup.value, parentFormGroup, context):null\" (keydown.enter)=\"handleKeydownEnter($event)\" />\r\n </mat-form-field>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region VD-Select column -->\r\n @case (ColumnType.Select) {\r\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" dense-3 layout=\"column\" layout-align=\"center start\" (click)=\"$event.stopPropagation();\">\r\n <vd-select [formControl]=\"formGroup\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"column.enumFilter | func:parentFormGroup.value:context\" [options]=\"column.options\" [defaultOption]=\"column.defaultOption??true\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" (selectionChange)=\"column.change?column.change(parentFormGroup.value, parentFormGroup, context):patch(parentFormGroup.value, [column.name], rowValue, column.patchIncludes)\" (keydown.enter)=\"handleKeydownEnter($event)\"></vd-select>\r\n </mat-form-field>\r\n }\r\n <!-- #endregion -->\r\n }\r\n } @else {\r\n <!-- If not the last segment, create a nested form group -->\r\n <ng-container [formGroupName]=\"columnNameSegments[0]\">\r\n <!-- Recursive call to handle nested segments -->\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: columnNameSegments.slice(1), parentFormGroup:formGroup, formGroup: formGroup.get(columnNameSegments[0])}\"></ng-container>\r\n </ng-container>\r\n }\r\n </ng-container>\r\n }\r\n </ng-template>\r\n </ng-template>\r\n </td>\r\n </ng-container>\r\n <!-- #endregion -->\r\n }\r\n <!-- #region Filter row -->\r\n @if (dataSource && filterable) {\r\n @for (column of columns$ | async; track column) {\r\n <ng-container cdkColumnDef=\"filter.{{column.filter || column.name}}\" [sticky]=\"column.sticky\" [stickyEnd]=\"column.stickyEnd\">\r\n <th mat-header-cell *cdkHeaderCellDef [hidden]=\"column.hidden\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\" [ngClass]=\"column.displayNgClass\">\r\n <!-- #region Select filter -->\r\n @if(column.endpoint || column.enumType || column.options){\r\n <span filter-select [endpoint]=\"column.endpoint\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"column.enumFilter | func:{}:context\" [options]=\"column.options\" [text]=\"column.filterOptionText || 'name'\"></span>\r\n }\r\n <!-- #region Text filter -->\r\n @else if(column.type == ColumnType.Text || column.type == ColumnType.TextInput || column.type == ColumnType.Number) {\r\n <span filter-input [onlyNumber]=\"column.filterInputNumber??false\" [matTooltip]=\"column.filterTooltip ? column.filterTooltip(context):null\" [matTooltipClass]=\"column.filterTooltipClass??''\" [operator]=\"!useFilterOperator ? undefined : column.filterOperator\"></span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Date filter -->\r\n @else if (column.type == ColumnType.Date) {\r\n <span filter-date></span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Action filter (clear) -->\r\n @else if (column.type == ColumnType.Action) {\r\n <span filter-clear></span>\r\n }\r\n <!-- #endregion -->\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Details column -->\r\n <ng-container cdkColumnDef=\"expandedDetail\">\r\n <td mat-cell *matCellDef=\"let row; let index = index\" [attr.colspan]=\"(displayedColumns$ | async)?.length\">\r\n <div class=\"row-detail\" [@detailExpand]=\"row == expandedRow ? 'expanded' : 'collapsed'\" #detailsTemplate>\r\n @if (templateRef && row === expandedRow) {\r\n <ng-container *ngTemplateOutlet=\"templateRef; context:{row: row, index: index, context: context}\"></ng-container>\r\n }\r\n </div>\r\n </td>\r\n </ng-container>\r\n <!-- #endregion -->\r\n <!-- #region Filter header -->\r\n @if (filterable) {\r\n <tr mat-header-row *cdkHeaderRowDef=\"displayedFilterColumns$ | async\"></tr>\r\n }\r\n <!-- #endregion -->\r\n <tr mat-header-row *cdkHeaderRowDef=\"displayedColumns$ | async; sticky: stickyFilter\"></tr>\r\n <tr mat-row *cdkRowDef=\"let row; columns: displayedColumns$ | async; let index = dataIndex\" [ngClass]=\"rowNgClass?rowNgClass(row, context):null\" [class.expanded-row]=\"expandedRow === row\" (click)=\"handleRowClick(index, row)\" (contextmenu)=\"handleRowRightClick($event, row)\"></tr>\r\n <!-- #region Detrails row -->\r\n @if (detailsTemplate || templateRef) {\r\n <tr mat-row *cdkRowDef=\"let row; columns: ['expandedDetail']\" class=\"detail-row\" [ngClass]=\"rowNgClass?rowNgClass(row, context):null\"></tr>\r\n }\r\n <!-- #endregion -->\r\n </table>\r\n <!-- #region Modern No Results Message -->\r\n @if (dataSource?.filteredData?.length <= 0 && dataSource?.total <= 0) {\r\n <div class=\"no-results-overlay\">\r\n <mat-icon class=\"no-results-icon\">search_off</mat-icon>\r\n <div class=\"no-results-text mat-body-1\">\r\n <h3 i18n=\"@@noResultsFound\">No results found</h3>\r\n <p i18n=\"@@tryAdjustFilters\"> Try adjusting your filters or search criteria. </p>\r\n </div>\r\n </div>\r\n }\r\n <!-- #endregion -->\r\n</div>\r\n<!-- #endregion -->\r\n<!-- #region Debug value -->\r\n@if (debugValue) {\r\n <code>\r\n <pre>{{formValue | json}}</pre>\r\n</code>\r\n}\r\n<!-- #endregion -->\r\n<div class=\"table-footer\" layout=\"row\">\r\n <ng-content select=\"[table-footer]\"></ng-content>\r\n <span flex></span>\r\n @if (paginable) {\r\n <mat-paginator [pageSize]=\"pageSize\" [pageSizeOptions]=\"pageSizeOptions\" showFirstLastButtons=\"true\"></mat-paginator>\r\n }\r\n</div>", styles: ["::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-form-field .mat-form-field-wrapper{width:100%}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip{height:24px;margin-top:2px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip .mdc-evolution-chip__action--primary{padding-left:9px;padding-right:9px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip:last-child{margin-bottom:2px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip *{font-size:.8rem}@media(max-width:389px){::ng-deep .mat-mdc-table [gt-xs],::ng-deep .mat-mdc-table .gt-xs{display:none}::ng-deep .mat-mdc-table [gt-sm],::ng-deep .mat-mdc-table .gt-sm{display:none}::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:599px){::ng-deep .mat-mdc-table [gt-sm],::ng-deep .mat-mdc-table .gt-sm{display:none}::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:959px){::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1279px){::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1919px){::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1979px){::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}.mat-table-container{width:100%;max-width:100%;overflow:auto}.mat-table-container .mat-mdc-header-cell,.mat-table-container .mat-mdc-footer-cell,.mat-table-container .mat-mdc-cell{min-width:80px;box-sizing:border-box}.mat-table-container .mat-mdc-header-row,.mat-table-container .mat-mdc-footer-row,.mat-table-container .mat-mdc-row{min-width:1920px}.mat-table-container.mat-table-sticky .mat-mdc-table-sticky-border-elem-right{box-shadow:-3px 0 5px #0000001a}.mat-table-container.mat-table-sticky .mat-mdc-table-sticky-border-elem-left{box-shadow:3px 0 5px #0000001a}\n"], dependencies: [{ kind: "ngmodule", type: CdkTableModule }, { kind: "directive", type: i2$3.CdkRowDef, selector: "[cdkRowDef]", inputs: ["cdkRowDefColumns", "cdkRowDefWhen"] }, { kind: "directive", type: i2$3.CdkCellDef, selector: "[cdkCellDef]" }, { kind: "directive", type: i2$3.CdkHeaderCellDef, selector: "[cdkHeaderCellDef]" }, { kind: "directive", type: i2$3.CdkColumnDef, selector: "[cdkColumnDef]", inputs: ["cdkColumnDef", "sticky", "stickyEnd"] }, { kind: "directive", type: i2$3.CdkHeaderRowDef, selector: "[cdkHeaderRowDef]", inputs: ["cdkHeaderRowDef", "cdkHeaderRowDefSticky"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i7.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i10.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i3.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i12.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i12.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i1$5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i16.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "directive", type:
19008
19035
  //----------------------
19009
19036
  DataSourceFilterDirective, selector: "[dataSourceFilter]", inputs: ["dataSource", "dataSourceFilter"] }, { kind: "directive", type: DisableControlDirective, selector: "[disableControl]", inputs: ["disableControl"] }, { kind: "component", type: FilterDateComponent, selector: "mat-header-cell[filter-date], [mat-header-cell][filter-date], [filter-date]", inputs: ["field", "debounce", "placeholder"] }, { kind: "component", type: FilterInputComponent, selector: "mat-header-cell[filter-input], [mat-header-cell][filter-input], [filter-input]", inputs: ["field", "operator", "onlyNumber", "debounce", "placeholder"] }, { kind: "component", type: FilterSelectComponent, selector: "mat-header-cell[filter-select], [mat-header-cell][filter-select], [filter-select]", inputs: ["endpoint", "params", "projection", "sortBy", "sorted", "enumFilter", "enum", "enumMetadata", "key", "text", "prefix", "multiple", "options", "filteredOptions", "filterable", "field", "placeholder", "cache"] }, { kind: "component", type: FilterClearComponent, selector: "mat-header-cell[filter-clear], [mat-header-cell][filter-clear], [filter-clear]" }, { kind: "component", type: VdDynamicMenuComponent, selector: "vd-dynamic-menu", inputs: ["items", "data", "index", "context", "contextMenu"] }, { kind: "component", type: VdSelectComponent, selector: "vd-select", inputs: ["triggerCssClass"] }, { kind: "component", type: MsaEnumDisplayComponent, selector: "msa-enum-display", inputs: ["value", "enumType", "metadata", "showIcon", "entity", "context"] }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$2.JsonPipe, name: "json" }, { kind: "pipe", type: i1$2.SlicePipe, name: "slice" }, { kind: "pipe", type: i1$2.DatePipe, name: "date" }, { kind: "pipe", type:
19010
19037
  //----------------------
@@ -19058,7 +19085,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
19058
19085
  state('expanded', style({ height: AUTO_STYLE })),
19059
19086
  transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
19060
19087
  ]),
19061
- ], template: "@if (!static) {\r\n <div class=\"loading-progress\">\r\n @if (dataSource?.isLoading) {\r\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\r\n }\r\n </div>\r\n}\r\n\r\n<!-- #region Data table -->\r\n<div class=\"mat-table-container scrollbar-secondary\" [ngClass]=\"{'mat-table-sticky': sticky}\" #scrollContainer>\r\n <table mat-table #table [dataSource]=\"dataSource\" [dataSourceFilter]=\"dataSourceFilter\" [ngClass]=\"{'table-fixed': !sticky && !detailsTemplate && !templateRef, 'table-stick': sticky}\" [trackBy]=\"trackBy\" matSort matSortDisableClear [matSortActive]=\"sortActive||'id'\" [matSortDirection]=\"sortDirection\" multiTemplateDataRows>\r\n @for (column of columns$ | async; track columnsTrackBy($index, column)) {\r\n <!-- #region Column def -->\r\n <ng-container [cdkColumnDef]=\"column.name\" [sticky]=\"column.sticky\" [stickyEnd]=\"column.stickyEnd\">\r\n <ng-template #header [ngTemplateOutlet]=\"header\" let-headerText=\"headerText\" [ngTemplateOutletContext]=\"{headerText: column.header | func:context}\">\r\n <th mat-header-cell *cdkHeaderCellDef [mat-sort-header]=\"column.sortBy || column.name\" [hidden]=\"column.hidden\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\" [disabled]=\"column.type == ColumnType.Checkbox || column.disabled\" [ngClass]=\"{'gt-xs': column.display == Grid.Xs, 'gt-sm': column.display == Grid.Sm, 'gt-md': column.display == Grid.Md, 'gt-lg': column.display == Grid.Lg, 'gt-xl': column.display == Grid.Xl, 'gt-xxl': column.display == Grid.Xxl, 'hidden': column.display == Grid.None}\" [arrowPosition]=\"column.arrowBefore?'before':'after'\">\r\n @if (column.type == ColumnType.Checkbox) {\r\n <mat-checkbox (change)=\"$event ? dataSource.toggleSelect($event, selectAllFilter) : null\" [disabled]=\"!dataSource.paginator?.length\" [checked]=\"dataSource.selectionModel.hasValue() && dataSource.isAllSelected()\" [indeterminate]=\"dataSource.selectionModel.hasValue() && !dataSource.isAllSelected()\"></mat-checkbox>\r\n } @if (column.type != ColumnType.Checkbox) {\r\n <span [matTooltip]=\"headerText\">{{headerText}}</span>\r\n }\r\n </th>\r\n </ng-template>\r\n <td mat-cell *cdkCellDef=\"let row; let rowIndex = dataIndex\" [matTooltip]=\"column.tooltip?column.tooltip(row, undefined, context):null\" [matTooltipClass]=\"column.tooltipClass??''\" [hidden]=\"column.hidden\" [ngClass]=\"getRowClasses(column, row)\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\">\r\n <ng-template #rowVal [ngTemplateOutlet]=\"rowVal\" let-rowValue [ngTemplateOutletContext]=\"{$implicit: column?.content && column?.content(row, undefined, context)}\">\r\n @switch (column.type) {\r\n <!-- #region Checkbox column -->\r\n @case (ColumnType.Checkbox) {\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? dataSource.selectionModel.toggle(row) : null\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" [checked]=\"dataSource.selectionModel.isSelected(row)\"></mat-checkbox>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Enum column -->\r\n @case (ColumnType.Enum) {\r\n <span>\r\n @if (column.enumMetadata) {\r\n @if (column.multiple) {\r\n @for (item of rowValue; track item; let i = $index) {\r\n @if (i < 2) {\r\n <ng-template let-displayValue=\"displayValue\" [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"{ displayValue: column.enumMetadata[item].display }\"></ng-template>\r\n }\r\n @if (i === 1 && rowValue?.length > 2) {\r\n <small [matTooltip]=\"(rowValue | slice:2 | map:column.enumMetadata | map:'display') | join:'\\n'\" matTooltipClass=\"mat-tooltip-multiline\">...</small>\r\n }\r\n }\r\n <ng-template #template let-displayValue=\"displayValue\">\r\n <mat-chip-row disableRipple=\"true\" selectable=\"false\" [matTooltip]=\"displayValue\">\r\n <span>{{ displayValue }}</span>\r\n </mat-chip-row>\r\n </ng-template>\r\n } @else {\r\n @if (rowValue >= 0) {\r\n <span class=\"na\" [ngStyle]=\"{ color: ((column.enumMetadata[rowValue] || {}).textColor || 'inherit') }\" [innerHtml]=\"(column.enumMetadata[rowValue]||{}).display\"></span>\r\n }\r\n }\r\n } @else {\r\n @if (column.multiple) {\r\n @for (item of rowValue; track item; let i = $index; let last = $last) {\r\n <div>\r\n @if (i<2) {\r\n <small>\r\n <msa-enum-display [value]=\"item\" [enumType]=\"column.enumType\" [metadata]=\"column.enumMetadata\"></msa-enum-display>\r\n </small>\r\n } @if (i==1 && rowValue?.length > 2) {\r\n <small>, ...</small>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @if (rowValue >= 0) {\r\n <msa-enum-display [value]=\"rowValue\" [enumType]=\"column.enumType\" [metadata]=\"column.enumMetadata\"></msa-enum-display>\r\n }\r\n }\r\n }\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Toggle column -->\r\n @case (ColumnType.Toggle) {\r\n @if (!formArray) {\r\n <mat-slide-toggle [ngModel]=\"row | property:column.name\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);handleModelChange(column, row, undefined);\" (click)=\"$event.stopPropagation();\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" color=\"accent\"></mat-slide-toggle>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Date column -->\r\n @case (ColumnType.Date) {\r\n <span>{{rowValue | date:column.shortDate?'dd.MM.yyyy':'dd.MM.yyyy HH:mm:ss'}}</span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Text Input column -->\r\n @case (ColumnType.TextInput) {\r\n @if (!formArray) {\r\n <mat-form-field appearance=\"outline\" layout=\"column\" layout-align=\"center start\" subscriptSizing=\"dynamic\" dense-3 (click)=\"$event.stopPropagation();\">\r\n @if (!formArray) {\r\n <input matInput type=\"{{column.inputType}}\" autocomplete=\"none\" name=\"{{column.name}}{{rowIndex}}\" [ngModel]=\"row | property:column.name\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" [min]=\"column.inputMin?column.inputMin(row, undefined, context):null\" [max]=\"column.inputMax?column.inputMax(row, undefined, context):null\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);(column.change?column.change(row, undefined, context):patch(row, [column.name], $event, column.patchIncludes));\" [ngModelOptions]=\"{updateOn: 'blur'}\" (keydown.enter)=\"handleKeydownEnter($event)\" />\r\n }\r\n </mat-form-field>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region VD-Select column -->\r\n @case (ColumnType.Select) {\r\n @if (!formArray) {\r\n <mat-form-field appearance=\"outline\" layout=\"column\" layout-align=\"center start\" subscriptSizing=\"dynamic\" dense-3 (click)=\"$event.stopPropagation();\">\r\n @if (!formArray) {\r\n <vd-select name=\"{{column.name}}{{rowIndex}}\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"$safeNavigationMigration(column?.enumFilter) | func:row:context\" [options]=\"column.options\" [defaultOption]=\"column.defaultOption??true\" [ngModel]=\"row | property:column.name\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" (change)=\"column.change?column.change(row, undefined, context):patch(row, [column.name], $event.value, column.patchIncludes)\" (keydown.enter)=\"handleKeydownEnter($event)\"></vd-select>\r\n }\r\n </mat-form-field>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Action -->\r\n @case (ColumnType.Action) {\r\n @if (column.menu) {\r\n @if (menu?.matMenu && !row.locked && hasVisibleRowMenuItems(row, column)) {\r\n <div id=\"menu-{{row.id}}\" style=\"visibility: hidden; position: fixed\" #contextMenuTrigger=\"matMenuTrigger\" [matMenuTriggerFor]=\"menu.matMenu!\"></div>\r\n }\r\n <vd-dynamic-menu [items]=\"[column.menu]\" [data]=\"row\" [context]=\"context\" #menu></vd-dynamic-menu>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Menu -->\r\n @case (ColumnType.Menu) {\r\n @if (column.menu) {\r\n <vd-dynamic-menu [items]=\"[column.menu]\" [data]=\"row\" [context]=\"context\"></vd-dynamic-menu>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region icon -->\r\n @case (ColumnType.Icon) {\r\n <span layout=\"row\" layout-align=\"start center\">\r\n @if(column && column.icon){\r\n @if ( column.icon.matIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\">{{handleExpression($safeNavigationMigration(column.icon.matIcon)!, row)}}</mat-icon>\r\n }\r\n @if (column.icon.svgIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\" [svgIcon]=\"handleExpression($safeNavigationMigration(column.icon.svgIcon)!, row)!\"></mat-icon>\r\n }\r\n @if (column.icon.fontIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\" [fontIcon]=\"handleExpression($safeNavigationMigration(column.icon.fontIcon)!, row)!\"></mat-icon>\r\n }\r\n }\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region icon button -->\r\n @case (ColumnType.IconButton) {\r\n <a mat-icon-button (click)=\"$event.stopPropagation();column.iconButton?.event?column.iconButton.event(row, context):null\">\r\n <mat-icon fontSet=\"{{column.iconButton?.iconFontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.iconButton?.iconClass??'', row)\">{{handleExpression(column.iconButton?.icon??'radio_button_checked', row) || 'radio_button_checked'}}</mat-icon>\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Other column types -->\r\n @default {\r\n <span [innerHtml]=\"rowValue??''\"></span>\r\n }\r\n <!-- #endregion -->\r\n }\r\n <ng-template #recursiveContainer let-columnNameSegments=\"segments\" let-formGroup=\"formGroup\" let-parentFormGroup=\"parentFormGroup\">\r\n @if (formGroup) {\r\n <ng-container [formGroup]=\"formGroup\">\r\n <!-- If the columnNameSegments array is empty, we're at the leaf node -->\r\n @if (!columnNameSegments.length) {\r\n @switch (column.type) {\r\n <!-- #region Toggle column -->\r\n @case (ColumnType.Toggle) {\r\n <mat-slide-toggle [formControl]=\"formGroup\" (click)=\"$event.stopPropagation();\" (change)=\"column.change?column.change(parentFormGroup.value, parentFormGroup, context):handleModelChange(column, parentFormGroup.value, parentFormGroup)\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" color=\"accent\"></mat-slide-toggle>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Text Input column -->\r\n @case (ColumnType.TextInput) {\r\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" dense-3 layout=\"column\" layout-align=\"center start\" (click)=\"$event.stopPropagation();\">\r\n <input matInput [formControl]=\"formGroup\" type=\"{{column.inputType}}\" autocomplete=\"none\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" [min]=\"column.inputMin?column.inputMin(parentFormGroup.value, parentFormGroup, context):null\" [max]=\"column.inputMax?column.inputMax(parentFormGroup.value, parentFormGroup, context):null\" (keydown.enter)=\"handleKeydownEnter($event)\" />\r\n </mat-form-field>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region VD-Select column -->\r\n @case (ColumnType.Select) {\r\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" dense-3 layout=\"column\" layout-align=\"center start\" (click)=\"$event.stopPropagation();\">\r\n <vd-select [formControl]=\"formGroup\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"column.enumFilter | func:parentFormGroup.value:context\" [options]=\"column.options\" [defaultOption]=\"column.defaultOption??true\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" (selectionChange)=\"column.change?column.change(parentFormGroup.value, parentFormGroup, context):patch(parentFormGroup.value, [column.name], rowValue, column.patchIncludes)\" (keydown.enter)=\"handleKeydownEnter($event)\"></vd-select>\r\n </mat-form-field>\r\n }\r\n <!-- #endregion -->\r\n }\r\n } @else {\r\n <!-- If not the last segment, create a nested form group -->\r\n <ng-container [formGroupName]=\"columnNameSegments[0]\">\r\n <!-- Recursive call to handle nested segments -->\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: columnNameSegments.slice(1), parentFormGroup:formGroup, formGroup: formGroup.get(columnNameSegments[0])}\"></ng-container>\r\n </ng-container>\r\n }\r\n </ng-container>\r\n }\r\n </ng-template>\r\n </ng-template>\r\n </td>\r\n </ng-container>\r\n <!-- #endregion -->\r\n }\r\n\r\n <!-- #region Filter row -->\r\n @if (dataSource && filterable) {\r\n @for (column of columns$ | async; track column) {\r\n <ng-container cdkColumnDef=\"filter.{{column.filter || column.name}}\" [sticky]=\"column.sticky\" [stickyEnd]=\"column.stickyEnd\">\r\n <th mat-header-cell *cdkHeaderCellDef [hidden]=\"column.hidden\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\" [ngClass]=\"{'gt-xs': column.display == Grid.Xs, 'gt-sm': column.display == Grid.Sm, 'gt-md': column.display == Grid.Md, 'gt-lg': column.display == Grid.Lg, 'gt-xl': column.display == Grid.Xl, 'gt-xxl': column.display == Grid.Xxl, 'hidden': column.display == Grid.None}\">\r\n <!-- #region Select filter -->\r\n @if(column.endpoint || column.enumType || column.options){\r\n <span filter-select [endpoint]=\"column.endpoint\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"column.enumFilter | func:{}:context\" [options]=\"column.options\" [text]=\"column.filterOptionText || 'name'\"></span>\r\n }\r\n <!-- #region Text filter -->\r\n @else if(column.type == ColumnType.Text || column.type == ColumnType.TextInput || column.type == ColumnType.Number) {\r\n <span filter-input [onlyNumber]=\"column.filterInputNumber??false\" [matTooltip]=\"column.filterTooltip ? column.filterTooltip(context):null\" [matTooltipClass]=\"column.filterTooltipClass??''\" [operator]=\"!useFilterOperator ? undefined : column.filterOperator\"></span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Date filter -->\r\n @else if (column.type == ColumnType.Date) {\r\n <span filter-date></span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Action filter (clear) -->\r\n @else if (column.type == ColumnType.Action) {\r\n <span filter-clear></span>\r\n }\r\n <!-- #endregion -->\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n\r\n <!-- #region Details column -->\r\n <ng-container cdkColumnDef=\"expandedDetail\">\r\n <td mat-cell *matCellDef=\"let row; let index = index\" [attr.colspan]=\"(displayedColumns$ | async)?.length\">\r\n <div class=\"row-detail\" [@detailExpand]=\"row == expandedRow ? 'expanded' : 'collapsed'\" #detailsTemplate>\r\n @if (templateRef && row === expandedRow) {\r\n <ng-container *ngTemplateOutlet=\"templateRef; context:{row: row, index: index, context: context}\"></ng-container>\r\n }\r\n </div>\r\n </td>\r\n </ng-container>\r\n <!-- #endregion -->\r\n\r\n <!-- #region Filter header -->\r\n @if (filterable) {\r\n <tr mat-header-row *cdkHeaderRowDef=\"displayedFilterColumns$ | async\"></tr>\r\n }\r\n <!-- #endregion -->\r\n\r\n <tr mat-header-row *cdkHeaderRowDef=\"displayedColumns$ | async; sticky: stickyFilter\"></tr>\r\n <tr mat-row *cdkRowDef=\"let row; columns: displayedColumns$ | async; let index = dataIndex\" [ngClass]=\"rowNgClass?rowNgClass(row, context):null\" [class.expanded-row]=\"expandedRow === row\" (click)=\"handleRowClick(index, row)\" (contextmenu)=\"handleRowRightClick($event, row)\"></tr>\r\n\r\n <!-- #region Detrails row -->\r\n @if (detailsTemplate || templateRef) {\r\n <tr mat-row *cdkRowDef=\"let row; columns: ['expandedDetail']\" class=\"detail-row\" [ngClass]=\"rowNgClass?rowNgClass(row, context):null\"></tr>\r\n }\r\n <!-- #endregion -->\r\n </table>\r\n\r\n <!-- #region Modern No Results Message -->\r\n @if (dataSource?.filteredData?.length <= 0 && dataSource?.total <= 0) {\r\n <div class=\"no-results-overlay\">\r\n <mat-icon class=\"no-results-icon\">search_off</mat-icon>\r\n <div class=\"no-results-text mat-body-1\">\r\n <h3 i18n=\"@@noResultsFound\">No results found</h3>\r\n <p i18n=\"@@tryAdjustFilters\">\r\n Try adjusting your filters or search criteria.\r\n </p>\r\n </div>\r\n </div>\r\n }\r\n <!-- #endregion -->\r\n</div>\r\n<!-- #endregion -->\r\n\r\n<!-- #region Debug value -->\r\n@if (debugValue) {\r\n <code>\r\n <pre>{{formValue | json}}</pre>\r\n</code>\r\n}\r\n<!-- #endregion -->\r\n\r\n<div class=\"table-footer\" layout=\"row\">\r\n <ng-content select=\"[table-footer]\"></ng-content>\r\n <span flex></span>\r\n @if (paginable) {\r\n <mat-paginator [pageSize]=\"pageSize\" [pageSizeOptions]=\"pageSizeOptions\" showFirstLastButtons=\"true\"></mat-paginator>\r\n }\r\n</div>", styles: ["::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-form-field .mat-form-field-wrapper{width:100%}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip{height:24px;margin-top:2px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip .mdc-evolution-chip__action--primary{padding-left:9px;padding-right:9px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip:last-child{margin-bottom:2px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip *{font-size:.8rem}@media(max-width:389px){::ng-deep .mat-mdc-table [gt-xs],::ng-deep .mat-mdc-table .gt-xs{display:none}::ng-deep .mat-mdc-table [gt-sm],::ng-deep .mat-mdc-table .gt-sm{display:none}::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:599px){::ng-deep .mat-mdc-table [gt-sm],::ng-deep .mat-mdc-table .gt-sm{display:none}::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:959px){::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1279px){::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1919px){::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1979px){::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}.mat-table-container{width:100%;max-width:100%;overflow:auto}.mat-table-container .mat-mdc-header-cell,.mat-table-container .mat-mdc-footer-cell,.mat-table-container .mat-mdc-cell{min-width:80px;box-sizing:border-box}.mat-table-container .mat-mdc-header-row,.mat-table-container .mat-mdc-footer-row,.mat-table-container .mat-mdc-row{min-width:1920px}.mat-table-container.mat-table-sticky .mat-mdc-table-sticky-border-elem-right{box-shadow:-3px 0 5px #0000001a}.mat-table-container.mat-table-sticky .mat-mdc-table-sticky-border-elem-left{box-shadow:3px 0 5px #0000001a}\n"] }]
19088
+ ], template: "@if (!static) {\r\n <div class=\"loading-progress\">\r\n @if (dataSource?.isLoading) {\r\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\r\n }\r\n </div>\r\n}\r\n<!-- #region Data table -->\r\n<div class=\"mat-table-container scrollbar-secondary\" [ngClass]=\"{'mat-table-sticky': sticky}\" #scrollContainer>\r\n <table mat-table #table [dataSource]=\"dataSource\" [dataSourceFilter]=\"dataSourceFilter\" [ngClass]=\"{'table-fixed': !sticky && !detailsTemplate && !templateRef, 'table-stick': sticky}\" [trackBy]=\"trackBy\" matSort matSortDisableClear [matSortActive]=\"sortActive||'id'\" [matSortDirection]=\"sortDirection\" multiTemplateDataRows>\r\n @for (column of columns$ | async; track columnsTrackBy($index, column)) {\r\n <!-- #region Column def -->\r\n <ng-container [cdkColumnDef]=\"column.name\" [sticky]=\"column.sticky\" [stickyEnd]=\"column.stickyEnd\">\r\n <ng-template #header [ngTemplateOutlet]=\"header\" let-headerText=\"headerText\" [ngTemplateOutletContext]=\"{headerText: column.header | func:context}\">\r\n <th mat-header-cell *cdkHeaderCellDef [mat-sort-header]=\"column.sortBy || column.name\" [hidden]=\"column.hidden\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\" [disabled]=\"column.type == ColumnType.Checkbox || column.disabled\" [ngClass]=\"column.displayNgClass\" [arrowPosition]=\"column.arrowBefore?'before':'after'\">\r\n @if (column.type == ColumnType.Checkbox) {\r\n <mat-checkbox (change)=\"$event ? dataSource.toggleSelect($event, selectAllFilter) : null\" [disabled]=\"!dataSource.paginator?.length\" [checked]=\"dataSource.selectionModel.hasValue() && dataSource.isAllSelected()\" [indeterminate]=\"dataSource.selectionModel.hasValue() && !dataSource.isAllSelected()\"></mat-checkbox>\r\n } @if (column.type != ColumnType.Checkbox) {\r\n <span [matTooltip]=\"headerText\">{{headerText}}</span>\r\n }\r\n </th>\r\n </ng-template>\r\n <td mat-cell *cdkCellDef=\"let row; let rowIndex = dataIndex\" [matTooltip]=\"column.tooltip?column.tooltip(row, undefined, context):null\" [matTooltipClass]=\"column.tooltipClass??''\" [hidden]=\"column.hidden\" [ngClass]=\"getRowClasses(column, row)\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\">\r\n <ng-template #rowVal [ngTemplateOutlet]=\"rowVal\" let-rowValue [ngTemplateOutletContext]=\"{$implicit: column?.content && column?.content(row, undefined, context)}\">\r\n @switch (column.type) {\r\n <!-- #region Checkbox column -->\r\n @case (ColumnType.Checkbox) {\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? dataSource.selectionModel.toggle(row) : null\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" [checked]=\"dataSource.selectionModel.isSelected(row)\"></mat-checkbox>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Enum column -->\r\n @case (ColumnType.Enum) {\r\n <span>\r\n @if (column.enumMetadata) {\r\n @if (column.multiple) {\r\n @for (item of rowValue; track item; let i = $index) {\r\n @if (i < 2) {\r\n <ng-template let-displayValue=\"displayValue\" [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"{ displayValue: column.enumMetadata[item].display }\"></ng-template>\r\n }\r\n @if (i === 1 && rowValue?.length > 2) {\r\n <small [matTooltip]=\"(rowValue | slice:2 | map:column.enumMetadata | map:'display') | join:'\\n'\" matTooltipClass=\"mat-tooltip-multiline\">...</small>\r\n }\r\n }\r\n <ng-template #template let-displayValue=\"displayValue\">\r\n <mat-chip-row disableRipple=\"true\" selectable=\"false\" [matTooltip]=\"displayValue\">\r\n <span>{{ displayValue }}</span>\r\n </mat-chip-row>\r\n </ng-template>\r\n } @else {\r\n @if (rowValue >= 0) {\r\n <span class=\"na\" [ngStyle]=\"{ color: ((column.enumMetadata[rowValue] || {}).textColor || 'inherit') }\" [innerHtml]=\"(column.enumMetadata[rowValue]||{}).display\"></span>\r\n }\r\n }\r\n } @else {\r\n @if (column.multiple) {\r\n @for (item of rowValue; track item; let i = $index; let last = $last) {\r\n <div>\r\n @if (i<2) {\r\n <small>\r\n <msa-enum-display [value]=\"item\" [enumType]=\"column.enumType\" [metadata]=\"column.enumMetadata\"></msa-enum-display>\r\n </small>\r\n } @if (i==1 && rowValue?.length > 2) {\r\n <small>, ...</small>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @if (rowValue >= 0) {\r\n <msa-enum-display [value]=\"rowValue\" [enumType]=\"column.enumType\" [metadata]=\"column.enumMetadata\"></msa-enum-display>\r\n }\r\n }\r\n }\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Toggle column -->\r\n @case (ColumnType.Toggle) {\r\n @if (!formArray) {\r\n <mat-slide-toggle [ngModel]=\"row | property:column.name\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);handleModelChange(column, row, undefined);\" (click)=\"$event.stopPropagation();\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" color=\"accent\"></mat-slide-toggle>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Date column -->\r\n @case (ColumnType.Date) {\r\n <span>{{rowValue | date:column.shortDate?'dd.MM.yyyy':'dd.MM.yyyy HH:mm:ss'}}</span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Text Input column -->\r\n @case (ColumnType.TextInput) {\r\n @if (!formArray) {\r\n <mat-form-field appearance=\"outline\" layout=\"column\" layout-align=\"center start\" subscriptSizing=\"dynamic\" dense-3 (click)=\"$event.stopPropagation();\">\r\n @if (!formArray) {\r\n <input matInput type=\"{{column.inputType}}\" autocomplete=\"none\" name=\"{{column.name}}{{rowIndex}}\" [ngModel]=\"row | property:column.name\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" [min]=\"column.inputMin?column.inputMin(row, undefined, context):null\" [max]=\"column.inputMax?column.inputMax(row, undefined, context):null\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);(column.change?column.change(row, undefined, context):patch(row, [column.name], $event, column.patchIncludes));\" [ngModelOptions]=\"{updateOn: 'blur'}\" (keydown.enter)=\"handleKeydownEnter($event)\" />\r\n }\r\n </mat-form-field>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region VD-Select column -->\r\n @case (ColumnType.Select) {\r\n @if (!formArray) {\r\n <mat-form-field appearance=\"outline\" layout=\"column\" layout-align=\"center start\" subscriptSizing=\"dynamic\" dense-3 (click)=\"$event.stopPropagation();\">\r\n @if (!formArray) {\r\n <vd-select name=\"{{column.name}}{{rowIndex}}\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"$safeNavigationMigration(column?.enumFilter) | func:row:context\" [options]=\"column.options\" [defaultOption]=\"column.defaultOption??true\" [ngModel]=\"row | property:column.name\" (ngModelChange)=\"setNestedProperty(row, column.name, $event);\" [disabled]=\"readonly || (column.disabled || (column.disable && column.disable(row, undefined, context)))\" (change)=\"column.change?column.change(row, undefined, context):patch(row, [column.name], $event.value, column.patchIncludes)\" (keydown.enter)=\"handleKeydownEnter($event)\"></vd-select>\r\n }\r\n </mat-form-field>\r\n } @if (formArray) {\r\n <ng-container [formGroup]=\"$any(formArray.controls)[rowIndex] | formGroup\">\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: column.name.split('.'), formGroup: formArray.controls[rowIndex]}\"></ng-container>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Action -->\r\n @case (ColumnType.Action) {\r\n @if (column.menu) {\r\n @if (menu?.matMenu && !row.locked && hasVisibleRowMenuItems(row, column)) {\r\n <div id=\"menu-{{row.id}}\" style=\"visibility: hidden; position: fixed\" #contextMenuTrigger=\"matMenuTrigger\" [matMenuTriggerFor]=\"menu.matMenu!\"></div>\r\n }\r\n <vd-dynamic-menu [items]=\"[column.menu]\" [data]=\"row\" [context]=\"context\" #menu></vd-dynamic-menu>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Menu -->\r\n @case (ColumnType.Menu) {\r\n @if (column.menu) {\r\n <vd-dynamic-menu [items]=\"[column.menu]\" [data]=\"row\" [context]=\"context\"></vd-dynamic-menu>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region icon -->\r\n @case (ColumnType.Icon) {\r\n <span layout=\"row\" layout-align=\"start center\">\r\n @if(column && column.icon){\r\n @if ( column.icon.matIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\">{{handleExpression($safeNavigationMigration(column.icon.matIcon)!, row)}}</mat-icon>\r\n }\r\n @if (column.icon.svgIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\" [svgIcon]=\"handleExpression($safeNavigationMigration(column.icon.svgIcon)!, row)!\"></mat-icon>\r\n }\r\n @if (column.icon.fontIcon) {\r\n <mat-icon fontSet=\"{{column.icon.fontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.icon.cssClass??'', row)\" [fontIcon]=\"handleExpression($safeNavigationMigration(column.icon.fontIcon)!, row)!\"></mat-icon>\r\n }\r\n }\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region icon button -->\r\n @case (ColumnType.IconButton) {\r\n <a mat-icon-button (click)=\"$event.stopPropagation();column.iconButton?.event?column.iconButton.event(row, context):null\">\r\n <mat-icon fontSet=\"{{column.iconButton?.iconFontSet || 'material-symbols-outlined'}}\" [class]=\"handleExpression(column.iconButton?.iconClass??'', row)\">{{handleExpression(column.iconButton?.icon??'radio_button_checked', row) || 'radio_button_checked'}}</mat-icon>\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Other column types -->\r\n @default {\r\n <span [innerHtml]=\"rowValue??''\"></span>\r\n }\r\n <!-- #endregion -->\r\n }\r\n <ng-template #recursiveContainer let-columnNameSegments=\"segments\" let-formGroup=\"formGroup\" let-parentFormGroup=\"parentFormGroup\">\r\n @if (formGroup) {\r\n <ng-container [formGroup]=\"formGroup\">\r\n <!-- If the columnNameSegments array is empty, we're at the leaf node -->\r\n @if (!columnNameSegments.length) {\r\n @switch (column.type) {\r\n <!-- #region Toggle column -->\r\n @case (ColumnType.Toggle) {\r\n <mat-slide-toggle [formControl]=\"formGroup\" (click)=\"$event.stopPropagation();\" (change)=\"column.change?column.change(parentFormGroup.value, parentFormGroup, context):handleModelChange(column, parentFormGroup.value, parentFormGroup)\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" color=\"accent\"></mat-slide-toggle>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Text Input column -->\r\n @case (ColumnType.TextInput) {\r\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" dense-3 layout=\"column\" layout-align=\"center start\" (click)=\"$event.stopPropagation();\">\r\n <input matInput [formControl]=\"formGroup\" type=\"{{column.inputType}}\" autocomplete=\"none\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" [min]=\"column.inputMin?column.inputMin(parentFormGroup.value, parentFormGroup, context):null\" [max]=\"column.inputMax?column.inputMax(parentFormGroup.value, parentFormGroup, context):null\" (keydown.enter)=\"handleKeydownEnter($event)\" />\r\n </mat-form-field>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region VD-Select column -->\r\n @case (ColumnType.Select) {\r\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" dense-3 layout=\"column\" layout-align=\"center start\" (click)=\"$event.stopPropagation();\">\r\n <vd-select [formControl]=\"formGroup\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"column.enumFilter | func:parentFormGroup.value:context\" [options]=\"column.options\" [defaultOption]=\"column.defaultOption??true\" [disableControl]=\"readonly || (column.disabled || (column.disable && column.disable(parentFormGroup.value, parentFormGroup, context)))\" (selectionChange)=\"column.change?column.change(parentFormGroup.value, parentFormGroup, context):patch(parentFormGroup.value, [column.name], rowValue, column.patchIncludes)\" (keydown.enter)=\"handleKeydownEnter($event)\"></vd-select>\r\n </mat-form-field>\r\n }\r\n <!-- #endregion -->\r\n }\r\n } @else {\r\n <!-- If not the last segment, create a nested form group -->\r\n <ng-container [formGroupName]=\"columnNameSegments[0]\">\r\n <!-- Recursive call to handle nested segments -->\r\n <ng-container [ngTemplateOutlet]=\"recursiveContainer\" [ngTemplateOutletContext]=\"{segments: columnNameSegments.slice(1), parentFormGroup:formGroup, formGroup: formGroup.get(columnNameSegments[0])}\"></ng-container>\r\n </ng-container>\r\n }\r\n </ng-container>\r\n }\r\n </ng-template>\r\n </ng-template>\r\n </td>\r\n </ng-container>\r\n <!-- #endregion -->\r\n }\r\n <!-- #region Filter row -->\r\n @if (dataSource && filterable) {\r\n @for (column of columns$ | async; track column) {\r\n <ng-container cdkColumnDef=\"filter.{{column.filter || column.name}}\" [sticky]=\"column.sticky\" [stickyEnd]=\"column.stickyEnd\">\r\n <th mat-header-cell *cdkHeaderCellDef [hidden]=\"column.hidden\" [ngStyle]=\"{maxWidth:column.maxWidth?(column.maxWidth+(column.maxWidthUnit || 'px')):null,minWidth:column.minWidth?(column.minWidth+(column.minWidthUnit || 'px')):null,width:column.width?(column.width+(column.widthUnit || 'px')):null}\" [ngClass]=\"column.displayNgClass\">\r\n <!-- #region Select filter -->\r\n @if(column.endpoint || column.enumType || column.options){\r\n <span filter-select [endpoint]=\"column.endpoint\" [enum]=\"column.enumType\" [enumMetadata]=\"column.enumMetadata\" [enumFilter]=\"column.enumFilter | func:{}:context\" [options]=\"column.options\" [text]=\"column.filterOptionText || 'name'\"></span>\r\n }\r\n <!-- #region Text filter -->\r\n @else if(column.type == ColumnType.Text || column.type == ColumnType.TextInput || column.type == ColumnType.Number) {\r\n <span filter-input [onlyNumber]=\"column.filterInputNumber??false\" [matTooltip]=\"column.filterTooltip ? column.filterTooltip(context):null\" [matTooltipClass]=\"column.filterTooltipClass??''\" [operator]=\"!useFilterOperator ? undefined : column.filterOperator\"></span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Date filter -->\r\n @else if (column.type == ColumnType.Date) {\r\n <span filter-date></span>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Action filter (clear) -->\r\n @else if (column.type == ColumnType.Action) {\r\n <span filter-clear></span>\r\n }\r\n <!-- #endregion -->\r\n </th>\r\n </ng-container>\r\n }\r\n }\r\n <!-- #endregion -->\r\n <!-- #region Details column -->\r\n <ng-container cdkColumnDef=\"expandedDetail\">\r\n <td mat-cell *matCellDef=\"let row; let index = index\" [attr.colspan]=\"(displayedColumns$ | async)?.length\">\r\n <div class=\"row-detail\" [@detailExpand]=\"row == expandedRow ? 'expanded' : 'collapsed'\" #detailsTemplate>\r\n @if (templateRef && row === expandedRow) {\r\n <ng-container *ngTemplateOutlet=\"templateRef; context:{row: row, index: index, context: context}\"></ng-container>\r\n }\r\n </div>\r\n </td>\r\n </ng-container>\r\n <!-- #endregion -->\r\n <!-- #region Filter header -->\r\n @if (filterable) {\r\n <tr mat-header-row *cdkHeaderRowDef=\"displayedFilterColumns$ | async\"></tr>\r\n }\r\n <!-- #endregion -->\r\n <tr mat-header-row *cdkHeaderRowDef=\"displayedColumns$ | async; sticky: stickyFilter\"></tr>\r\n <tr mat-row *cdkRowDef=\"let row; columns: displayedColumns$ | async; let index = dataIndex\" [ngClass]=\"rowNgClass?rowNgClass(row, context):null\" [class.expanded-row]=\"expandedRow === row\" (click)=\"handleRowClick(index, row)\" (contextmenu)=\"handleRowRightClick($event, row)\"></tr>\r\n <!-- #region Detrails row -->\r\n @if (detailsTemplate || templateRef) {\r\n <tr mat-row *cdkRowDef=\"let row; columns: ['expandedDetail']\" class=\"detail-row\" [ngClass]=\"rowNgClass?rowNgClass(row, context):null\"></tr>\r\n }\r\n <!-- #endregion -->\r\n </table>\r\n <!-- #region Modern No Results Message -->\r\n @if (dataSource?.filteredData?.length <= 0 && dataSource?.total <= 0) {\r\n <div class=\"no-results-overlay\">\r\n <mat-icon class=\"no-results-icon\">search_off</mat-icon>\r\n <div class=\"no-results-text mat-body-1\">\r\n <h3 i18n=\"@@noResultsFound\">No results found</h3>\r\n <p i18n=\"@@tryAdjustFilters\"> Try adjusting your filters or search criteria. </p>\r\n </div>\r\n </div>\r\n }\r\n <!-- #endregion -->\r\n</div>\r\n<!-- #endregion -->\r\n<!-- #region Debug value -->\r\n@if (debugValue) {\r\n <code>\r\n <pre>{{formValue | json}}</pre>\r\n</code>\r\n}\r\n<!-- #endregion -->\r\n<div class=\"table-footer\" layout=\"row\">\r\n <ng-content select=\"[table-footer]\"></ng-content>\r\n <span flex></span>\r\n @if (paginable) {\r\n <mat-paginator [pageSize]=\"pageSize\" [pageSizeOptions]=\"pageSizeOptions\" showFirstLastButtons=\"true\"></mat-paginator>\r\n }\r\n</div>", styles: ["::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-form-field .mat-form-field-wrapper{width:100%}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip{height:24px;margin-top:2px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip .mdc-evolution-chip__action--primary{padding-left:9px;padding-right:9px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip:last-child{margin-bottom:2px}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .mat-mdc-table .mat-mdc-row .mat-mdc-cell .mat-mdc-chip *{font-size:.8rem}@media(max-width:389px){::ng-deep .mat-mdc-table [gt-xs],::ng-deep .mat-mdc-table .gt-xs{display:none}::ng-deep .mat-mdc-table [gt-sm],::ng-deep .mat-mdc-table .gt-sm{display:none}::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:599px){::ng-deep .mat-mdc-table [gt-sm],::ng-deep .mat-mdc-table .gt-sm{display:none}::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:959px){::ng-deep .mat-mdc-table [gt-md],::ng-deep .mat-mdc-table .gt-md{display:none}::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1279px){::ng-deep .mat-mdc-table [gt-lg],::ng-deep .mat-mdc-table .gt-lg{display:none}::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1919px){::ng-deep .mat-mdc-table [gt-xl],::ng-deep .mat-mdc-table .gt-xl{display:none}::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}@media(max-width:1979px){::ng-deep .mat-mdc-table [gt-xxl],::ng-deep .mat-mdc-table .gt-xxl{display:none}}.mat-table-container{width:100%;max-width:100%;overflow:auto}.mat-table-container .mat-mdc-header-cell,.mat-table-container .mat-mdc-footer-cell,.mat-table-container .mat-mdc-cell{min-width:80px;box-sizing:border-box}.mat-table-container .mat-mdc-header-row,.mat-table-container .mat-mdc-footer-row,.mat-table-container .mat-mdc-row{min-width:1920px}.mat-table-container.mat-table-sticky .mat-mdc-table-sticky-border-elem-right{box-shadow:-3px 0 5px #0000001a}.mat-table-container.mat-table-sticky .mat-mdc-table-sticky-border-elem-left{box-shadow:3px 0 5px #0000001a}\n"] }]
19062
19089
  }], ctorParameters: () => [{ type: DynamicBuilder }, { type: i0.ChangeDetectorRef }], propDecorators: { table: [{
19063
19090
  type: ViewChild,
19064
19091
  args: ['table']
@@ -19201,6 +19228,7 @@ __decorate([
19201
19228
  __decorate([
19202
19229
  Column({
19203
19230
  type: TableColumnType.TextInput,
19231
+ width: 80,
19204
19232
  maxWidth: 80,
19205
19233
  change: (_, __, ctx) => ctx?.updateColumns()
19206
19234
  }),
@@ -19215,13 +19243,14 @@ __decorate([
19215
19243
  defaultOption: false
19216
19244
  }),
19217
19245
  Display($localize `:@@display:Display`),
19218
- __metadata("design:type", Number)
19246
+ __metadata("design:type", Object)
19219
19247
  ], TableColumnConfig.prototype, "display", void 0);
19220
19248
  __decorate([
19221
19249
  Column({
19222
19250
  type: TableColumnType.TextInput,
19223
19251
  inputMin: () => 0,
19224
19252
  inputMax: () => 2000,
19253
+ width: 80,
19225
19254
  maxWidth: 80,
19226
19255
  display: Grid.Md,
19227
19256
  change: (_, __, ctx) => ctx?.updateColumns()
@@ -19234,6 +19263,7 @@ __decorate([
19234
19263
  type: TableColumnType.TextInput,
19235
19264
  inputMin: () => 0,
19236
19265
  inputMax: () => 2000,
19266
+ width: 80,
19237
19267
  maxWidth: 80,
19238
19268
  display: Grid.Md
19239
19269
  }),
@@ -19245,6 +19275,7 @@ __decorate([
19245
19275
  type: TableColumnType.TextInput,
19246
19276
  inputMin: () => 0,
19247
19277
  inputMax: () => 2000,
19278
+ width: 80,
19248
19279
  maxWidth: 80,
19249
19280
  display: Grid.Md,
19250
19281
  change: (x) => x ? (x.width ??= x.maxWidth) : null
@@ -19386,7 +19417,11 @@ class VdDynamicTableConfigDialogComponent extends BaseComponent {
19386
19417
  this.configForm.controls["sticky"].valueChanges.subscribe(value => genericList.dynamicTable.sticky = value);
19387
19418
  }
19388
19419
  /* Filter columns that are configurable from the provided dynamic table configuration */
19389
- this.columns = genericList?.dynamicTable?.columns?.filter((x) => x.configurable);
19420
+ const activeColumnSets = genericList?.dynamicTable?.columnSets || [];
19421
+ /* Filter columns that are configurable from the provided dynamic table configuration */
19422
+ this.columns = genericList?.dynamicTable?.columns
19423
+ ?.filter((x) => x.configurable)
19424
+ ?.filter((x) => !activeColumnSets?.length || x.columnSets?.some(cs => activeColumnSets.includes(cs)));
19390
19425
  }
19391
19426
  /**
19392
19427
  * Saves the current column configuration and closes the dialog.
@@ -25441,7 +25476,7 @@ class MsaGenericFormMsaChipsFieldComponent extends MsaGenericFormFieldBaseCompon
25441
25476
  <mat-hint>{{field.hint}}</mat-hint>
25442
25477
  }
25443
25478
  @if (vdChip.emptyResult) {
25444
- <mat-hint class="tc-red-400" i18n="@@noResultsFound">No results were found.</mat-hint>
25479
+ <mat-hint class="tc-red-400" i18n="@@noResultsFound">No results found</mat-hint>
25445
25480
  }
25446
25481
  @for (errorMessage of $any(formGroup.controls[field.name!])['errorMessages']; track errorMessage) {
25447
25482
  <mat-error>{{errorMessage}}</mat-error>
@@ -25500,7 +25535,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
25500
25535
  <mat-hint>{{field.hint}}</mat-hint>
25501
25536
  }
25502
25537
  @if (vdChip.emptyResult) {
25503
- <mat-hint class="tc-red-400" i18n="@@noResultsFound">No results were found.</mat-hint>
25538
+ <mat-hint class="tc-red-400" i18n="@@noResultsFound">No results found</mat-hint>
25504
25539
  }
25505
25540
  @for (errorMessage of $any(formGroup.controls[field.name!])['errorMessages']; track errorMessage) {
25506
25541
  <mat-error>{{errorMessage}}</mat-error>
@@ -25553,7 +25588,7 @@ class VdListComponent extends AbstractSelectFormField {
25553
25588
  this.selectEl?.focus();
25554
25589
  }
25555
25590
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: VdListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
25556
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: VdListComponent, isStandalone: true, selector: "vd-list", host: { classAttribute: "vd-list" }, providers: [{ provide: MatFormFieldControl, useExisting: VdListComponent }], queries: [{ propertyName: "optionTemplate", first: true, predicate: VdListOptionDirective, descendants: true }], viewQueries: [{ propertyName: "selectEl", first: true, predicate: MatSelectionList, descendants: true }, { propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<mat-selection-list i18n-placeholder [(ngModel)]=\"value\" #select=\"matSelectionList\" (selectionChange)=\"handleChange($event)\" [multiple]=\"multiple\" [compareWith]=\"compareWith??defaultCompareWith\" [disabled]=\"disabled || readonly\" [hideSingleSelectionIndicator]=\"false\" flex>\r\n <!-- #region Options -->\r\n @for (option of filteredOptions; track option; let first = $first) {\r\n <mat-list-option [value]=\"mapper ? option : option[optionValueProperty]\">\r\n @if (!optionTemplate?.templateRef) {\r\n <span i18n=\"@@selection\">{option[optionTextProperty], select, option {option} other{{{option[optionTextProperty]}}}}</span>\r\n } @if (optionTemplate?.templateRef) {\r\n <ng-template [ngTemplateOutlet]=\"$safeNavigationMigration(optionTemplate.templateRef)!\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\r\n }\r\n </mat-list-option>\r\n }\r\n <!-- #endregion -->\r\n</mat-selection-list>", styles: ["::ng-deep .vd-list{overflow:auto;max-height:100%}::ng-deep .mat-mdc-form-field-type-vd-list .mat-mdc-form-field-infix{padding-top:0!important;padding-bottom:0!important}::ng-deep .mat-mdc-form-field-type-vd-list .mdc-text-field{padding:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
25591
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: VdListComponent, isStandalone: true, selector: "vd-list", host: { classAttribute: "vd-list" }, providers: [{ provide: MatFormFieldControl, useExisting: VdListComponent }], queries: [{ propertyName: "optionTemplate", first: true, predicate: VdListOptionDirective, descendants: true }], viewQueries: [{ propertyName: "selectEl", first: true, predicate: MatSelectionList, descendants: true }, { propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<mat-selection-list i18n-placeholder [(ngModel)]=\"value\" #select=\"matSelectionList\" (selectionChange)=\"handleChange($event)\" [multiple]=\"multiple\" [compareWith]=\"compareWith??defaultCompareWith\" [disabled]=\"disabled || readonly\" [hideSingleSelectionIndicator]=\"false\" flex>\r\n <!-- #region Options -->\r\n @for (option of filteredOptions; track option; let first = $first) {\r\n <mat-list-option [value]=\"mapper ? option : option[optionValueProperty]\">\r\n @if (!optionTemplate?.templateRef) {\r\n <msa-selection-label [label]=\"option[optionTextProperty]\"></msa-selection-label>\r\n }\r\n @if (optionTemplate?.templateRef) {\r\n <ng-template [ngTemplateOutlet]=\"$safeNavigationMigration(optionTemplate.templateRef)!\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\r\n }\r\n </mat-list-option>\r\n }\r\n <!-- #endregion -->\r\n</mat-selection-list>", styles: ["::ng-deep .vd-list{overflow:auto;max-height:100%}::ng-deep .mat-mdc-form-field-type-vd-list .mat-mdc-form-field-infix{padding-top:0!important;padding-bottom:0!important}::ng-deep .mat-mdc-form-field-type-vd-list .mdc-text-field{padding:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MsaSelectionLabelComponent, selector: "msa-selection-label", inputs: ["label"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
25557
25592
  }
25558
25593
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: VdListComponent, decorators: [{
25559
25594
  type: Component,
@@ -25561,8 +25596,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
25561
25596
  CommonModule,
25562
25597
  MatSelectionList,
25563
25598
  MatListOption,
25564
- FormsModule
25565
- ], template: "<mat-selection-list i18n-placeholder [(ngModel)]=\"value\" #select=\"matSelectionList\" (selectionChange)=\"handleChange($event)\" [multiple]=\"multiple\" [compareWith]=\"compareWith??defaultCompareWith\" [disabled]=\"disabled || readonly\" [hideSingleSelectionIndicator]=\"false\" flex>\r\n <!-- #region Options -->\r\n @for (option of filteredOptions; track option; let first = $first) {\r\n <mat-list-option [value]=\"mapper ? option : option[optionValueProperty]\">\r\n @if (!optionTemplate?.templateRef) {\r\n <span i18n=\"@@selection\">{option[optionTextProperty], select, option {option} other{{{option[optionTextProperty]}}}}</span>\r\n } @if (optionTemplate?.templateRef) {\r\n <ng-template [ngTemplateOutlet]=\"$safeNavigationMigration(optionTemplate.templateRef)!\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\r\n }\r\n </mat-list-option>\r\n }\r\n <!-- #endregion -->\r\n</mat-selection-list>", styles: ["::ng-deep .vd-list{overflow:auto;max-height:100%}::ng-deep .mat-mdc-form-field-type-vd-list .mat-mdc-form-field-infix{padding-top:0!important;padding-bottom:0!important}::ng-deep .mat-mdc-form-field-type-vd-list .mdc-text-field{padding:0}\n"] }]
25599
+ FormsModule,
25600
+ MsaSelectionLabelComponent
25601
+ ], template: "<mat-selection-list i18n-placeholder [(ngModel)]=\"value\" #select=\"matSelectionList\" (selectionChange)=\"handleChange($event)\" [multiple]=\"multiple\" [compareWith]=\"compareWith??defaultCompareWith\" [disabled]=\"disabled || readonly\" [hideSingleSelectionIndicator]=\"false\" flex>\r\n <!-- #region Options -->\r\n @for (option of filteredOptions; track option; let first = $first) {\r\n <mat-list-option [value]=\"mapper ? option : option[optionValueProperty]\">\r\n @if (!optionTemplate?.templateRef) {\r\n <msa-selection-label [label]=\"option[optionTextProperty]\"></msa-selection-label>\r\n }\r\n @if (optionTemplate?.templateRef) {\r\n <ng-template [ngTemplateOutlet]=\"$safeNavigationMigration(optionTemplate.templateRef)!\" [ngTemplateOutletContext]=\"{ option: option }\"></ng-template>\r\n }\r\n </mat-list-option>\r\n }\r\n <!-- #endregion -->\r\n</mat-selection-list>", styles: ["::ng-deep .vd-list{overflow:auto;max-height:100%}::ng-deep .mat-mdc-form-field-type-vd-list .mat-mdc-form-field-infix{padding-top:0!important;padding-bottom:0!important}::ng-deep .mat-mdc-form-field-type-vd-list .mdc-text-field{padding:0}\n"] }]
25566
25602
  }], ctorParameters: () => [], propDecorators: { optionTemplate: [{
25567
25603
  type: ContentChild,
25568
25604
  args: [VdListOptionDirective]
@@ -28253,7 +28289,7 @@ class VdMenuComponent {
28253
28289
  // this.onMouseLeave.emit({ event: $event, item: item });
28254
28290
  }
28255
28291
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: VdMenuComponent, deps: [{ token: VdMediaService }], target: i0.ɵɵFactoryTarget.Component });
28256
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: VdMenuComponent, isStandalone: true, selector: "vd-menu", inputs: { items: "items", activeExact: "activeExact", fontSet: "fontSet", avatar: "avatar", mobile: "mobile" }, outputs: { onClick: "click", onMouseEnter: "over", onMouseLeave: "out" }, ngImport: i0, template: "<mat-nav-list>\r\n <!-- #region main-menu-accordion -->\r\n <mat-accordion displayMode=\"flat\">\r\n @for (item of items; track item; let last = $last) {\r\n <!-- #region mobile-item-with-submenu -->\r\n @if ((item?.items?.length ?? 0) > 0 && mobile) {\r\n <mat-expansion-panel class=\"mat-elevation-z raw\"\r\n (click)=\"$event.stopPropagation();\"\r\n [disabled]=\"!mobile\"\r\n [hideToggle]=\"!mobile || !item?.items?.length\"\r\n [ngClass]=\"{'icon-only': !item.title, 'mobile': mobile}\"\r\n (delayedHover)=\"(item.items?.length ?? 0) > 0 && itemMouseEnter(item.event ? item.event : $event, item)\"\r\n (mouseleave)=\"(item.items?.length ?? 0) >0 && false&& itemMouseLeave(item.event ? item.event : $event, item)\"\r\n [routerLinkActive]=\"['active']\"\r\n [routerLinkActiveOptions]=\"{exact:false}\">\r\n <!-- #region mobile-parent-item-header -->\r\n <mat-expansion-panel-header [expandedHeight]=\"'48px'\">\r\n <mat-panel-title>\r\n <!-- #region parent-item-icon-and-title -->\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\"\r\n [style.color]=\"item.iconColor\"\r\n [matBadge]=\"item.badge ? item.badge() : null\"\r\n [matBadgeHidden]=\"!item.badge || item.badge() === 0\"\r\n aria-hidden=\"false\">\r\n {{(item.icon | func:item) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n @if (!avatar && item.title) {\r\n <span [style.color]=\"item.textColor\">{{item.title}}</span>\r\n }\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\">{{(item.icon | func:item) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n @if (avatar) {\r\n <h3>{{item.title}}</h3>\r\n }\r\n <!-- #endregion -->\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <!-- #endregion -->\r\n\r\n <!-- #region mobile-submenu-items -->\r\n <mat-nav-list>\r\n @for (subItem of item.items; track subItem; let subLast = $last) {\r\n <!-- #region visible-submenu-link -->\r\n @if (subItem.enabled) {\r\n <a mat-list-item\r\n [style.backgroundColor]=\"subItem.backgroundColor\"\r\n [routerLink]=\"subItem.path\"\r\n target=\"_{{MenuItemTarget[item.target??0].toLowerCase()}}\"\r\n [routerLinkActive]=\"['active']\" [ngClass]=\"{'icon-only': !subItem.title}\"\r\n [routerLinkActiveOptions]=\"{exact:subItem.activeExact??false}\"\r\n [fragment]=\"subItem.fragment\"\r\n (click)=\"itemClicked($event, subItem)\">\r\n <!-- #region submenu-icon-and-text -->\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" [style.color]=\"subItem.iconColor\" aria-hidden=\"false\">\r\n {{(subItem.icon | func:subItem) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n\r\n @if (!avatar && subItem.title) {\r\n <span [style.color]=\"subItem.textColor\">{{subItem.title}}</span>\r\n }\r\n\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\">{{(subItem.icon | func:subItem) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n\r\n @if (avatar) {\r\n <h3>{{subItem.title}}</h3>\r\n }\r\n\r\n @if (avatar && subItem.description) {\r\n <p>{{subItem.description}}</p>\r\n }\r\n\r\n @if (subItem.badge && subItem.badge() !== 0) {\r\n <span matListItemMeta\r\n [matBadge]=\"subItem.badge()\"\r\n matBadgeOverlap=\"false\"\r\n matBadgePosition=\"above before\"\r\n class=\"menu-badge-align\">\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n\r\n <!-- #region submenu-divider-lines -->\r\n @if (subItem.divider && !avatar) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (!subItem.divider && avatar && !subLast) {\r\n <mat-divider [inset]=\"avatar\"></mat-divider>\r\n }\r\n <!-- #endregion -->\r\n }\r\n </mat-nav-list>\r\n <!-- #endregion -->\r\n </mat-expansion-panel>\r\n <!-- #endregion -->\r\n\r\n <!-- #region regular-menu-item -->\r\n } @else {\r\n <!-- #region regular-item-link -->\r\n @if (item.enabled) {\r\n <a mat-list-item [style.backgroundColor]=\"item.backgroundColor\" [routerLink]=\"item.path\" target=\"_{{MenuItemTarget[item.target??0].toLowerCase()}}\" [routerLinkActive]=\"['active']\" [ngClass]=\"{'icon-only': !item.title}\" [routerLinkActiveOptions]=\"{exact:item.activeExact??false}\" [fragment]=\"item.fragment\" (click)=\"itemClicked($event, item)\" (delayedHover)=\"(item.items?.length ?? 0) > 0 && itemMouseEnter(item.event ? item.event : $event, item)\" (mouseleave)=\"(item.items?.length ?? 0) >0 && false&& itemMouseLeave(item.event ? item.event : $event, item)\">\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\"\r\n [style.color]=\"item.iconColor\"\r\n aria-hidden=\"false\"\r\n matListItemIcon>\r\n {{(item.icon | func:item) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n\r\n @if (!avatar && item.title) {\r\n <span [style.color]=\"item.textColor\" matListItemTitle>{{item.title}}</span>\r\n }\r\n\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" matListAvatar>{{(item.icon | func:item) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n\r\n @if (avatar) {\r\n <h3 matLine>{{item.title}}</h3>\r\n }\r\n\r\n @if (avatar && item.description) {\r\n <p matLine>{{item.description}}</p>\r\n }\r\n\r\n @if (item.badge && item.badge() !== 0) {\r\n <span matListItemMeta\r\n [matBadge]=\"item.badge()\"\r\n matBadgeOverlap=\"false\"\r\n matBadgePosition=\"above before\"\r\n class=\"menu-badge-align\">\r\n </span>\r\n }\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n\r\n <!-- #region regular-item-divider-lines -->\r\n @if (item.divider && !avatar) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (!item.divider && avatar && !last) {\r\n <mat-divider [inset]=\"avatar\"></mat-divider>\r\n }\r\n <!-- #endregion -->\r\n }\r\n <!-- #endregion -->\r\n }\r\n </mat-accordion>\r\n <!-- #endregion -->\r\n</mat-nav-list>", styles: [":host ::ng-deep .mat-mdc-nav-list .mat-mdc-list-item.icon-only .mdc-list-item__content{display:none!important}:host ::ng-deep .mat-expansion-panel{background-color:transparent}:host ::ng-deep .mat-mdc-list-item:not(.active),:host ::ng-deep .mat-mdc-list-item:active,:host ::ng-deep .mat-mdc-list-item:focus,:host ::ng-deep .mat-expansion-panel:not(.active),:host ::ng-deep .mat-expansion-panel:active,:host ::ng-deep .mat-expansion-panel:focus{background-color:transparent!important}:host ::ng-deep .mat-mdc-list-item:not(.active):before,:host ::ng-deep .mat-mdc-list-item:active:before,:host ::ng-deep .mat-mdc-list-item:focus:before,:host ::ng-deep .mat-expansion-panel:not(.active):before,:host ::ng-deep .mat-expansion-panel:active:before,:host ::ng-deep .mat-expansion-panel:focus:before{background-color:transparent!important}:host ::ng-deep .mat-mdc-list-item,:host ::ng-deep .mat-expansion-panel{font-family:var(--mat-expansion-header-text-font, var(--mat-sys-title-medium-font));font-weight:var(--mat-expansion-header-text-weight, var(--mat-sys-title-medium-weight));line-height:var(--mat-expansion-header-text-line-height, var(--mat-sys-title-medium-line-height));letter-spacing:var(--mat-expansion-header-text-tracking, var(--mat-sys-title-medium-tracking))}:host ::ng-deep .mat-mdc-list-item mat-icon,:host ::ng-deep .mat-expansion-panel mat-icon{margin-right:18px;margin-bottom:3px}:host ::ng-deep .mat-mdc-list-item ::ng-deep .mat-expansion-panel-body,:host ::ng-deep .mat-expansion-panel ::ng-deep .mat-expansion-panel-body{padding-bottom:0!important}:host ::ng-deep .mat-mdc-list-item:not(.mobile)>.mat-expansion-panel-header,:host ::ng-deep .mat-expansion-panel:not(.mobile)>.mat-expansion-panel-header{padding:4px 8px}:host ::ng-deep .menu-badge-align{padding-top:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$6.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: i1$6.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i4$4.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i4$4.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: i4$4.MatListItemIcon, selector: "[matListItemIcon]" }, { kind: "component", type: i6.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i4$4.MatListItemTitle, selector: "[matListItemTitle]" }, { kind: "directive", type: i4$4.MatListItemMeta, selector: "[matListItemMeta]" }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i6$1.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i6$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i6$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i6$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i8.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: VdDelayedHoverDirective, selector: "[delayedHover]", inputs: ["duration"], outputs: ["delayedHover"], exportAs: ["hesitation"] }, { kind: "pipe", type: FuncPipe, name: "func" }], changeDetection: i0.ChangeDetectionStrategy.Eager });
28292
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: VdMenuComponent, isStandalone: true, selector: "vd-menu", inputs: { items: "items", activeExact: "activeExact", fontSet: "fontSet", avatar: "avatar", mobile: "mobile" }, outputs: { onClick: "click", onMouseEnter: "over", onMouseLeave: "out" }, ngImport: i0, template: "<mat-nav-list>\r\n <!-- #region main-menu-accordion -->\r\n <mat-accordion displayMode=\"flat\">\r\n @for (item of items; track item; let last = $last) {\r\n <!-- #region mobile-item-with-submenu -->\r\n @if ((item?.items?.length ?? 0) > 0 && mobile) {\r\n <mat-expansion-panel class=\"mat-elevation-z raw\" (click)=\"$event.stopPropagation();\" [disabled]=\"!mobile\" [hideToggle]=\"!mobile || !item?.items?.length\" [ngClass]=\"{'icon-only': !item.title, 'mobile': mobile}\" (delayedHover)=\"(item.items?.length ?? 0) > 0 && itemMouseEnter(item.event ? item.event : $event, item)\" (mouseleave)=\"(item.items?.length ?? 0) >0 && false&& itemMouseLeave(item.event ? item.event : $event, item)\" [routerLinkActive]=\"['active']\" [routerLinkActiveOptions]=\"{exact:false}\" [attr.data-ordering]=\"item.ordering\">\r\n <!-- #region mobile-parent-item-header -->\r\n <mat-expansion-panel-header [expandedHeight]=\"'48px'\">\r\n <mat-panel-title>\r\n <!-- #region parent-item-icon-and-title -->\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" [style.color]=\"item.iconColor\" [matBadge]=\"item.badge ? item.badge() : null\" [matBadgeHidden]=\"!item.badge || item.badge() === 0\" aria-hidden=\"false\">\r\n {{(item.icon | func:item) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n @if (!avatar && item.title) {\r\n <span [style.color]=\"item.textColor\">{{item.title}}</span>\r\n }\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\">{{(item.icon | func:item) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n @if (avatar) {\r\n <h3>{{item.title}}</h3>\r\n }\r\n <!-- #endregion -->\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <!-- #endregion -->\r\n <!-- #region mobile-submenu-items -->\r\n <mat-nav-list>\r\n @for (subItem of item.items; track subItem; let subLast = $last) {\r\n <!-- #region visible-submenu-link -->\r\n @if (subItem.enabled) {\r\n <a mat-list-item [style.backgroundColor]=\"subItem.backgroundColor\" [attr.data-ordering]=\"subItem.ordering\" [routerLink]=\"subItem.path\" target=\"_{{MenuItemTarget[item.target??0].toLowerCase()}}\" [routerLinkActive]=\"['active']\" [ngClass]=\"{'icon-only': !subItem.title}\" [routerLinkActiveOptions]=\"{exact:subItem.activeExact??false}\" [fragment]=\"subItem.fragment\" (click)=\"itemClicked($event, subItem)\">\r\n <!-- #region submenu-icon-and-text -->\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" [style.color]=\"subItem.iconColor\" aria-hidden=\"false\">\r\n {{(subItem.icon | func:subItem) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n @if (!avatar && subItem.title) {\r\n <span [style.color]=\"subItem.textColor\">{{subItem.title}}</span>\r\n }\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\">{{(subItem.icon | func:subItem) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n @if (avatar) {\r\n <h3>{{subItem.title}}</h3>\r\n }\r\n @if (avatar && subItem.description) {\r\n <p>{{subItem.description}}</p>\r\n }\r\n @if (subItem.badge && subItem.badge() !== 0) {\r\n <span matListItemMeta [matBadge]=\"subItem.badge()\" matBadgeOverlap=\"false\" matBadgePosition=\"above before\" class=\"menu-badge-align\">\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region submenu-divider-lines -->\r\n @if (subItem.divider && !avatar) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (!subItem.divider && avatar && !subLast) {\r\n <mat-divider [inset]=\"avatar\"></mat-divider>\r\n }\r\n <!-- #endregion -->\r\n }\r\n </mat-nav-list>\r\n <!-- #endregion -->\r\n </mat-expansion-panel>\r\n <!-- #endregion -->\r\n <!-- #region regular-menu-item -->\r\n } @else {\r\n <!-- #region regular-item-link -->\r\n @if (item.enabled) {\r\n <a mat-list-item [style.backgroundColor]=\"item.backgroundColor\" [attr.data-ordering]=\"item.ordering\" [routerLink]=\"item.path\" target=\"_{{MenuItemTarget[item.target??0].toLowerCase()}}\" [routerLinkActive]=\"['active']\" [ngClass]=\"{'icon-only': !item.title}\" [routerLinkActiveOptions]=\"{exact:item.activeExact??false}\" [fragment]=\"item.fragment\" (click)=\"itemClicked($event, item)\" (delayedHover)=\"(item.items?.length ?? 0) > 0 && itemMouseEnter(item.event ? item.event : $event, item)\" (mouseleave)=\"(item.items?.length ?? 0) >0 && false&& itemMouseLeave(item.event ? item.event : $event, item)\">\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" [style.color]=\"item.iconColor\" aria-hidden=\"false\" matListItemIcon>\r\n {{(item.icon | func:item) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n @if (!avatar && item.title) {\r\n <span [style.color]=\"item.textColor\" matListItemTitle>{{item.title}}</span>\r\n }\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" matListAvatar>{{(item.icon | func:item) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n @if (avatar) {\r\n <h3 matLine>{{item.title}}</h3>\r\n }\r\n @if (avatar && item.description) {\r\n <p matLine>{{item.description}}</p>\r\n }\r\n @if (item.badge && item.badge() !== 0) {\r\n <span matListItemMeta [matBadge]=\"item.badge()\" matBadgeOverlap=\"false\" matBadgePosition=\"above before\" class=\"menu-badge-align\">\r\n </span>\r\n }\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region regular-item-divider-lines -->\r\n @if (item.divider && !avatar) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (!item.divider && avatar && !last) {\r\n <mat-divider [inset]=\"avatar\"></mat-divider>\r\n }\r\n <!-- #endregion -->\r\n }\r\n <!-- #endregion -->\r\n }\r\n </mat-accordion>\r\n <!-- #endregion -->\r\n</mat-nav-list>", styles: [":host ::ng-deep .mat-mdc-nav-list .mat-mdc-list-item.icon-only .mdc-list-item__content{display:none!important}:host ::ng-deep .mat-expansion-panel{background-color:transparent}:host ::ng-deep .mat-mdc-list-item:not(.active),:host ::ng-deep .mat-mdc-list-item:active,:host ::ng-deep .mat-mdc-list-item:focus,:host ::ng-deep .mat-expansion-panel:not(.active),:host ::ng-deep .mat-expansion-panel:active,:host ::ng-deep .mat-expansion-panel:focus{background-color:transparent!important}:host ::ng-deep .mat-mdc-list-item:not(.active):before,:host ::ng-deep .mat-mdc-list-item:active:before,:host ::ng-deep .mat-mdc-list-item:focus:before,:host ::ng-deep .mat-expansion-panel:not(.active):before,:host ::ng-deep .mat-expansion-panel:active:before,:host ::ng-deep .mat-expansion-panel:focus:before{background-color:transparent!important}:host ::ng-deep .mat-mdc-list-item,:host ::ng-deep .mat-expansion-panel{font-family:var(--mat-expansion-header-text-font, var(--mat-sys-title-medium-font));font-weight:var(--mat-expansion-header-text-weight, var(--mat-sys-title-medium-weight));line-height:var(--mat-expansion-header-text-line-height, var(--mat-sys-title-medium-line-height));letter-spacing:var(--mat-expansion-header-text-tracking, var(--mat-sys-title-medium-tracking))}:host ::ng-deep .mat-mdc-list-item mat-icon,:host ::ng-deep .mat-expansion-panel mat-icon{margin-right:18px;margin-bottom:3px}:host ::ng-deep .mat-mdc-list-item ::ng-deep .mat-expansion-panel-body,:host ::ng-deep .mat-expansion-panel ::ng-deep .mat-expansion-panel-body{padding-bottom:0!important}:host ::ng-deep .mat-mdc-list-item:not(.mobile)>.mat-expansion-panel-header,:host ::ng-deep .mat-expansion-panel:not(.mobile)>.mat-expansion-panel-header{padding:4px 8px}:host ::ng-deep .menu-badge-align{padding-top:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$6.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: i1$6.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i4$4.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i4$4.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: i4$4.MatListItemIcon, selector: "[matListItemIcon]" }, { kind: "component", type: i6.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i4$4.MatListItemTitle, selector: "[matListItemTitle]" }, { kind: "directive", type: i4$4.MatListItemMeta, selector: "[matListItemMeta]" }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i6$1.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i6$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i6$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i6$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i8.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: VdDelayedHoverDirective, selector: "[delayedHover]", inputs: ["duration"], outputs: ["delayedHover"], exportAs: ["hesitation"] }, { kind: "pipe", type: FuncPipe, name: "func" }], changeDetection: i0.ChangeDetectionStrategy.Eager });
28257
28293
  }
28258
28294
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: VdMenuComponent, decorators: [{
28259
28295
  type: Component,
@@ -28267,7 +28303,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
28267
28303
  MatBadgeModule,
28268
28304
  VdDelayedHoverDirective,
28269
28305
  FuncPipe
28270
- ], template: "<mat-nav-list>\r\n <!-- #region main-menu-accordion -->\r\n <mat-accordion displayMode=\"flat\">\r\n @for (item of items; track item; let last = $last) {\r\n <!-- #region mobile-item-with-submenu -->\r\n @if ((item?.items?.length ?? 0) > 0 && mobile) {\r\n <mat-expansion-panel class=\"mat-elevation-z raw\"\r\n (click)=\"$event.stopPropagation();\"\r\n [disabled]=\"!mobile\"\r\n [hideToggle]=\"!mobile || !item?.items?.length\"\r\n [ngClass]=\"{'icon-only': !item.title, 'mobile': mobile}\"\r\n (delayedHover)=\"(item.items?.length ?? 0) > 0 && itemMouseEnter(item.event ? item.event : $event, item)\"\r\n (mouseleave)=\"(item.items?.length ?? 0) >0 && false&& itemMouseLeave(item.event ? item.event : $event, item)\"\r\n [routerLinkActive]=\"['active']\"\r\n [routerLinkActiveOptions]=\"{exact:false}\">\r\n <!-- #region mobile-parent-item-header -->\r\n <mat-expansion-panel-header [expandedHeight]=\"'48px'\">\r\n <mat-panel-title>\r\n <!-- #region parent-item-icon-and-title -->\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\"\r\n [style.color]=\"item.iconColor\"\r\n [matBadge]=\"item.badge ? item.badge() : null\"\r\n [matBadgeHidden]=\"!item.badge || item.badge() === 0\"\r\n aria-hidden=\"false\">\r\n {{(item.icon | func:item) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n @if (!avatar && item.title) {\r\n <span [style.color]=\"item.textColor\">{{item.title}}</span>\r\n }\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\">{{(item.icon | func:item) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n @if (avatar) {\r\n <h3>{{item.title}}</h3>\r\n }\r\n <!-- #endregion -->\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <!-- #endregion -->\r\n\r\n <!-- #region mobile-submenu-items -->\r\n <mat-nav-list>\r\n @for (subItem of item.items; track subItem; let subLast = $last) {\r\n <!-- #region visible-submenu-link -->\r\n @if (subItem.enabled) {\r\n <a mat-list-item\r\n [style.backgroundColor]=\"subItem.backgroundColor\"\r\n [routerLink]=\"subItem.path\"\r\n target=\"_{{MenuItemTarget[item.target??0].toLowerCase()}}\"\r\n [routerLinkActive]=\"['active']\" [ngClass]=\"{'icon-only': !subItem.title}\"\r\n [routerLinkActiveOptions]=\"{exact:subItem.activeExact??false}\"\r\n [fragment]=\"subItem.fragment\"\r\n (click)=\"itemClicked($event, subItem)\">\r\n <!-- #region submenu-icon-and-text -->\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" [style.color]=\"subItem.iconColor\" aria-hidden=\"false\">\r\n {{(subItem.icon | func:subItem) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n\r\n @if (!avatar && subItem.title) {\r\n <span [style.color]=\"subItem.textColor\">{{subItem.title}}</span>\r\n }\r\n\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\">{{(subItem.icon | func:subItem) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n\r\n @if (avatar) {\r\n <h3>{{subItem.title}}</h3>\r\n }\r\n\r\n @if (avatar && subItem.description) {\r\n <p>{{subItem.description}}</p>\r\n }\r\n\r\n @if (subItem.badge && subItem.badge() !== 0) {\r\n <span matListItemMeta\r\n [matBadge]=\"subItem.badge()\"\r\n matBadgeOverlap=\"false\"\r\n matBadgePosition=\"above before\"\r\n class=\"menu-badge-align\">\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n\r\n <!-- #region submenu-divider-lines -->\r\n @if (subItem.divider && !avatar) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (!subItem.divider && avatar && !subLast) {\r\n <mat-divider [inset]=\"avatar\"></mat-divider>\r\n }\r\n <!-- #endregion -->\r\n }\r\n </mat-nav-list>\r\n <!-- #endregion -->\r\n </mat-expansion-panel>\r\n <!-- #endregion -->\r\n\r\n <!-- #region regular-menu-item -->\r\n } @else {\r\n <!-- #region regular-item-link -->\r\n @if (item.enabled) {\r\n <a mat-list-item [style.backgroundColor]=\"item.backgroundColor\" [routerLink]=\"item.path\" target=\"_{{MenuItemTarget[item.target??0].toLowerCase()}}\" [routerLinkActive]=\"['active']\" [ngClass]=\"{'icon-only': !item.title}\" [routerLinkActiveOptions]=\"{exact:item.activeExact??false}\" [fragment]=\"item.fragment\" (click)=\"itemClicked($event, item)\" (delayedHover)=\"(item.items?.length ?? 0) > 0 && itemMouseEnter(item.event ? item.event : $event, item)\" (mouseleave)=\"(item.items?.length ?? 0) >0 && false&& itemMouseLeave(item.event ? item.event : $event, item)\">\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\"\r\n [style.color]=\"item.iconColor\"\r\n aria-hidden=\"false\"\r\n matListItemIcon>\r\n {{(item.icon | func:item) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n\r\n @if (!avatar && item.title) {\r\n <span [style.color]=\"item.textColor\" matListItemTitle>{{item.title}}</span>\r\n }\r\n\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" matListAvatar>{{(item.icon | func:item) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n\r\n @if (avatar) {\r\n <h3 matLine>{{item.title}}</h3>\r\n }\r\n\r\n @if (avatar && item.description) {\r\n <p matLine>{{item.description}}</p>\r\n }\r\n\r\n @if (item.badge && item.badge() !== 0) {\r\n <span matListItemMeta\r\n [matBadge]=\"item.badge()\"\r\n matBadgeOverlap=\"false\"\r\n matBadgePosition=\"above before\"\r\n class=\"menu-badge-align\">\r\n </span>\r\n }\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n\r\n <!-- #region regular-item-divider-lines -->\r\n @if (item.divider && !avatar) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (!item.divider && avatar && !last) {\r\n <mat-divider [inset]=\"avatar\"></mat-divider>\r\n }\r\n <!-- #endregion -->\r\n }\r\n <!-- #endregion -->\r\n }\r\n </mat-accordion>\r\n <!-- #endregion -->\r\n</mat-nav-list>", styles: [":host ::ng-deep .mat-mdc-nav-list .mat-mdc-list-item.icon-only .mdc-list-item__content{display:none!important}:host ::ng-deep .mat-expansion-panel{background-color:transparent}:host ::ng-deep .mat-mdc-list-item:not(.active),:host ::ng-deep .mat-mdc-list-item:active,:host ::ng-deep .mat-mdc-list-item:focus,:host ::ng-deep .mat-expansion-panel:not(.active),:host ::ng-deep .mat-expansion-panel:active,:host ::ng-deep .mat-expansion-panel:focus{background-color:transparent!important}:host ::ng-deep .mat-mdc-list-item:not(.active):before,:host ::ng-deep .mat-mdc-list-item:active:before,:host ::ng-deep .mat-mdc-list-item:focus:before,:host ::ng-deep .mat-expansion-panel:not(.active):before,:host ::ng-deep .mat-expansion-panel:active:before,:host ::ng-deep .mat-expansion-panel:focus:before{background-color:transparent!important}:host ::ng-deep .mat-mdc-list-item,:host ::ng-deep .mat-expansion-panel{font-family:var(--mat-expansion-header-text-font, var(--mat-sys-title-medium-font));font-weight:var(--mat-expansion-header-text-weight, var(--mat-sys-title-medium-weight));line-height:var(--mat-expansion-header-text-line-height, var(--mat-sys-title-medium-line-height));letter-spacing:var(--mat-expansion-header-text-tracking, var(--mat-sys-title-medium-tracking))}:host ::ng-deep .mat-mdc-list-item mat-icon,:host ::ng-deep .mat-expansion-panel mat-icon{margin-right:18px;margin-bottom:3px}:host ::ng-deep .mat-mdc-list-item ::ng-deep .mat-expansion-panel-body,:host ::ng-deep .mat-expansion-panel ::ng-deep .mat-expansion-panel-body{padding-bottom:0!important}:host ::ng-deep .mat-mdc-list-item:not(.mobile)>.mat-expansion-panel-header,:host ::ng-deep .mat-expansion-panel:not(.mobile)>.mat-expansion-panel-header{padding:4px 8px}:host ::ng-deep .menu-badge-align{padding-top:8px}\n"] }]
28306
+ ], template: "<mat-nav-list>\r\n <!-- #region main-menu-accordion -->\r\n <mat-accordion displayMode=\"flat\">\r\n @for (item of items; track item; let last = $last) {\r\n <!-- #region mobile-item-with-submenu -->\r\n @if ((item?.items?.length ?? 0) > 0 && mobile) {\r\n <mat-expansion-panel class=\"mat-elevation-z raw\" (click)=\"$event.stopPropagation();\" [disabled]=\"!mobile\" [hideToggle]=\"!mobile || !item?.items?.length\" [ngClass]=\"{'icon-only': !item.title, 'mobile': mobile}\" (delayedHover)=\"(item.items?.length ?? 0) > 0 && itemMouseEnter(item.event ? item.event : $event, item)\" (mouseleave)=\"(item.items?.length ?? 0) >0 && false&& itemMouseLeave(item.event ? item.event : $event, item)\" [routerLinkActive]=\"['active']\" [routerLinkActiveOptions]=\"{exact:false}\" [attr.data-ordering]=\"item.ordering\">\r\n <!-- #region mobile-parent-item-header -->\r\n <mat-expansion-panel-header [expandedHeight]=\"'48px'\">\r\n <mat-panel-title>\r\n <!-- #region parent-item-icon-and-title -->\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" [style.color]=\"item.iconColor\" [matBadge]=\"item.badge ? item.badge() : null\" [matBadgeHidden]=\"!item.badge || item.badge() === 0\" aria-hidden=\"false\">\r\n {{(item.icon | func:item) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n @if (!avatar && item.title) {\r\n <span [style.color]=\"item.textColor\">{{item.title}}</span>\r\n }\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\">{{(item.icon | func:item) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n @if (avatar) {\r\n <h3>{{item.title}}</h3>\r\n }\r\n <!-- #endregion -->\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <!-- #endregion -->\r\n <!-- #region mobile-submenu-items -->\r\n <mat-nav-list>\r\n @for (subItem of item.items; track subItem; let subLast = $last) {\r\n <!-- #region visible-submenu-link -->\r\n @if (subItem.enabled) {\r\n <a mat-list-item [style.backgroundColor]=\"subItem.backgroundColor\" [attr.data-ordering]=\"subItem.ordering\" [routerLink]=\"subItem.path\" target=\"_{{MenuItemTarget[item.target??0].toLowerCase()}}\" [routerLinkActive]=\"['active']\" [ngClass]=\"{'icon-only': !subItem.title}\" [routerLinkActiveOptions]=\"{exact:subItem.activeExact??false}\" [fragment]=\"subItem.fragment\" (click)=\"itemClicked($event, subItem)\">\r\n <!-- #region submenu-icon-and-text -->\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" [style.color]=\"subItem.iconColor\" aria-hidden=\"false\">\r\n {{(subItem.icon | func:subItem) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n @if (!avatar && subItem.title) {\r\n <span [style.color]=\"subItem.textColor\">{{subItem.title}}</span>\r\n }\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\">{{(subItem.icon | func:subItem) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n @if (avatar) {\r\n <h3>{{subItem.title}}</h3>\r\n }\r\n @if (avatar && subItem.description) {\r\n <p>{{subItem.description}}</p>\r\n }\r\n @if (subItem.badge && subItem.badge() !== 0) {\r\n <span matListItemMeta [matBadge]=\"subItem.badge()\" matBadgeOverlap=\"false\" matBadgePosition=\"above before\" class=\"menu-badge-align\">\r\n </span>\r\n }\r\n <!-- #endregion -->\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region submenu-divider-lines -->\r\n @if (subItem.divider && !avatar) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (!subItem.divider && avatar && !subLast) {\r\n <mat-divider [inset]=\"avatar\"></mat-divider>\r\n }\r\n <!-- #endregion -->\r\n }\r\n </mat-nav-list>\r\n <!-- #endregion -->\r\n </mat-expansion-panel>\r\n <!-- #endregion -->\r\n <!-- #region regular-menu-item -->\r\n } @else {\r\n <!-- #region regular-item-link -->\r\n @if (item.enabled) {\r\n <a mat-list-item [style.backgroundColor]=\"item.backgroundColor\" [attr.data-ordering]=\"item.ordering\" [routerLink]=\"item.path\" target=\"_{{MenuItemTarget[item.target??0].toLowerCase()}}\" [routerLinkActive]=\"['active']\" [ngClass]=\"{'icon-only': !item.title}\" [routerLinkActiveOptions]=\"{exact:item.activeExact??false}\" [fragment]=\"item.fragment\" (click)=\"itemClicked($event, item)\" (delayedHover)=\"(item.items?.length ?? 0) > 0 && itemMouseEnter(item.event ? item.event : $event, item)\" (mouseleave)=\"(item.items?.length ?? 0) >0 && false&& itemMouseLeave(item.event ? item.event : $event, item)\">\r\n @if (!avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" [style.color]=\"item.iconColor\" aria-hidden=\"false\" matListItemIcon>\r\n {{(item.icon | func:item) || 'radio_button_unchecked'}}\r\n </mat-icon>\r\n }\r\n @if (!avatar && item.title) {\r\n <span [style.color]=\"item.textColor\" matListItemTitle>{{item.title}}</span>\r\n }\r\n @if (avatar) {\r\n <mat-icon [fontSet]=\"fontSet\" matListAvatar>{{(item.icon | func:item) || 'radio_button_unchecked'}}</mat-icon>\r\n }\r\n @if (avatar) {\r\n <h3 matLine>{{item.title}}</h3>\r\n }\r\n @if (avatar && item.description) {\r\n <p matLine>{{item.description}}</p>\r\n }\r\n @if (item.badge && item.badge() !== 0) {\r\n <span matListItemMeta [matBadge]=\"item.badge()\" matBadgeOverlap=\"false\" matBadgePosition=\"above before\" class=\"menu-badge-align\">\r\n </span>\r\n }\r\n </a>\r\n }\r\n <!-- #endregion -->\r\n <!-- #region regular-item-divider-lines -->\r\n @if (item.divider && !avatar) {\r\n <mat-divider></mat-divider>\r\n }\r\n @if (!item.divider && avatar && !last) {\r\n <mat-divider [inset]=\"avatar\"></mat-divider>\r\n }\r\n <!-- #endregion -->\r\n }\r\n <!-- #endregion -->\r\n }\r\n </mat-accordion>\r\n <!-- #endregion -->\r\n</mat-nav-list>", styles: [":host ::ng-deep .mat-mdc-nav-list .mat-mdc-list-item.icon-only .mdc-list-item__content{display:none!important}:host ::ng-deep .mat-expansion-panel{background-color:transparent}:host ::ng-deep .mat-mdc-list-item:not(.active),:host ::ng-deep .mat-mdc-list-item:active,:host ::ng-deep .mat-mdc-list-item:focus,:host ::ng-deep .mat-expansion-panel:not(.active),:host ::ng-deep .mat-expansion-panel:active,:host ::ng-deep .mat-expansion-panel:focus{background-color:transparent!important}:host ::ng-deep .mat-mdc-list-item:not(.active):before,:host ::ng-deep .mat-mdc-list-item:active:before,:host ::ng-deep .mat-mdc-list-item:focus:before,:host ::ng-deep .mat-expansion-panel:not(.active):before,:host ::ng-deep .mat-expansion-panel:active:before,:host ::ng-deep .mat-expansion-panel:focus:before{background-color:transparent!important}:host ::ng-deep .mat-mdc-list-item,:host ::ng-deep .mat-expansion-panel{font-family:var(--mat-expansion-header-text-font, var(--mat-sys-title-medium-font));font-weight:var(--mat-expansion-header-text-weight, var(--mat-sys-title-medium-weight));line-height:var(--mat-expansion-header-text-line-height, var(--mat-sys-title-medium-line-height));letter-spacing:var(--mat-expansion-header-text-tracking, var(--mat-sys-title-medium-tracking))}:host ::ng-deep .mat-mdc-list-item mat-icon,:host ::ng-deep .mat-expansion-panel mat-icon{margin-right:18px;margin-bottom:3px}:host ::ng-deep .mat-mdc-list-item ::ng-deep .mat-expansion-panel-body,:host ::ng-deep .mat-expansion-panel ::ng-deep .mat-expansion-panel-body{padding-bottom:0!important}:host ::ng-deep .mat-mdc-list-item:not(.mobile)>.mat-expansion-panel-header,:host ::ng-deep .mat-expansion-panel:not(.mobile)>.mat-expansion-panel-header{padding:4px 8px}:host ::ng-deep .menu-badge-align{padding-top:8px}\n"] }]
28271
28307
  }], ctorParameters: () => [{ type: VdMediaService }], propDecorators: { items: [{
28272
28308
  type: Input
28273
28309
  }], activeExact: [{
@@ -28295,6 +28331,42 @@ var MenuScope;
28295
28331
  MenuScope[MenuScope["Admin"] = 1] = "Admin";
28296
28332
  })(MenuScope || (MenuScope = {}));
28297
28333
 
28334
+ /**
28335
+ * Class decorator to define a table with its configuration.
28336
+ * @param tableDefinition Optional partial table definition to customize the table's behavior and appearance.
28337
+ * @returns A function that takes the target class and applies the table definition metadata.
28338
+ */
28339
+ function Table(tableDefinition) {
28340
+ return function (target) {
28341
+ if (tableDefinition?.columns) {
28342
+ /* Add action menus from table definition, if any */
28343
+ var actionColmun = tableDefinition.columns?.find(x => x.name == 'action');
28344
+ if (!actionColmun) {
28345
+ actionColmun = new TableColumn({
28346
+ index: 2000,
28347
+ name: 'action',
28348
+ columnSets: ['action', 'common'],
28349
+ type: TableColumnType.Action,
28350
+ disabled: true,
28351
+ rowMenuItems: actions,
28352
+ configurable: false,
28353
+ stickyEnd: true
28354
+ });
28355
+ /* Add the action column into the table columns */
28356
+ tableDefinition.columns.push(actionColmun);
28357
+ }
28358
+ /* Get custom action, if any */
28359
+ var actions = tableDefinition?.actions;
28360
+ if (actions != null && actionColmun != null) {
28361
+ actionColmun.rowMenuItems ??= [];
28362
+ actions.forEach(y => actionColmun.rowMenuItems.push(y));
28363
+ }
28364
+ }
28365
+ /* Save the table defintion in the metadata */
28366
+ Reflect.defineMetadata(TABLE_DEFINITION_METADATA_KEY, tableDefinition, target);
28367
+ };
28368
+ }
28369
+
28298
28370
  /**
28299
28371
  * @class
28300
28372
  */
@@ -29184,78 +29256,87 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
29184
29256
  type: Injectable
29185
29257
  }] });
29186
29258
 
29187
- class MenuItemService extends GenericService {
29259
+ class MenuService extends GenericService {
29188
29260
  /**
29189
29261
  * Constructor
29190
29262
  * @param _http
29191
29263
  */
29192
29264
  constructor() {
29193
- super('menuitem');
29265
+ super('menu');
29194
29266
  }
29195
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuItemService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
29196
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuItemService, providedIn: 'root' });
29267
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
29268
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuService, providedIn: 'root' });
29197
29269
  }
29198
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuItemService, decorators: [{
29270
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuService, decorators: [{
29199
29271
  type: Injectable,
29200
29272
  args: [{ providedIn: 'root' }]
29201
29273
  }], ctorParameters: () => [] });
29202
29274
 
29203
- class MenuService extends GenericService {
29275
+ class MenuItemService extends GenericService {
29204
29276
  /**
29205
29277
  * Constructor
29206
29278
  * @param _http
29207
29279
  */
29208
29280
  constructor() {
29209
- super('menu');
29281
+ super('menuitem');
29210
29282
  }
29211
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
29212
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuService, providedIn: 'root' });
29283
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuItemService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
29284
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuItemService, providedIn: 'root' });
29213
29285
  }
29214
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuService, decorators: [{
29286
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuItemService, decorators: [{
29215
29287
  type: Injectable,
29216
29288
  args: [{ providedIn: 'root' }]
29217
29289
  }], ctorParameters: () => [] });
29218
29290
 
29291
+ /**
29292
+ * Injection token for the MenuResolveOptions
29293
+ */
29294
+ const MENU_RESOLVE_OPTIONS = new InjectionToken('MENU_RESOLVE_OPTIONS');
29219
29295
  /**
29220
29296
  * Menu resolve service
29221
29297
  */
29222
29298
  class MenuResolve {
29223
29299
  menuService;
29300
+ options;
29224
29301
  /**
29225
29302
  * Constructor
29226
- * @param menuService
29303
+ * @param menuService The menu service
29304
+ * @param options The menu resolve options
29227
29305
  */
29228
- constructor(menuService) {
29306
+ constructor(menuService, options) {
29229
29307
  this.menuService = menuService;
29308
+ this.options = options;
29230
29309
  }
29231
29310
  /**
29232
29311
  * Resolves menu items
29233
- * @param route
29312
+ * @param route The activated route snapshot
29313
+ * @returns An observable of menu items
29234
29314
  */
29235
29315
  resolve(route) {
29236
- return this.menuService.getList(route.data || {}, undefined, { cache: 'yes' });
29316
+ const options = this.options ?? route.data ?? {};
29317
+ return this.menuService.getList(options, undefined, { cache: 'yes' });
29237
29318
  }
29238
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuResolve, deps: [{ token: MenuService }], target: i0.ɵɵFactoryTarget.Injectable });
29319
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuResolve, deps: [{ token: MenuService }, { token: MENU_RESOLVE_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
29239
29320
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuResolve, providedIn: 'root' });
29240
29321
  }
29241
29322
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuResolve, decorators: [{
29242
29323
  type: Injectable,
29243
29324
  args: [{ providedIn: 'root' }]
29244
- }], ctorParameters: () => [{ type: MenuService }] });
29325
+ }], ctorParameters: () => [{ type: MenuService }, { type: undefined, decorators: [{
29326
+ type: Optional
29327
+ }, {
29328
+ type: Inject,
29329
+ args: [MENU_RESOLVE_OPTIONS]
29330
+ }] }] });
29245
29331
  /**
29246
29332
  * Submenu resolve service
29247
29333
  */
29248
29334
  class SubMenuResolve {
29249
- router;
29250
- route3;
29251
- constructor(router, route3) {
29252
- this.router = router;
29253
- this.route3 = route3;
29254
- }
29255
29335
  /**
29256
- * Resolves menu items
29257
- * @param route
29258
- * @param state
29336
+ * Resolve method to get the submenu item based on the current route
29337
+ * @param route The activated route snapshot
29338
+ * @param state The router state snapshot
29339
+ * @returns The submenu item or undefined if not found
29259
29340
  */
29260
29341
  resolve(route, state) {
29261
29342
  /* Get menu from route data */
@@ -29272,13 +29353,13 @@ class SubMenuResolve {
29272
29353
  }
29273
29354
  return undefined;
29274
29355
  }
29275
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SubMenuResolve, deps: [{ token: i1$6.Router }, { token: i1$6.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Injectable });
29356
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SubMenuResolve, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
29276
29357
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SubMenuResolve, providedIn: 'root' });
29277
29358
  }
29278
29359
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SubMenuResolve, decorators: [{
29279
29360
  type: Injectable,
29280
29361
  args: [{ providedIn: 'root' }]
29281
- }], ctorParameters: () => [{ type: i1$6.Router }, { type: i1$6.ActivatedRoute }] });
29362
+ }] });
29282
29363
 
29283
29364
  class VdLayoutComponent {
29284
29365
  media;
@@ -31047,6 +31128,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
31047
31128
  args: ['mediaStyles']
31048
31129
  }] } });
31049
31130
 
31131
+ /**
31132
+ * Decorator function to define columns for a table object.
31133
+ * @param type The constructor function of the table object.
31134
+ * @returns A decorator function.
31135
+ */
31136
+ function ColumnObject(type) {
31137
+ return function (target, propertyKey) {
31138
+ /* Retrieve table definition */
31139
+ var tableDef = getTableDefinition(type);
31140
+ /* Retrieve columns from the table definition */
31141
+ var columns = tableDef.columns;
31142
+ /* Update column names with property key prefix */
31143
+ columns?.forEach(x => x.name = `${propertyKey}.${x.name}`);
31144
+ /* Get existing table columns from metadata */
31145
+ let previousTableColumns = Reflect.getMetadata(TABLE_COLUMNS_METADATA_KEY, target);
31146
+ /* Create a copy of the existing columns array and append new columns */
31147
+ let tableColumns = previousTableColumns ? previousTableColumns.concat(columns ?? []) : [];
31148
+ /* Set column index if not already set */
31149
+ tableColumns.forEach((x, i) => x.index ??= i);
31150
+ /* Sort the columns by index */
31151
+ Utils.sortArray(tableColumns, 'index');
31152
+ /* Override the table columns in the metadata */
31153
+ Reflect.defineMetadata(TABLE_COLUMNS_METADATA_KEY, tableColumns, target);
31154
+ };
31155
+ }
31156
+
31050
31157
  /**
31051
31158
  * VdTableFieldDirective class
31052
31159
  */
@@ -31232,5 +31339,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
31232
31339
  * Generated bundle index. Do not edit.
31233
31340
  */
31234
31341
 
31235
- export { AbstractMatFormField, AbstractSelectFormField, ActionItem, Api, ApiResponse, AppEvent, AppEventType, AppSetting, AppStorage, AsyncValidationDirective, AuditEntity, AuditUser, AuthHelper, AuthUser, AutofocusDirective, BaseComponent, BaseDirective, BaseEntity, BaseInterceptor, BaseService, BindPipe, CachingInterceptor, Column, ColumnObject, Common, CommonError, CommonHandlerContext, ConfirmExitGuard, ContextHelper, DIALOG_PROVIDER, DIALOG_PROVIDER_FACTORY, DataSourceFilterDirective, DataSourcePipe, DatePickerHeaderComponent, DisableControlDirective, Display, DisplayNameNumberProjection, DisplayNameProjection, DynamicBuilder, DynamicComponentCompiler, EXPORT_DIALOG_COMPONENT, EmptyStringResetDirective, EnumMetadata, EnumPipe, EnumService, EqualValidator, ErrorMessageBindingStrategy, EventQueueService, Facet, FacetValue, FieldFuncPipe, FileControlDirective, FileService, FileSizePipe, FilterClearComponent, FilterDateComponent, FilterGlue, FilterInputComponent, FilterOperator, FilterPipe, FilterSelectComponent, FirstLetterPipe, Form, FormArrayPipe, FormBuilderConfiguration, FormControlPipe, FormDefinition, FormField, FormFieldDefinition, FormFieldGroup, FormFieldGroupDefinition, FormFieldType, FormGroupPipe, FuncPipe, GenericEmbeddedListComponent, GenericFormBaseComponent, GenericFormComponent, GenericListComponent, GenericReactiveFormComponent, GenericService, GlobalRoles, Grid, GroupFilterPipe, HtmlControlTemplateDirective, IAbstractControl, Icon, ImageFileControlDirective, IpVersion, KeyValue, KeysPipe, LayoutToggle, LoadingScreenInterceptor, LoadingScreenService, MEDIA_PROVIDER, MEDIA_PROVIDER_FACTORY, MatFormFieldEditorDirective, MatFormFieldRadioDirective, MatFormFieldReadonlyDirective, MatInputRequiredDirective, MatSelectRequiredDirective, Menu, MenuClient, MenuDepartment, MenuFormIncludesResolve, MenuItem, MenuItemClient, MenuItemDepartment, MenuItemFormIncludesResolve, MenuItemService, MenuItemTarget, MenuListProjectionResolve, MenuResolve, MenuScope, MenuSettings, MenuSettingsResolve, MessageType, ModifiableEntity, MonthNamePipe, MsaEditFormActionsComponent, MsaEnumDisplayComponent, MsaSelectRequiredDirective, NameNumberProjection, NameProjection, NativeElementInjectorDirective, NumericValueType, OnlyNumberDirective, OrderPipe, Pagination, PaginatorIntl, ParseDecimalDirective, Permission, PlaceholderPipe, PrefixDirective, PrintService, PropertyJoinPipe, ReactiveFormConfig, ReactiveTypedFormsModule, RemoveWhitespaceDirective, ResetFormType, RxFormArray, RxFormBuilder, RxFormControl, RxFormControlDirective, RxFormGroup, RxReactiveFormsModule, RxwebFormDirective, RxwebValidators, SafeHtmlPipe, Salutation, SaveAction, SplitPipe, SubMenuResolve, SuffixButton, Table, TableColumn, TableColumnConfig, TableColumnType, TableConfig, TableDataSource, TableDefinition, TableQueryConfig, TableStaticDataSource, TaskDialogData, Templates, TimePipe, TitleCase, TitleProjection, TruncatePipe, TypedForm, TypedFormBuilder, UniqueValidatorDirective, UrlValidationType, Utils, ValidationAlphabetLocale, ValueAccessorBase, ValuesPipe, VdAlertDialogComponent, VdChipsComponent, VdCodeDirective, VdConfirmDialogComponent, VdCustomDirective, VdDelayedHoverDirective, VdDialogActionsDirective, VdDialogComponent, VdDialogContentDirective, VdDialogHeaderActionsComponent, VdDialogHeaderComponent, VdDialogMaximizeDirective, VdDialogService, VdDialogTitleDirective, VdDynamicMenuComponent, VdDynamicTableComponent, VdDynamicTableConfigDialogComponent, VdEditorDirective, VdFileDirective, VdFileInputComponent, VdFileModule, VdFilterOptionDirective, VdGenericFormComponent, VdGenericFormCustomFieldDirective, VdLayoutCardOverComponent, VdLayoutCloseDirective, VdLayoutCompactComponent, VdLayoutComponent, VdLayoutFooterComponent, VdLayoutManageListCloseDirective, VdLayoutManageListComponent, VdLayoutManageListOpenDirective, VdLayoutManageListToggleDirective, VdLayoutNavComponent, VdLayoutNavListCloseDirective, VdLayoutNavListComponent, VdLayoutNavListOpenDirective, VdLayoutNavListToggleDirective, VdLayoutOpenDirective, VdLayoutToggleDirective, VdListOptionDirective, VdListToolbarComponent, VdMediaService, VdMediaToggleDirective, VdMenuComponent, VdNavigationDrawerComponent, VdNavigationDrawerMenuDirective, VdNavigationDrawerToolbarDirective, VdPromptDialogComponent, VdSelectComponent, VdSelectOptionDirective, VdSelectTriggerDirective, VdTableFieldDirective, VdTaskDialogComponent, allOf, allOfAsync, alpha, alphaAsync, alphaNumeric, alphaNumericAsync, and, ascii, async, blacklist, choice, choiceAsync, compare, compose, contains, containsAsync, creditCard, creditCardAsync, cusip, custom, customAsync, dataUri, date, dateAsync, different, digit, disable, elementClass, email, endpointMetadataKey, endsWith, endsWithAsync, error, escape, even, extension, extensionAsync, factor, factorAsync, file, fileAsync, fileSize, fileSizeAsync, formDefinitionMetadataKey, formFieldGroupsMetadataKey, formFieldsMetadataKey, getDisplay, getEndpoint, getFormDefinition, getFormGroups, getTableDefinition, graphql, greaterThan, greaterThanAsync, greaterThanEqualTo, greaterThanEqualToAsync, grid, hasRequiredValidator, headerMetadataKey, hexColor, iban, ibanAsync, image, imageAsync, json, latLong, latitude, leapYear, lessThan, lessThanAsync, lessThanEqualTo, lessThanEqualToAsync, longitude, lowerCase, ltrim, mac, mask, maxDate, maxDateAsync, maxLength, maxLengthAsync, maxNumber, maxNumberAsync, maxTime, maxTimeAsync, minDate, minDateAsync, minLength, minLengthAsync, minNumber, minNumberAsync, minTime, minTimeAsync, mixinDisableRipple, mixinDisabled, model, noneOf, noneOfAsync, not, notEmpty, numeric, numericAsync, odd, oneOf, oneOfAsync, or, parseProjectionArray, parseProjectionString, password, passwordAsync, pattern, patternAsync, port, prefix, primeNumber, prop, propArray, propObject, range, rangeAsync, required, requiredTrue, rtrim, rule, sanitize, startsWith, startsWithAsync, stripLow, suffix, tableColumnsMetadataKey, tableDefinitionMetadataKey, time, timeAsync, toBoolean, toDate, toDouble, toFloat, toInt, toString, trim, unique, updateOn, upperCase, url, urlAsync, whitelist };
31342
+ export { AbstractMatFormField, AbstractSelectFormField, ActionItem, Api, ApiResponse, AppEvent, AppEventType, AppSetting, AppStorage, AsyncValidationDirective, AuditEntity, AuditUser, AuthHelper, AuthUser, AutofocusDirective, BaseComponent, BaseDirective, BaseEntity, BaseInterceptor, BaseService, BindPipe, CachingInterceptor, Column, ColumnObject, Common, CommonError, CommonHandlerContext, ConfirmExitGuard, ContextHelper, DIALOG_PROVIDER, DIALOG_PROVIDER_FACTORY, DataSourceFilterDirective, DataSourcePipe, DatePickerHeaderComponent, DisableControlDirective, Display, DisplayNameNumberProjection, DisplayNameProjection, DynamicBuilder, DynamicComponentCompiler, EXPORT_DIALOG_COMPONENT, EmptyStringResetDirective, EnumMetadata, EnumPipe, EnumService, EqualValidator, ErrorMessageBindingStrategy, EventQueueService, Facet, FacetValue, FieldFuncPipe, FileControlDirective, FileService, FileSizePipe, FilterClearComponent, FilterDateComponent, FilterGlue, FilterInputComponent, FilterOperator, FilterPipe, FilterSelectComponent, FirstLetterPipe, Form, FormArrayPipe, FormBuilderConfiguration, FormControlPipe, FormDefinition, FormField, FormFieldDefinition, FormFieldGroup, FormFieldGroupDefinition, FormFieldType, FormGroupPipe, FuncPipe, GenericEmbeddedListComponent, GenericFormBaseComponent, GenericFormComponent, GenericListComponent, GenericReactiveFormComponent, GenericService, GlobalRoles, Grid, GroupFilterPipe, HtmlControlTemplateDirective, IAbstractControl, Icon, ImageFileControlDirective, IpVersion, KeyValue, KeysPipe, LayoutToggle, LoadingScreenInterceptor, LoadingScreenService, MEDIA_PROVIDER, MEDIA_PROVIDER_FACTORY, MENU_RESOLVE_OPTIONS, MatFormFieldEditorDirective, MatFormFieldRadioDirective, MatFormFieldReadonlyDirective, MatInputRequiredDirective, MatSelectRequiredDirective, Menu, MenuClient, MenuDepartment, MenuFormIncludesResolve, MenuItem, MenuItemClient, MenuItemDepartment, MenuItemFormIncludesResolve, MenuItemService, MenuItemTarget, MenuListProjectionResolve, MenuResolve, MenuScope, MenuService, MenuSettings, MenuSettingsResolve, MessageType, ModifiableEntity, MonthNamePipe, MsaEditFormActionsComponent, MsaEnumDisplayComponent, MsaSelectRequiredDirective, MsaSelectionLabelComponent, NameNumberProjection, NameProjection, NativeElementInjectorDirective, NumericValueType, OnlyNumberDirective, OrderPipe, Pagination, PaginatorIntl, ParseDecimalDirective, Permission, PlaceholderPipe, PrefixDirective, PrintService, PropertyJoinPipe, ReactiveFormConfig, ReactiveTypedFormsModule, RemoveWhitespaceDirective, ResetFormType, RxFormArray, RxFormBuilder, RxFormControl, RxFormControlDirective, RxFormGroup, RxReactiveFormsModule, RxwebFormDirective, RxwebValidators, SafeHtmlPipe, Salutation, SaveAction, SplitPipe, SubMenuResolve, SuffixButton, TABLE_COLUMNS_METADATA_KEY, TABLE_DEFINITION_METADATA_KEY, Table, TableColumn, TableColumnConfig, TableColumnType, TableConfig, TableDataSource, TableDefinition, TableQueryConfig, TableStaticDataSource, TaskDialogData, Templates, TimePipe, TitleCase, TitleProjection, TruncatePipe, TypedForm, TypedFormBuilder, UniqueValidatorDirective, UrlValidationType, Utils, ValidationAlphabetLocale, ValueAccessorBase, ValuesPipe, VdAlertDialogComponent, VdChipsComponent, VdCodeDirective, VdConfirmDialogComponent, VdCustomDirective, VdDelayedHoverDirective, VdDialogActionsDirective, VdDialogComponent, VdDialogContentDirective, VdDialogHeaderActionsComponent, VdDialogHeaderComponent, VdDialogMaximizeDirective, VdDialogService, VdDialogTitleDirective, VdDynamicMenuComponent, VdDynamicTableComponent, VdDynamicTableConfigDialogComponent, VdEditorDirective, VdFileDirective, VdFileInputComponent, VdFileModule, VdFilterOptionDirective, VdGenericFormComponent, VdGenericFormCustomFieldDirective, VdLayoutCardOverComponent, VdLayoutCloseDirective, VdLayoutCompactComponent, VdLayoutComponent, VdLayoutFooterComponent, VdLayoutManageListCloseDirective, VdLayoutManageListComponent, VdLayoutManageListOpenDirective, VdLayoutManageListToggleDirective, VdLayoutNavComponent, VdLayoutNavListCloseDirective, VdLayoutNavListComponent, VdLayoutNavListOpenDirective, VdLayoutNavListToggleDirective, VdLayoutOpenDirective, VdLayoutToggleDirective, VdListOptionDirective, VdListToolbarComponent, VdMediaService, VdMediaToggleDirective, VdMenuComponent, VdNavigationDrawerComponent, VdNavigationDrawerMenuDirective, VdNavigationDrawerToolbarDirective, VdPromptDialogComponent, VdSelectComponent, VdSelectOptionDirective, VdSelectTriggerDirective, VdTableFieldDirective, VdTaskDialogComponent, allOf, allOfAsync, alpha, alphaAsync, alphaNumeric, alphaNumericAsync, and, ascii, async, blacklist, choice, choiceAsync, compare, compose, contains, containsAsync, creditCard, creditCardAsync, cusip, custom, customAsync, dataUri, date, dateAsync, different, digit, disable, elementClass, email, endpointMetadataKey, endsWith, endsWithAsync, error, escape, even, extension, extensionAsync, factor, factorAsync, file, fileAsync, fileSize, fileSizeAsync, formDefinitionMetadataKey, formFieldGroupsMetadataKey, formFieldsMetadataKey, getDisplay, getEndpoint, getFormDefinition, getFormGroups, getTableDefinition, graphql, greaterThan, greaterThanAsync, greaterThanEqualTo, greaterThanEqualToAsync, grid, hasRequiredValidator, headerMetadataKey, hexColor, iban, ibanAsync, image, imageAsync, json, latLong, latitude, leapYear, lessThan, lessThanAsync, lessThanEqualTo, lessThanEqualToAsync, longitude, lowerCase, ltrim, mac, mask, maxDate, maxDateAsync, maxLength, maxLengthAsync, maxNumber, maxNumberAsync, maxTime, maxTimeAsync, minDate, minDateAsync, minLength, minLengthAsync, minNumber, minNumberAsync, minTime, minTimeAsync, mixinDisableRipple, mixinDisabled, model, noneOf, noneOfAsync, not, notEmpty, numeric, numericAsync, odd, oneOf, oneOfAsync, or, parseProjectionArray, parseProjectionString, password, passwordAsync, pattern, patternAsync, port, prefix, primeNumber, prop, propArray, propObject, range, rangeAsync, required, requiredTrue, rtrim, rule, sanitize, startsWith, startsWithAsync, stripLow, suffix, time, timeAsync, toBoolean, toDate, toDouble, toFloat, toInt, toString, trim, unique, updateOn, upperCase, url, urlAsync, whitelist };
31236
31343
  //# sourceMappingURL=messaia-cdk.mjs.map