@acorex/platform 20.6.0-next.18 → 20.6.0-next.19

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.
@@ -1,10 +1,10 @@
1
1
  import { AXPSessionService, AXPAuthGuard } from '@acorex/platform/auth';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, Injectable, input, viewChild, signal, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, InjectionToken, computed, Injector, runInInjectionContext, ChangeDetectorRef, effect, viewChildren, linkedSignal, untracked, HostBinding, ViewChild, NgModule } from '@angular/core';
3
+ import { inject, Injectable, input, viewChild, signal, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, InjectionToken, computed, Injector, runInInjectionContext, afterNextRender, ViewEncapsulation, ChangeDetectorRef, effect, viewChildren, linkedSignal, untracked, HostBinding, ViewChild, NgModule } from '@angular/core';
4
4
  import { Router, RouterModule, ROUTES } from '@angular/router';
5
5
  import * as i3 from '@acorex/components/button';
6
6
  import { AXButtonModule } from '@acorex/components/button';
7
- import * as i4 from '@acorex/components/loading';
7
+ import * as i1 from '@acorex/components/loading';
8
8
  import { AXLoadingModule } from '@acorex/components/loading';
9
9
  import * as i2 from '@acorex/components/popover';
10
10
  import { AXPopoverModule } from '@acorex/components/popover';
@@ -18,9 +18,9 @@ import { CommonModule } from '@angular/common';
18
18
  import { castArray, get, cloneDeep, set, merge, orderBy, isNil, isEqual, isEmpty, sortBy } from 'lodash-es';
19
19
  import { AXDataSource } from '@acorex/cdk/common';
20
20
  import { AXFormatService } from '@acorex/core/format';
21
- import * as i4$1 from '@acorex/platform/common';
21
+ import * as i4 from '@acorex/platform/common';
22
22
  import { AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, getEntityInfo, AXPSettingService, AXPRefreshEvent, AXPReloadEvent, AXPCommonSettings, AXPCleanNestedFilters, AXPWorkflowNavigateAction, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER } from '@acorex/platform/common';
23
- import * as i1$1 from '@acorex/platform/core';
23
+ import * as i1$3 from '@acorex/platform/core';
24
24
  import { resolveActionLook, AXPExpressionEvaluatorService, AXPDistributedEventListenerService, AXPBroadcastEventService, AXPPlatformScope, extractValue, setSmart, AXPDeviceService, getChangedPaths, AXPSystemActionType } from '@acorex/platform/core';
25
25
  import * as i2$3 from '@acorex/platform/workflow';
26
26
  import { AXPWorkflowService, ofType, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowModule } from '@acorex/platform/workflow';
@@ -31,30 +31,30 @@ import { AXDialogService } from '@acorex/components/dialog';
31
31
  import { AXLoadingDialogService } from '@acorex/components/loading-dialog';
32
32
  import { AXPopupService } from '@acorex/components/popup';
33
33
  import { AXPlatform } from '@acorex/core/platform';
34
- import * as i3$2 from '@acorex/components/decorators';
34
+ import * as i1$1 from '@acorex/components/decorators';
35
35
  import { AXDecoratorModule } from '@acorex/components/decorators';
36
36
  import { AXBasePageComponent } from '@acorex/components/page';
37
- import * as i3$3 from '@acorex/components/search-box';
37
+ import * as i3$2 from '@acorex/components/search-box';
38
38
  import { AXSearchBoxModule, AXSearchBoxComponent } from '@acorex/components/search-box';
39
- import * as i4$2 from '@acorex/components/skeleton';
39
+ import * as i4$1 from '@acorex/components/skeleton';
40
40
  import { AXSkeletonModule } from '@acorex/components/skeleton';
41
41
  import { AXTreeViewComponent } from '@acorex/components/tree-view';
42
42
  import * as i2$1 from '@acorex/components/badge';
43
43
  import { AXBadgeModule } from '@acorex/components/badge';
44
44
  import * as i5$1 from '@acorex/components/form';
45
45
  import { AXFormModule } from '@acorex/components/form';
46
- import * as i7 from '@acorex/components/select-box';
47
- import { AXSelectBoxModule } from '@acorex/components/select-box';
48
- import * as i6$1 from '@acorex/components/tag-box';
49
- import { AXTagBoxModule, AXTagBoxComponent } from '@acorex/components/tag-box';
50
46
  import { AXValidationModule } from '@acorex/core/validation';
51
- import * as i1 from '@angular/forms';
52
- import { FormsModule } from '@angular/forms';
53
47
  import { AXP_DISABLED_PROPERTY, AXP_ALLOW_CLEAR_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DATA_PROPERTY_GROUP, AXP_ALLOW_MULTIPLE_PROPERTY, AXP_NAME_PROPERTY, AXPFileUploaderWidgetService } from '@acorex/platform/layout/widgets';
54
- import * as i4$3 from '@acorex/components/dropdown';
48
+ import * as i4$2 from '@acorex/components/dropdown';
55
49
  import { AXDropdownModule } from '@acorex/components/dropdown';
50
+ import * as i1$2 from '@angular/forms';
51
+ import { FormsModule } from '@angular/forms';
52
+ import * as i7 from '@acorex/components/select-box';
53
+ import { AXSelectBoxModule } from '@acorex/components/select-box';
56
54
  import * as i2$2 from '@acorex/components/text-box';
57
55
  import { AXTextBoxModule, AXTextBoxComponent } from '@acorex/components/text-box';
56
+ import * as i6$1 from '@acorex/components/tag-box';
57
+ import { AXTagBoxComponent, AXTagBoxModule } from '@acorex/components/tag-box';
58
58
  import { AXPDataSelectorService, AXPWidgetPropertyViewerComponent } from '@acorex/platform/layout/components';
59
59
  import { AXPLayoutBuilderService } from '@acorex/platform/layout/builder';
60
60
  import { transform, isEqual as isEqual$1 } from 'lodash';
@@ -391,7 +391,7 @@ class AXPEntityDetailPopoverComponent {
391
391
  return importantProperties;
392
392
  }
393
393
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityDetailPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
394
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityDetailPopoverComponent, isStandalone: true, selector: "axp-entity-detail-popover", inputs: { entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: true, transformFunction: null }, entityId: { classPropertyName: "entityId", publicName: "entityId", isSignal: true, isRequired: true, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "detailPopover", first: true, predicate: ["detailPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "<ax-popover [openOn]=\"'manual'\" #detailPopover (openChange)=\"onDetailPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface ax-border ax-rounded-lg ax-shadow-lg ax-p-4 ax-min-w-[400px]\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold ax-text-on-lightest-surface\">\n @if (entityDetails()?.entityData?.[textField()]) {\n {{ entityDetails()?.entityData[textField()] }}\n } @else {\n {{ item()?.[textField()] }}\n }\n </h3>\n </div>\n @if (isLoadingDetails()) {\n <div class=\"ax-flex ax-items-center ax-justify-center ax-py-8\">\n <ax-loading>Loading details...</ax-loading>\n </div>\n } @else if (entityDetails()) {\n <div class=\"ax-space-y-3 ax-mb-4\">\n <!-- Important Entity Data -->\n @if (entityDetails()?.entityData) {\n <axp-widgets-container [context]=\"entityDetails()?.entityData\">\n <div class=\"ax-space-y-2\">\n @for (item of getEntityPropertiesWithWidgets(); track item.name) {\n <div class=\"ax-flex ax-justify-between ax-items-center\">\n <span class=\"ax-text-sm ax-font-medium\">{{ item.title | translate | async }}:</span>\n <div class=\"ax-flex-1 ax-ml-2 ax-max-w-48\">\n <ng-container axp-widget-renderer [node]=\"item.node\" [mode]=\"'view'\"></ng-container>\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n }\n </div>\n <div class=\"ax-flex ax-gap-2 ax-justify-end ax-sm\">\n <ax-button [color]=\"'primary'\" [look]=\"'solid'\" text=\"Open Details\" (click)=\"navigateToDetails()\"> </ax-button>\n </div>\n }\n </div>\n</ax-popover>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i3$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
394
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityDetailPopoverComponent, isStandalone: true, selector: "axp-entity-detail-popover", inputs: { entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: true, transformFunction: null }, entityId: { classPropertyName: "entityId", publicName: "entityId", isSignal: true, isRequired: true, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "detailPopover", first: true, predicate: ["detailPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "<ax-popover [openOn]=\"'manual'\" #detailPopover (openChange)=\"onDetailPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface ax-border ax-rounded-lg ax-shadow-lg ax-p-4 ax-min-w-[400px]\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold ax-text-on-lightest-surface\">\n @if (entityDetails()?.entityData?.[textField()]) {\n {{ entityDetails()?.entityData[textField()] }}\n } @else {\n {{ item()?.[textField()] }}\n }\n </h3>\n </div>\n @if (isLoadingDetails()) {\n <div class=\"ax-flex ax-items-center ax-justify-center ax-py-8\">\n <ax-loading>Loading details...</ax-loading>\n </div>\n } @else if (entityDetails()) {\n <div class=\"ax-space-y-3 ax-mb-4\">\n <!-- Important Entity Data -->\n @if (entityDetails()?.entityData) {\n <axp-widgets-container [context]=\"entityDetails()?.entityData\">\n <div class=\"ax-space-y-2\">\n @for (item of getEntityPropertiesWithWidgets(); track item.name) {\n <div class=\"ax-flex ax-justify-between ax-items-center\">\n <span class=\"ax-text-sm ax-font-medium\">{{ item.title | translate | async }}:</span>\n <div class=\"ax-flex-1 ax-ml-2 ax-max-w-48\">\n <ng-container axp-widget-renderer [node]=\"item.node\" [mode]=\"'view'\"></ng-container>\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n }\n </div>\n <div class=\"ax-flex ax-gap-2 ax-justify-end ax-sm\">\n <ax-button [color]=\"'primary'\" [look]=\"'solid'\" text=\"Open Details\" (click)=\"navigateToDetails()\"> </ax-button>\n </div>\n }\n </div>\n</ax-popover>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i3$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i1.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
395
395
  }
396
396
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityDetailPopoverComponent, decorators: [{
397
397
  type: Component,
@@ -3222,6 +3222,16 @@ class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
3222
3222
  async convert(relatedEntity, context) {
3223
3223
  const { entityDef } = await this.getEntityDefinition(relatedEntity, context.entityResolver);
3224
3224
  const baseHelpers = this.createEntityHelpers(entityDef);
3225
+ // Get update interface to determine editable properties
3226
+ const updateInterface = entityDef?.interfaces?.master?.update;
3227
+ const editablePropertyNames = new Set(updateInterface?.properties?.map((p) => p.name) ?? []);
3228
+ // Check if page should be readonly (no editable properties or all editable properties are readonly)
3229
+ const isPageReadonly = editablePropertyNames.size === 0 ||
3230
+ (editablePropertyNames.size > 0 &&
3231
+ [...editablePropertyNames].every((propName) => {
3232
+ const prop = entityDef?.properties?.find((p) => p.name === propName);
3233
+ return prop?.schema?.readonly === true;
3234
+ }));
3225
3235
  // If referenced strategy with mapping and detail type, exclude mapped properties from UI
3226
3236
  const p = relatedEntity?.persistence || {};
3227
3237
  const strategy = p.strategy || 'embedded';
@@ -3258,6 +3268,7 @@ class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
3258
3268
  title: `${context.rootTitle}`,
3259
3269
  label: relatedEntity.title ?? entityDef?.formats.displayName ?? '',
3260
3270
  icon: relatedEntity.icon || entityDef.icon,
3271
+ isReadonly: isPageReadonly,
3261
3272
  settings: this.createPageSettings(),
3262
3273
  load: this.createLoadFunction(entityDef, relatedEntity, evaluateExpressions),
3263
3274
  execute: this.createExecuteFunction(entityDef, actions, evaluateExpressions, context),
@@ -3962,6 +3973,13 @@ class AXPMainEntityContentBuilder {
3962
3973
  });
3963
3974
  const afterSections = sortRelatedSections(afterExtraSections);
3964
3975
  const combinedSections = [...beforeSections, ...middleBlock, ...afterSections];
3976
+ // Check if page should be readonly (no editable properties or all editable properties are readonly)
3977
+ const isPageReadonly = editablePropertyNames.size === 0 ||
3978
+ (editablePropertyNames.size > 0 &&
3979
+ [...editablePropertyNames].every((propName) => {
3980
+ const prop = entity?.properties?.find((p) => p.name === propName);
3981
+ return prop?.schema?.readonly === true;
3982
+ }));
3965
3983
  // Debug: Log final sorted sections for verification
3966
3984
  try {
3967
3985
  const beforeEntityOrderMap = new Map(beforeExtraSections.map((e) => [e.section?.id, e.entityOrder ?? Number.MAX_SAFE_INTEGER]));
@@ -4014,6 +4032,7 @@ class AXPMainEntityContentBuilder {
4014
4032
  icon: entity?.icon,
4015
4033
  actions: await this.buildEvaluatedActions(actions, evaluateExpressions),
4016
4034
  isPrimary: true,
4035
+ isReadonly: isPageReadonly,
4017
4036
  settings: {
4018
4037
  commands: {
4019
4038
  reject: {
@@ -4468,7 +4487,7 @@ class AXPLayoutAdapterFactory {
4468
4487
  const title = await dependencies.expressionEvaluator.evaluate(entity.interfaces?.master?.single?.title, rootContext);
4469
4488
  return title;
4470
4489
  }
4471
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutAdapterFactory, deps: [{ token: AXPRelatedEntityConverterFactory }, { token: AXPMainEntityContentBuilder }, { token: AXPLayoutAdapterBuilder }, { token: i4$1.AXPFilterOperatorMiddlewareService }], target: i0.ɵɵFactoryTarget.Injectable }); }
4490
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutAdapterFactory, deps: [{ token: AXPRelatedEntityConverterFactory }, { token: AXPMainEntityContentBuilder }, { token: AXPLayoutAdapterBuilder }, { token: i4.AXPFilterOperatorMiddlewareService }], target: i0.ɵɵFactoryTarget.Injectable }); }
4472
4491
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutAdapterFactory, providedIn: 'root' }); }
4473
4492
  }
4474
4493
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutAdapterFactory, decorators: [{
@@ -4476,7 +4495,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
4476
4495
  args: [{
4477
4496
  providedIn: 'root',
4478
4497
  }]
4479
- }], ctorParameters: () => [{ type: AXPRelatedEntityConverterFactory }, { type: AXPMainEntityContentBuilder }, { type: AXPLayoutAdapterBuilder }, { type: i4$1.AXPFilterOperatorMiddlewareService }] });
4498
+ }], ctorParameters: () => [{ type: AXPRelatedEntityConverterFactory }, { type: AXPMainEntityContentBuilder }, { type: AXPLayoutAdapterBuilder }, { type: i4.AXPFilterOperatorMiddlewareService }] });
4480
4499
 
4481
4500
  const AXPLayoutDetailsViewRouteResolver = async (route, state, entityResolver = inject(AXPEntityDefinitionRegistryService), expressionEvaluator = inject(AXPExpressionEvaluatorService), session = inject(AXPSessionService), formatService = inject(AXFormatService), workflowService = inject(AXPWorkflowService), commandService = inject(AXPCommandService), layoutAdapterFactory = inject(AXPLayoutAdapterFactory)) => {
4482
4501
  const moduleName = route.parent?.paramMap.get('module');
@@ -4961,25 +4980,25 @@ class AXPCategoryTreeService {
4961
4980
  const allItemsLabel = await this.translate.translateAsync('@general:terms.interface.selection.all-items');
4962
4981
  const rootNode = {
4963
4982
  id: 'all',
4964
- label: allItemsLabel,
4983
+ title: allItemsLabel,
4965
4984
  icon: 'fa-solid fa-folder',
4966
4985
  childrenCount: items.length,
4967
4986
  expanded: true,
4968
4987
  data: { [valueField]: 'all', [textField]: allItemsLabel },
4969
4988
  };
4970
4989
  const childNodes = items.map((item) => this.convertToTreeNode(item, config));
4971
- rootNode.children = childNodes;
4990
+ rootNode['children'] = childNodes;
4972
4991
  return rootNode;
4973
4992
  }
4974
4993
  /**
4975
- * Convert entity item to AXTreeNode format
4994
+ * Convert entity item to AXTreeViewNode format
4976
4995
  */
4977
4996
  convertToTreeNode(item, config) {
4978
4997
  const textField = config.textField ?? 'title';
4979
4998
  const valueField = config.valueField ?? 'id';
4980
4999
  return {
4981
5000
  id: String(item[valueField] ?? ''),
4982
- label: String(item[textField] ?? ''),
5001
+ title: String(item[textField] ?? ''),
4983
5002
  icon: 'fa-solid fa-folder',
4984
5003
  childrenCount: item['childrenCount'] || item['children']?.length || 0,
4985
5004
  expanded: false,
@@ -5014,7 +5033,7 @@ class AXPCategoryTreeService {
5014
5033
  ...treeData.basicQueryEvent,
5015
5034
  filter: {
5016
5035
  field: treeData.categoryEntityDef.parentKey,
5017
- value: node.id,
5036
+ value: node['id'],
5018
5037
  operator: { type: 'equal' },
5019
5038
  },
5020
5039
  };
@@ -5076,11 +5095,12 @@ class AXPCategoryTreeService {
5076
5095
  */
5077
5096
  updateChildrenAtPath(nodes, targetId, childNodes) {
5078
5097
  return nodes.map((node) => {
5079
- if (node.id === targetId) {
5080
- return { ...node, children: childNodes, childrenCount: childNodes.length };
5098
+ if (node['id'] === targetId) {
5099
+ return { ...node, ['children']: childNodes, childrenCount: childNodes.length };
5081
5100
  }
5082
- if (node.children?.length) {
5083
- return { ...node, children: this.updateChildrenAtPath(node.children, targetId, childNodes) };
5101
+ const nodeChildren = node['children'];
5102
+ if (nodeChildren?.length) {
5103
+ return { ...node, ['children']: this.updateChildrenAtPath(nodeChildren, targetId, childNodes) };
5084
5104
  }
5085
5105
  return node;
5086
5106
  });
@@ -5106,8 +5126,10 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5106
5126
  this.textField = signal('title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
5107
5127
  this.valueField = signal('id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
5108
5128
  this.allowMultiple = signal(false, ...(ngDevMode ? [{ debugName: "allowMultiple" }] : []));
5129
+ this.selectionBehavior = signal('leaf', ...(ngDevMode ? [{ debugName: "selectionBehavior" }] : []));
5109
5130
  this.selectedValues = signal([], ...(ngDevMode ? [{ debugName: "selectedValues" }] : []));
5110
5131
  this.searchPlaceholder = signal('@general:terms.interface.category.search.placeholder', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
5132
+ this.excludedNodeId = signal(undefined, ...(ngDevMode ? [{ debugName: "excludedNodeId" }] : [])); // Node ID to disable
5111
5133
  //#endregion
5112
5134
  //#region ---- View Queries ----
5113
5135
  this.tree = viewChild('tree', ...(ngDevMode ? [{ debugName: "tree" }] : []));
@@ -5115,6 +5137,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5115
5137
  //#region ---- Component State ----
5116
5138
  this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
5117
5139
  this.selectedNodeIds = signal([], ...(ngDevMode ? [{ debugName: "selectedNodeIds" }] : []));
5140
+ this.searchValue = signal('', ...(ngDevMode ? [{ debugName: "searchValue" }] : []));
5118
5141
  //#endregion
5119
5142
  //#region ---- Private Properties ----
5120
5143
  this.treeData = null;
@@ -5129,10 +5152,31 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5129
5152
  // If no id provided, return root nodes (or search results if available)
5130
5153
  if (!id) {
5131
5154
  // If we have search results, use them
5132
- if (this.searchResults) {
5155
+ if (this.searchResults && this.searchResults.length > 0) {
5133
5156
  const rootNode = await this.categoryTreeService.createRootNode(this.searchResults, this.treeConfig);
5157
+ // Mark excluded node as disabled in root node structure
5158
+ const excludedId = this.excludedNodeId();
5159
+ if (excludedId) {
5160
+ this.markNodeAsDisabled(rootNode, excludedId);
5161
+ }
5162
+ // Mark pre-selected nodes as selected in search results
5163
+ this.markNodesAsSelected(rootNode);
5164
+ // After tree loads, programmatically select pre-selected nodes
5165
+ const treeComponent = this.tree();
5166
+ if (treeComponent) {
5167
+ const selectedIds = this.selectedNodeIds();
5168
+ selectedIds.forEach((selectedId) => {
5169
+ if (selectedId && selectedId !== 'all') {
5170
+ treeComponent.selectNode(selectedId);
5171
+ }
5172
+ });
5173
+ }
5134
5174
  return [rootNode];
5135
5175
  }
5176
+ // If search was performed but returned no results, return empty array
5177
+ if (this.searchResults !== null && this.searchResults.length === 0) {
5178
+ return [];
5179
+ }
5136
5180
  // Otherwise load root categories
5137
5181
  const items = await this.categoryTreeService.loadRootCategories(this.treeData, this.treeConfig);
5138
5182
  if (!items) {
@@ -5140,27 +5184,71 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5140
5184
  }
5141
5185
  // Cache node data for getSelectedItems
5142
5186
  items.forEach((item) => {
5143
- const itemId = item[this.treeConfig.valueField || 'id'];
5144
- if (itemId) {
5187
+ const itemId = String(item[this.treeConfig.valueField || 'id'] ?? '');
5188
+ if (itemId && typeof item === 'object' && item !== null) {
5145
5189
  this.nodeDataCache.set(itemId, item);
5146
5190
  }
5147
5191
  });
5148
5192
  const rootNode = await this.categoryTreeService.createRootNode(items, this.treeConfig);
5193
+ // Mark excluded node as disabled in root node structure
5194
+ const excludedId = this.excludedNodeId();
5195
+ if (excludedId) {
5196
+ this.markNodeAsDisabled(rootNode, excludedId);
5197
+ }
5198
+ // Mark pre-selected nodes as selected in the root node structure
5199
+ this.markNodesAsSelected(rootNode);
5200
+ // After tree loads, programmatically select pre-selected nodes
5201
+ const treeComponent = this.tree();
5202
+ if (treeComponent) {
5203
+ const selectedIds = this.selectedNodeIds();
5204
+ selectedIds.forEach((id) => {
5205
+ if (id && id !== 'all') {
5206
+ treeComponent.selectNode(id);
5207
+ }
5208
+ });
5209
+ }
5149
5210
  return [rootNode];
5150
5211
  }
5151
5212
  // Create a minimal node object with just the id (loadChildren only needs node.id)
5152
5213
  const targetNode = {
5153
5214
  id,
5154
- label: '',
5215
+ title: '',
5155
5216
  data: {},
5156
5217
  };
5157
5218
  const childNodes = await this.categoryTreeService.loadChildren(targetNode, this.treeData, this.treeConfig);
5158
5219
  // Cache child node data for getSelectedItems
5159
5220
  childNodes.forEach((node) => {
5160
- if (node.data && node.id) {
5161
- this.nodeDataCache.set(node.id, node.data);
5221
+ const nodeId = String(node['id'] ?? '');
5222
+ const nodeData = node['data'];
5223
+ if (nodeData && nodeId && typeof nodeData === 'object') {
5224
+ this.nodeDataCache.set(nodeId, nodeData);
5162
5225
  }
5163
5226
  });
5227
+ // Mark excluded node as disabled
5228
+ const excludedId = this.excludedNodeId();
5229
+ if (excludedId) {
5230
+ childNodes.forEach((node) => {
5231
+ const nodeId = String(node['id'] ?? '');
5232
+ if (nodeId === excludedId) {
5233
+ node['disabled'] = true;
5234
+ }
5235
+ });
5236
+ }
5237
+ // Mark pre-selected nodes as selected in the child nodes
5238
+ childNodes.forEach((node) => {
5239
+ this.markNodeAsSelectedIfNeeded(node);
5240
+ });
5241
+ // After children load, programmatically select pre-selected nodes
5242
+ const treeComponent = this.tree();
5243
+ if (treeComponent) {
5244
+ const selectedIds = this.selectedNodeIds();
5245
+ childNodes.forEach((node) => {
5246
+ const nodeId = String(node['id'] ?? '');
5247
+ if (nodeId && selectedIds.includes(nodeId) && nodeId !== 'all') {
5248
+ treeComponent.selectNode(nodeId);
5249
+ }
5250
+ });
5251
+ }
5164
5252
  return childNodes;
5165
5253
  };
5166
5254
  }
@@ -5205,94 +5293,125 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5205
5293
  }
5206
5294
  //#endregion
5207
5295
  //#region ---- Public Methods ----
5208
- async handleSearchChange(e) {
5296
+ /**
5297
+ * Handles search input value changes
5298
+ */
5299
+ async handleSearchChange(event) {
5209
5300
  if (!this.treeData || !this.treeConfig) {
5210
5301
  return;
5211
5302
  }
5303
+ // Only process user interactions to avoid unnecessary updates
5304
+ if (!event.isUserInteraction) {
5305
+ return;
5306
+ }
5307
+ const searchTerm = (event.value ?? '').trim();
5308
+ this.searchValue.set(searchTerm);
5309
+ // If search is cleared, reset to normal tree view
5310
+ if (!searchTerm) {
5311
+ this.resetSearch();
5312
+ return;
5313
+ }
5212
5314
  this.loading.set(true);
5213
5315
  try {
5214
- const items = await this.categoryTreeService.searchCategories(e.value, this.treeData, this.treeConfig);
5215
- if (!items) {
5216
- this.searchResults = null;
5217
- return;
5218
- }
5219
- // Store search results for datasource callback
5220
- this.searchResults = items;
5316
+ const items = await this.categoryTreeService.searchCategories(searchTerm, this.treeData, this.treeConfig);
5317
+ // Store search results for datasource callback (even if empty array)
5318
+ this.searchResults = items || null;
5221
5319
  // Cache node data for getSelectedItems
5222
- items.forEach((item) => {
5223
- const id = item[this.treeConfig.valueField || 'id'];
5224
- if (id) {
5225
- this.nodeDataCache.set(id, item);
5226
- }
5227
- });
5320
+ if (items && items.length > 0) {
5321
+ const valueField = this.treeConfig.valueField || 'id';
5322
+ items.forEach((item) => {
5323
+ const id = String(item[valueField] ?? '');
5324
+ if (id) {
5325
+ this.nodeDataCache.set(id, item);
5326
+ }
5327
+ });
5328
+ }
5228
5329
  // Trigger tree refresh
5229
5330
  const treeComponent = this.tree();
5230
5331
  if (treeComponent) {
5231
- treeComponent.refresh?.();
5332
+ treeComponent.refresh();
5232
5333
  }
5233
5334
  }
5234
5335
  catch (error) {
5235
5336
  console.error('Error searching categories:', error);
5337
+ this.resetSearch();
5236
5338
  }
5237
5339
  finally {
5238
5340
  this.loading.set(false);
5239
5341
  }
5240
5342
  }
5343
+ /**
5344
+ * Resets search state and refreshes tree to show normal view
5345
+ */
5346
+ resetSearch() {
5347
+ this.searchResults = null;
5348
+ this.loading.set(false);
5349
+ const treeComponent = this.tree();
5350
+ if (treeComponent) {
5351
+ treeComponent.refresh();
5352
+ }
5353
+ }
5241
5354
  async onNodeToggle(event) {
5242
5355
  // Tree component handles lazy loading via datasource callback
5243
5356
  }
5244
5357
  async onNodeSelect(event) {
5245
5358
  const node = event.node;
5246
- if (!node || node.id === 'all') {
5247
- return;
5248
- }
5249
- // Cache node data for getSelectedItems
5250
- if (node.data) {
5251
- this.nodeDataCache.set(node.id, node.data);
5252
- }
5253
- const currentIds = this.selectedNodeIds();
5254
- if (node.selected) {
5255
- // Add to selection if not already selected
5256
- if (!currentIds.includes(node.id)) {
5257
- this.selectedNodeIds.set([...currentIds, node.id]);
5258
- }
5259
- }
5260
- else {
5261
- // Remove from selection
5262
- this.selectedNodeIds.set(currentIds.filter((id) => id !== node.id));
5263
- }
5264
- }
5265
- handleNodeClick(event) {
5266
- // Extract node from event - could be { node: AXTreeNode } or just AXTreeNode
5267
- const node = event?.node || event;
5268
- if (!node || node.id === 'all') {
5359
+ const nodeId = String(node['id'] ?? '');
5360
+ if (!node || nodeId === 'all') {
5269
5361
  return;
5270
5362
  }
5271
5363
  // Cache node data for getSelectedItems
5272
- if (node.data) {
5273
- this.nodeDataCache.set(node.id, node.data);
5274
- }
5275
- if (this.allowMultiple()) {
5276
- // In multiple mode with checkboxes, clicking the node should toggle the checkbox
5277
- // The checkbox state is handled by onNodeSelect, so we just sync the selection here
5278
- const currentIds = this.selectedNodeIds();
5279
- const isSelected = currentIds.includes(node.id);
5280
- // Toggle selection state
5281
- if (isSelected) {
5282
- this.selectedNodeIds.set(currentIds.filter((id) => id !== node.id));
5283
- }
5284
- else {
5285
- this.selectedNodeIds.set([...currentIds, node.id]);
5364
+ const nodeData = node['data'];
5365
+ if (nodeData && typeof nodeData === 'object' && nodeData !== null && !Array.isArray(nodeData)) {
5366
+ this.nodeDataCache.set(nodeId, nodeData);
5367
+ }
5368
+ }
5369
+ async onSelectionChange(event) {
5370
+ // Update selected node IDs from the tree component's selection state
5371
+ const selectedNodes = event.selectedNodes || [];
5372
+ const selectedIds = selectedNodes.map((node) => String(node['id'] ?? '')).filter((id) => id && id !== 'all');
5373
+ this.selectedNodeIds.set(selectedIds);
5374
+ // Cache node data for all selected nodes
5375
+ selectedNodes.forEach((node) => {
5376
+ const nodeId = String(node['id'] ?? '');
5377
+ const nodeData = node['data'];
5378
+ if (nodeData && nodeId && typeof nodeData === 'object') {
5379
+ this.nodeDataCache.set(nodeId, nodeData);
5286
5380
  }
5287
- }
5288
- else {
5289
- // Single selection - auto-confirm on click
5290
- this.selectedNodeIds.set([node.id]);
5291
- this.close({ selected: this.getSelectedItems() });
5292
- }
5381
+ });
5293
5382
  }
5383
+ // protected handleNodeClick(event: any): void {
5384
+ // // Extract node from event - could be { node: AXTreeNode } or just AXTreeNode
5385
+ // const node: AXTreeViewNode = event?.node || event;
5386
+ // if (!node || node.id === 'all') {
5387
+ // return;
5388
+ // }
5389
+ // // Cache node data for getSelectedItems
5390
+ // if (node.data) {
5391
+ // this.nodeDataCache.set(node.id, node.data);
5392
+ // }
5393
+ // if (this.allowMultiple()) {
5394
+ // // In multiple mode with checkboxes, clicking the node should toggle the checkbox
5395
+ // // The checkbox state is handled by onNodeSelect event, so we just sync the selection here
5396
+ // const currentIds = this.selectedNodeIds();
5397
+ // const isSelected = currentIds.includes(node.id);
5398
+ // // Toggle selection state
5399
+ // // Note: The actual checkbox toggle is handled by the tree component's onNodeSelect event
5400
+ // if (isSelected) {
5401
+ // this.selectedNodeIds.set(currentIds.filter((id) => id !== node.id));
5402
+ // } else {
5403
+ // this.selectedNodeIds.set([...currentIds, node.id]);
5404
+ // }
5405
+ // } else {
5406
+ // // Single selection - auto-confirm on click
5407
+ // this.selectedNodeIds.set([node.id]);
5408
+ // this.close({ selected: this.getSelectedItems() });
5409
+ // }
5410
+ // }
5294
5411
  async onConfirm() {
5295
- this.close({ selected: this.getSelectedItems() });
5412
+ // Use internal selectedNodeIds state which is kept in sync via onNodeSelect events
5413
+ const selectedItems = await this.getSelectedItems();
5414
+ this.close({ selected: selectedItems });
5296
5415
  }
5297
5416
  async onCancel() {
5298
5417
  await this.close();
@@ -5308,9 +5427,9 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5308
5427
  // Fetch node data for pre-selected items that aren't in the cache
5309
5428
  // This ensures getSelectedItems() can retrieve them even if their branches aren't expanded
5310
5429
  await this.loadMissingNodeData(ids);
5311
- // Note: Selection syncing is now handled by the tree component
5312
- // The tree component should handle the selected state based on selectedNodeIds
5313
- // If the tree component requires manual syncing, we may need to trigger a refresh
5430
+ // Note: Selection state is maintained in selectedNodeIds signal
5431
+ // The tree component will sync selection state when nodes are loaded via datasource
5432
+ // We mark nodes as selected in the datasource callback by setting node.selected = true
5314
5433
  }
5315
5434
  /**
5316
5435
  * Loads node data for IDs that are selected but not yet in the cache.
@@ -5347,7 +5466,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5347
5466
  if (res?.items) {
5348
5467
  // Cache the fetched node data
5349
5468
  res.items.forEach((item) => {
5350
- const itemId = item[valueField];
5469
+ const itemId = String(item[valueField] ?? '');
5351
5470
  if (itemId) {
5352
5471
  this.nodeDataCache.set(itemId, item);
5353
5472
  }
@@ -5358,13 +5477,170 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5358
5477
  console.error('Error loading missing node data:', error);
5359
5478
  }
5360
5479
  }
5361
- getSelectedItems() {
5480
+ /**
5481
+ * Marks nodes as selected in the tree structure based on selectedNodeIds.
5482
+ * This ensures pre-selected nodes appear selected when the tree is rendered.
5483
+ */
5484
+ markNodesAsSelected(node) {
5485
+ const selectedIds = this.selectedNodeIds();
5486
+ if (selectedIds.length === 0) {
5487
+ return;
5488
+ }
5489
+ // Mark the node itself if it's selected
5490
+ this.markNodeAsSelectedIfNeeded(node);
5491
+ // Recursively mark children
5492
+ const nodeChildren = node['children'];
5493
+ if (nodeChildren) {
5494
+ nodeChildren.forEach((child) => {
5495
+ this.markNodesAsSelected(child);
5496
+ });
5497
+ }
5498
+ }
5499
+ /**
5500
+ * Marks a single node as selected if it's in the selectedNodeIds list.
5501
+ */
5502
+ markNodeAsSelectedIfNeeded(node) {
5503
+ const selectedIds = this.selectedNodeIds();
5504
+ const nodeId = String(node['id'] ?? '');
5505
+ if (nodeId && selectedIds.includes(nodeId)) {
5506
+ node['selected'] = true;
5507
+ }
5508
+ }
5509
+ /**
5510
+ * Marks a node and its children as disabled if the node ID matches the excluded ID.
5511
+ */
5512
+ markNodeAsDisabled(node, excludedId) {
5513
+ const nodeId = String(node['id'] ?? '');
5514
+ if (nodeId === excludedId) {
5515
+ node['disabled'] = true;
5516
+ }
5517
+ // Recursively mark children
5518
+ const nodeChildren = node['children'];
5519
+ if (nodeChildren) {
5520
+ nodeChildren.forEach((child) => {
5521
+ this.markNodeAsDisabled(child, excludedId);
5522
+ });
5523
+ }
5524
+ }
5525
+ /**
5526
+ * Calculate the full path from root to the selected node.
5527
+ * Returns an array of strings like ["C", "B"] for node B under parent C.
5528
+ */
5529
+ async calculateNodePath(nodeId, nodeData) {
5530
+ if (!this.treeData || !this.treeConfig) {
5531
+ const title = this.getNodeTitle(nodeData);
5532
+ return title ? [title] : [];
5533
+ }
5534
+ const parentKey = this.treeData.categoryEntityDef?.parentKey;
5535
+ if (!parentKey) {
5536
+ // No parent key means flat structure, return just the node title as array
5537
+ const title = this.getNodeTitle(nodeData);
5538
+ return title ? [title] : [];
5539
+ }
5540
+ const path = [];
5541
+ let currentId = nodeId;
5542
+ let currentData = nodeData;
5543
+ const visitedIds = new Set(); // Prevent infinite loops
5544
+ // Build path by traversing up the parent chain
5545
+ while (currentId && currentData && !visitedIds.has(currentId)) {
5546
+ visitedIds.add(currentId);
5547
+ const title = this.getNodeTitle(currentData);
5548
+ if (title) {
5549
+ path.unshift(title); // Add to beginning to maintain hierarchy order
5550
+ }
5551
+ // Get parent ID from current node data
5552
+ const parentId = currentData[parentKey];
5553
+ if (!parentId || parentId === 'all' || parentId === currentId) {
5554
+ break; // Reached root or invalid parent
5555
+ }
5556
+ // Try to get parent data from cache first
5557
+ let parentData = this.nodeDataCache.get(String(parentId));
5558
+ if (!parentData && this.treeData.categoryEntityQueryFunc) {
5559
+ // Parent not in cache, fetch it
5560
+ try {
5561
+ const valueField = this.treeConfig.valueField || 'id';
5562
+ const event = {
5563
+ ...this.treeData.basicQueryEvent,
5564
+ filter: {
5565
+ field: valueField,
5566
+ value: parentId,
5567
+ operator: { type: 'equal' },
5568
+ },
5569
+ };
5570
+ const res = await this.treeData.categoryEntityQueryFunc(event);
5571
+ if (res?.items && res.items.length > 0) {
5572
+ parentData = res.items[0];
5573
+ // Cache the parent data
5574
+ this.nodeDataCache.set(String(parentId), parentData);
5575
+ }
5576
+ }
5577
+ catch (error) {
5578
+ console.error('Error fetching parent node:', error);
5579
+ break;
5580
+ }
5581
+ }
5582
+ if (!parentData) {
5583
+ break; // Parent not found, stop traversal
5584
+ }
5585
+ currentId = String(parentId);
5586
+ currentData = parentData;
5587
+ }
5588
+ // Return path array, or just the node title if no path
5589
+ return path.length > 0 ? path : this.getNodeTitle(nodeData) ? [this.getNodeTitle(nodeData)] : [];
5590
+ }
5591
+ /**
5592
+ * Get the display title for a node.
5593
+ */
5594
+ getNodeTitle(nodeData) {
5595
+ if (!nodeData || !this.treeConfig) {
5596
+ return '';
5597
+ }
5598
+ const textField = this.treeConfig.textField || 'title';
5599
+ return String(nodeData[textField] ?? '');
5600
+ }
5601
+ async getSelectedItems() {
5602
+ // Use tree component's getSelectedNodes if available for more accurate selection
5603
+ const treeComponent = this.tree();
5604
+ if (treeComponent) {
5605
+ const selectedNodes = treeComponent.getSelectedNodes();
5606
+ const items = await Promise.all(selectedNodes.map(async (node) => {
5607
+ const nodeId = String(node['id'] ?? '');
5608
+ if (nodeId === 'all') {
5609
+ return null;
5610
+ }
5611
+ const nodeData = node['data'] || node;
5612
+ if (!nodeData) {
5613
+ return null;
5614
+ }
5615
+ // Calculate path for this node
5616
+ const path = await this.calculateNodePath(nodeId, nodeData);
5617
+ return {
5618
+ ...nodeData,
5619
+ id: nodeId,
5620
+ path: path,
5621
+ };
5622
+ }));
5623
+ return items.filter((item) => item != null);
5624
+ }
5625
+ // Fallback to cached data
5362
5626
  const selectedIds = this.selectedNodeIds();
5363
5627
  if (selectedIds.length === 0) {
5364
5628
  return [];
5365
5629
  }
5366
- // Get node data from cache
5367
- return selectedIds.map((id) => this.nodeDataCache.get(id)).filter((item) => item != null);
5630
+ // Get node data from cache and calculate paths
5631
+ const items = await Promise.all(selectedIds.map(async (id) => {
5632
+ const nodeData = this.nodeDataCache.get(id);
5633
+ if (!nodeData) {
5634
+ return null;
5635
+ }
5636
+ const path = await this.calculateNodePath(id, nodeData);
5637
+ return {
5638
+ ...nodeData,
5639
+ id: id,
5640
+ path: path,
5641
+ };
5642
+ }));
5643
+ return items.filter((item) => item != null);
5368
5644
  }
5369
5645
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryTreeSelectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
5370
5646
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityCategoryTreeSelectorComponent, isStandalone: true, selector: "axp-entity-category-tree-selector", viewQueries: [{ propertyName: "tree", first: true, predicate: ["tree"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
@@ -5380,6 +5656,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5380
5656
  <div class="ax-p-4 ax-border-b">
5381
5657
  <ax-search-box
5382
5658
  (onValueChanged)="handleSearchChange($event)"
5659
+ [value]="searchValue()"
5383
5660
  [delayTime]="300"
5384
5661
  [placeholder]="searchPlaceholder()"
5385
5662
  ></ax-search-box>
@@ -5387,11 +5664,15 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5387
5664
  <div class="ax-flex-1 ax-overflow-auto ax-p-4">
5388
5665
  <ax-tree-view
5389
5666
  [datasource]="datasource"
5390
- [showCheckbox]="allowMultiple()"
5667
+ [dragBehavior]="'none'"
5668
+ [selectMode]="allowMultiple() ? 'multiple' : 'single'"
5669
+ [selectionBehavior]="selectionBehavior()"
5391
5670
  [showIcons]="true"
5671
+ [titleField]="textField()"
5672
+ [idField]="valueField()"
5392
5673
  (onNodeSelect)="onNodeSelect($event)"
5674
+ (onSelectionChange)="onSelectionChange($event)"
5393
5675
  (onNodeToggle)="onNodeToggle($event)"
5394
- (onNodeClick)="handleNodeClick($event)"
5395
5676
  #tree
5396
5677
  >
5397
5678
  </ax-tree-view>
@@ -5403,24 +5684,22 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5403
5684
  </div>
5404
5685
  }
5405
5686
  </div>
5406
- @if (allowMultiple()) {
5407
- <ax-footer>
5408
- <ax-suffix>
5409
- <ax-button
5410
- look="solid"
5411
- [text]="'@general:actions.cancel.title' | translate | async"
5412
- (onClick)="onCancel()"
5413
- ></ax-button>
5414
- <ax-button
5415
- look="solid"
5416
- color="primary"
5417
- [text]="'@general:actions.ok.title' | translate | async"
5418
- (onClick)="onConfirm()"
5419
- ></ax-button>
5420
- </ax-suffix>
5421
- </ax-footer>
5422
- }
5423
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i3$3.AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i4$2.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "component", type: AXTreeViewComponent, selector: "ax-tree-view", inputs: ["datasource", "selectMode", "showCheckbox", "checkChildrenOnSelect", "intermediateState", "checkOnClick", "dragMode", "dragOperationType", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "nodeHeight", "look", "itemTemplate"], outputs: ["datasourceChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5687
+ <ax-footer>
5688
+ <ax-suffix>
5689
+ <ax-button
5690
+ look="solid"
5691
+ [text]="'@general:actions.cancel.title' | translate | async"
5692
+ (onClick)="onCancel()"
5693
+ ></ax-button>
5694
+ <ax-button
5695
+ look="solid"
5696
+ color="primary"
5697
+ [text]="'@general:actions.ok.title' | translate | async"
5698
+ (onClick)="onConfirm()"
5699
+ ></ax-button>
5700
+ </ax-suffix>
5701
+ </ax-footer>
5702
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i3$2.AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i4$1.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "component", type: AXTreeViewComponent, selector: "ax-tree-view", inputs: ["datasource", "selectMode", "showCheckbox", "selectionBehavior", "dragArea", "dragBehavior", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "look", "nodeTemplate", "idField", "titleField", "tooltipField", "iconField", "expandedField", "selectedField", "indeterminateField", "disabledField", "hiddenField", "childrenField", "childrenCountField", "dataField"], outputs: ["datasourceChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onSelectionChange", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5424
5703
  }
5425
5704
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryTreeSelectorComponent, decorators: [{
5426
5705
  type: Component,
@@ -5439,6 +5718,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
5439
5718
  <div class="ax-p-4 ax-border-b">
5440
5719
  <ax-search-box
5441
5720
  (onValueChanged)="handleSearchChange($event)"
5721
+ [value]="searchValue()"
5442
5722
  [delayTime]="300"
5443
5723
  [placeholder]="searchPlaceholder()"
5444
5724
  ></ax-search-box>
@@ -5446,11 +5726,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
5446
5726
  <div class="ax-flex-1 ax-overflow-auto ax-p-4">
5447
5727
  <ax-tree-view
5448
5728
  [datasource]="datasource"
5449
- [showCheckbox]="allowMultiple()"
5729
+ [dragBehavior]="'none'"
5730
+ [selectMode]="allowMultiple() ? 'multiple' : 'single'"
5731
+ [selectionBehavior]="selectionBehavior()"
5450
5732
  [showIcons]="true"
5733
+ [titleField]="textField()"
5734
+ [idField]="valueField()"
5451
5735
  (onNodeSelect)="onNodeSelect($event)"
5736
+ (onSelectionChange)="onSelectionChange($event)"
5452
5737
  (onNodeToggle)="onNodeToggle($event)"
5453
- (onNodeClick)="handleNodeClick($event)"
5454
5738
  #tree
5455
5739
  >
5456
5740
  </ax-tree-view>
@@ -5462,23 +5746,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
5462
5746
  </div>
5463
5747
  }
5464
5748
  </div>
5465
- @if (allowMultiple()) {
5466
- <ax-footer>
5467
- <ax-suffix>
5468
- <ax-button
5469
- look="solid"
5470
- [text]="'@general:actions.cancel.title' | translate | async"
5471
- (onClick)="onCancel()"
5472
- ></ax-button>
5473
- <ax-button
5474
- look="solid"
5475
- color="primary"
5476
- [text]="'@general:actions.ok.title' | translate | async"
5477
- (onClick)="onConfirm()"
5478
- ></ax-button>
5479
- </ax-suffix>
5480
- </ax-footer>
5481
- }
5749
+ <ax-footer>
5750
+ <ax-suffix>
5751
+ <ax-button
5752
+ look="solid"
5753
+ [text]="'@general:actions.cancel.title' | translate | async"
5754
+ (onClick)="onCancel()"
5755
+ ></ax-button>
5756
+ <ax-button
5757
+ look="solid"
5758
+ color="primary"
5759
+ [text]="'@general:actions.ok.title' | translate | async"
5760
+ (onClick)="onConfirm()"
5761
+ ></ax-button>
5762
+ </ax-suffix>
5763
+ </ax-footer>
5482
5764
  `,
5483
5765
  changeDetection: ChangeDetectionStrategy.OnPush,
5484
5766
  imports: [
@@ -5673,20 +5955,397 @@ var entityCategoryWidgetColumn_component = /*#__PURE__*/Object.freeze({
5673
5955
  AXPEntityCategoryWidgetColumnComponent: AXPEntityCategoryWidgetColumnComponent
5674
5956
  });
5675
5957
 
5958
+ //#region ---- Constants ----
5959
+ const DEFAULT_CHARACTER_LIMIT = 20;
5960
+ const DEFAULT_SECTION_LIMIT = 2;
5961
+ const ELLIPSIS_ICON = 'fa-solid fa-ellipsis';
5962
+ const SEPARATOR_ICON = 'fa-solid fa-chevron-right';
5963
+ const EYE_ICON = 'fa-solid fa-eye';
5964
+ const SEPARATOR_WIDTH = 16; // Approximate width of separator icon + gap
5965
+ const ELLIPSIS_WIDTH = 24; // Approximate width of ellipsis icon + gaps
5966
+ const MIN_CHAR_WIDTH = 8; // Minimum character width estimate
5967
+ const MAX_CHAR_WIDTH = 12; // Maximum character width estimate
5968
+ //#endregion
5969
+ class AXPTruncatedBreadcrumbComponent {
5970
+ //#endregion
5971
+ //#region ---- Constructor & Lifecycle ----
5972
+ constructor() {
5973
+ //#region ---- Component Inputs ----
5974
+ /**
5975
+ * Array of path sections to display
5976
+ */
5977
+ this.sections = input([], ...(ngDevMode ? [{ debugName: "sections" }] : []));
5978
+ /**
5979
+ * Maximum number of characters per section.
5980
+ * Can be a number or 'auto' to calculate based on available space.
5981
+ */
5982
+ this.characterLimit = input(DEFAULT_CHARACTER_LIMIT, ...(ngDevMode ? [{ debugName: "characterLimit" }] : []));
5983
+ /**
5984
+ * Maximum number of sections to display before showing ellipsis.
5985
+ * Can be a number or 'auto' to calculate based on available space.
5986
+ */
5987
+ this.sectionLimit = input(DEFAULT_SECTION_LIMIT, ...(ngDevMode ? [{ debugName: "sectionLimit" }] : []));
5988
+ /**
5989
+ * Icon class for separator between sections
5990
+ */
5991
+ this.separatorIcon = input(SEPARATOR_ICON, ...(ngDevMode ? [{ debugName: "separatorIcon" }] : []));
5992
+ /**
5993
+ * Icon class for ellipsis
5994
+ */
5995
+ this.ellipsisIcon = input(ELLIPSIS_ICON, ...(ngDevMode ? [{ debugName: "ellipsisIcon" }] : []));
5996
+ /**
5997
+ * Icon class for eye icon (collapse button)
5998
+ */
5999
+ this.eyeIcon = input(EYE_ICON, ...(ngDevMode ? [{ debugName: "eyeIcon" }] : []));
6000
+ //#endregion
6001
+ //#region ---- View Queries ----
6002
+ this.container = viewChild('container', ...(ngDevMode ? [{ debugName: "container" }] : []));
6003
+ //#endregion
6004
+ //#region ---- Component State ----
6005
+ this.isExpanded = signal(false, ...(ngDevMode ? [{ debugName: "isExpanded" }] : []));
6006
+ this.containerWidth = signal(0, ...(ngDevMode ? [{ debugName: "containerWidth" }] : []));
6007
+ this.resizeObserver = null;
6008
+ //#endregion
6009
+ //#region ---- Computed Properties ----
6010
+ /**
6011
+ * Effective character limit (calculated if 'auto', otherwise uses input value)
6012
+ */
6013
+ this.effectiveCharacterLimit = computed(() => {
6014
+ const limit = this.characterLimit();
6015
+ if (limit === 'auto') {
6016
+ return this.calculateAutoCharacterLimit();
6017
+ }
6018
+ return limit;
6019
+ }, ...(ngDevMode ? [{ debugName: "effectiveCharacterLimit" }] : []));
6020
+ /**
6021
+ * Effective section limit (calculated if 'auto', otherwise uses input value)
6022
+ */
6023
+ this.effectiveSectionLimit = computed(() => {
6024
+ const limit = this.sectionLimit();
6025
+ if (limit === 'auto') {
6026
+ return this.calculateAutoSectionLimit();
6027
+ }
6028
+ return limit;
6029
+ }, ...(ngDevMode ? [{ debugName: "effectiveSectionLimit" }] : []));
6030
+ /**
6031
+ * All sections with truncated text (for collapsed display)
6032
+ */
6033
+ this.allSections = computed(() => {
6034
+ if (this.isExpanded()) {
6035
+ return this.sections().map((section) => ({ text: section, original: section }));
6036
+ }
6037
+ const charLimit = this.effectiveCharacterLimit();
6038
+ return this.sections().map((section) => ({
6039
+ text: this.truncateText(section, charLimit),
6040
+ original: section,
6041
+ }));
6042
+ }, ...(ngDevMode ? [{ debugName: "allSections" }] : []));
6043
+ /**
6044
+ * All sections with full text (for expanded display)
6045
+ */
6046
+ this.allSectionsFull = computed(() => {
6047
+ return this.sections();
6048
+ }, ...(ngDevMode ? [{ debugName: "allSectionsFull" }] : []));
6049
+ /**
6050
+ * Sections to display (first N sections) when collapsed
6051
+ */
6052
+ this.displayedSections = computed(() => {
6053
+ const limit = this.effectiveSectionLimit();
6054
+ const sections = this.allSections();
6055
+ return sections.slice(0, limit);
6056
+ }, ...(ngDevMode ? [{ debugName: "displayedSections" }] : []));
6057
+ /**
6058
+ * Last section (always shown if there are hidden sections)
6059
+ */
6060
+ this.lastSection = computed(() => {
6061
+ const sections = this.allSections();
6062
+ return sections[sections.length - 1] || { text: '', original: '' };
6063
+ }, ...(ngDevMode ? [{ debugName: "lastSection" }] : []));
6064
+ /**
6065
+ * Check if there are hidden sections
6066
+ */
6067
+ this.hasHiddenSections = computed(() => {
6068
+ const totalSections = this.sections().length;
6069
+ const limit = this.effectiveSectionLimit();
6070
+ // If we have more sections than the limit, we need to show ellipsis + last section
6071
+ // Example: total=2, limit=1 -> show [section0, ellipsis, section1]
6072
+ // Example: total=3, limit=1 -> show [section0, ellipsis, section2]
6073
+ // Example: total=2, limit=2 -> show [section0, section1] (no ellipsis)
6074
+ return totalSections > limit;
6075
+ }, ...(ngDevMode ? [{ debugName: "hasHiddenSections" }] : []));
6076
+ afterNextRender(() => {
6077
+ this.initializeResizeObserver();
6078
+ });
6079
+ }
6080
+ ngOnDestroy() {
6081
+ if (this.resizeObserver) {
6082
+ this.resizeObserver.disconnect();
6083
+ this.resizeObserver = null;
6084
+ }
6085
+ }
6086
+ //#endregion
6087
+ //#region ---- Public Methods ----
6088
+ /**
6089
+ * Handles click on separator icon to expand
6090
+ */
6091
+ handleSeparatorClick(event) {
6092
+ if (!this.hasHiddenSections()) {
6093
+ return;
6094
+ }
6095
+ event.stopPropagation();
6096
+ this.isExpanded.set(true);
6097
+ }
6098
+ /**
6099
+ * Handles click on ellipsis icon to expand
6100
+ */
6101
+ handleEllipsisClick(event) {
6102
+ event.stopPropagation();
6103
+ this.isExpanded.set(true);
6104
+ }
6105
+ /**
6106
+ * Handles click on eye icon to collapse
6107
+ */
6108
+ handleCollapseClick(event) {
6109
+ event.stopPropagation();
6110
+ this.isExpanded.set(false);
6111
+ }
6112
+ //#endregion
6113
+ //#region ---- Private Methods ----
6114
+ /**
6115
+ * Initializes ResizeObserver to track container width
6116
+ */
6117
+ initializeResizeObserver() {
6118
+ const containerElement = this.container()?.nativeElement;
6119
+ if (!containerElement) {
6120
+ return;
6121
+ }
6122
+ // Set initial width
6123
+ this.containerWidth.set(containerElement.offsetWidth);
6124
+ // Create ResizeObserver
6125
+ this.resizeObserver = new ResizeObserver((entries) => {
6126
+ for (const entry of entries) {
6127
+ const width = entry.contentRect.width;
6128
+ this.containerWidth.set(width);
6129
+ }
6130
+ });
6131
+ // Observe container
6132
+ this.resizeObserver.observe(containerElement);
6133
+ }
6134
+ /**
6135
+ * Calculates automatic character limit based on available space
6136
+ */
6137
+ calculateAutoCharacterLimit() {
6138
+ const width = this.containerWidth();
6139
+ if (width === 0) {
6140
+ return DEFAULT_CHARACTER_LIMIT;
6141
+ }
6142
+ // Estimate: assume average character width
6143
+ const avgCharWidth = (MIN_CHAR_WIDTH + MAX_CHAR_WIDTH) / 2;
6144
+ // Reserve space for separators, ellipsis, and padding
6145
+ const reservedSpace = SEPARATOR_WIDTH * 2 + ELLIPSIS_WIDTH + 32; // Extra padding
6146
+ const availableSpace = width - reservedSpace;
6147
+ // Calculate how many characters can fit
6148
+ const estimatedChars = Math.floor(availableSpace / avgCharWidth);
6149
+ return Math.max(10, Math.min(estimatedChars, 100)); // Clamp between 10 and 100
6150
+ }
6151
+ /**
6152
+ * Calculates automatic section limit based on available space
6153
+ */
6154
+ calculateAutoSectionLimit() {
6155
+ const width = this.containerWidth();
6156
+ const sections = this.sections();
6157
+ if (width === 0 || sections.length === 0) {
6158
+ return DEFAULT_SECTION_LIMIT;
6159
+ }
6160
+ // Calculate average section length
6161
+ const avgSectionLength = sections.reduce((sum, section) => sum + section.length, 0) / sections.length;
6162
+ const charLimit = this.effectiveCharacterLimit();
6163
+ const truncatedLength = Math.min(avgSectionLength, charLimit);
6164
+ // Estimate section width: text + separator
6165
+ const avgCharWidth = (MIN_CHAR_WIDTH + MAX_CHAR_WIDTH) / 2;
6166
+ const sectionWidth = truncatedLength * avgCharWidth + SEPARATOR_WIDTH;
6167
+ // First, check if all sections can fit without ellipsis
6168
+ const totalWidthNeeded = sections.length * sectionWidth;
6169
+ if (totalWidthNeeded <= width - 32) {
6170
+ // All sections fit, return full length
6171
+ return sections.length;
6172
+ }
6173
+ // Reserve space for ellipsis and last section
6174
+ const lastSectionLength = Math.min(sections[sections.length - 1]?.length || 0, charLimit);
6175
+ const lastSectionWidth = lastSectionLength * avgCharWidth;
6176
+ const reservedSpace = ELLIPSIS_WIDTH + SEPARATOR_WIDTH * 2 + lastSectionWidth + 32; // Extra padding
6177
+ const availableSpace = width - reservedSpace;
6178
+ // Calculate how many sections can fit
6179
+ const estimatedSections = Math.floor(availableSpace / sectionWidth);
6180
+ // At least 1, but can return up to sections.length if all fit
6181
+ return Math.max(1, Math.min(estimatedSections, sections.length));
6182
+ }
6183
+ /**
6184
+ * Truncates text to character limit with ellipsis
6185
+ */
6186
+ truncateText(text, limit) {
6187
+ if (!text || text.length <= limit) {
6188
+ return text;
6189
+ }
6190
+ return text.substring(0, limit) + '...';
6191
+ }
6192
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPTruncatedBreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6193
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPTruncatedBreadcrumbComponent, isStandalone: true, selector: "axp-truncated-breadcrumb", inputs: { sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, characterLimit: { classPropertyName: "characterLimit", publicName: "characterLimit", isSignal: true, isRequired: false, transformFunction: null }, sectionLimit: { classPropertyName: "sectionLimit", publicName: "sectionLimit", isSignal: true, isRequired: false, transformFunction: null }, separatorIcon: { classPropertyName: "separatorIcon", publicName: "separatorIcon", isSignal: true, isRequired: false, transformFunction: null }, ellipsisIcon: { classPropertyName: "ellipsisIcon", publicName: "ellipsisIcon", isSignal: true, isRequired: false, transformFunction: null }, eyeIcon: { classPropertyName: "eyeIcon", publicName: "eyeIcon", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ax-block" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, isSignal: true }], ngImport: i0, template: `
6194
+ <div class="ax-flex ax-items-center ax-gap-2 ax-flex-wrap" #container>
6195
+ @if (sections().length === 0) {
6196
+ <span class="ax-text-muted">---</span>
6197
+ } @else {
6198
+ @if (isExpanded()) {
6199
+ <!-- Expanded view with eye icon at the end to collapse -->
6200
+ @for (section of allSectionsFull(); track $index; let isLast = $last) {
6201
+ <span class="ax-text-sm">{{ section }}</span>
6202
+ @if (!isLast) {
6203
+ <ax-icon [class]="separatorIcon()" class="ax-text-muted ax-text-xs"></ax-icon>
6204
+ }
6205
+ }
6206
+ <span
6207
+ class="ax-text-sm ax-text-primary ax-cursor-pointer hover:ax-opacity-75 ax-transition-opacity ax-ml-1"
6208
+ (click)="handleCollapseClick($event)"
6209
+ title="Collapse breadcrumb"
6210
+ >
6211
+ <ax-icon [class]="eyeIcon()" class="ax-text-primary"></ax-icon>
6212
+ </span>
6213
+ } @else {
6214
+ <!-- Collapsed view with limits -->
6215
+ @for (section of displayedSections(); track $index; let isLast = $last) {
6216
+ <span class="ax-text-sm">{{ section.text }}</span>
6217
+ @if (!isLast) {
6218
+ <ax-icon
6219
+ [class]="separatorIcon()"
6220
+ [class.ax-cursor-pointer]="hasHiddenSections()"
6221
+ [class.hover:ax-opacity-75]="hasHiddenSections()"
6222
+ class="ax-text-muted ax-text-xs ax-transition-opacity"
6223
+ (click)="handleSeparatorClick($event)"
6224
+ [title]="hasHiddenSections() ? 'Expand to show full path' : ''"
6225
+ ></ax-icon>
6226
+ }
6227
+ }
6228
+
6229
+ @if (hasHiddenSections()) {
6230
+ <ax-icon
6231
+ [class]="separatorIcon()"
6232
+ [class.ax-cursor-pointer]="true"
6233
+ [class.hover:ax-opacity-75]="true"
6234
+ class="ax-text-muted ax-text-xs ax-transition-opacity"
6235
+ (click)="handleSeparatorClick($event)"
6236
+ title="Expand to show full path"
6237
+ ></ax-icon>
6238
+ <span
6239
+ class="ax-text-sm ax-text-primary ax-cursor-pointer hover:ax-opacity-75 ax-transition-opacity"
6240
+ (click)="handleEllipsisClick($event)"
6241
+ title="Expand to show full path"
6242
+ >
6243
+ <ax-icon [class]="ellipsisIcon()" class="ax-text-primary"></ax-icon>
6244
+ </span>
6245
+ <ax-icon
6246
+ [class]="separatorIcon()"
6247
+ [class.ax-cursor-pointer]="true"
6248
+ [class.hover:ax-opacity-75]="true"
6249
+ class="ax-text-muted ax-text-xs ax-transition-opacity"
6250
+ (click)="handleSeparatorClick($event)"
6251
+ title="Expand to show full path"
6252
+ ></ax-icon>
6253
+ <span class="ax-text-sm">{{ lastSection().text }}</span>
6254
+ }
6255
+ }
6256
+ }
6257
+ </div>
6258
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6259
+ }
6260
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPTruncatedBreadcrumbComponent, decorators: [{
6261
+ type: Component,
6262
+ args: [{
6263
+ selector: 'axp-truncated-breadcrumb',
6264
+ standalone: true,
6265
+ encapsulation: ViewEncapsulation.None,
6266
+ host: {
6267
+ class: 'ax-block',
6268
+ },
6269
+ template: `
6270
+ <div class="ax-flex ax-items-center ax-gap-2 ax-flex-wrap" #container>
6271
+ @if (sections().length === 0) {
6272
+ <span class="ax-text-muted">---</span>
6273
+ } @else {
6274
+ @if (isExpanded()) {
6275
+ <!-- Expanded view with eye icon at the end to collapse -->
6276
+ @for (section of allSectionsFull(); track $index; let isLast = $last) {
6277
+ <span class="ax-text-sm">{{ section }}</span>
6278
+ @if (!isLast) {
6279
+ <ax-icon [class]="separatorIcon()" class="ax-text-muted ax-text-xs"></ax-icon>
6280
+ }
6281
+ }
6282
+ <span
6283
+ class="ax-text-sm ax-text-primary ax-cursor-pointer hover:ax-opacity-75 ax-transition-opacity ax-ml-1"
6284
+ (click)="handleCollapseClick($event)"
6285
+ title="Collapse breadcrumb"
6286
+ >
6287
+ <ax-icon [class]="eyeIcon()" class="ax-text-primary"></ax-icon>
6288
+ </span>
6289
+ } @else {
6290
+ <!-- Collapsed view with limits -->
6291
+ @for (section of displayedSections(); track $index; let isLast = $last) {
6292
+ <span class="ax-text-sm">{{ section.text }}</span>
6293
+ @if (!isLast) {
6294
+ <ax-icon
6295
+ [class]="separatorIcon()"
6296
+ [class.ax-cursor-pointer]="hasHiddenSections()"
6297
+ [class.hover:ax-opacity-75]="hasHiddenSections()"
6298
+ class="ax-text-muted ax-text-xs ax-transition-opacity"
6299
+ (click)="handleSeparatorClick($event)"
6300
+ [title]="hasHiddenSections() ? 'Expand to show full path' : ''"
6301
+ ></ax-icon>
6302
+ }
6303
+ }
6304
+
6305
+ @if (hasHiddenSections()) {
6306
+ <ax-icon
6307
+ [class]="separatorIcon()"
6308
+ [class.ax-cursor-pointer]="true"
6309
+ [class.hover:ax-opacity-75]="true"
6310
+ class="ax-text-muted ax-text-xs ax-transition-opacity"
6311
+ (click)="handleSeparatorClick($event)"
6312
+ title="Expand to show full path"
6313
+ ></ax-icon>
6314
+ <span
6315
+ class="ax-text-sm ax-text-primary ax-cursor-pointer hover:ax-opacity-75 ax-transition-opacity"
6316
+ (click)="handleEllipsisClick($event)"
6317
+ title="Expand to show full path"
6318
+ >
6319
+ <ax-icon [class]="ellipsisIcon()" class="ax-text-primary"></ax-icon>
6320
+ </span>
6321
+ <ax-icon
6322
+ [class]="separatorIcon()"
6323
+ [class.ax-cursor-pointer]="true"
6324
+ [class.hover:ax-opacity-75]="true"
6325
+ class="ax-text-muted ax-text-xs ax-transition-opacity"
6326
+ (click)="handleSeparatorClick($event)"
6327
+ title="Expand to show full path"
6328
+ ></ax-icon>
6329
+ <span class="ax-text-sm">{{ lastSection().text }}</span>
6330
+ }
6331
+ }
6332
+ }
6333
+ </div>
6334
+ `,
6335
+ changeDetection: ChangeDetectionStrategy.OnPush,
6336
+ imports: [CommonModule, AXDecoratorModule],
6337
+ }]
6338
+ }], ctorParameters: () => [], propDecorators: { sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], characterLimit: [{ type: i0.Input, args: [{ isSignal: true, alias: "characterLimit", required: false }] }], sectionLimit: [{ type: i0.Input, args: [{ isSignal: true, alias: "sectionLimit", required: false }] }], separatorIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "separatorIcon", required: false }] }], ellipsisIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "ellipsisIcon", required: false }] }], eyeIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "eyeIcon", required: false }] }], container: [{ type: i0.ViewChild, args: ['container', { isSignal: true }] }] } });
6339
+
5676
6340
  class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
5677
6341
  constructor() {
5678
6342
  super(...arguments);
5679
6343
  //#region ---- Services & Dependencies ----
5680
6344
  this.entityResolver = inject(AXPEntityResolver);
5681
- this.formatService = inject(AXFormatService);
5682
6345
  this.popupService = inject(AXPopupService);
5683
6346
  this.translateService = inject(AXTranslationService);
5684
6347
  this.cdr = inject(ChangeDetectorRef);
5685
6348
  //#endregion
5686
- //#region ---- View Queries ----
5687
- this.selectBox = viewChild('selectBox', ...(ngDevMode ? [{ debugName: "selectBox" }] : []));
5688
- this.tagBox = viewChild('tagBoxComponent', ...(ngDevMode ? [{ debugName: "tagBox" }] : []));
5689
- //#endregion
5690
6349
  //#region ---- Computed Properties ----
5691
6350
  this.entity = computed(() => this.options()['entity'] ?? '', ...(ngDevMode ? [{ debugName: "entity" }] : []));
5692
6351
  this.multiple = computed(() => (this.options()['multiple'] ?? false), ...(ngDevMode ? [{ debugName: "multiple" }] : []));
@@ -5695,7 +6354,8 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
5695
6354
  this.valueField = computed(() => this.options()['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
5696
6355
  this.expose = computed(() => this.options()['expose'], ...(ngDevMode ? [{ debugName: "expose" }] : []));
5697
6356
  this.allowClear = computed(() => (this.options()['allowClear'] ?? false), ...(ngDevMode ? [{ debugName: "allowClear" }] : []));
5698
- this.look = computed(() => this.options()['look'] ?? 'lookup', ...(ngDevMode ? [{ debugName: "look" }] : []));
6357
+ this.characterLimit = computed(() => this.options()['characterLimit'] ?? 'auto', ...(ngDevMode ? [{ debugName: "characterLimit" }] : []));
6358
+ this.sectionLimit = computed(() => this.options()['sectionLimit'] ?? 'auto', ...(ngDevMode ? [{ debugName: "sectionLimit" }] : []));
5699
6359
  this.defaultTextField = computed(() => {
5700
6360
  const textField = this.entityDef()?.formats.lookup ?? this.entityDef()?.properties.find((c) => c.name != 'id')?.name ?? 'title';
5701
6361
  return textField;
@@ -5712,27 +6372,9 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
5712
6372
  this.selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
5713
6373
  this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
5714
6374
  this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
5715
- this.searchTerm = signal(null, ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
5716
6375
  //#endregion
5717
6376
  //#region ---- Private Properties ----
5718
6377
  this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : []));
5719
- this.dataSource = computed(() => {
5720
- const entity = this.entityDef();
5721
- if (!entity)
5722
- return null;
5723
- return new AXDataSource({
5724
- byKey: (key) => {
5725
- const func = entity.queries.byKey.execute;
5726
- return func();
5727
- },
5728
- load: (e) => {
5729
- const func = entity.queries.list?.execute;
5730
- return func(e);
5731
- },
5732
- pageSize: 10,
5733
- key: 'id',
5734
- });
5735
- }, ...(ngDevMode ? [{ debugName: "dataSource" }] : []));
5736
6378
  //#endregion
5737
6379
  //#region ---- Effects ----
5738
6380
  this.#efEntity = effect(async () => {
@@ -5743,7 +6385,13 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
5743
6385
  this.entityDef.set(await this.entityResolver.get(module, entity));
5744
6386
  }, ...(ngDevMode ? [{ debugName: "#efEntity" }] : []));
5745
6387
  this.#efValue = effect(() => {
5746
- if (this.getValue()) {
6388
+ const value = this.getValue();
6389
+ const entity = this.entityDef();
6390
+ // Wait for entity definition to be loaded before processing value
6391
+ if (!entity) {
6392
+ return;
6393
+ }
6394
+ if (value) {
5747
6395
  this.findByValue();
5748
6396
  }
5749
6397
  else {
@@ -5775,9 +6423,16 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
5775
6423
  #efSearchPlaceholder;
5776
6424
  //#endregion
5777
6425
  //#region ---- Public Methods ----
5778
- handleOnClick(e) {
6426
+ handleAddClick(e) {
5779
6427
  this.showTreeSelector();
5780
6428
  }
6429
+ handleRemoveItemClick(event, item) {
6430
+ event.nativeEvent.stopPropagation();
6431
+ this.removeItem(item);
6432
+ }
6433
+ handleClearClick() {
6434
+ this.clear();
6435
+ }
5781
6436
  async showTreeSelector() {
5782
6437
  this.isOpen.set(true);
5783
6438
  const currentValue = this.getValue();
@@ -5786,21 +6441,61 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
5786
6441
  .map((v) => String(extractValue(v, this.valueField())))
5787
6442
  .filter((id) => id && id !== 'all')
5788
6443
  : [];
6444
+ // Get current entity ID from context (if editing an entity)
6445
+ const currentEntityId = this.contextService.getValue('id');
6446
+ const excludedNodeId = currentEntityId ? String(currentEntityId) : undefined;
5789
6447
  try {
5790
6448
  const result = await this.popupService.open(AXPEntityCategoryTreeSelectorComponent, {
5791
6449
  title: `${this.translateService.translateSync('@general:widgets.lookup.search')} ${this.translateService.translateSync(this.entityDef()?.formats.plural ?? '')}`,
5792
- size: 'lg',
6450
+ size: 'md',
5793
6451
  data: {
5794
6452
  entityKey: signal(this.entity()),
5795
6453
  textField: signal(this.textField()),
5796
6454
  valueField: signal(this.valueField()),
5797
- allowMultiple: signal(this.multiple() ?? false),
6455
+ allowMultiple: signal(this.multiple()),
5798
6456
  selectedValues: signal(selectedIds),
5799
6457
  searchPlaceholder: signal(this.searchPlaceholderText()),
6458
+ excludedNodeId: signal(excludedNodeId),
5800
6459
  },
5801
6460
  });
5802
6461
  if (result?.data?.selected && Array.isArray(result.data.selected)) {
5803
- this.setItems(result.data.selected);
6462
+ if (this.multiple()) {
6463
+ // In multiple mode, merge with existing selection
6464
+ const existingItems = this.selectedItems();
6465
+ const newItems = result.data.selected;
6466
+ // Create a map of existing items by their ID
6467
+ const existingItemsMap = new Map();
6468
+ existingItems.forEach((item) => {
6469
+ const id = String(get(item, this.valueField()) ?? '');
6470
+ if (id) {
6471
+ existingItemsMap.set(id, item);
6472
+ }
6473
+ });
6474
+ // Merge items, preferring new items (with paths) over existing ones
6475
+ const mergedItems = [];
6476
+ const processedIds = new Set();
6477
+ // First, add all new items (they have paths)
6478
+ newItems.forEach((item) => {
6479
+ const id = String(get(item, this.valueField()) ?? '');
6480
+ if (id && !processedIds.has(id)) {
6481
+ mergedItems.push(item);
6482
+ processedIds.add(id);
6483
+ }
6484
+ });
6485
+ // Then, add existing items that weren't in new items (preserve them)
6486
+ existingItems.forEach((item) => {
6487
+ const id = String(get(item, this.valueField()) ?? '');
6488
+ if (id && !processedIds.has(id)) {
6489
+ mergedItems.push(item);
6490
+ processedIds.add(id);
6491
+ }
6492
+ });
6493
+ await this.setItems(mergedItems);
6494
+ }
6495
+ else {
6496
+ // In single mode, replace selection
6497
+ await this.setItems(result.data.selected);
6498
+ }
5804
6499
  }
5805
6500
  }
5806
6501
  catch (error) {
@@ -5808,77 +6503,98 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
5808
6503
  }
5809
6504
  finally {
5810
6505
  this.isOpen.set(false);
5811
- this.selectBox()?.focus();
5812
6506
  }
5813
6507
  }
5814
- selectBoxValueChange(e) {
5815
- const items = e.component.selectedItems;
5816
- this.setItems(items);
5817
- }
5818
- handleValueChange(e) {
5819
- if (e.isUserInteraction) {
5820
- if (isNil(e.value) || (Array.isArray(e.value) && e.value.length === 0)) {
5821
- this.clear();
5822
- }
5823
- else {
5824
- this.setValue(this.singleOrMultiple(e.value));
5825
- }
6508
+ async removeItem(item) {
6509
+ if (this.disabled()) {
6510
+ return;
5826
6511
  }
5827
- }
5828
- handleSearchInputChange(e) {
5829
- if (e.isUserInteraction) {
5830
- this.searchTerm.set(e.value ?? '');
6512
+ const currentItems = this.selectedItems();
6513
+ const itemId = get(item, this.valueField());
6514
+ const filteredItems = currentItems.filter((i) => get(i, this.valueField()) !== itemId);
6515
+ if (filteredItems.length === 0) {
6516
+ this.clear();
5831
6517
  }
5832
- }
5833
- handleKeyUp(e) {
5834
- const keyEvent = e.nativeEvent;
5835
- if (keyEvent.code == 'ArrowDown') {
5836
- this.showTreeSelector();
6518
+ else {
6519
+ await this.setItems(filteredItems);
5837
6520
  }
5838
6521
  }
5839
- handleOnBlur(e) {
5840
- setTimeout(() => {
5841
- if (!this.isOpen()) {
5842
- this.clearInput();
5843
- }
5844
- }, 100);
5845
- }
5846
- handleClearClick() {
5847
- this.clear();
5848
- }
5849
6522
  clear() {
5850
6523
  this.setValue(null);
5851
- this.clearInput();
5852
6524
  this.selectedItems.set([]);
5853
- }
5854
- clearInput() {
5855
- this.tagBox()?.inputValue.set('');
5856
- this.searchTerm.set('');
6525
+ this.cdr.markForCheck();
5857
6526
  }
5858
6527
  //#endregion
5859
6528
  //#region ---- Private Methods ----
5860
6529
  async findByValue() {
5861
6530
  this.isLoading.set(true);
5862
6531
  const rawValue = this.getValue();
6532
+ // If no value, clear and return
6533
+ if (!rawValue) {
6534
+ this.setItems([]);
6535
+ this.isLoading.set(false);
6536
+ return;
6537
+ }
5863
6538
  const values = castArray(rawValue);
5864
6539
  const byKey = this.entityDef()?.queries.byKey?.execute;
5865
- if (byKey && values.length) {
6540
+ if (!byKey) {
6541
+ this.setItems([]);
6542
+ this.isLoading.set(false);
6543
+ return;
6544
+ }
6545
+ if (values.length === 0) {
6546
+ this.setItems([]);
6547
+ this.isLoading.set(false);
6548
+ return;
6549
+ }
6550
+ try {
5866
6551
  if (this.multiple()) {
5867
- const items = await Promise.all(values.map((value) => byKey(extractValue(value, this.valueField()))));
5868
- this.setItems(items);
6552
+ // Filter out null/undefined/empty values
6553
+ const validValues = values.filter((v) => v != null && v !== '' && v !== 'all');
6554
+ if (validValues.length === 0) {
6555
+ this.setItems([]);
6556
+ this.isLoading.set(false);
6557
+ return;
6558
+ }
6559
+ const items = await Promise.all(validValues.map((value) => {
6560
+ const id = extractValue(value, this.valueField());
6561
+ if (!id)
6562
+ return null;
6563
+ return byKey(id);
6564
+ }));
6565
+ // Filter out null results
6566
+ const validItems = items.filter((item) => item != null);
6567
+ // Calculate paths for items loaded from value
6568
+ const itemsWithPaths = await Promise.all(validItems.map((item) => this.calculateItemPath(item)));
6569
+ this.setItems(itemsWithPaths);
5869
6570
  }
5870
6571
  else {
5871
6572
  const id = extractValue(values[0], this.valueField());
6573
+ if (!id || id === 'all') {
6574
+ this.setItems([]);
6575
+ this.isLoading.set(false);
6576
+ return;
6577
+ }
5872
6578
  const item = await byKey(id);
5873
- this.setItems(item);
6579
+ if (!item) {
6580
+ this.setItems([]);
6581
+ this.isLoading.set(false);
6582
+ return;
6583
+ }
6584
+ // Calculate path for item loaded from value
6585
+ const itemWithPath = await this.calculateItemPath(item);
6586
+ this.setItems(itemWithPath);
5874
6587
  }
5875
6588
  }
5876
- else {
6589
+ catch (error) {
6590
+ console.error('Error loading category items from value:', error);
5877
6591
  this.setItems([]);
5878
6592
  }
5879
- this.isLoading.set(false);
6593
+ finally {
6594
+ this.isLoading.set(false);
6595
+ }
5880
6596
  }
5881
- setItems(items) {
6597
+ async setItems(items) {
5882
6598
  if (!items || items.length == 0) {
5883
6599
  this.selectedItems.set([]);
5884
6600
  this.setValue(null);
@@ -5886,24 +6602,31 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
5886
6602
  return;
5887
6603
  }
5888
6604
  items = castArray(items);
5889
- this.clearInput();
5890
- this.selectedItems.set(items);
5891
- const keys = items.map((item) => get(item, this.valueField()));
5892
- const text = items.map((item) => get(item, this.displayField()));
6605
+ // Ensure all items have paths
6606
+ const itemsWithPaths = await Promise.all(items.map(async (item) => {
6607
+ // If item already has a path array, return it as is
6608
+ if (item.path && Array.isArray(item.path) && item.path.length > 0) {
6609
+ return item;
6610
+ }
6611
+ // Otherwise, calculate the path
6612
+ return await this.calculateItemPath(item);
6613
+ }));
6614
+ this.selectedItems.set(itemsWithPaths);
6615
+ const keys = itemsWithPaths.map((item) => get(item, this.valueField()));
5893
6616
  // Extract data from valueField and set context by expose path
5894
6617
  if (this.expose()) {
5895
6618
  const exposeValue = castArray(this.expose());
5896
6619
  const itemToExpose = {};
5897
6620
  exposeValue.forEach((i) => {
5898
6621
  if (typeof i == 'string') {
5899
- const values = items.map((item) => set({}, i, get(item, i)));
6622
+ const values = itemsWithPaths.map((item) => set({}, i, get(item, i)));
5900
6623
  setSmart(itemToExpose, i, this.singleOrMultiple(values));
5901
6624
  }
5902
6625
  else {
5903
6626
  // Extract data from item by source path and set context by target path
5904
6627
  const values = this.multiple()
5905
- ? items.map((item) => set({}, i.source, get(item, i.source)))
5906
- : items.map((item) => get(item, i.source));
6628
+ ? itemsWithPaths.map((item) => set({}, i.source, get(item, i.source)))
6629
+ : itemsWithPaths.map((item) => get(item, i.source));
5907
6630
  setSmart(itemToExpose, i.target, this.singleOrMultiple(values));
5908
6631
  }
5909
6632
  });
@@ -5914,232 +6637,230 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
5914
6637
  else {
5915
6638
  this.setValue(this.singleOrMultiple(keys));
5916
6639
  }
5917
- // Trigger change detection to update selectbox/tagbox
6640
+ // Trigger change detection
5918
6641
  this.cdr.markForCheck();
5919
6642
  }
5920
6643
  singleOrMultiple(values) {
5921
6644
  return this.multiple() ? values : values[0];
5922
6645
  }
5923
- getTagLabel(item) {
6646
+ getItemLabel(item) {
5924
6647
  if (!item) {
5925
6648
  return '';
5926
6649
  }
6650
+ // If path is available as array, join it with customizable separator
6651
+ if (item.path && Array.isArray(item.path) && item.path.length > 0) {
6652
+ return this.joinPath(item.path);
6653
+ }
6654
+ // Fall back to display field if no path
5927
6655
  return get(item, this.displayField()) ?? '';
5928
6656
  }
6657
+ /**
6658
+ * Get item path as array for breadcrumb component
6659
+ */
6660
+ getItemPath(item) {
6661
+ if (!item) {
6662
+ return [];
6663
+ }
6664
+ // If path is available as array, return it
6665
+ if (item.path && Array.isArray(item.path) && item.path.length > 0) {
6666
+ return item.path;
6667
+ }
6668
+ // Fall back to display field if no path
6669
+ const displayValue = get(item, this.displayField());
6670
+ return displayValue ? [String(displayValue)] : [];
6671
+ }
6672
+ /**
6673
+ * Join path array with separator.
6674
+ * Override this method to customize the separator (e.g., " > ", " -> ", " / ")
6675
+ */
6676
+ joinPath(path) {
6677
+ return path.join(' > ');
6678
+ }
6679
+ getItemId(item) {
6680
+ if (!item) {
6681
+ return '';
6682
+ }
6683
+ return String(get(item, this.valueField()) ?? '');
6684
+ }
6685
+ /**
6686
+ * Calculate the full path from root to the item.
6687
+ * Returns an array of strings like ["C", "B"] for item B under parent C.
6688
+ */
6689
+ async calculateItemPath(item) {
6690
+ if (!item || !this.entityDef()) {
6691
+ return item;
6692
+ }
6693
+ // If item already has a path array, return it as is
6694
+ if (item.path && Array.isArray(item.path) && item.path.length > 0) {
6695
+ return item;
6696
+ }
6697
+ const parentKey = this.entityDef()?.parentKey;
6698
+ if (!parentKey) {
6699
+ // No parent key means flat structure, return item with just its title as path array
6700
+ const title = get(item, this.displayField()) ?? '';
6701
+ return { ...item, path: title ? [title] : [] };
6702
+ }
6703
+ const valueField = this.valueField();
6704
+ const textField = this.displayField();
6705
+ const byKey = this.entityDef()?.queries.byKey?.execute;
6706
+ if (!byKey) {
6707
+ return item;
6708
+ }
6709
+ const path = [];
6710
+ let currentItem = item;
6711
+ const visitedIds = new Set(); // Prevent infinite loops
6712
+ // Build path by traversing up the parent chain
6713
+ while (currentItem) {
6714
+ const currentId = String(get(currentItem, valueField) ?? '');
6715
+ if (!currentId || visitedIds.has(currentId)) {
6716
+ break; // Prevent infinite loops
6717
+ }
6718
+ visitedIds.add(currentId);
6719
+ const title = String(get(currentItem, textField) ?? '');
6720
+ if (title) {
6721
+ path.unshift(title); // Add to beginning to maintain hierarchy order
6722
+ }
6723
+ // Get parent ID from current item
6724
+ const parentId = get(currentItem, parentKey);
6725
+ if (!parentId || parentId === 'all' || parentId === currentId) {
6726
+ break; // Reached root or invalid parent
6727
+ }
6728
+ try {
6729
+ // Fetch parent item
6730
+ const parentItem = await byKey(parentId);
6731
+ if (!parentItem) {
6732
+ break; // Parent not found, stop traversal
6733
+ }
6734
+ currentItem = parentItem;
6735
+ }
6736
+ catch (error) {
6737
+ console.error('Error fetching parent item:', error);
6738
+ break;
6739
+ }
6740
+ }
6741
+ // Return item with path array, or just the item title if no path
6742
+ const pathArray = path.length > 0 ? path : get(item, textField) ? [String(get(item, textField))] : [];
6743
+ return { ...item, path: pathArray };
6744
+ }
5929
6745
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetEditComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
5930
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityCategoryWidgetEditComponent, isStandalone: true, selector: "axp-entity-category-widget-edit", viewQueries: [{ propertyName: "selectBox", first: true, predicate: ["selectBox"], descendants: true, isSignal: true }, { propertyName: "tagBox", first: true, predicate: ["tagBoxComponent"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
5931
- @if (dataSource()) {
5932
- @if (look() == 'select') {
5933
- <ax-select-box
5934
- #selectBox
5935
- [dataSource]="dataSource()!"
5936
- [ngModel]="selectedItems()"
5937
- [textField]="displayField()"
5938
- [valueField]="valueField()"
5939
- [disabled]="disabled()"
5940
- [multiple]="multiple()"
5941
- (onValueChanged)="selectBoxValueChange($event)"
5942
- >
5943
- <ax-search-box
5944
- [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
5945
- (onValueChanged)="handleSearchInputChange($event)"
5946
- >
5947
- <ax-clear-button></ax-clear-button>
5948
- </ax-search-box>
5949
- @for (validation of validationRules(); track $index) {
5950
- <ax-validation-rule
5951
- [rule]="validation.rule"
5952
- [message]="validation.options?.message"
5953
- [options]="validation.options"
5954
- ></ax-validation-rule>
6746
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityCategoryWidgetEditComponent, isStandalone: true, selector: "axp-entity-category-widget-edit", usesInheritance: true, ngImport: i0, template: `
6747
+ <div class="ax-flex ax-flex-col ax-gap-3">
6748
+ @if (selectedItems().length > 0) {
6749
+ <div class="ax-flex ax-flex-col ax-gap-2">
6750
+ @for (item of selectedItems(); track getItemId(item)) {
6751
+ <div class="ax-flex ax-items-center ax-gap-2 ax-p-2 ax-border ax-primary-lightest ax-rounded-xl">
6752
+ <axp-truncated-breadcrumb
6753
+ [sections]="getItemPath(item)"
6754
+ [characterLimit]="characterLimit()"
6755
+ [sectionLimit]="sectionLimit()"
6756
+ class="ax-flex-1"
6757
+ ></axp-truncated-breadcrumb>
6758
+ <ax-button color="ghost" look="blank" class="ax-xs" (onClick)="handleRemoveItemClick($event, item)">
6759
+ <ax-icon icon="ax-icon ax-icon-close"></ax-icon>
6760
+ </ax-button>
6761
+ </div>
5955
6762
  }
5956
- @if (allowClear()) {
5957
- <ax-clear-button (click)="handleClearClick()"></ax-clear-button>
5958
- }
5959
- <ax-suffix>
5960
- <ax-button
5961
- color="ghost"
5962
- look="blank"
5963
- [disabled]="isLoading() || disabled()"
5964
- (onClick)="handleOnClick($event)"
5965
- >
5966
- @if (isLoading()) {
5967
- <ax-loading></ax-loading>
5968
- } @else {
5969
- <ax-icon icon="far fa-search"></ax-icon>
5970
- }
5971
- </ax-button>
5972
- </ax-suffix>
5973
- </ax-select-box>
5974
- } @else {
5975
- <ax-tag-box
5976
- #tagBoxComponent
5977
- [tagTemplate]="tagTemplate"
5978
- [ngModel]="selectedItems()"
5979
- [textField]="displayField()"
5980
- [valueField]="valueField()"
5981
- (onValueChanged)="handleValueChange($event)"
5982
- [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
5983
- [addOnEnter]="false"
5984
- [addOnComma]="false"
5985
- [disabled]="disabled()"
5986
- (onKeyUp)="handleKeyUp($event)"
5987
- (onBlur)="handleOnBlur($event)"
6763
+ </div>
6764
+ }
6765
+
6766
+ <div class="ax-flex ax-items-center ax-gap-2">
6767
+ <ax-button
6768
+ [text]="'@general:actions.add.title' | translate | async"
6769
+ color="primary"
6770
+ [disabled]="isLoading() || disabled()"
6771
+ (onClick)="handleAddClick($event)"
5988
6772
  >
5989
- @for (validation of validationRules(); track $index) {
5990
- <ax-validation-rule
5991
- [rule]="validation.rule"
5992
- [message]="validation.options?.message"
5993
- [options]="validation.options"
5994
- ></ax-validation-rule>
5995
- }
5996
- @if (selectedItems().length > 1 || allowClear()) {
5997
- <ax-clear-button (click)="handleClearClick()"></ax-clear-button>
6773
+ @if (isLoading()) {
6774
+ <ax-loading></ax-loading>
6775
+ } @else {
6776
+ <ax-icon icon="far fa-plus"></ax-icon>
5998
6777
  }
6778
+ </ax-button>
5999
6779
 
6000
- <ax-suffix>
6001
- <ax-button
6002
- color="ghost"
6003
- look="blank"
6004
- [disabled]="isLoading() || disabled()"
6005
- (onClick)="handleOnClick($event)"
6006
- >
6007
- @if (isLoading()) {
6008
- <ax-loading></ax-loading>
6009
- } @else {
6010
- <ax-icon icon="far fa-search"></ax-icon>
6011
- }
6012
- </ax-button>
6013
- </ax-suffix>
6014
- </ax-tag-box>
6015
- <ng-template #tagTemplate let-item let-index="index">
6016
- <div class="ax-inline-flex ax-items-center ax-gap-1.5 ax-rounded-md ax-px-3 ax-py-1 ax-text-sm ax-surface">
6017
- <span>{{ getTagLabel(item) }}</span>
6018
- <button type="button" (click)="tagBoxComponent.removeItem(index)">
6019
- <ax-icon class="ax-icon ax-icon-close"></ax-icon>
6020
- </button>
6021
- </div>
6022
- </ng-template>
6780
+ @if (allowClear() && selectedItems().length > 0) {
6781
+ <ax-button color="ghost" look="outline" [disabled]="disabled()" (onClick)="handleClearClick()">
6782
+ Clear All
6783
+ </ax-button>
6784
+ }
6785
+ </div>
6786
+
6787
+ @for (validation of validationRules(); track $index) {
6788
+ <ax-validation-rule
6789
+ [rule]="validation.rule"
6790
+ [message]="validation.options?.message"
6791
+ [options]="validation.options"
6792
+ ></ax-validation-rule>
6023
6793
  }
6024
- }
6025
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "directive", type: i5$1.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "ngmodule", type: AXTagBoxModule }, { kind: "component", type: i6$1.AXTagBoxComponent, selector: "ax-tag-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "allowNull", "type", "look", "addOnComma", "addOnEnter", "valueField", "textField", "readonlyField", "allowDuplicateValues", "tagTemplate"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onTagClick", "onTagDblClick", "onTagContextMenu"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "component", type: i7.AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6794
+ </div>
6795
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i1.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "directive", type: i5$1.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPTruncatedBreadcrumbComponent, selector: "axp-truncated-breadcrumb", inputs: ["sections", "characterLimit", "sectionLimit", "separatorIcon", "ellipsisIcon", "eyeIcon"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6026
6796
  }
6027
6797
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetEditComponent, decorators: [{
6028
6798
  type: Component,
6029
6799
  args: [{
6030
6800
  selector: 'axp-entity-category-widget-edit',
6031
6801
  template: `
6032
- @if (dataSource()) {
6033
- @if (look() == 'select') {
6034
- <ax-select-box
6035
- #selectBox
6036
- [dataSource]="dataSource()!"
6037
- [ngModel]="selectedItems()"
6038
- [textField]="displayField()"
6039
- [valueField]="valueField()"
6040
- [disabled]="disabled()"
6041
- [multiple]="multiple()"
6042
- (onValueChanged)="selectBoxValueChange($event)"
6043
- >
6044
- <ax-search-box
6045
- [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
6046
- (onValueChanged)="handleSearchInputChange($event)"
6047
- >
6048
- <ax-clear-button></ax-clear-button>
6049
- </ax-search-box>
6050
- @for (validation of validationRules(); track $index) {
6051
- <ax-validation-rule
6052
- [rule]="validation.rule"
6053
- [message]="validation.options?.message"
6054
- [options]="validation.options"
6055
- ></ax-validation-rule>
6802
+ <div class="ax-flex ax-flex-col ax-gap-3">
6803
+ @if (selectedItems().length > 0) {
6804
+ <div class="ax-flex ax-flex-col ax-gap-2">
6805
+ @for (item of selectedItems(); track getItemId(item)) {
6806
+ <div class="ax-flex ax-items-center ax-gap-2 ax-p-2 ax-border ax-primary-lightest ax-rounded-xl">
6807
+ <axp-truncated-breadcrumb
6808
+ [sections]="getItemPath(item)"
6809
+ [characterLimit]="characterLimit()"
6810
+ [sectionLimit]="sectionLimit()"
6811
+ class="ax-flex-1"
6812
+ ></axp-truncated-breadcrumb>
6813
+ <ax-button color="ghost" look="blank" class="ax-xs" (onClick)="handleRemoveItemClick($event, item)">
6814
+ <ax-icon icon="ax-icon ax-icon-close"></ax-icon>
6815
+ </ax-button>
6816
+ </div>
6056
6817
  }
6057
- @if (allowClear()) {
6058
- <ax-clear-button (click)="handleClearClick()"></ax-clear-button>
6059
- }
6060
- <ax-suffix>
6061
- <ax-button
6062
- color="ghost"
6063
- look="blank"
6064
- [disabled]="isLoading() || disabled()"
6065
- (onClick)="handleOnClick($event)"
6066
- >
6067
- @if (isLoading()) {
6068
- <ax-loading></ax-loading>
6069
- } @else {
6070
- <ax-icon icon="far fa-search"></ax-icon>
6071
- }
6072
- </ax-button>
6073
- </ax-suffix>
6074
- </ax-select-box>
6075
- } @else {
6076
- <ax-tag-box
6077
- #tagBoxComponent
6078
- [tagTemplate]="tagTemplate"
6079
- [ngModel]="selectedItems()"
6080
- [textField]="displayField()"
6081
- [valueField]="valueField()"
6082
- (onValueChanged)="handleValueChange($event)"
6083
- [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
6084
- [addOnEnter]="false"
6085
- [addOnComma]="false"
6086
- [disabled]="disabled()"
6087
- (onKeyUp)="handleKeyUp($event)"
6088
- (onBlur)="handleOnBlur($event)"
6818
+ </div>
6819
+ }
6820
+
6821
+ <div class="ax-flex ax-items-center ax-gap-2">
6822
+ <ax-button
6823
+ [text]="'@general:actions.add.title' | translate | async"
6824
+ color="primary"
6825
+ [disabled]="isLoading() || disabled()"
6826
+ (onClick)="handleAddClick($event)"
6089
6827
  >
6090
- @for (validation of validationRules(); track $index) {
6091
- <ax-validation-rule
6092
- [rule]="validation.rule"
6093
- [message]="validation.options?.message"
6094
- [options]="validation.options"
6095
- ></ax-validation-rule>
6096
- }
6097
- @if (selectedItems().length > 1 || allowClear()) {
6098
- <ax-clear-button (click)="handleClearClick()"></ax-clear-button>
6828
+ @if (isLoading()) {
6829
+ <ax-loading></ax-loading>
6830
+ } @else {
6831
+ <ax-icon icon="far fa-plus"></ax-icon>
6099
6832
  }
6833
+ </ax-button>
6100
6834
 
6101
- <ax-suffix>
6102
- <ax-button
6103
- color="ghost"
6104
- look="blank"
6105
- [disabled]="isLoading() || disabled()"
6106
- (onClick)="handleOnClick($event)"
6107
- >
6108
- @if (isLoading()) {
6109
- <ax-loading></ax-loading>
6110
- } @else {
6111
- <ax-icon icon="far fa-search"></ax-icon>
6112
- }
6113
- </ax-button>
6114
- </ax-suffix>
6115
- </ax-tag-box>
6116
- <ng-template #tagTemplate let-item let-index="index">
6117
- <div class="ax-inline-flex ax-items-center ax-gap-1.5 ax-rounded-md ax-px-3 ax-py-1 ax-text-sm ax-surface">
6118
- <span>{{ getTagLabel(item) }}</span>
6119
- <button type="button" (click)="tagBoxComponent.removeItem(index)">
6120
- <ax-icon class="ax-icon ax-icon-close"></ax-icon>
6121
- </button>
6122
- </div>
6123
- </ng-template>
6835
+ @if (allowClear() && selectedItems().length > 0) {
6836
+ <ax-button color="ghost" look="outline" [disabled]="disabled()" (onClick)="handleClearClick()">
6837
+ Clear All
6838
+ </ax-button>
6839
+ }
6840
+ </div>
6841
+
6842
+ @for (validation of validationRules(); track $index) {
6843
+ <ax-validation-rule
6844
+ [rule]="validation.rule"
6845
+ [message]="validation.options?.message"
6846
+ [options]="validation.options"
6847
+ ></ax-validation-rule>
6124
6848
  }
6125
- }
6849
+ </div>
6126
6850
  `,
6127
6851
  changeDetection: ChangeDetectionStrategy.OnPush,
6128
6852
  imports: [
6129
6853
  CommonModule,
6130
- FormsModule,
6131
6854
  AXButtonModule,
6132
6855
  AXDecoratorModule,
6133
6856
  AXLoadingModule,
6134
6857
  AXValidationModule,
6135
6858
  AXFormModule,
6136
- AXTagBoxModule,
6137
6859
  AXTranslationModule,
6138
- AXSelectBoxModule,
6139
- AXSearchBoxComponent,
6860
+ AXPTruncatedBreadcrumbComponent,
6140
6861
  ],
6141
6862
  }]
6142
- }], propDecorators: { selectBox: [{ type: i0.ViewChild, args: ['selectBox', { isSignal: true }] }], tagBox: [{ type: i0.ViewChild, args: ['tagBoxComponent', { isSignal: true }] }] } });
6863
+ }] });
6143
6864
 
6144
6865
  var entityCategoryWidgetEdit_component = /*#__PURE__*/Object.freeze({
6145
6866
  __proto__: null,
@@ -6241,7 +6962,7 @@ class AXPEntityCategoryWidgetViewComponent extends AXPValueWidgetComponent {
6241
6962
  <span class="ax-text-muted">---</span>
6242
6963
  }
6243
6964
  }
6244
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6965
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i1.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6245
6966
  }
6246
6967
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetViewComponent, decorators: [{
6247
6968
  type: Component,
@@ -7137,7 +7858,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
7137
7858
  ></ng-container>
7138
7859
  }
7139
7860
  </div>
7140
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i3.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i3.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i4$3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7861
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i3.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i3.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i4$2.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7141
7862
  }
7142
7863
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityListWidgetViewComponent, decorators: [{
7143
7864
  type: Component,
@@ -7708,7 +8429,7 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
7708
8429
  <span class="ax-text-muted">---</span>
7709
8430
  }
7710
8431
  }
7711
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8432
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i1.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7712
8433
  }
7713
8434
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLookupWidgetViewComponent, decorators: [{
7714
8435
  type: Component,
@@ -8424,9 +9145,9 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
8424
9145
  </ng-template>
8425
9146
  }
8426
9147
  }
8427
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type:
9148
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type:
8428
9149
  //
8429
- AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "directive", type: i5$1.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "ngmodule", type: AXTagBoxModule }, { kind: "component", type: i6$1.AXTagBoxComponent, selector: "ax-tag-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "allowNull", "type", "look", "addOnComma", "addOnEnter", "valueField", "textField", "readonlyField", "allowDuplicateValues", "tagTemplate"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onTagClick", "onTagDblClick", "onTagContextMenu"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "component", type: i7.AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9150
+ AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1$1.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i1$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i1.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "directive", type: i5$1.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "ngmodule", type: AXTagBoxModule }, { kind: "component", type: i6$1.AXTagBoxComponent, selector: "ax-tag-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "allowNull", "type", "look", "addOnComma", "addOnEnter", "valueField", "textField", "readonlyField", "allowDuplicateValues", "tagTemplate"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onTagClick", "onTagDblClick", "onTagContextMenu"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "component", type: i7.AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8430
9151
  }
8431
9152
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLookupWidgetEditComponent, decorators: [{
8432
9153
  type: Component,
@@ -8799,7 +9520,7 @@ class AXPWidgetSelectorWidgetEditComponent extends AXPValueWidgetComponent {
8799
9520
  <axp-widget-property-viewer [widget]="selectedWidgetNode()!" (onChanged)="handleChangeWidget($event)">
8800
9521
  </axp-widget-property-viewer>
8801
9522
  }
8802
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i2$2.AXTextBoxComponent, selector: "ax-text-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "maxLength", "allowNull", "type", "autoComplete", "look", "mask-options", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "directive", type: i5$1.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "component", type: AXPWidgetPropertyViewerComponent, selector: "axp-widget-property-viewer", inputs: ["widget", "mode"], outputs: ["onChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9523
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i2$2.AXTextBoxComponent, selector: "ax-text-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "maxLength", "allowNull", "type", "autoComplete", "look", "mask-options", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "directive", type: i5$1.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "component", type: AXPWidgetPropertyViewerComponent, selector: "axp-widget-property-viewer", inputs: ["widget", "mode"], outputs: ["onChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8803
9524
  }
8804
9525
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWidgetSelectorWidgetEditComponent, decorators: [{
8805
9526
  type: Component,
@@ -9318,7 +10039,7 @@ class AXPEntityModule {
9318
10039
  },
9319
10040
  });
9320
10041
  }
9321
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityModule, deps: [{ token: i1$1.AXPAppStartUpService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.NgModule }); }
10042
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityModule, deps: [{ token: i1$3.AXPAppStartUpService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.NgModule }); }
9322
10043
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityModule, imports: [RouterModule, i2$3.AXPWorkflowModule, i3$1.AXPWidgetCoreModule] }); }
9323
10044
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityModule, providers: [
9324
10045
  {
@@ -9494,7 +10215,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
9494
10215
  ]),
9495
10216
  ],
9496
10217
  }]
9497
- }], ctorParameters: () => [{ type: i1$1.AXPAppStartUpService }, { type: i0.Injector }] });
10218
+ }], ctorParameters: () => [{ type: i1$3.AXPAppStartUpService }, { type: i0.Injector }] });
9498
10219
 
9499
10220
  //#endregion
9500
10221
  //#region ---- Get Entity Details Query ----
@@ -10051,5 +10772,5 @@ function detectEntityChanges(oldObj, newObj) {
10051
10772
  * Generated bundle index. Do not edit.
10052
10773
  */
10053
10774
 
10054
- export { AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorService, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityDynamicDialogService, AXPEntityEventDispatcherService, AXPEntityListTableService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityReferenceWidget, AXPEntityReferenceWidgetColumnComponent, AXPEntityReferenceWidgetDesignerComponent, AXPEntityReferenceWidgetEditComponent, AXPEntityReferenceWidgetPrintComponent, AXPEntityReferenceWidgetViewComponent, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPGetEntityDetailsQuery, AXPLookupFilterWidget, AXPLookupFilterWidgetEditComponent, AXPLookupWidget, AXPLookupWidgetColumnComponent, AXPLookupWidgetEditComponent, AXPLookupWidgetViewComponent, AXPMiddlewareAbortError, AXPMiddlewareEntityStorageService, AXPModifyEntitySectionWorkflow, AXPOpenEntityDetailsCommand, AXPQuickEntityModifyPopupAction, AXPQuickModifyEntityWorkflow, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPWidgetSelectorWidget, AXPWidgetSelectorWidgetEditComponent, AXPWidgetSelectorWidgetViewComponent, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER, AXP_ENTITY_MODIFIER, AXP_ENTITY_STORAGE_BACKEND, AXP_ENTITY_STORAGE_MIDDLEWARE, DEFAULT_COLUMN_WIDTHS, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, actionExists, columnWidthMiddlewareFactory, columnWidthMiddlewareProvider, createColumnWidthMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, detectEntityChanges, ensureListActions, entityDetailsCreateActions, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, isAXPMiddlewareAbortError, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider };
10775
+ export { AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorService, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityDynamicDialogService, AXPEntityEventDispatcherService, AXPEntityListTableService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityReferenceWidget, AXPEntityReferenceWidgetColumnComponent, AXPEntityReferenceWidgetDesignerComponent, AXPEntityReferenceWidgetEditComponent, AXPEntityReferenceWidgetPrintComponent, AXPEntityReferenceWidgetViewComponent, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPGetEntityDetailsQuery, AXPLookupFilterWidget, AXPLookupFilterWidgetEditComponent, AXPLookupWidget, AXPLookupWidgetColumnComponent, AXPLookupWidgetEditComponent, AXPLookupWidgetViewComponent, AXPMiddlewareAbortError, AXPMiddlewareEntityStorageService, AXPModifyEntitySectionWorkflow, AXPOpenEntityDetailsCommand, AXPQuickEntityModifyPopupAction, AXPQuickModifyEntityWorkflow, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPTruncatedBreadcrumbComponent, AXPWidgetSelectorWidget, AXPWidgetSelectorWidgetEditComponent, AXPWidgetSelectorWidgetViewComponent, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER, AXP_ENTITY_MODIFIER, AXP_ENTITY_STORAGE_BACKEND, AXP_ENTITY_STORAGE_MIDDLEWARE, DEFAULT_COLUMN_WIDTHS, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, actionExists, columnWidthMiddlewareFactory, columnWidthMiddlewareProvider, createColumnWidthMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, detectEntityChanges, ensureListActions, entityDetailsCreateActions, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, isAXPMiddlewareAbortError, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider };
10055
10776
  //# sourceMappingURL=acorex-platform-layout-entity.mjs.map