@masterteam/properties 0.0.33 → 0.0.35

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.
@@ -8,7 +8,7 @@
8
8
  "columnName": "الاسم",
9
9
  "columnType": "النوع",
10
10
  "columnRequired": "مطلوب",
11
- "columnCalculated": "محسوبة",
11
+ "columnCalculated": "هل هي محسوبة",
12
12
  "createAction": "إنشاء",
13
13
  "editAction": "تعديل",
14
14
  "deleteAction": "حذف",
@@ -8,7 +8,7 @@
8
8
  "columnName": "Name",
9
9
  "columnType": "Type",
10
10
  "columnRequired": "Required",
11
- "columnCalculated": "Calculated",
11
+ "columnCalculated": "Is Calculated",
12
12
  "createAction": "Create",
13
13
  "editAction": "Edit",
14
14
  "deleteAction": "Delete",
@@ -6,7 +6,7 @@ import { Router, ActivatedRoute } from '@angular/router';
6
6
  import { HttpClient, HttpContextToken } from '@angular/common/http';
7
7
  import { Action, Selector, State, Store, select } from '@ngxs/store';
8
8
  import { of, finalize, startWith, map, distinctUntilChanged, Subscription } from 'rxjs';
9
- import { CrudStateBase, handleApiRequest, PickListFieldConfig, ValidatorConfig, ColorPickerFieldConfig, IconFieldConfig } from '@masterteam/components';
9
+ import { CrudStateBase, handleApiRequest, ValidatorConfig, PickListFieldConfig, ColorPickerFieldConfig, IconFieldConfig } from '@masterteam/components';
10
10
  import { Breadcrumb } from '@masterteam/components/breadcrumb';
11
11
  import { Card } from '@masterteam/components/card';
12
12
  import { Avatar } from '@masterteam/components/avatar';
@@ -340,7 +340,7 @@ let PropertiesState = class PropertiesState extends CrudStateBase {
340
340
  key: PropertiesActionKey.GetAll,
341
341
  request$: req$,
342
342
  onSuccess: (response) => ({
343
- properties: response.data ?? [],
343
+ properties: (response.data?.properties ?? []).map(mapCatalogProperty),
344
344
  }),
345
345
  });
346
346
  }
@@ -525,7 +525,7 @@ let PropertiesState = class PropertiesState extends CrudStateBase {
525
525
  key: PropertiesActionKey.GetConfigProperties,
526
526
  request$: req$,
527
527
  onSuccess: (response) => ({
528
- configTypeProperties: response.data ?? [],
528
+ configTypeProperties: (response.data ?? []).map(mapCatalogProperty),
529
529
  }),
530
530
  });
531
531
  }
@@ -837,6 +837,21 @@ PropertiesState = __decorate([
837
837
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesState, decorators: [{
838
838
  type: Injectable
839
839
  }], propDecorators: { getAll: [], getOne: [], getLookups: [], getGroups: [], getConfigAsType: [], getCountries: [], testApiConfiguration: [], getPropertyStatuses: [], createPropertyStatus: [], updatePropertyStatus: [], deletePropertyStatus: [], reorderPropertyStatuses: [], getPropertiesForConfigType: [], resetConfigProperties: [], resetConfigScopes: [], resetSelectedProperty: [], resetApiConfiguration: [], resetPropertyStatuses: [], setModuleInfo: [], SetPropertyTypes: [], setBreadcrumb: [], setDefaultViewType: [], createProperty: [], updateProperty: [], deleteProperty: [] } });
840
+ function mapCatalogProperty(property) {
841
+ return {
842
+ id: property.id,
843
+ key: property.key,
844
+ normalizedKey: property.normalizedKey,
845
+ viewType: property.viewType,
846
+ viewTypeLabel: property.viewType,
847
+ name: { display: property.label },
848
+ order: property.order,
849
+ isRequired: property.isRequired,
850
+ isSystem: property.isSystem,
851
+ isCalculated: property.source?.toLowerCase().includes('calculated'),
852
+ configuration: property.configuration ?? undefined,
853
+ };
854
+ }
840
855
 
841
856
  class PropertiesFacade {
842
857
  store = inject(Store);
@@ -1086,7 +1101,7 @@ class PropertiesList {
1086
1101
  },
1087
1102
  },
1088
1103
  {
1089
- key: 'isRequired',
1104
+ key: 'isCalculated',
1090
1105
  label: this.transloco.translate('properties.list.columnCalculated'),
1091
1106
  type: 'boolean',
1092
1107
  readonly: true,
@@ -1488,6 +1503,7 @@ class CheckListFormConfiguration {
1488
1503
  optionValue: 'id',
1489
1504
  filter: true,
1490
1505
  options: this.lookups(),
1506
+ validators: [ValidatorConfig.required()],
1491
1507
  },
1492
1508
  {
1493
1509
  key: 'scopeId',
@@ -1497,6 +1513,7 @@ class CheckListFormConfiguration {
1497
1513
  optionValue: 'id',
1498
1514
  options: this.scopeItems(),
1499
1515
  filter: true,
1516
+ validators: [ValidatorConfig.required()],
1500
1517
  },
1501
1518
  new PickListFieldConfig({
1502
1519
  key: 'properties',
@@ -1506,6 +1523,7 @@ class CheckListFormConfiguration {
1506
1523
  optionValue: 'key',
1507
1524
  sourceHeader: this.transloco.translate('properties.form.availableProperties'),
1508
1525
  targetHeader: this.transloco.translate('properties.form.selectedProperties'),
1526
+ validators: [ValidatorConfig.required()],
1509
1527
  }),
1510
1528
  ],
1511
1529
  },
@@ -1586,6 +1604,7 @@ class EntityListConfiguration {
1586
1604
  optionValue: 'id',
1587
1605
  options: this.moduleItems(),
1588
1606
  filter: true,
1607
+ validators: [ValidatorConfig.required()],
1589
1608
  },
1590
1609
  {
1591
1610
  key: 'access',
@@ -1594,6 +1613,7 @@ class EntityListConfiguration {
1594
1613
  optionLabel: 'label',
1595
1614
  optionValue: 'value',
1596
1615
  options: this.accessOptions,
1616
+ validators: [ValidatorConfig.required()],
1597
1617
  },
1598
1618
  {
1599
1619
  key: 'snapshotMode',
@@ -1611,6 +1631,7 @@ class EntityListConfiguration {
1611
1631
  optionValue: 'key',
1612
1632
  sourceHeader: 'Available Read Fields',
1613
1633
  targetHeader: 'Selected Read Fields',
1634
+ validators: [ValidatorConfig.required()],
1614
1635
  }),
1615
1636
  new PickListFieldConfig({
1616
1637
  key: 'writeFields',
@@ -1620,6 +1641,7 @@ class EntityListConfiguration {
1620
1641
  optionValue: 'key',
1621
1642
  sourceHeader: 'Available Write Fields',
1622
1643
  targetHeader: 'Selected Write Fields',
1644
+ validators: [ValidatorConfig.required()],
1623
1645
  relations: [
1624
1646
  { action: 'show', key: 'access', value: 'Write' },
1625
1647
  { action: 'show', key: 'access', value: 'ReadWrite' },
@@ -1699,6 +1721,7 @@ class LocationConfiguration {
1699
1721
  optionValue: 'name',
1700
1722
  options: this.countries(),
1701
1723
  filter: true,
1724
+ validators: [ValidatorConfig.required()],
1702
1725
  },
1703
1726
  ],
1704
1727
  },
@@ -1746,6 +1769,7 @@ class LookupConfiguration {
1746
1769
  optionValue: 'id',
1747
1770
  options: this.lookups(),
1748
1771
  filter: true,
1772
+ validators: [ValidatorConfig.required()],
1749
1773
  },
1750
1774
  ],
1751
1775
  },
@@ -2320,6 +2344,7 @@ class AttachmentConfiguration {
2320
2344
  sourceHeader: this.transloco.translate('properties.form.availableTypes'),
2321
2345
  targetHeader: this.transloco.translate('properties.form.selectedTypes'),
2322
2346
  cssClass: 'md:col-span-2',
2347
+ validators: [ValidatorConfig.required()],
2323
2348
  }),
2324
2349
  {
2325
2350
  key: 'IsMulitple',
@@ -2372,14 +2397,13 @@ class PropertyForm {
2372
2397
  mainControl = this.propertyForm.get('main');
2373
2398
  configurationControl = this.propertyForm.get('configuration');
2374
2399
  formulaControl = this.propertyForm.get('formula');
2400
+ mainValue = signal(this.mainControl.value, ...(ngDevMode ? [{ debugName: "mainValue" }] : []));
2375
2401
  creating = this.facade.isCreating;
2376
2402
  updating = this.facade.isUpdating;
2377
2403
  loading = this.facade.isLoadingOne;
2378
2404
  submitting = computed(() => this.creating() || this.updating(), ...(ngDevMode ? [{ debugName: "submitting" }] : []));
2379
- propertyType = toSignal(this.mainControl.valueChanges.pipe(map((v) => v?.viewType), distinctUntilChanged()));
2380
- isCalculated = toSignal(this.mainControl.valueChanges.pipe(map((v) => Boolean(v?.isCalculated)), distinctUntilChanged()), {
2381
- initialValue: Boolean(this.mainControl.value?.isCalculated),
2382
- });
2405
+ propertyType = computed(() => this.mainValue()?.viewType ?? null, ...(ngDevMode ? [{ debugName: "propertyType" }] : []));
2406
+ isCalculated = computed(() => Boolean(this.mainValue()?.isCalculated), ...(ngDevMode ? [{ debugName: "isCalculated" }] : []));
2383
2407
  formulaSchemaId = computed(() => this.resolveSchemaId(this.facade.parentModuleId() ?? this.facade.moduleId()), ...(ngDevMode ? [{ debugName: "formulaSchemaId" }] : []));
2384
2408
  selectedViewType = computed(() => this.propertyType() ??
2385
2409
  this.facade.selected()?.viewType, ...(ngDevMode ? [{ debugName: "selectedViewType" }] : []));
@@ -2407,7 +2431,8 @@ class PropertyForm {
2407
2431
  configurationComponentRef = null;
2408
2432
  configurationComponentLoadId = 0;
2409
2433
  externalConfigurationForm = signal(null, ...(ngDevMode ? [{ debugName: "externalConfigurationForm" }] : []));
2410
- externalConfigurationSubscriptions = null;
2434
+ externalConfigurationSubscriptions = new Subscription();
2435
+ subscriptions = new Subscription();
2411
2436
  externalConfigurationInvalid = signal(false, ...(ngDevMode ? [{ debugName: "externalConfigurationInvalid" }] : []));
2412
2437
  lastStatusScrollKey = signal(null, ...(ngDevMode ? [{ debugName: "lastStatusScrollKey" }] : []));
2413
2438
  configurationComponentExists = computed(() => !!this.configurationComponentType(), ...(ngDevMode ? [{ debugName: "configurationComponentExists" }] : []));
@@ -2478,16 +2503,6 @@ class PropertyForm {
2478
2503
  key: 'viewType',
2479
2504
  value: 'Checkbox',
2480
2505
  },
2481
- {
2482
- action: 'show',
2483
- key: 'viewType',
2484
- value: 'Lookup',
2485
- },
2486
- {
2487
- action: 'show',
2488
- key: 'viewType',
2489
- value: 'LookupMultiSelect',
2490
- },
2491
2506
  {
2492
2507
  action: 'show',
2493
2508
  key: 'viewType',
@@ -2536,6 +2551,7 @@ class PropertyForm {
2536
2551
  ],
2537
2552
  }), ...(ngDevMode ? [{ debugName: "dynamicFormConfigMain" }] : []));
2538
2553
  constructor() {
2554
+ this.subscriptions.add(this.mainControl.valueChanges.subscribe((value) => this.mainValue.set(value)));
2539
2555
  // Load when editing
2540
2556
  effect(() => {
2541
2557
  if (this.propertyId()) {
@@ -2581,6 +2597,11 @@ class PropertyForm {
2581
2597
  effect(() => {
2582
2598
  this.renderConfigurationComponent(this.configurationComponentType());
2583
2599
  });
2600
+ effect(() => {
2601
+ const calculated = this.isCalculated();
2602
+ this.formulaControl.setValidators(calculated ? [Validators.required] : []);
2603
+ this.formulaControl.updateValueAndValidity({ emitEvent: false });
2604
+ });
2584
2605
  effect(() => {
2585
2606
  const fragment = this.routeFragment();
2586
2607
  const section = this.statusConfigurationSection();
@@ -2618,8 +2639,9 @@ class PropertyForm {
2618
2639
  this.connectExternalConfigurationForm(componentRef.instance);
2619
2640
  }
2620
2641
  destroyConfigurationComponent() {
2621
- this.externalConfigurationSubscriptions?.unsubscribe();
2622
- this.externalConfigurationSubscriptions = null;
2642
+ const formSubscriptions = this.externalConfigurationSubscriptions;
2643
+ this.externalConfigurationSubscriptions = new Subscription();
2644
+ formSubscriptions.unsubscribe();
2623
2645
  this.externalConfigurationForm.set(null);
2624
2646
  this.externalConfigurationInvalid.set(false);
2625
2647
  this.configurationComponentRef?.destroy();
@@ -2639,7 +2661,6 @@ class PropertyForm {
2639
2661
  this.configurationControl.setValue(form.value ?? null, {
2640
2662
  emitEvent: false,
2641
2663
  });
2642
- this.externalConfigurationSubscriptions = new Subscription();
2643
2664
  this.externalConfigurationSubscriptions.add(form.valueChanges.subscribe((value) => this.configurationControl.setValue(value, { emitEvent: false })));
2644
2665
  this.externalConfigurationSubscriptions.add(form.statusChanges.subscribe(() => this.externalConfigurationInvalid.set(form.invalid)));
2645
2666
  }
@@ -2726,6 +2747,7 @@ class PropertyForm {
2726
2747
  this.mainControl.patchValue(property, {
2727
2748
  emitEvent: false,
2728
2749
  });
2750
+ this.mainValue.set(this.mainControl.value);
2729
2751
  this.configurationControl.setValue(property?.configuration);
2730
2752
  this.formulaControl.setValue(property.formula ?? null, {
2731
2753
  emitEvent: false,
@@ -2781,6 +2803,7 @@ class PropertyForm {
2781
2803
  this.facade.resetSelectedProperty();
2782
2804
  this.facade.setDefaultViewType('');
2783
2805
  this.destroyConfigurationComponent();
2806
+ this.subscriptions.unsubscribe();
2784
2807
  }
2785
2808
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertyForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
2786
2809
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: PropertyForm, isStandalone: true, selector: "mt-property-form", inputs: { propertyId: { classPropertyName: "propertyId", publicName: "propertyId", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "statusConfigurationSection", first: true, predicate: ["statusConfigurationSection"], descendants: true, isSignal: true }, { propertyName: "configurationHost", first: true, predicate: ["configurationHost"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<mt-page\n [title]=\"\n propertyId()\n ? ('properties.form.editProperty' | transloco)\n : ('properties.form.createNewProperty' | transloco)\n \"\n avatarIcon=\"custom.products-and-services\"\n [avatarStyle]=\"{\n '--p-avatar-background': 'var(--p-sky-50)',\n '--p-avatar-color': 'var(--p-sky-700)',\n }\"\n (backButtonClick)=\"goBack()\"\n backButton\n class=\"h-full\"\n>\n <ng-template #headerEnd>\n <mt-button\n class=\"mx-2\"\n [label]=\"submitLabel()\"\n [icon]=\"isEditing() ? 'custom.pencil' : 'general.plus'\"\n [loading]=\"submitting()\"\n [disabled]=\"submitDisabled() || this.propertyForm.invalid\"\n (click)=\"createOrEditProperty()\"\n />\n </ng-template>\n <div\n [formGroup]=\"propertyForm\"\n class=\"h-full py-4 h-full overflow-y-auto flex justify-center\"\n >\n <div class=\"w-2/3 flex flex-col gap-6\">\n @if (loading()) {\n <!-- Skeleton Loading State -->\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\n <div class=\"flex justify-between items-center gap-6\">\n <p-skeleton width=\"50%\" height=\"3rem\"></p-skeleton>\n <p-skeleton width=\"8rem\" height=\"2.5rem\"></p-skeleton>\n </div>\n </div>\n\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\n <p-skeleton\n width=\"12rem\"\n height=\"1.5rem\"\n styleClass=\"mb-4\"\n ></p-skeleton>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <p-skeleton height=\"3rem\"></p-skeleton>\n <p-skeleton height=\"3rem\"></p-skeleton>\n <p-skeleton height=\"6rem\" styleClass=\"md:col-span-2\"></p-skeleton>\n <p-skeleton height=\"3rem\" styleClass=\"md:col-span-2\"></p-skeleton>\n </div>\n </div>\n\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\n <p-skeleton\n width=\"10rem\"\n height=\"1.5rem\"\n styleClass=\"mb-4\"\n ></p-skeleton>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <p-skeleton height=\"3rem\"></p-skeleton>\n <p-skeleton height=\"3rem\"></p-skeleton>\n <p-skeleton height=\"8rem\" styleClass=\"md:col-span-2\"></p-skeleton>\n </div>\n </div>\n } @else {\n <mt-dynamic-form\n [formConfig]=\"dynamicFormConfigMain()\"\n [formControlName]=\"'main'\"\n />\n @if (configurationFormConfig()) {\n <mt-dynamic-form\n formControlName=\"configuration\"\n [formConfig]=\"configurationFormConfig()!\"\n />\n } @else {\n <ng-container #configurationHost></ng-container>\n @if (!configurationComponentExists()) {\n @switch (propertyType()) {\n @case (\"User\") {\n <mt-user-configuration />\n }\n @case (\"Percentage\") {\n <mt-percentage-configuration />\n }\n @case (\"Lookup\") {\n <mt-lookup-configuration />\n }\n @case (\"LookupMultiSelect\") {\n <mt-lookup-configuration />\n }\n @case (\"EntityList\") {\n <mt-entity-list-configuration />\n }\n @case (\"API\") {\n <mt-api-configuration formControlName=\"configuration\" />\n }\n @case (\"Status\") {\n <section #statusConfigurationSection>\n <mt-status-configuration\n [propertyId]=\"statusPropertyId()\"\n [levelSchemaId]=\"formulaSchemaId()\"\n />\n </section>\n }\n <!-- @case('ViewList') { REMOVED FOR NOW\n <mt-view-list-configuration />\n } -->\n @case (\"Attachment\") {\n <mt-attachment-configuration />\n }\n <!-- @case('ReferenceProperty') { REMOVED FOR NOW\n } -->\n @case (\"LookupModuleCheckList\") {\n <mt-check-list-form-configuration />\n }\n <!-- @case('LookupMatrix') { REMOVED FOR NOW\n <mt-lookup-configuration />\n } -->\n @case (\"Location\") {\n <mt-location-configuration />\n }\n }\n }\n }\n @if (isCalculated()) {\n <mt-card title=\"Formula\">\n <mt-formula-builder\n formControlName=\"formula\"\n [levelSchemaId]=\"formulaSchemaId()\"\n />\n </mt-card>\n }\n }\n </div>\n </div>\n</mt-page>\n", styles: [""], dependencies: [{ kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { 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"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys"], outputs: ["runtimeMessagesChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: FormulaBuilder, selector: "mt-formula-builder", inputs: ["propertiesByPath", "levelSchemaId", "templateId", "placeholder", "hideToolbar", "hideStatusBar"], outputs: ["validationChange", "tokensChange"] }, { kind: "component", type: ApiConfiguration, selector: "mt-api-configuration" }, { kind: "component", type: CheckListFormConfiguration, selector: "mt-check-list-form-configuration" }, { kind: "component", type: EntityListConfiguration, selector: "mt-entity-list-configuration" }, { kind: "component", type: LocationConfiguration, selector: "mt-location-configuration" }, { kind: "component", type: LookupConfiguration, selector: "mt-lookup-configuration" }, { kind: "component", type: PercentageConfiguration, selector: "mt-percentage-configuration" }, { kind: "component", type: StatusConfiguration, selector: "mt-status-configuration", inputs: ["propertyId", "levelSchemaId"] }, { kind: "component", type: UserConfiguration, selector: "mt-user-configuration" }, { kind: "component", type: AttachmentConfiguration, selector: "mt-attachment-configuration" }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });