@masterteam/components 0.0.162 → 0.0.164

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.
Files changed (32) hide show
  1. package/assets/common.css +1 -1
  2. package/assets/i18n/ar.json +24 -0
  3. package/assets/i18n/en.json +24 -0
  4. package/fesm2022/masterteam-components-business-fields.mjs +290 -90
  5. package/fesm2022/masterteam-components-business-fields.mjs.map +1 -1
  6. package/fesm2022/masterteam-components-color-picker-field.mjs +11 -3
  7. package/fesm2022/masterteam-components-color-picker-field.mjs.map +1 -1
  8. package/fesm2022/masterteam-components-entities.mjs +3 -2
  9. package/fesm2022/masterteam-components-entities.mjs.map +1 -1
  10. package/fesm2022/masterteam-components-field-validation.mjs +19 -18
  11. package/fesm2022/masterteam-components-field-validation.mjs.map +1 -1
  12. package/fesm2022/masterteam-components-sidebar.mjs +2 -2
  13. package/fesm2022/masterteam-components-sidebar.mjs.map +1 -1
  14. package/fesm2022/masterteam-components-table.mjs +1 -11
  15. package/fesm2022/masterteam-components-table.mjs.map +1 -1
  16. package/fesm2022/masterteam-components-text-field.mjs +21 -26
  17. package/fesm2022/masterteam-components-text-field.mjs.map +1 -1
  18. package/fesm2022/masterteam-components-toast.mjs +28 -23
  19. package/fesm2022/masterteam-components-toast.mjs.map +1 -1
  20. package/fesm2022/masterteam-components-topbar.mjs +2 -2
  21. package/fesm2022/masterteam-components-topbar.mjs.map +1 -1
  22. package/fesm2022/masterteam-components-user-search-field.mjs +7 -3
  23. package/fesm2022/masterteam-components-user-search-field.mjs.map +1 -1
  24. package/fesm2022/masterteam-components.mjs +1 -1
  25. package/fesm2022/masterteam-components.mjs.map +1 -1
  26. package/package.json +2 -2
  27. package/types/masterteam-components-business-fields.d.ts +67 -21
  28. package/types/masterteam-components-entities.d.ts +1 -0
  29. package/types/masterteam-components-text-field.d.ts +11 -2
  30. package/types/masterteam-components-toast.d.ts +1 -0
  31. package/types/masterteam-components-user-search-field.d.ts +2 -0
  32. package/types/masterteam-components.d.ts +7 -5
@@ -1,17 +1,17 @@
1
1
  import * as i1 from '@angular/common';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { input, inject, DestroyRef, signal, computed, ChangeDetectionStrategy, Component, effect, untracked, viewChild, linkedSignal } from '@angular/core';
4
+ import { input, inject, DestroyRef, signal, computed, ChangeDetectionStrategy, Component, effect, untracked, viewChild, linkedSignal, InjectionToken } from '@angular/core';
5
5
  import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
6
6
  import * as i1$1 from '@angular/forms';
7
7
  import { ControlContainer, Validators, NgControl, FormsModule } from '@angular/forms';
8
- import { startWith, finalize, catchError, of } from 'rxjs';
8
+ import { startWith, finalize, catchError, of, take } from 'rxjs';
9
9
  import { Tooltip } from '@masterteam/components/tooltip';
10
10
  import { Icon } from '@masterteam/icons';
11
11
  import { SelectField } from '@masterteam/components/select-field';
12
12
  import { MultiSelectField } from '@masterteam/components/multi-select-field';
13
13
  import { FieldValidation } from '@masterteam/components/field-validation';
14
- import { HttpClient, HttpParams } from '@angular/common/http';
14
+ import { HttpClient } from '@angular/common/http';
15
15
  import * as i2 from '@jsverse/transloco';
16
16
  import { TranslocoService, TranslocoModule } from '@jsverse/transloco';
17
17
  import { Button } from '@masterteam/components/button';
@@ -19,7 +19,7 @@ import { NumberField } from '@masterteam/components/number-field';
19
19
  import { Table } from '@masterteam/components/table';
20
20
  import { Skeleton } from 'primeng/skeleton';
21
21
  import { Message } from 'primeng/message';
22
- import { Card } from '@masterteam/components/card';
22
+ import { ModalService } from '@masterteam/components/modal';
23
23
 
24
24
  class LookupMatrixField {
25
25
  config = input.required(...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
@@ -352,13 +352,13 @@ class SchemaConnectionField {
352
352
  this.disabled.set(disabled);
353
353
  }
354
354
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SchemaConnectionField, deps: [], target: i0.ɵɵFactoryTarget.Component });
355
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: SchemaConnectionField, isStandalone: true, selector: "mt-schema-connection-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, configuration: { classPropertyName: "configuration", publicName: "configuration", isSignal: true, isRequired: true, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "grid gap-1" }, ngImport: i0, template: "<!-- @if (label()) {\r\n <label\r\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\r\n [for]=\"ngControl?.name || label()\"\r\n >\r\n {{ label() }}\r\n </label>\r\n} -->\r\n\r\n<div class=\"flex gap-4 w-full\">\r\n @for (state of sourceLevelStates(); track getSourceId(state.source)) {\r\n <div [style.width]=\"dropdownWidth()\" class=\"min-w-0\">\r\n @if (sourceLevelStates().length > 1) {\r\n <span class=\"text-sm text-muted-color mb-1 block truncate\">\r\n {{\r\n state.source.name?.en ||\r\n state.source.levelKey ||\r\n state.source.moduleKey\r\n }}\r\n </span>\r\n }\r\n\r\n @if (state.source.allowManyToMany) {\r\n <mt-multi-select-field\r\n [field]=\"false\"\r\n [(ngModel)]=\"selections[getSourceId(state.source)]\"\r\n (ngModelChange)=\"syncValue()\"\r\n [options]=\"state.options\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"placeholder() || state.source.name?.en || 'Select...'\"\r\n [readonly]=\"disabled() || readonly()\"\r\n [filter]=\"filter()\"\r\n [showClear]=\"true\"\r\n display=\"chip\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [field]=\"false\"\r\n [(ngModel)]=\"selections[getSourceId(state.source)]\"\r\n (ngModelChange)=\"syncValue()\"\r\n [options]=\"state.options\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"placeholder() || state.source.name?.en || 'Select...'\"\r\n [readonly]=\"disabled() || readonly()\"\r\n [filter]=\"filter()\"\r\n [loading]=\"state.loading\"\r\n [showClear]=\"true\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n\r\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: FieldValidation, selector: "mt-field-validation", inputs: ["control", "touched"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
355
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: SchemaConnectionField, isStandalone: true, selector: "mt-schema-connection-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, configuration: { classPropertyName: "configuration", publicName: "configuration", isSignal: true, isRequired: true, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "grid gap-1" }, ngImport: i0, template: "<!-- @if (label()) {\r\n <label\r\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\r\n [for]=\"ngControl?.name || label()\"\r\n >\r\n {{ label() }}\r\n </label>\r\n} -->\r\n\r\n<div class=\"flex gap-4 w-full\">\r\n @for (state of sourceLevelStates(); track getSourceId(state.source)) {\r\n <div [style.width]=\"dropdownWidth()\" class=\"min-w-0\">\r\n @if (sourceLevelStates().length > 0) {\r\n <span class=\"text-sm text-muted-color mb-1 block truncate\">\r\n {{\r\n state.source.name?.en ||\r\n state.source.levelKey ||\r\n state.source.moduleKey\r\n }}\r\n </span>\r\n }\r\n\r\n @if (state.source.allowManyToMany) {\r\n <mt-multi-select-field\r\n [field]=\"false\"\r\n [(ngModel)]=\"selections[getSourceId(state.source)]\"\r\n (ngModelChange)=\"syncValue()\"\r\n [options]=\"state.options\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"placeholder() || state.source.name?.en || 'Select...'\"\r\n [readonly]=\"disabled() || readonly()\"\r\n [filter]=\"filter()\"\r\n [showClear]=\"true\"\r\n display=\"chip\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [field]=\"false\"\r\n [(ngModel)]=\"selections[getSourceId(state.source)]\"\r\n (ngModelChange)=\"syncValue()\"\r\n [options]=\"state.options\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"placeholder() || state.source.name?.en || 'Select...'\"\r\n [readonly]=\"disabled() || readonly()\"\r\n [filter]=\"filter()\"\r\n [loading]=\"state.loading\"\r\n [showClear]=\"true\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n\r\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: FieldValidation, selector: "mt-field-validation", inputs: ["control", "touched"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
356
356
  }
357
357
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SchemaConnectionField, decorators: [{
358
358
  type: Component,
359
359
  args: [{ selector: 'mt-schema-connection-field', standalone: true, imports: [FormsModule, SelectField, MultiSelectField, FieldValidation], changeDetection: ChangeDetectionStrategy.OnPush, host: {
360
360
  class: 'grid gap-1',
361
- }, template: "<!-- @if (label()) {\r\n <label\r\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\r\n [for]=\"ngControl?.name || label()\"\r\n >\r\n {{ label() }}\r\n </label>\r\n} -->\r\n\r\n<div class=\"flex gap-4 w-full\">\r\n @for (state of sourceLevelStates(); track getSourceId(state.source)) {\r\n <div [style.width]=\"dropdownWidth()\" class=\"min-w-0\">\r\n @if (sourceLevelStates().length > 1) {\r\n <span class=\"text-sm text-muted-color mb-1 block truncate\">\r\n {{\r\n state.source.name?.en ||\r\n state.source.levelKey ||\r\n state.source.moduleKey\r\n }}\r\n </span>\r\n }\r\n\r\n @if (state.source.allowManyToMany) {\r\n <mt-multi-select-field\r\n [field]=\"false\"\r\n [(ngModel)]=\"selections[getSourceId(state.source)]\"\r\n (ngModelChange)=\"syncValue()\"\r\n [options]=\"state.options\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"placeholder() || state.source.name?.en || 'Select...'\"\r\n [readonly]=\"disabled() || readonly()\"\r\n [filter]=\"filter()\"\r\n [showClear]=\"true\"\r\n display=\"chip\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [field]=\"false\"\r\n [(ngModel)]=\"selections[getSourceId(state.source)]\"\r\n (ngModelChange)=\"syncValue()\"\r\n [options]=\"state.options\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"placeholder() || state.source.name?.en || 'Select...'\"\r\n [readonly]=\"disabled() || readonly()\"\r\n [filter]=\"filter()\"\r\n [loading]=\"state.loading\"\r\n [showClear]=\"true\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n\r\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\r\n" }]
361
+ }, template: "<!-- @if (label()) {\r\n <label\r\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\r\n [for]=\"ngControl?.name || label()\"\r\n >\r\n {{ label() }}\r\n </label>\r\n} -->\r\n\r\n<div class=\"flex gap-4 w-full\">\r\n @for (state of sourceLevelStates(); track getSourceId(state.source)) {\r\n <div [style.width]=\"dropdownWidth()\" class=\"min-w-0\">\r\n @if (sourceLevelStates().length > 0) {\r\n <span class=\"text-sm text-muted-color mb-1 block truncate\">\r\n {{\r\n state.source.name?.en ||\r\n state.source.levelKey ||\r\n state.source.moduleKey\r\n }}\r\n </span>\r\n }\r\n\r\n @if (state.source.allowManyToMany) {\r\n <mt-multi-select-field\r\n [field]=\"false\"\r\n [(ngModel)]=\"selections[getSourceId(state.source)]\"\r\n (ngModelChange)=\"syncValue()\"\r\n [options]=\"state.options\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"placeholder() || state.source.name?.en || 'Select...'\"\r\n [readonly]=\"disabled() || readonly()\"\r\n [filter]=\"filter()\"\r\n [showClear]=\"true\"\r\n display=\"chip\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n [field]=\"false\"\r\n [(ngModel)]=\"selections[getSourceId(state.source)]\"\r\n (ngModelChange)=\"syncValue()\"\r\n [options]=\"state.options\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"placeholder() || state.source.name?.en || 'Select...'\"\r\n [readonly]=\"disabled() || readonly()\"\r\n [filter]=\"filter()\"\r\n [loading]=\"state.loading\"\r\n [showClear]=\"true\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n\r\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\r\n" }]
362
362
  }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], configuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "configuration", required: true }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }] } });
363
363
 
364
364
  const PREDECESSOR_TYPE_BY_TOKEN = {
@@ -612,72 +612,126 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
612
612
  }, template: "@if (label()) {\r\n <label\r\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\r\n [for]=\"ngControl?.name || label()\"\r\n >\r\n {{ label() }}\r\n </label>\r\n}\r\n\r\n<div class=\"grid gap-3\">\r\n <div class=\"flex items-center justify-end\">\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"'components.schedulePredecessorField.add' | transloco\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n [disabled]=\"disabled() || readonly() || !canAddRow()\"\r\n [tooltip]=\"addTooltip()\"\r\n (onClick)=\"addRow()\"\r\n />\r\n </div>\r\n\r\n <ng-template #predecessorCellTpl let-row>\r\n <mt-select-field\r\n [field]=\"false\"\r\n [options]=\"availableTaskOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"\r\n placeholder() ||\r\n ('components.schedulePredecessorField.selectPredecessor' | transloco)\r\n \"\r\n [filter]=\"true\"\r\n [showClear]=\"true\"\r\n [loading]=\"loading()\"\r\n [readonly]=\"disabled() || readonly()\"\r\n [ngModel]=\"row.predecessorId || undefined\"\r\n (onChange)=\"updateRow(row.key, { predecessorId: $event ?? '' })\"\r\n />\r\n </ng-template>\r\n\r\n <ng-template #typeCellTpl let-row>\r\n <mt-select-field\r\n [field]=\"false\"\r\n [options]=\"typeOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [readonly]=\"disabled() || readonly()\"\r\n [ngModel]=\"row.type\"\r\n (onChange)=\"updateRow(row.key, { type: $event ?? 0 })\"\r\n />\r\n </ng-template>\r\n\r\n <ng-template #lagCellTpl let-row>\r\n <mt-number-field\r\n [field]=\"false\"\r\n [useGrouping]=\"false\"\r\n [placeholder]=\"'components.schedulePredecessorField.lagDays' | transloco\"\r\n [readonly]=\"disabled() || readonly()\"\r\n [ngModel]=\"row.lagDays\"\r\n (ngModelChange)=\"updateRow(row.key, { lagDays: $event ?? 0 })\"\r\n />\r\n </ng-template>\r\n\r\n <mt-table\r\n [data]=\"rows()\"\r\n [columns]=\"columns()\"\r\n [rowActions]=\"rowActions()\"\r\n [pageSize]=\"pageSize()\"\r\n [generalSearch]=\"false\"\r\n [showFilters]=\"false\"\r\n [dataKey]=\"'key'\"\r\n storageKey=\"schedule-predecessor-field-table\"\r\n [loading]=\"loading()\"\r\n >\r\n <ng-template #empty>\r\n <div\r\n class=\"rounded-xl border border-dashed border-surface px-4 py-5 text-sm text-muted-color\"\r\n >\r\n {{ \"components.schedulePredecessorField.empty\" | transloco }}\r\n </div>\r\n </ng-template>\r\n </mt-table>\r\n</div>\r\n\r\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\r\n" }]
613
613
  }], ctorParameters: () => [], propDecorators: { predecessorCellTpl: [{ type: i0.ViewChild, args: ['predecessorCellTpl', { isSignal: true }] }], typeCellTpl: [{ type: i0.ViewChild, args: ['typeCellTpl', { isSignal: true }] }], lagCellTpl: [{ type: i0.ViewChild, args: ['lagCellTpl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], configuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "configuration", required: false }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }] } });
614
614
 
615
+ /**
616
+ * Token used by `mt-entity-list-field` (Write mode) to open the rich add-row
617
+ * dialog backed by `@masterteam/forms`'s `mt-client-form`. Apps that want this
618
+ * behavior should call `provideEntityListAddForm()` from
619
+ * `@masterteam/forms/entity-list-add-form` in their app providers. When the
620
+ * token is not registered, the field falls back to a minimal text-only popup.
621
+ */
622
+ const ENTITY_LIST_ADD_DIALOG_COMPONENT = new InjectionToken('ENTITY_LIST_ADD_DIALOG_COMPONENT');
623
+
624
+ const UNSORTABLE_ENTITY_VIEW_TYPES = new Set([
625
+ 'Attachment',
626
+ 'Checkbox',
627
+ ]);
615
628
  class EntityListField {
616
629
  // Inputs
617
630
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
618
631
  readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
619
632
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
620
- /** EntityList property id used in the read endpoint route. */
633
+ /** EntityList property id (kept for back-compat; unused by fetch/query). */
621
634
  propertyId = input(null, ...(ngDevMode ? [{ debugName: "propertyId" }] : /* istanbul ignore next */ []));
622
- /** Property configuration (sourceType, moduleId, access, etc). */
635
+ /** Property configuration (sourceType, moduleId, access, readFields, etc). */
623
636
  configuration = input(null, ...(ngDevMode ? [{ debugName: "configuration" }] : /* istanbul ignore next */ []));
624
637
  /** Runtime ids needed to call the read endpoint. */
625
638
  runtimeContext = input(null, ...(ngDevMode ? [{ debugName: "runtimeContext" }] : /* istanbul ignore next */ []));
626
- /** Optional HttpContext (e.g. to disable base URL prefixing). */
639
+ /** Optional HttpContext (kept for back-compat). */
627
640
  context = input(undefined, ...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
628
641
  // CVA state — pass-through value (EntityList stored JSON shape).
629
642
  storedValue = signal(null, ...(ngDevMode ? [{ debugName: "storedValue" }] : /* istanbul ignore next */ []));
630
- // Loaded rows from the read endpoint.
643
+ // Loaded table state.
644
+ columns = signal([], ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
631
645
  rows = signal([], ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
632
646
  loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
633
647
  errorMessage = signal(null, ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
634
648
  disabled = signal(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
635
649
  requiredValidator = Validators.required;
636
650
  ngControl = null;
637
- sourceId = computed(() => {
638
- const ctx = this.runtimeContext();
639
- const raw = ctx?.sourceId ?? ctx?.levelDataId ?? null;
640
- if (raw == null || raw === '' || raw === 0)
641
- return null;
642
- const id = typeof raw === 'string' ? Number(raw) : raw;
643
- return Number.isFinite(id) && id > 0 ? id : null;
644
- }, ...(ngDevMode ? [{ debugName: "sourceId" }] : /* istanbul ignore next */ []));
645
- levelDataIdParam = computed(() => {
651
+ levelId = computed(() => {
652
+ const raw = this.runtimeContext()?.levelId ?? null;
653
+ return raw == null || raw === '' ? null : raw;
654
+ }, ...(ngDevMode ? [{ debugName: "levelId" }] : /* istanbul ignore next */ []));
655
+ levelDataId = computed(() => {
646
656
  const raw = this.runtimeContext()?.levelDataId ?? null;
647
- if (raw == null || raw === '' || raw === 0)
648
- return null;
649
- const id = typeof raw === 'string' ? Number(raw) : raw;
650
- return Number.isFinite(id) && id > 0 ? id : null;
651
- }, ...(ngDevMode ? [{ debugName: "levelDataIdParam" }] : /* istanbul ignore next */ []));
657
+ return raw == null || raw === '' ? null : raw;
658
+ }, ...(ngDevMode ? [{ debugName: "levelDataId" }] : /* istanbul ignore next */ []));
659
+ moduleId = computed(() => {
660
+ const raw = this.configuration()
661
+ ?.moduleId;
662
+ return raw == null || raw === '' ? null : raw;
663
+ }, ...(ngDevMode ? [{ debugName: "moduleId" }] : /* istanbul ignore next */ []));
664
+ readFields = computed(() => {
665
+ const raw = this.configuration()
666
+ ?.readFields;
667
+ if (!Array.isArray(raw))
668
+ return [];
669
+ return raw.filter((f) => typeof f === 'string' && f.length > 0);
670
+ }, ...(ngDevMode ? [{ debugName: "readFields" }] : /* istanbul ignore next */ []));
652
671
  canRead = computed(() => {
653
672
  const access = String(this.configuration()?.access ?? 'Auto');
654
673
  return access !== 'Write' && access !== 'None';
655
674
  }, ...(ngDevMode ? [{ debugName: "canRead" }] : /* istanbul ignore next */ []));
656
- hasRows = computed(() => this.rows().length > 0, ...(ngDevMode ? [{ debugName: "hasRows" }] : /* istanbul ignore next */ []));
675
+ canWrite = computed(() => {
676
+ const access = String(this.configuration()?.access ?? 'Auto');
677
+ return access === 'Write';
678
+ }, ...(ngDevMode ? [{ debugName: "canWrite" }] : /* istanbul ignore next */ []));
679
+ writeFields = computed(() => {
680
+ const raw = this.configuration()
681
+ ?.writeFields;
682
+ if (!Array.isArray(raw))
683
+ return [];
684
+ return raw.filter((f) => typeof f === 'string' && f.length > 0);
685
+ }, ...(ngDevMode ? [{ debugName: "writeFields" }] : /* istanbul ignore next */ []));
686
+ /** Locally-added rows (Write mode). Persisted via CVA value. */
687
+ localRows = signal([], ...(ngDevMode ? [{ debugName: "localRows" }] : /* istanbul ignore next */ []));
688
+ localRowSeq = 0;
689
+ displayRows = computed(() => this.canWrite() ? this.localRows() : this.rows(), ...(ngDevMode ? [{ debugName: "displayRows" }] : /* istanbul ignore next */ []));
690
+ hasRows = computed(() => this.displayRows().length > 0, ...(ngDevMode ? [{ debugName: "hasRows" }] : /* istanbul ignore next */ []));
691
+ hasRequiredContext = computed(() => this.levelId() != null &&
692
+ this.levelDataId() != null &&
693
+ this.moduleId() != null &&
694
+ this.readFields().length > 0, ...(ngDevMode ? [{ debugName: "hasRequiredContext" }] : /* istanbul ignore next */ []));
657
695
  onTouched = () => { };
658
696
  onModelChange = () => { };
659
697
  http = inject(HttpClient);
660
698
  destroyRef = inject(DestroyRef);
699
+ modal = inject(ModalService);
700
+ /**
701
+ * Optional rich add-row dialog (provided by `@masterteam/forms` via
702
+ * `provideEntityListAddForm()`). When available, used instead of the local
703
+ * minimal dialog so the popup renders `mt-client-form` filtered by
704
+ * `writeFields`.
705
+ */
706
+ addDialogComponent = inject(ENTITY_LIST_ADD_DIALOG_COMPONENT, { optional: true });
661
707
  constructor() {
662
708
  this.ngControl = inject(NgControl, { self: true, optional: true });
663
709
  if (this.ngControl) {
664
710
  this.ngControl.valueAccessor = this;
665
711
  }
666
- // Trigger fetch when source/property/value change.
712
+ // Trigger fetch when context inputs change. Always fetch columns from
713
+ // /api/fetch/query (both Read and Write modes); rows are ignored in Write
714
+ // mode and replaced by locally-added rows.
667
715
  effect(() => {
668
- const sourceId = this.sourceId();
669
- const propertyId = this.propertyId();
670
- const allowed = this.canRead();
671
- const stored = this.storedValue();
672
- const levelDataId = this.levelDataIdParam();
716
+ const allowedRead = this.canRead();
717
+ const allowedWrite = this.canWrite();
718
+ const ready = this.hasRequiredContext();
719
+ const levelId = this.levelId();
720
+ const levelDataId = this.levelDataId();
721
+ const moduleId = this.moduleId();
722
+ const readFields = this.readFields();
673
723
  untracked(() => {
674
- if (!allowed || !sourceId || !propertyId) {
724
+ if ((!allowedRead && !allowedWrite) ||
725
+ !ready ||
726
+ levelId == null ||
727
+ levelDataId == null ||
728
+ moduleId == null) {
729
+ this.columns.set([]);
675
730
  this.rows.set([]);
676
731
  this.errorMessage.set(null);
677
732
  return;
678
733
  }
679
- const selectedIds = (stored?.entityIds ?? []).filter((n) => typeof n === 'number' && n > 0);
680
- this.fetchRows(sourceId, propertyId, levelDataId, selectedIds);
734
+ this.fetchRows(levelId, levelDataId, moduleId, readFields);
681
735
  });
682
736
  });
683
737
  }
@@ -686,6 +740,12 @@ class EntityListField {
686
740
  // ============================================================================
687
741
  writeValue(value) {
688
742
  this.storedValue.set(value ?? null);
743
+ const rows = Array.isArray(value?.rows)
744
+ ? value.rows
745
+ : [];
746
+ // Re-hydrate local rows if a value is written (e.g. form reset / patch).
747
+ this.localRows.set(rows);
748
+ this.localRowSeq = rows.length;
689
749
  }
690
750
  registerOnChange(fn) {
691
751
  this.onModelChange = fn;
@@ -697,84 +757,224 @@ class EntityListField {
697
757
  this.disabled.set(isDisabled);
698
758
  }
699
759
  // ============================================================================
700
- // Read endpoint
760
+ // Write mode — Add row dialog
761
+ // ============================================================================
762
+ /** Row actions shown in Write mode — edit and delete (local-only). */
763
+ writeRowActions = computed(() => [
764
+ {
765
+ icon: 'custom.pencil',
766
+ tooltip: 'Edit',
767
+ action: (row) => this.openEditDialog(row),
768
+ },
769
+ {
770
+ icon: 'general.trash-01',
771
+ tooltip: 'Delete',
772
+ color: 'danger',
773
+ confirmation: {
774
+ type: 'popup',
775
+ confirmationType: 'delete',
776
+ },
777
+ action: (row) => this.deleteLocalRow(row),
778
+ },
779
+ ], ...(ngDevMode ? [{ debugName: "writeRowActions" }] : /* istanbul ignore next */ []));
780
+ openAddDialog() {
781
+ if (this.disabled())
782
+ return;
783
+ const component = this.addDialogComponent;
784
+ if (!component)
785
+ return;
786
+ const ref = this.modal.openModal(component, 'dialog', {
787
+ header: 'Add',
788
+ styleClass: '!w-[48rem] max-w-[96vw]',
789
+ dismissableMask: true,
790
+ inputValues: {
791
+ moduleId: this.moduleId(),
792
+ levelId: this.levelId(),
793
+ levelDataId: this.levelDataId(),
794
+ writeFields: this.writeFields(),
795
+ },
796
+ });
797
+ ref.onClose.pipe(take(1)).subscribe((result) => {
798
+ if (!result || typeof result !== 'object')
799
+ return;
800
+ const values = result;
801
+ this.localRowSeq += 1;
802
+ const newRow = this.buildRowFromValues(`local-${this.localRowSeq}`, values);
803
+ const next = [...this.localRows(), newRow];
804
+ this.localRows.set(next);
805
+ this.emitLocalValue(next);
806
+ });
807
+ }
808
+ openEditDialog(row) {
809
+ if (this.disabled())
810
+ return;
811
+ const component = this.addDialogComponent;
812
+ if (!component)
813
+ return;
814
+ const originalValues = row['__values'] ?? {};
815
+ const ref = this.modal.openModal(component, 'dialog', {
816
+ header: 'Edit',
817
+ styleClass: '!w-[48rem] max-w-[96vw]',
818
+ dismissableMask: true,
819
+ inputValues: {
820
+ moduleId: this.moduleId(),
821
+ levelId: this.levelId(),
822
+ levelDataId: this.levelDataId(),
823
+ writeFields: this.writeFields(),
824
+ initialValues: originalValues,
825
+ },
826
+ });
827
+ ref.onClose.pipe(take(1)).subscribe((result) => {
828
+ if (!result || typeof result !== 'object')
829
+ return;
830
+ const values = result;
831
+ const rowId = row['Id'];
832
+ const updatedRow = this.buildRowFromValues(rowId, values);
833
+ const next = this.localRows().map((r) => r['Id'] === rowId ? updatedRow : r);
834
+ this.localRows.set(next);
835
+ this.emitLocalValue(next);
836
+ });
837
+ }
838
+ deleteLocalRow(row) {
839
+ const rowId = row['Id'];
840
+ const next = this.localRows().filter((r) => r['Id'] !== rowId);
841
+ this.localRows.set(next);
842
+ this.emitLocalValue(next);
843
+ }
844
+ buildRowFromValues(id, values) {
845
+ const row = { Id: id, __values: values };
846
+ for (const column of this.columns()) {
847
+ // Form values are keyed by catalog property key (e.g. "task_name"),
848
+ // but column.key is the normalizedKey (e.g. "Name"). Use propertyKey
849
+ // for the lookup so the value is found.
850
+ const raw = values[column.propertyKey ?? column.key];
851
+ row[column.key] = {
852
+ name: column.label ?? column.key,
853
+ key: column.key,
854
+ viewType: column.viewType ?? 'Text',
855
+ value: raw ?? '',
856
+ rawValue: raw ?? null,
857
+ };
858
+ }
859
+ return row;
860
+ }
861
+ emitLocalValue(rows) {
862
+ const current = this.storedValue();
863
+ const next = { ...(current ?? {}), rows };
864
+ this.storedValue.set(next);
865
+ this.onModelChange(next);
866
+ this.onTouched();
867
+ }
868
+ // ============================================================================
869
+ // Read endpoint — POST /api/fetch/query (Table projection)
701
870
  // ============================================================================
702
- fetchRows(sourceId, propertyId, levelDataId, selectedIds) {
871
+ fetchRows(levelId, levelDataId, moduleId, propertyKeys) {
703
872
  this.loading.set(true);
704
873
  this.errorMessage.set(null);
705
874
  const ctx = this.context();
706
- const url = `Properties/${sourceId}/${propertyId}/entitylistvalues`;
707
- let params = new HttpParams();
708
- if (levelDataId && levelDataId !== sourceId) {
709
- params = params.set('levelDataId', String(levelDataId));
710
- }
711
- if (selectedIds.length > 0) {
712
- params = params.set('selectedValues', selectedIds.join(','));
713
- }
875
+ const body = {
876
+ contextKey: `level:${levelId}/module:${moduleId}`,
877
+ projection: 'Table',
878
+ surfaceKey: 'table',
879
+ propertyKeys,
880
+ filters: [
881
+ {
882
+ key: 'levelDataId',
883
+ operator: 'Equals',
884
+ value: String(levelDataId),
885
+ },
886
+ ],
887
+ page: 1,
888
+ pageSize: 3000,
889
+ };
714
890
  this.http
715
- .get(url, {
716
- params,
717
- ...(ctx ? { context: ctx } : {}),
718
- })
891
+ .post('fetch/query', body, ctx ? { context: ctx } : {})
719
892
  .pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.loading.set(false)), catchError((err) => {
720
- console.error('EntityList read failed', err);
893
+ console.error('EntityList fetch/query failed', err);
721
894
  this.errorMessage.set('Failed to load related items');
722
- return of([]);
895
+ return of({});
723
896
  }))
724
897
  .subscribe((response) => {
725
- const data = Array.isArray(response)
726
- ? response
727
- : (response?.data ?? []);
728
- this.rows.set(Array.isArray(data) ? data : []);
898
+ const payload = response && typeof response === 'object' && 'data' in response
899
+ ? (response.data ?? response)
900
+ : response;
901
+ this.applyResponse(payload);
729
902
  });
730
903
  }
731
- // ============================================================================
732
- // Display helpers
733
- // ============================================================================
734
- rowTitle(row) {
735
- const values = row.values ?? [];
736
- // Prefer common name-like keys, otherwise first non-empty value.
737
- const preferredKeys = ['name', 'title', 'displayName'];
738
- for (const key of preferredKeys) {
739
- const match = values.find((v) => (v.propertyKey ?? '').toLowerCase() === key);
740
- const value = match?.rawValue ?? match?.value;
741
- if (value != null && value !== '')
742
- return String(value);
904
+ applyResponse(response) {
905
+ // Build property maps first so column defs can include the propertyKey
906
+ // mapping (normalizedKey → catalog key) needed for Write-mode row lookup.
907
+ const propertyByKey = new Map();
908
+ const propertyByNormalizedKey = new Map();
909
+ for (const property of response.catalog?.properties ?? []) {
910
+ propertyByKey.set(property.key, property);
911
+ propertyByNormalizedKey.set(property.normalizedKey, property);
743
912
  }
744
- const firstWithValue = values.find((v) => (v.rawValue ?? v.value) != null && (v.rawValue ?? v.value) !== '');
745
- const fallback = firstWithValue?.rawValue ?? firstWithValue?.value;
746
- return fallback != null
747
- ? String(fallback)
748
- : `#${row.entityId ?? ''}`.trim();
749
- }
750
- rowFields(row) {
751
- return (row.values ?? []).filter((v) => (v.rawValue ?? v.value) != null && (v.rawValue ?? v.value) !== '');
752
- }
753
- trackByRow(_i, row) {
754
- return row.entityId ?? _i;
755
- }
756
- trackByField(_i, value) {
757
- return value.propertyKey ?? value.propertyId ?? _i;
913
+ const columns = (response.projectionMeta?.columns ?? [])
914
+ .filter((column) => column.visible)
915
+ .sort((a, b) => a.order - b.order)
916
+ .map((column) => ({
917
+ key: column.key,
918
+ label: column.label,
919
+ type: 'entity',
920
+ sortable: !UNSORTABLE_ENTITY_VIEW_TYPES.has(column.viewType),
921
+ viewType: column.viewType,
922
+ order: column.order,
923
+ visible: column.visible,
924
+ configuration: column.configuration ?? null,
925
+ // Store the catalog property key so Write-mode buildRowFromValues can
926
+ // look up form values keyed by property key (e.g. "task_name") rather
927
+ // than the normalizedKey used as the column display key (e.g. "Name").
928
+ propertyKey: propertyByNormalizedKey.get(column.key)?.key ?? column.key,
929
+ }));
930
+ this.columns.set(columns);
931
+ // In Write mode the table is filled locally — ignore server records.
932
+ if (this.canWrite()) {
933
+ this.rows.set([]);
934
+ return;
935
+ }
936
+ const rows = (response.records ?? []).map((record) => {
937
+ const row = { Id: record.id };
938
+ for (const column of columns) {
939
+ const property = propertyByKey.get(column.key) ??
940
+ propertyByNormalizedKey.get(column.key);
941
+ const cell = record.values?.[property?.key ?? column.key];
942
+ row[column.key] = this.toEntityData(column, cell, property, record.id);
943
+ }
944
+ return row;
945
+ });
946
+ this.rows.set(rows);
758
947
  }
759
- formatValue(value) {
760
- const raw = value.rawValue ?? value.value;
761
- if (raw == null)
762
- return '';
763
- if (typeof raw === 'object')
764
- return JSON.stringify(raw);
765
- return String(raw);
948
+ toEntityData(column, cell, property, recordId) {
949
+ return {
950
+ id: recordId,
951
+ propertyId: property?.id,
952
+ key: property?.key ?? column.key,
953
+ normalizedKey: property?.normalizedKey ?? column.key,
954
+ name: column.label ?? property?.label ?? column.key,
955
+ rawValue: cell?.raw === null || cell?.raw === undefined
956
+ ? undefined
957
+ : String(cell.raw),
958
+ value: (cell?.value ?? ''),
959
+ viewType: (column.viewType ?? 'Text'),
960
+ type: property?.source,
961
+ order: column.order ?? property?.order,
962
+ configuration: column.configuration,
963
+ propertyConfiguration: property?.configuration ?? undefined,
964
+ comparison: cell?.comparison,
965
+ };
766
966
  }
767
967
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: EntityListField, deps: [], target: i0.ɵɵFactoryTarget.Component });
768
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: EntityListField, isStandalone: true, selector: "mt-entity-list-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, propertyId: { classPropertyName: "propertyId", publicName: "propertyId", isSignal: true, isRequired: false, transformFunction: null }, configuration: { classPropertyName: "configuration", publicName: "configuration", isSignal: true, isRequired: false, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "grid gap-1" }, ngImport: i0, template: "<div class=\"flex flex-col gap-2\">\r\n @if (label()) {\r\n <label class=\"text-sm font-medium text-color\">\r\n {{ label() }}\r\n @if (required()) {\r\n <span class=\"text-red-500\">*</span>\r\n }\r\n </label>\r\n }\r\n\r\n @if (loading()) {\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"100%\" height=\"3rem\" />\r\n <p-skeleton width=\"100%\" height=\"3rem\" />\r\n </div>\r\n } @else if (errorMessage(); as err) {\r\n <p-message severity=\"error\" [text]=\"err\" styleClass=\"w-full\" />\r\n } @else if (!sourceId()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n Save the form first to manage related items.\r\n </div>\r\n } @else if (!canRead()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n Reading is not allowed for this field.\r\n </div>\r\n } @else if (!hasRows()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n No related items.\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-2\">\r\n @for (row of rows(); track trackByRow($index, row)) {\r\n <mt-card [title]=\"rowTitle(row)\" class=\"block\">\r\n @if (rowFields(row).length > 0) {\r\n <dl class=\"grid grid-cols-1 md:grid-cols-2 gap-x-4 gap-y-1 text-sm\">\r\n @for (\r\n field of rowFields(row);\r\n track trackByField($index, field)\r\n ) {\r\n <div class=\"flex gap-2\">\r\n <dt class=\"font-medium text-muted-color\">\r\n {{ field.propertyKey }}:\r\n </dt>\r\n <dd class=\"text-color break-words\">\r\n {{ formatValue(field) }}\r\n </dd>\r\n </div>\r\n }\r\n </dl>\r\n }\r\n </mt-card>\r\n }\r\n </div>\r\n }\r\n\r\n @if (ngControl?.control) {\r\n <mt-field-validation\r\n [control]=\"ngControl?.control!\"\r\n [touched]=\"ngControl?.touched ?? false\"\r\n />\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: FieldValidation, selector: "mt-field-validation", inputs: ["control", "touched"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant", "motionOptions"], outputs: ["onClose"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
968
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: EntityListField, isStandalone: true, selector: "mt-entity-list-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, propertyId: { classPropertyName: "propertyId", publicName: "propertyId", isSignal: true, isRequired: false, transformFunction: null }, configuration: { classPropertyName: "configuration", publicName: "configuration", isSignal: true, isRequired: false, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "grid gap-1" }, ngImport: i0, template: "<div class=\"flex flex-col gap-2\">\r\n @if (label()) {\r\n <label class=\"text-sm font-medium text-color\">\r\n {{ label() }}\r\n @if (required()) {\r\n <span class=\"text-red-500\">*</span>\r\n }\r\n </label>\r\n }\r\n\r\n @if (errorMessage(); as err) {\r\n <p-message severity=\"error\" [text]=\"err\" styleClass=\"w-full\" />\r\n } @else if (canWrite()) {\r\n <div class=\"flex justify-end\">\r\n <mt-button\r\n label=\"Add\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n [disabled]=\"disabled()\"\r\n (onClick)=\"openAddDialog()\"\r\n />\r\n </div>\r\n <mt-table\r\n [noCard]=\"true\"\r\n [data]=\"displayRows()\"\r\n [columns]=\"columns()\"\r\n [rowActions]=\"writeRowActions()\"\r\n dataKey=\"Id\"\r\n [loading]=\"loading()\"\r\n />\r\n } @else if (!canRead()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n Reading is not allowed for this field.\r\n </div>\r\n } @else if (!hasRequiredContext()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n Save the form first to manage related items.\r\n </div>\r\n } @else if (loading() && !hasRows()) {\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"100%\" height=\"3rem\" />\r\n <p-skeleton width=\"100%\" height=\"3rem\" />\r\n </div>\r\n } @else if (!hasRows()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n No related items.\r\n </div>\r\n } @else {\r\n <mt-table\r\n [noCard]=\"true\"\r\n [data]=\"rows()\"\r\n [columns]=\"columns()\"\r\n dataKey=\"Id\"\r\n [loading]=\"loading()\"\r\n />\r\n }\r\n\r\n @if (ngControl?.control) {\r\n <mt-field-validation\r\n [control]=\"ngControl?.control!\"\r\n [touched]=\"ngControl?.touched ?? false\"\r\n />\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: FieldValidation, selector: "mt-field-validation", inputs: ["control", "touched"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant", "motionOptions"], outputs: ["onClose"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "exportable", "printable", "groupable", "cellClickFilter", "freezeActions", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
769
969
  }
770
970
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: EntityListField, decorators: [{
771
971
  type: Component,
772
- args: [{ selector: 'mt-entity-list-field', standalone: true, imports: [CommonModule, Card, FieldValidation, Skeleton, Message], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'grid gap-1' }, template: "<div class=\"flex flex-col gap-2\">\r\n @if (label()) {\r\n <label class=\"text-sm font-medium text-color\">\r\n {{ label() }}\r\n @if (required()) {\r\n <span class=\"text-red-500\">*</span>\r\n }\r\n </label>\r\n }\r\n\r\n @if (loading()) {\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"100%\" height=\"3rem\" />\r\n <p-skeleton width=\"100%\" height=\"3rem\" />\r\n </div>\r\n } @else if (errorMessage(); as err) {\r\n <p-message severity=\"error\" [text]=\"err\" styleClass=\"w-full\" />\r\n } @else if (!sourceId()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n Save the form first to manage related items.\r\n </div>\r\n } @else if (!canRead()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n Reading is not allowed for this field.\r\n </div>\r\n } @else if (!hasRows()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n No related items.\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-2\">\r\n @for (row of rows(); track trackByRow($index, row)) {\r\n <mt-card [title]=\"rowTitle(row)\" class=\"block\">\r\n @if (rowFields(row).length > 0) {\r\n <dl class=\"grid grid-cols-1 md:grid-cols-2 gap-x-4 gap-y-1 text-sm\">\r\n @for (\r\n field of rowFields(row);\r\n track trackByField($index, field)\r\n ) {\r\n <div class=\"flex gap-2\">\r\n <dt class=\"font-medium text-muted-color\">\r\n {{ field.propertyKey }}:\r\n </dt>\r\n <dd class=\"text-color break-words\">\r\n {{ formatValue(field) }}\r\n </dd>\r\n </div>\r\n }\r\n </dl>\r\n }\r\n </mt-card>\r\n }\r\n </div>\r\n }\r\n\r\n @if (ngControl?.control) {\r\n <mt-field-validation\r\n [control]=\"ngControl?.control!\"\r\n [touched]=\"ngControl?.touched ?? false\"\r\n />\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"] }]
972
+ args: [{ selector: 'mt-entity-list-field', standalone: true, imports: [CommonModule, FieldValidation, Skeleton, Message, Table, Button], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'grid gap-1' }, template: "<div class=\"flex flex-col gap-2\">\r\n @if (label()) {\r\n <label class=\"text-sm font-medium text-color\">\r\n {{ label() }}\r\n @if (required()) {\r\n <span class=\"text-red-500\">*</span>\r\n }\r\n </label>\r\n }\r\n\r\n @if (errorMessage(); as err) {\r\n <p-message severity=\"error\" [text]=\"err\" styleClass=\"w-full\" />\r\n } @else if (canWrite()) {\r\n <div class=\"flex justify-end\">\r\n <mt-button\r\n label=\"Add\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n [disabled]=\"disabled()\"\r\n (onClick)=\"openAddDialog()\"\r\n />\r\n </div>\r\n <mt-table\r\n [noCard]=\"true\"\r\n [data]=\"displayRows()\"\r\n [columns]=\"columns()\"\r\n [rowActions]=\"writeRowActions()\"\r\n dataKey=\"Id\"\r\n [loading]=\"loading()\"\r\n />\r\n } @else if (!canRead()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n Reading is not allowed for this field.\r\n </div>\r\n } @else if (!hasRequiredContext()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n Save the form first to manage related items.\r\n </div>\r\n } @else if (loading() && !hasRows()) {\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"100%\" height=\"3rem\" />\r\n <p-skeleton width=\"100%\" height=\"3rem\" />\r\n </div>\r\n } @else if (!hasRows()) {\r\n <div\r\n class=\"rounded border border-dashed border-surface-300 bg-surface-50 p-3 text-sm text-muted-color\"\r\n >\r\n No related items.\r\n </div>\r\n } @else {\r\n <mt-table\r\n [noCard]=\"true\"\r\n [data]=\"rows()\"\r\n [columns]=\"columns()\"\r\n dataKey=\"Id\"\r\n [loading]=\"loading()\"\r\n />\r\n }\r\n\r\n @if (ngControl?.control) {\r\n <mt-field-validation\r\n [control]=\"ngControl?.control!\"\r\n [touched]=\"ngControl?.touched ?? false\"\r\n />\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"] }]
773
973
  }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], propertyId: [{ type: i0.Input, args: [{ isSignal: true, alias: "propertyId", required: false }] }], configuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "configuration", required: false }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }] } });
774
974
 
775
975
  /**
776
976
  * Generated bundle index. Do not edit.
777
977
  */
778
978
 
779
- export { EntityListField, LookupMatrixField, SchedulePredecessorField, SchemaConnectionField };
979
+ export { ENTITY_LIST_ADD_DIALOG_COMPONENT, EntityListField, LookupMatrixField, SchedulePredecessorField, SchemaConnectionField };
780
980
  //# sourceMappingURL=masterteam-components-business-fields.mjs.map