@acorex/platform 20.6.0-next.22 → 20.6.0-next.24

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,20 +1,20 @@
1
1
  import { AXToastService } from '@acorex/components/toast';
2
2
  import * as i6 from '@acorex/core/translation';
3
3
  import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
4
- import * as i4 from '@acorex/platform/common';
4
+ import * as i4$1 from '@acorex/platform/common';
5
5
  import { AXPSettingService, AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, getEntityInfo, AXPRefreshEvent, AXPReloadEvent, AXPCommonSettings, AXPCleanNestedFilters, AXPWorkflowNavigateAction, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER } from '@acorex/platform/common';
6
- import * as i1$2 from '@acorex/platform/core';
6
+ import * as i1$1 from '@acorex/platform/core';
7
7
  import { AXPDeviceService, AXPBroadcastEventService, resolveActionLook, AXPExpressionEvaluatorService, AXPDistributedEventListenerService, AXPPlatformScope, AXHighlightService, extractValue, setSmart, getChangedPaths, AXPSystemActionType } from '@acorex/platform/core';
8
8
  import * as i0 from '@angular/core';
9
9
  import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, input, viewChild, signal, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, computed, effect, Input, afterNextRender, ViewEncapsulation, ChangeDetectorRef, viewChildren, linkedSignal, untracked, HostBinding, ViewChild, NgModule } from '@angular/core';
10
10
  import { Subject, takeUntil } from 'rxjs';
11
11
  import { AXPLayoutBuilderService } from '@acorex/platform/layout/builder';
12
- import { merge, castArray, get, cloneDeep, set, orderBy, isNil, isEqual, isEmpty, sortBy } from 'lodash-es';
12
+ import { merge, castArray, get, cloneDeep, set, orderBy, isNil, isEmpty, isEqual, sortBy } from 'lodash-es';
13
13
  import { AXPSessionService, AXPAuthGuard } from '@acorex/platform/auth';
14
14
  import { Router, RouterModule, ROUTES } from '@angular/router';
15
15
  import * as i3 from '@acorex/components/button';
16
16
  import { AXButtonModule } from '@acorex/components/button';
17
- import * as i1 from '@acorex/components/loading';
17
+ import * as i4 from '@acorex/components/loading';
18
18
  import { AXLoadingModule } from '@acorex/components/loading';
19
19
  import * as i2 from '@acorex/components/popover';
20
20
  import { AXPopoverModule } from '@acorex/components/popover';
@@ -33,32 +33,33 @@ import { AXDialogService } from '@acorex/components/dialog';
33
33
  import { AXLoadingDialogService } from '@acorex/components/loading-dialog';
34
34
  import { AXPopupService } from '@acorex/components/popup';
35
35
  import { AXPlatform } from '@acorex/core/platform';
36
+ import * as i2$1 from '@acorex/components/check-box';
36
37
  import { AXCheckBoxModule } from '@acorex/components/check-box';
37
- import * as i2$1 from '@acorex/components/decorators';
38
+ import * as i3$2 from '@acorex/components/decorators';
38
39
  import { AXDecoratorModule } from '@acorex/components/decorators';
39
40
  import { AXBasePageComponent } from '@acorex/components/page';
40
- import * as i3$2 from '@acorex/components/search-box';
41
+ import * as i4$2 from '@acorex/components/search-box';
41
42
  import { AXSearchBoxModule, AXSearchBoxComponent } from '@acorex/components/search-box';
42
- import * as i4$1 from '@acorex/components/skeleton';
43
+ import * as i5$1 from '@acorex/components/skeleton';
43
44
  import { AXSkeletonModule } from '@acorex/components/skeleton';
44
45
  import { AXTreeViewComponent } from '@acorex/components/tree-view';
45
46
  import { AXPStateMessageComponent, AXPDataSelectorService, AXPWidgetPropertyViewerComponent } from '@acorex/platform/layout/components';
46
- import * as i1$1 from '@angular/forms';
47
+ import * as i1 from '@angular/forms';
47
48
  import { FormsModule } from '@angular/forms';
48
49
  import * as i2$2 from '@acorex/components/badge';
49
50
  import { AXBadgeModule } from '@acorex/components/badge';
50
- import * as i5$1 from '@acorex/components/form';
51
+ import * as i5$2 from '@acorex/components/form';
51
52
  import { AXFormModule } from '@acorex/components/form';
53
+ import * as i6$1 from '@acorex/components/tag-box';
54
+ import { AXTagBoxModule, AXTagBoxComponent } from '@acorex/components/tag-box';
52
55
  import { AXValidationModule } from '@acorex/core/validation';
53
56
  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$2 from '@acorex/components/dropdown';
57
+ import * as i4$3 from '@acorex/components/dropdown';
55
58
  import { AXDropdownModule } from '@acorex/components/dropdown';
56
59
  import * as i7 from '@acorex/components/select-box';
57
60
  import { AXSelectBoxModule } from '@acorex/components/select-box';
58
61
  import * as i2$3 from '@acorex/components/text-box';
59
62
  import { AXTextBoxModule, AXTextBoxComponent } from '@acorex/components/text-box';
60
- import * as i6$1 from '@acorex/components/tag-box';
61
- import { AXTagBoxComponent, AXTagBoxModule } from '@acorex/components/tag-box';
62
63
  import { transform, isEqual as isEqual$1 } from 'lodash';
63
64
 
64
65
  function ensureListActions(ctx) {
@@ -1035,7 +1036,7 @@ class AXPCreateEntityCommand {
1035
1036
  const entityRef = await this.entityService.resolve(moduleName, entityName);
1036
1037
  let dialogRef;
1037
1038
  try {
1038
- let chain = this.entityForm.entity(`${moduleName}.${entityName}`).create(input.__metadata__);
1039
+ let chain = this.entityForm.entity(`${moduleName}.${entityName}`).create(data);
1039
1040
  chain.actions((actions) => {
1040
1041
  actions.cancel('@general:actions.cancel.title');
1041
1042
  actions.submit('@general:actions.create.title');
@@ -1680,7 +1681,7 @@ class AXPEntityDetailPopoverComponent {
1680
1681
  return importantProperties;
1681
1682
  }
1682
1683
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityDetailPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1683
- 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 }); }
1684
+ 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 }); }
1684
1685
  }
1685
1686
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityDetailPopoverComponent, decorators: [{
1686
1687
  type: Component,
@@ -4324,24 +4325,48 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
4324
4325
  message: {
4325
4326
  code: 'ACTION_NOT_FOUND',
4326
4327
  text: `Action ${commandName} not found`,
4327
- }
4328
+ },
4328
4329
  };
4329
4330
  }
4330
- await context.workflowService.execute(commandName, {
4331
- entity: getEntityInfo(entityDef).source,
4332
- entityInfo: {
4333
- name: entityDef.name,
4334
- module: entityDef.module,
4335
- title: entityDef.title,
4336
- parentKey: entityDef.parentKey,
4337
- source: `${entityDef.module}.${entityDef.name}`,
4338
- },
4339
- data: action.scope == AXPEntityCommandScope.Selected
4340
- ? executeContext
4341
- : action.options?.['process']?.data || null,
4342
- options: action.options,
4343
- metadata: action.metadata,
4344
- });
4331
+ if (context.commandService.exists(commandName)) {
4332
+ // check options for evaluation
4333
+ await context.commandService.execute(commandName, {
4334
+ __context__: {
4335
+ entity: getEntityInfo(entityDef).source,
4336
+ entityInfo: {
4337
+ name: entityDef.name,
4338
+ module: entityDef.module,
4339
+ title: entityDef.title,
4340
+ parentKey: entityDef.parentKey,
4341
+ source: `${entityDef.module}.${entityDef.name}`,
4342
+ },
4343
+ data: action.scope == AXPEntityCommandScope.Selected
4344
+ ? executeContext
4345
+ : action.options?.['process']?.data || null,
4346
+ options: action.options,
4347
+ metadata: action.metadata,
4348
+ },
4349
+ options: action.options,
4350
+ metadata: action.metadata,
4351
+ });
4352
+ }
4353
+ else {
4354
+ await context.workflowService.execute(commandName, {
4355
+ entity: getEntityInfo(entityDef).source,
4356
+ entityInfo: {
4357
+ name: entityDef.name,
4358
+ module: entityDef.module,
4359
+ title: entityDef.title,
4360
+ parentKey: entityDef.parentKey,
4361
+ source: `${entityDef.module}.${entityDef.name}`,
4362
+ },
4363
+ data: action.scope == AXPEntityCommandScope.Selected
4364
+ ? executeContext
4365
+ : action.options?.['process']?.data || null,
4366
+ options: action.options,
4367
+ metadata: action.metadata,
4368
+ });
4369
+ }
4345
4370
  return { success: true };
4346
4371
  }
4347
4372
  catch (error) {
@@ -4368,6 +4393,7 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
4368
4393
  entity: relatedEntity.entity,
4369
4394
  showEntityActions: false,
4370
4395
  actions: evaluatedActions,
4396
+ includeColumns: relatedEntity.columns,
4371
4397
  },
4372
4398
  },
4373
4399
  ],
@@ -4978,6 +5004,7 @@ class AXPMainEntityContentBuilder {
4978
5004
  : editablePropertyNames.has(p.name);
4979
5005
  // Check if property has its own disabled option
4980
5006
  const hasOwnDisabled = p.schema.interface?.options?.disabled !== undefined;
5007
+ console.log('visible: ', p.schema.visible);
4981
5008
  return {
4982
5009
  type: 'grid-item-layout',
4983
5010
  name: prefixed,
@@ -4985,7 +5012,7 @@ class AXPMainEntityContentBuilder {
4985
5012
  colSpan: layout?.positions?.lg?.colSpan,
4986
5013
  colStart: layout?.positions?.lg?.colStart,
4987
5014
  colEnd: layout?.positions?.lg?.colEnd,
4988
- hidden: !(p.schema.visible ?? true),
5015
+ visible: p.schema.visible,
4989
5016
  },
4990
5017
  children: [
4991
5018
  {
@@ -5275,7 +5302,7 @@ class AXPLayoutAdapterFactory {
5275
5302
  const title = await dependencies.expressionEvaluator.evaluate(entity.interfaces?.master?.single?.title, rootContext);
5276
5303
  return title;
5277
5304
  }
5278
- 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 }); }
5305
+ 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 }); }
5279
5306
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutAdapterFactory, providedIn: 'root' }); }
5280
5307
  }
5281
5308
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutAdapterFactory, decorators: [{
@@ -5283,7 +5310,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
5283
5310
  args: [{
5284
5311
  providedIn: 'root',
5285
5312
  }]
5286
- }], ctorParameters: () => [{ type: AXPRelatedEntityConverterFactory }, { type: AXPMainEntityContentBuilder }, { type: AXPLayoutAdapterBuilder }, { type: i4.AXPFilterOperatorMiddlewareService }] });
5313
+ }], ctorParameters: () => [{ type: AXPRelatedEntityConverterFactory }, { type: AXPMainEntityContentBuilder }, { type: AXPLayoutAdapterBuilder }, { type: i4$1.AXPFilterOperatorMiddlewareService }] });
5287
5314
 
5288
5315
  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)) => {
5289
5316
  const moduleName = route.parent?.paramMap.get('module');
@@ -5905,7 +5932,6 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5905
5932
  this.textField = signal('title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
5906
5933
  this.valueField = signal('id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
5907
5934
  this.allowMultiple = signal(false, ...(ngDevMode ? [{ debugName: "allowMultiple" }] : []));
5908
- this.selectionBehavior = signal('all', ...(ngDevMode ? [{ debugName: "selectionBehavior" }] : []));
5909
5935
  this.selectedValues = signal([], ...(ngDevMode ? [{ debugName: "selectedValues" }] : []));
5910
5936
  this.searchPlaceholder = signal('@general:terms.interface.category.search.placeholder', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
5911
5937
  this.excludedNodeId = signal(undefined, ...(ngDevMode ? [{ debugName: "excludedNodeId" }] : [])); // Node ID to disable
@@ -5924,6 +5950,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5924
5950
  this.noRecordsTitle = signal('', ...(ngDevMode ? [{ debugName: "noRecordsTitle" }] : []));
5925
5951
  this.currentSearchTerm = null;
5926
5952
  this.isRefreshing = false;
5953
+ this.isUpdatingSelection = false; // Flag to prevent recursive updates during batch operations
5927
5954
  /**
5928
5955
  * Computed property to check if we should show the "no search results" empty state.
5929
5956
  * Returns true when search is active, not searching, and no results found.
@@ -5943,6 +5970,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5943
5970
  this.relevantNodeIds = new Set(); // For search filtering
5944
5971
  this.expandedNodesBeforeSearch = []; // Store expanded nodes before search to restore after
5945
5972
  this.nodesExpandedDuringSearch = []; // Track nodes we expanded during search
5973
+ this.isInitializing = false; // Flag to track if we're in initialization phase
5946
5974
  /** Datasource callback for tree-view component. */
5947
5975
  this.datasource = async (id) => {
5948
5976
  if (!this.treeData || !this.treeConfig) {
@@ -5994,15 +6022,42 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5994
6022
  this.markNodeAsSelectedIfNeeded(node);
5995
6023
  });
5996
6024
  // After children load, programmatically select pre-selected nodes
6025
+ // Use a small delay to ensure nodes are fully added to tree structure
5997
6026
  const treeComponent = this.tree();
5998
6027
  if (treeComponent) {
5999
- const selectedIds = this.selectedNodeIds();
6000
- childNodes.forEach((node) => {
6001
- const nodeId = String(node['id'] ?? '');
6002
- if (nodeId && selectedIds.includes(nodeId) && nodeId !== 'all') {
6003
- treeComponent.selectNode(nodeId);
6004
- }
6005
- });
6028
+ // Use setTimeout to ensure nodes are in tree structure before selecting
6029
+ setTimeout(() => {
6030
+ const selectedIds = this.selectedNodeIds();
6031
+ childNodes.forEach((node) => {
6032
+ const nodeId = String(node['id'] ?? '');
6033
+ if (nodeId && selectedIds.includes(nodeId) && nodeId !== 'all') {
6034
+ try {
6035
+ // Try to find and select the node
6036
+ const treeNode = treeComponent.findNode(nodeId);
6037
+ if (treeNode) {
6038
+ treeComponent.selectNode(nodeId);
6039
+ }
6040
+ else {
6041
+ // If node not found, try again after a short delay (might still be loading)
6042
+ setTimeout(() => {
6043
+ try {
6044
+ const retryNode = treeComponent.findNode(nodeId);
6045
+ if (retryNode) {
6046
+ treeComponent.selectNode(nodeId);
6047
+ }
6048
+ }
6049
+ catch {
6050
+ // Node still not found, will be selected when it loads
6051
+ }
6052
+ }, 50);
6053
+ }
6054
+ }
6055
+ catch (error) {
6056
+ // Node might not be in tree yet, will be selected when it loads
6057
+ }
6058
+ }
6059
+ });
6060
+ }, 10);
6006
6061
  }
6007
6062
  return childNodes;
6008
6063
  };
@@ -6021,6 +6076,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
6021
6076
  return;
6022
6077
  }
6023
6078
  this.loading.set(true);
6079
+ this.isInitializing = true; // Mark that we're in initialization phase
6024
6080
  try {
6025
6081
  this.treeConfig = {
6026
6082
  entityKey: this.entityKey(),
@@ -6030,6 +6086,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
6030
6086
  this.treeData = await this.categoryTreeService.initializeCategoryTree(this.treeConfig);
6031
6087
  if (!this.treeData) {
6032
6088
  this.loading.set(false);
6089
+ this.isInitializing = false;
6033
6090
  return;
6034
6091
  }
6035
6092
  // Get parentKey from entity definition
@@ -6037,13 +6094,22 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
6037
6094
  this.treeConfig.parentKey = this.treeData.categoryEntityDef.parentKey;
6038
6095
  }
6039
6096
  // Initialize selected nodes and load their data into cache
6097
+ // Wait for tree to be ready before syncing selection
6098
+ await new Promise((resolve) => setTimeout(resolve, 100));
6040
6099
  await this.updateSelectedNodes(this.selectedValues());
6100
+ // After initial sync, wait a bit more and sync again to catch any nodes that loaded late
6101
+ await new Promise((resolve) => setTimeout(resolve, 200));
6102
+ const finalSelectedIds = this.selectedNodeIds();
6103
+ if (finalSelectedIds.length > 0) {
6104
+ await this.syncSelectionWithTree(finalSelectedIds);
6105
+ }
6041
6106
  }
6042
6107
  catch (error) {
6043
6108
  console.error('Error loading entity definition:', error);
6044
6109
  }
6045
6110
  finally {
6046
6111
  this.loading.set(false);
6112
+ this.isInitializing = false; // Mark initialization as complete
6047
6113
  }
6048
6114
  }
6049
6115
  //#endregion
@@ -6499,11 +6565,22 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
6499
6565
  if (nodeData && typeof nodeData === 'object' && nodeData !== null && !Array.isArray(nodeData)) {
6500
6566
  this.nodeDataCache.set(nodeId, nodeData);
6501
6567
  }
6568
+ // NOTE: We do NOT call loadAndSelectChildrenRecursively here
6569
+ // The recursive selection should only happen when user explicitly selects a node via checkbox
6570
+ // (handled in handleCheckboxChange). This prevents intermediate parent states from
6571
+ // triggering unwanted sibling selections.
6502
6572
  }
6503
6573
  async onSelectionChange(event) {
6574
+ // Don't process during initialization or batch updates - let those handle it
6575
+ if (this.isInitializing || this.isUpdatingSelection) {
6576
+ return;
6577
+ }
6504
6578
  // Update selected node IDs from the tree component's selection state
6579
+ // The tree component with intermediate-nested behavior automatically manages parent states
6505
6580
  const selectedNodes = event.selectedNodes || [];
6506
6581
  const selectedIds = selectedNodes.map((node) => String(node['id'] ?? '')).filter((id) => id && id !== 'all');
6582
+ // Sync with tree component's selection state
6583
+ // This includes parents that are automatically selected when all children are selected
6507
6584
  this.selectedNodeIds.set(selectedIds);
6508
6585
  // Cache node data for all selected nodes
6509
6586
  selectedNodes.forEach((node) => {
@@ -6568,171 +6645,884 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
6568
6645
  }
6569
6646
  /**
6570
6647
  * Handles checkbox change event to toggle node selection
6648
+ * In multiple mode: recursively selects/deselects children
6649
+ * Parent states are handled automatically by tree component's intermediate-nested behavior
6571
6650
  */
6572
- // protected handleCheckboxChange(nodeId: string | number | undefined, checked: boolean): void {
6573
- // if (!nodeId || nodeId === 'all') {
6574
- // return;
6575
- // }
6576
- // const id = String(nodeId);
6577
- // const treeComponent = this.tree();
6578
- // if (!treeComponent) {
6579
- // return;
6580
- // }
6581
- // if (checked) {
6582
- // // Select the node
6583
- // treeComponent.selectNode(id);
6584
- // } else {
6585
- // // Deselect the node
6586
- // treeComponent.deselectNode(id);
6587
- // }
6588
- // }
6589
- //#endregion
6590
- async updateSelectedNodes(selectedIds) {
6591
- if (!selectedIds || selectedIds.length === 0) {
6592
- this.selectedNodeIds.set([]);
6651
+ async handleCheckboxChange(nodeId, checked) {
6652
+ if (!nodeId || nodeId === 'all') {
6593
6653
  return;
6594
6654
  }
6595
- const ids = selectedIds.filter((id) => id && id !== 'all');
6596
- this.selectedNodeIds.set(ids);
6597
- // Fetch node data for pre-selected items that aren't in the cache
6598
- // This ensures getSelectedItems() can retrieve them even if their branches aren't expanded
6599
- await this.loadMissingNodeData(ids);
6600
- // Note: Selection state is maintained in selectedNodeIds signal
6601
- // The tree component will sync selection state when nodes are loaded via datasource
6602
- // We mark nodes as selected in the datasource callback by setting node.selected = true
6655
+ const id = String(nodeId);
6656
+ const treeComponent = this.tree();
6657
+ if (!treeComponent) {
6658
+ return;
6659
+ }
6660
+ if (checked) {
6661
+ // Select the node and recursively select all its children
6662
+ await this.selectNodeAndChildren(id);
6663
+ }
6664
+ else {
6665
+ // Deselect the node and recursively deselect all its children
6666
+ await this.deselectNodeAndChildren(id);
6667
+ }
6668
+ // Note: Parent states (select/intermediate) are handled automatically by the tree component
6669
+ // with selectionBehavior: 'intermediate-nested'. We don't need to manually update them.
6603
6670
  }
6604
6671
  /**
6605
- * Loads node data for IDs that are selected but not yet in the cache.
6606
- * This is critical for pre-selected values in collapsed branches.
6672
+ * Selects a node and recursively selects all its children
6607
6673
  */
6608
- async loadMissingNodeData(selectedIds) {
6609
- if (!this.treeData || !this.treeConfig || selectedIds.length === 0) {
6674
+ async selectNodeAndChildren(nodeId) {
6675
+ const treeComponent = this.tree();
6676
+ if (!treeComponent) {
6610
6677
  return;
6611
6678
  }
6612
- // Find IDs that are selected but not in cache
6613
- const missingIds = selectedIds.filter((id) => !this.nodeDataCache.has(id));
6614
- if (missingIds.length === 0) {
6679
+ // Set flag to prevent recursive updates during batch operation
6680
+ this.isUpdatingSelection = true;
6681
+ try {
6682
+ // Collect all nodes to select (node + all descendants)
6683
+ const nodesToSelect = new Set([nodeId]);
6684
+ await this.collectAllDescendants(nodeId, nodesToSelect);
6685
+ // Batch update selectedNodeIds
6686
+ const currentSelected = this.selectedNodeIds();
6687
+ const newSelected = [...currentSelected];
6688
+ for (const id of nodesToSelect) {
6689
+ if (!newSelected.includes(id)) {
6690
+ newSelected.push(id);
6691
+ }
6692
+ }
6693
+ this.selectedNodeIds.set(newSelected);
6694
+ // Batch select in tree component (with small delays to prevent glitches)
6695
+ for (const id of nodesToSelect) {
6696
+ try {
6697
+ const node = treeComponent.findNode(id);
6698
+ if (node) {
6699
+ treeComponent.selectNode(id);
6700
+ // Small delay to prevent overwhelming the tree component
6701
+ await new Promise((resolve) => setTimeout(resolve, 5));
6702
+ }
6703
+ }
6704
+ catch {
6705
+ // Node might not be in tree yet
6706
+ }
6707
+ }
6708
+ }
6709
+ finally {
6710
+ this.isUpdatingSelection = false;
6711
+ }
6712
+ }
6713
+ /**
6714
+ * Collects all descendant node IDs recursively
6715
+ */
6716
+ async collectAllDescendants(parentId, collection) {
6717
+ if (!this.treeData || !this.treeConfig || !parentId || parentId === 'all') {
6615
6718
  return;
6616
6719
  }
6617
6720
  try {
6618
- const valueField = this.treeConfig.valueField || 'id';
6619
- const categoryEntityQueryFunc = this.treeData.categoryEntityQueryFunc;
6620
- if (!categoryEntityQueryFunc) {
6721
+ const childNodes = await this.datasource(parentId);
6722
+ if (!childNodes || childNodes.length === 0) {
6621
6723
  return;
6622
6724
  }
6623
- // Query for missing nodes by their IDs
6624
- const event = {
6625
- ...this.treeData.basicQueryEvent,
6626
- filter: {
6627
- filters: missingIds.map((id) => ({
6628
- field: valueField,
6629
- value: id,
6630
- operator: { type: 'equal' },
6631
- })),
6632
- logic: 'or',
6633
- },
6634
- };
6635
- const res = await categoryEntityQueryFunc(event);
6636
- if (res?.items) {
6637
- // Cache the fetched node data
6638
- res.items.forEach((item) => {
6639
- const itemId = String(item[valueField] ?? '');
6640
- if (itemId) {
6641
- this.nodeDataCache.set(itemId, item);
6725
+ for (const childNode of childNodes) {
6726
+ const childId = String(childNode['id'] ?? '');
6727
+ if (childId && childId !== 'all' && !collection.has(childId)) {
6728
+ collection.add(childId);
6729
+ // Cache node data
6730
+ const nodeData = childNode['data'];
6731
+ if (nodeData && typeof nodeData === 'object') {
6732
+ this.nodeDataCache.set(childId, nodeData);
6642
6733
  }
6643
- });
6734
+ else if (childNode && typeof childNode === 'object') {
6735
+ const valueField = this.treeConfig.valueField || 'id';
6736
+ const textField = this.treeConfig.textField || 'title';
6737
+ const dataObj = {
6738
+ [valueField]: childId,
6739
+ [textField]: childNode['title'] ?? '',
6740
+ ...childNode,
6741
+ };
6742
+ this.nodeDataCache.set(childId, dataObj);
6743
+ }
6744
+ // Recursively collect descendants
6745
+ await this.collectAllDescendants(childId, collection);
6746
+ }
6644
6747
  }
6645
6748
  }
6646
6749
  catch (error) {
6647
- console.error('Error loading missing node data:', error);
6750
+ console.error(`Error collecting descendants for node ${parentId}:`, error);
6648
6751
  }
6649
6752
  }
6650
6753
  /**
6651
- * Marks nodes as selected in the tree structure based on selectedNodeIds.
6652
- * This ensures pre-selected nodes appear selected when the tree is rendered.
6754
+ * Deselects a node and recursively deselects all its children
6653
6755
  */
6654
- markNodesAsSelected(node) {
6655
- const selectedIds = this.selectedNodeIds();
6656
- if (selectedIds.length === 0) {
6756
+ async deselectNodeAndChildren(nodeId) {
6757
+ const treeComponent = this.tree();
6758
+ if (!treeComponent) {
6657
6759
  return;
6658
6760
  }
6659
- // Mark the node itself if it's selected
6660
- this.markNodeAsSelectedIfNeeded(node);
6661
- // Recursively mark children
6662
- const nodeChildren = node['children'];
6663
- if (nodeChildren) {
6664
- nodeChildren.forEach((child) => {
6665
- this.markNodesAsSelected(child);
6666
- });
6761
+ // Set flag to prevent recursive updates during batch operation
6762
+ this.isUpdatingSelection = true;
6763
+ try {
6764
+ // Collect all nodes to deselect (node + all descendants)
6765
+ const nodesToDeselect = new Set([nodeId]);
6766
+ await this.collectAllDescendants(nodeId, nodesToDeselect);
6767
+ // Batch update selectedNodeIds
6768
+ const currentSelected = this.selectedNodeIds();
6769
+ const newSelected = currentSelected.filter((id) => !nodesToDeselect.has(id));
6770
+ this.selectedNodeIds.set(newSelected);
6771
+ // Batch deselect in tree component (with small delays to prevent glitches)
6772
+ for (const id of nodesToDeselect) {
6773
+ try {
6774
+ const node = treeComponent.findNode(id);
6775
+ if (node) {
6776
+ treeComponent.deselectNode(id);
6777
+ // Small delay to prevent overwhelming the tree component
6778
+ await new Promise((resolve) => setTimeout(resolve, 5));
6779
+ }
6780
+ }
6781
+ catch {
6782
+ // Node might not be in tree
6783
+ }
6784
+ }
6667
6785
  }
6668
- }
6669
- /**
6670
- * Marks a single node as selected if it's in the selectedNodeIds list.
6671
- */
6672
- markNodeAsSelectedIfNeeded(node) {
6673
- const selectedIds = this.selectedNodeIds();
6674
- const nodeId = String(node['id'] ?? '');
6675
- if (nodeId && selectedIds.includes(nodeId)) {
6676
- node['selected'] = true;
6786
+ finally {
6787
+ this.isUpdatingSelection = false;
6677
6788
  }
6678
6789
  }
6679
6790
  /**
6680
- * Marks a node and its children as disabled if the node ID matches the excluded ID.
6791
+ * Recursively deselects all children of a parent node
6681
6792
  */
6682
- markNodeAsDisabled(node, excludedId) {
6683
- const nodeId = String(node['id'] ?? '');
6684
- if (nodeId === excludedId) {
6685
- node['disabled'] = true;
6793
+ async loadAndDeselectChildrenRecursively(parentId) {
6794
+ if (!this.treeData || !this.treeConfig || !parentId || parentId === 'all') {
6795
+ return;
6686
6796
  }
6687
- // Recursively mark children
6688
- const nodeChildren = node['children'];
6689
- if (nodeChildren) {
6690
- nodeChildren.forEach((child) => {
6691
- this.markNodeAsDisabled(child, excludedId);
6692
- });
6797
+ const treeComponent = this.tree();
6798
+ if (!treeComponent) {
6799
+ return;
6800
+ }
6801
+ try {
6802
+ // Load children using datasource
6803
+ const childNodes = await this.datasource(parentId);
6804
+ if (!childNodes || childNodes.length === 0) {
6805
+ return;
6806
+ }
6807
+ const childIdsToDeselect = [];
6808
+ // Collect all child IDs
6809
+ for (const childNode of childNodes) {
6810
+ const childId = String(childNode['id'] ?? '');
6811
+ if (childId && childId !== 'all') {
6812
+ childIdsToDeselect.push(childId);
6813
+ }
6814
+ }
6815
+ // Remove children from selectedNodeIds
6816
+ const currentSelected = this.selectedNodeIds();
6817
+ const updatedSelected = currentSelected.filter((id) => !childIdsToDeselect.includes(id));
6818
+ this.selectedNodeIds.set(updatedSelected);
6819
+ // Deselect in tree component
6820
+ for (const childId of childIdsToDeselect) {
6821
+ try {
6822
+ treeComponent.deselectNode(childId);
6823
+ }
6824
+ catch {
6825
+ // Node might not be in tree
6826
+ }
6827
+ }
6828
+ // Recursively deselect children of each child
6829
+ await Promise.all(childIdsToDeselect.map((childId) => this.loadAndDeselectChildrenRecursively(childId)));
6830
+ }
6831
+ catch (error) {
6832
+ console.error(`Error deselecting children for node ${parentId}:`, error);
6693
6833
  }
6694
6834
  }
6695
6835
  /**
6696
- * Processes root node: marks excluded as disabled, marks selected, and syncs selection with tree component
6836
+ * Updates parent states based on children selection (select/intermediate)
6837
+ * Called after a node is selected/deselected to update parent checkbox states
6697
6838
  */
6698
- processRootNode(rootNode) {
6699
- const excludedId = this.excludedNodeId();
6700
- if (excludedId) {
6701
- this.markNodeAsDisabled(rootNode, excludedId);
6839
+ async updateParentStates(changedNodeId) {
6840
+ if (!this.treeData || !this.treeConfig || !this.allowMultiple()) {
6841
+ return;
6842
+ }
6843
+ const parentKey = this.treeData.categoryEntityDef?.parentKey;
6844
+ if (!parentKey) {
6845
+ return; // No parent key means flat structure
6702
6846
  }
6703
- this.markNodesAsSelected(rootNode);
6704
- // Sync selection with tree component after a short delay to ensure tree is rendered
6705
6847
  const treeComponent = this.tree();
6706
- if (treeComponent) {
6707
- setTimeout(() => {
6708
- const selectedIds = this.selectedNodeIds();
6709
- selectedIds.forEach((id) => {
6710
- if (id && id !== 'all') {
6711
- treeComponent.selectNode(id);
6848
+ if (!treeComponent) {
6849
+ return;
6850
+ }
6851
+ // Start from the changed node's parent and work up the tree
6852
+ const processedParents = new Set();
6853
+ let currentId = changedNodeId;
6854
+ // Process all parents up to root
6855
+ while (currentId && currentId !== 'all') {
6856
+ const nodeData = this.nodeDataCache.get(currentId);
6857
+ if (!nodeData) {
6858
+ break;
6859
+ }
6860
+ const parentId = nodeData[parentKey];
6861
+ const parentIdStr = String(parentId);
6862
+ if (!parentId || parentId === 'all' || parentId === currentId || processedParents.has(parentIdStr)) {
6863
+ break;
6864
+ }
6865
+ processedParents.add(parentIdStr);
6866
+ // Load all children of this parent
6867
+ try {
6868
+ const childNodes = await this.datasource(parentIdStr);
6869
+ if (!childNodes || childNodes.length === 0) {
6870
+ currentId = parentIdStr;
6871
+ continue;
6872
+ }
6873
+ // Get current selection state (updated after each parent change)
6874
+ const currentSelected = this.selectedNodeIds();
6875
+ const selectedSet = new Set(currentSelected);
6876
+ let selectedCount = 0;
6877
+ let totalCount = 0;
6878
+ // Count selected children
6879
+ for (const childNode of childNodes) {
6880
+ const childId = String(childNode['id'] ?? '');
6881
+ if (childId && childId !== 'all') {
6882
+ totalCount++;
6883
+ if (selectedSet.has(childId)) {
6884
+ selectedCount++;
6885
+ }
6712
6886
  }
6713
- });
6714
- }, 0);
6887
+ }
6888
+ // Update parent selection state
6889
+ const isParentSelected = currentSelected.includes(parentIdStr);
6890
+ if (totalCount > 0) {
6891
+ if (selectedCount === totalCount) {
6892
+ // All children selected - select parent
6893
+ if (!isParentSelected) {
6894
+ this.selectedNodeIds.set([...currentSelected, parentIdStr]);
6895
+ try {
6896
+ treeComponent.selectNode(parentIdStr);
6897
+ }
6898
+ catch {
6899
+ // Parent might not be in tree
6900
+ }
6901
+ }
6902
+ }
6903
+ else if (selectedCount > 0) {
6904
+ // Some children selected - parent should be in intermediate state
6905
+ // The tree component handles intermediate state automatically via selectionBehavior
6906
+ // We just need to ensure parent is not fully selected
6907
+ if (isParentSelected) {
6908
+ // Deselect parent to show intermediate state
6909
+ this.selectedNodeIds.set(currentSelected.filter((id) => id !== parentIdStr));
6910
+ try {
6911
+ treeComponent.deselectNode(parentIdStr);
6912
+ }
6913
+ catch {
6914
+ // Parent might not be in tree
6915
+ }
6916
+ }
6917
+ }
6918
+ else {
6919
+ // No children selected - deselect parent
6920
+ if (isParentSelected) {
6921
+ this.selectedNodeIds.set(currentSelected.filter((id) => id !== parentIdStr));
6922
+ try {
6923
+ treeComponent.deselectNode(parentIdStr);
6924
+ }
6925
+ catch {
6926
+ // Parent might not be in tree
6927
+ }
6928
+ }
6929
+ }
6930
+ }
6931
+ // Cache parent data if not already cached
6932
+ if (!this.nodeDataCache.has(parentIdStr)) {
6933
+ const parentData = await this.fetchItemById(parentIdStr);
6934
+ if (parentData) {
6935
+ this.nodeDataCache.set(parentIdStr, parentData);
6936
+ }
6937
+ }
6938
+ currentId = parentIdStr;
6939
+ }
6940
+ catch (error) {
6941
+ console.error(`Error updating parent state for ${parentIdStr}:`, error);
6942
+ break;
6943
+ }
6715
6944
  }
6716
6945
  }
6717
6946
  /**
6718
- * Processes child nodes: marks excluded as disabled, marks selected, and syncs selection
6947
+ * Recursively loads and selects all children of a parent node using the datasource
6948
+ * This method directly calls datasource without expanding/collapsing nodes to avoid UI glitches
6719
6949
  */
6720
- processChildNodes(childNodes) {
6721
- const excludedId = this.excludedNodeId();
6722
- const selectedIds = this.selectedNodeIds();
6723
- childNodes.forEach((node) => {
6724
- const nodeId = String(node['id'] ?? '');
6725
- if (excludedId && nodeId === excludedId) {
6726
- node['disabled'] = true;
6727
- }
6728
- if (nodeId && selectedIds.includes(nodeId)) {
6729
- node['selected'] = true;
6730
- }
6731
- });
6732
- // Sync selection with tree component
6950
+ async loadAndSelectChildrenRecursively(parentId) {
6951
+ if (!this.treeData || !this.treeConfig || !parentId || parentId === 'all') {
6952
+ return;
6953
+ }
6733
6954
  const treeComponent = this.tree();
6734
- if (treeComponent) {
6735
- setTimeout(() => {
6955
+ if (!treeComponent) {
6956
+ return;
6957
+ }
6958
+ try {
6959
+ // Directly call datasource to get children data without expanding the node
6960
+ // This avoids UI glitches from expand/collapse operations
6961
+ // If node has no children, datasource will return empty array
6962
+ const childNodes = await this.datasource(parentId);
6963
+ if (!childNodes || childNodes.length === 0) {
6964
+ return; // No children to process
6965
+ }
6966
+ // Collect all child IDs to add to selectedNodeIds
6967
+ const childIdsToSelect = [];
6968
+ // Process all children and cache their data
6969
+ for (const childNode of childNodes) {
6970
+ const childId = String(childNode['id'] ?? '');
6971
+ if (childId && childId !== 'all') {
6972
+ childIdsToSelect.push(childId);
6973
+ // Cache node data for getSelectedItems
6974
+ // Try to get data from 'data' property first, then fallback to node itself
6975
+ let nodeData = childNode['data'];
6976
+ // If no data property, try to extract data from the node
6977
+ if (!nodeData || typeof nodeData !== 'object') {
6978
+ // Create a data object from the node properties
6979
+ const valueField = this.treeConfig.valueField || 'id';
6980
+ const textField = this.treeConfig.textField || 'title';
6981
+ nodeData = {
6982
+ [valueField]: childId,
6983
+ [textField]: childNode['title'] ?? '',
6984
+ ...childNode,
6985
+ };
6986
+ }
6987
+ // Cache the node data
6988
+ if (nodeData && typeof nodeData === 'object') {
6989
+ this.nodeDataCache.set(childId, nodeData);
6990
+ }
6991
+ }
6992
+ }
6993
+ if (childIdsToSelect.length === 0) {
6994
+ return; // No valid children to select
6995
+ }
6996
+ // Update selectedNodeIds to include all children
6997
+ const currentSelected = this.selectedNodeIds();
6998
+ const newSelected = [...currentSelected];
6999
+ let hasNewSelections = false;
7000
+ for (const childId of childIdsToSelect) {
7001
+ if (!newSelected.includes(childId)) {
7002
+ newSelected.push(childId);
7003
+ hasNewSelections = true;
7004
+ }
7005
+ }
7006
+ if (hasNewSelections) {
7007
+ this.selectedNodeIds.set(newSelected);
7008
+ }
7009
+ // Try to select children in tree component if they're already loaded
7010
+ // If not loaded yet, they'll be selected when the tree loads them (via markNodeAsSelectedIfNeeded)
7011
+ for (const childId of childIdsToSelect) {
7012
+ try {
7013
+ // Only try to select if node exists in tree (might not be loaded if parent isn't expanded)
7014
+ const node = treeComponent.findNode(childId);
7015
+ if (node) {
7016
+ treeComponent.selectNode(childId);
7017
+ }
7018
+ }
7019
+ catch {
7020
+ // If selection fails, it's okay - we've already added to selectedNodeIds
7021
+ // The tree will sync selection when the node is loaded via datasource callback
7022
+ }
7023
+ }
7024
+ // Recursively load and select children of each child
7025
+ // Use Promise.all for parallel processing to improve performance
7026
+ await Promise.all(childIdsToSelect.map((childId) => this.loadAndSelectChildrenRecursively(childId)));
7027
+ }
7028
+ catch (error) {
7029
+ console.error(`Error loading children for node ${parentId}:`, error);
7030
+ }
7031
+ }
7032
+ //#endregion
7033
+ async updateSelectedNodes(selectedIds) {
7034
+ if (!selectedIds || selectedIds.length === 0) {
7035
+ this.selectedNodeIds.set([]);
7036
+ return;
7037
+ }
7038
+ const ids = selectedIds.filter((id) => id && id !== 'all');
7039
+ // Set flag to prevent recursive updates during initialization
7040
+ this.isUpdatingSelection = true;
7041
+ try {
7042
+ // Fetch node data for pre-selected items that aren't in the cache
7043
+ await this.loadMissingNodeData(ids);
7044
+ // Collect all nodes to select (pre-selected + all their descendants)
7045
+ const allNodesToSelect = new Set(ids);
7046
+ for (const nodeId of ids) {
7047
+ await this.collectAllDescendants(nodeId, allNodesToSelect);
7048
+ }
7049
+ // Set all selected nodes at once
7050
+ this.selectedNodeIds.set(Array.from(allNodesToSelect));
7051
+ // Expand parents of pre-selected nodes so they're visible in the tree
7052
+ await this.expandParentsOfSelectedNodes(Array.from(allNodesToSelect));
7053
+ // Sync selection with tree component - wait for tree to be ready
7054
+ await this.syncSelectionWithTree(Array.from(allNodesToSelect));
7055
+ }
7056
+ finally {
7057
+ this.isUpdatingSelection = false;
7058
+ }
7059
+ }
7060
+ /**
7061
+ * Updates all parent states based on their children's selection
7062
+ * Used during initialization to ensure proper parent states (select/intermediate)
7063
+ */
7064
+ async updateAllParentStates(selectedIds) {
7065
+ if (!this.treeData || !this.treeConfig || !this.allowMultiple() || selectedIds.length === 0) {
7066
+ return;
7067
+ }
7068
+ const parentKey = this.treeData.categoryEntityDef?.parentKey;
7069
+ if (!parentKey) {
7070
+ return;
7071
+ }
7072
+ const treeComponent = this.tree();
7073
+ if (!treeComponent) {
7074
+ return;
7075
+ }
7076
+ const selectedSet = new Set(selectedIds);
7077
+ const processedParents = new Set();
7078
+ // Collect all unique parent IDs
7079
+ for (const selectedId of selectedIds) {
7080
+ if (selectedId === 'all') {
7081
+ continue;
7082
+ }
7083
+ const nodeData = this.nodeDataCache.get(selectedId);
7084
+ if (!nodeData) {
7085
+ continue;
7086
+ }
7087
+ let currentId = selectedId;
7088
+ while (currentId && currentId !== 'all') {
7089
+ const currentNodeData = this.nodeDataCache.get(currentId);
7090
+ if (!currentNodeData) {
7091
+ break;
7092
+ }
7093
+ const parentId = currentNodeData[parentKey];
7094
+ const parentIdStr = String(parentId);
7095
+ if (!parentId || parentId === 'all' || parentId === currentId || processedParents.has(parentIdStr)) {
7096
+ break;
7097
+ }
7098
+ processedParents.add(parentIdStr);
7099
+ currentId = parentIdStr;
7100
+ }
7101
+ }
7102
+ // Process parents multiple times to handle cascading parent selections
7103
+ // (when a parent is selected, its parent might also need to be selected)
7104
+ let hasChanges = true;
7105
+ let iterations = 0;
7106
+ const maxIterations = 10; // Prevent infinite loops
7107
+ while (hasChanges && iterations < maxIterations) {
7108
+ iterations++;
7109
+ hasChanges = false;
7110
+ // Update selectedSet with current selectedNodeIds
7111
+ const currentSelected = this.selectedNodeIds();
7112
+ currentSelected.forEach((id) => selectedSet.add(id));
7113
+ // Update each parent's state
7114
+ for (const parentId of processedParents) {
7115
+ try {
7116
+ const childNodes = await this.datasource(parentId);
7117
+ if (!childNodes || childNodes.length === 0) {
7118
+ continue;
7119
+ }
7120
+ let selectedCount = 0;
7121
+ let totalCount = 0;
7122
+ for (const childNode of childNodes) {
7123
+ const childId = String(childNode['id'] ?? '');
7124
+ if (childId && childId !== 'all') {
7125
+ totalCount++;
7126
+ if (selectedSet.has(childId)) {
7127
+ selectedCount++;
7128
+ }
7129
+ }
7130
+ }
7131
+ const isParentSelected = currentSelected.includes(parentId);
7132
+ if (totalCount > 0) {
7133
+ if (selectedCount === totalCount) {
7134
+ // All children selected - select parent
7135
+ if (!isParentSelected) {
7136
+ this.selectedNodeIds.set([...currentSelected, parentId]);
7137
+ selectedSet.add(parentId);
7138
+ hasChanges = true;
7139
+ try {
7140
+ treeComponent.selectNode(parentId);
7141
+ }
7142
+ catch {
7143
+ // Parent might not be in tree
7144
+ }
7145
+ }
7146
+ }
7147
+ else if (selectedCount > 0) {
7148
+ // Some children selected - parent should be in intermediate state
7149
+ if (isParentSelected) {
7150
+ // Deselect parent to show intermediate state
7151
+ this.selectedNodeIds.set(currentSelected.filter((id) => id !== parentId));
7152
+ selectedSet.delete(parentId);
7153
+ hasChanges = true;
7154
+ try {
7155
+ treeComponent.deselectNode(parentId);
7156
+ }
7157
+ catch {
7158
+ // Parent might not be in tree
7159
+ }
7160
+ }
7161
+ }
7162
+ else {
7163
+ // No children selected - deselect parent
7164
+ if (isParentSelected) {
7165
+ this.selectedNodeIds.set(currentSelected.filter((id) => id !== parentId));
7166
+ selectedSet.delete(parentId);
7167
+ hasChanges = true;
7168
+ try {
7169
+ treeComponent.deselectNode(parentId);
7170
+ }
7171
+ catch {
7172
+ // Parent might not be in tree
7173
+ }
7174
+ }
7175
+ }
7176
+ }
7177
+ }
7178
+ catch (error) {
7179
+ console.error(`Error updating parent state for ${parentId}:`, error);
7180
+ }
7181
+ }
7182
+ }
7183
+ }
7184
+ /**
7185
+ * Expands parents of selected nodes so they're visible when popup opens
7186
+ */
7187
+ async expandParentsOfSelectedNodes(selectedIds) {
7188
+ if (!this.treeData || !this.treeConfig || selectedIds.length === 0) {
7189
+ return;
7190
+ }
7191
+ const parentKey = this.treeData.categoryEntityDef?.parentKey;
7192
+ if (!parentKey) {
7193
+ return; // No parent key means flat structure
7194
+ }
7195
+ const treeComponent = this.tree();
7196
+ if (!treeComponent) {
7197
+ return;
7198
+ }
7199
+ // Collect all unique parent IDs that need to be expanded
7200
+ const parentsToExpand = new Set();
7201
+ for (const selectedId of selectedIds) {
7202
+ if (selectedId === 'all') {
7203
+ continue;
7204
+ }
7205
+ const nodeData = this.nodeDataCache.get(selectedId);
7206
+ if (!nodeData) {
7207
+ continue;
7208
+ }
7209
+ const parentId = nodeData[parentKey];
7210
+ if (parentId && parentId !== 'all') {
7211
+ const parentIdStr = String(parentId);
7212
+ parentsToExpand.add(parentIdStr);
7213
+ // Also expand grandparents, etc.
7214
+ let currentParentId = parentIdStr;
7215
+ while (currentParentId) {
7216
+ const parentData = this.nodeDataCache.get(currentParentId);
7217
+ if (!parentData) {
7218
+ break;
7219
+ }
7220
+ const grandParentId = parentData[parentKey];
7221
+ if (grandParentId && grandParentId !== 'all' && grandParentId !== currentParentId) {
7222
+ parentsToExpand.add(String(grandParentId));
7223
+ currentParentId = String(grandParentId);
7224
+ }
7225
+ else {
7226
+ break;
7227
+ }
7228
+ }
7229
+ }
7230
+ }
7231
+ // Expand all parents (starting from root to leaves)
7232
+ const sortedParents = Array.from(parentsToExpand).sort((a, b) => {
7233
+ // Simple sort - expand root nodes first
7234
+ return a.localeCompare(b);
7235
+ });
7236
+ for (const parentId of sortedParents) {
7237
+ try {
7238
+ if (!treeComponent.isNodeExpanded(parentId)) {
7239
+ await treeComponent.expandNode(parentId);
7240
+ // Small delay to ensure children are loaded
7241
+ await new Promise((resolve) => setTimeout(resolve, 50));
7242
+ }
7243
+ }
7244
+ catch {
7245
+ // Parent might not be in tree yet, ignore
7246
+ }
7247
+ }
7248
+ }
7249
+ /**
7250
+ * Selects parents whose all children are selected
7251
+ * This ensures that when all children of a parent are selected, the parent also appears selected
7252
+ */
7253
+ async selectParentsWithAllChildrenSelected(selectedIds) {
7254
+ if (!this.treeData || !this.treeConfig || selectedIds.length === 0) {
7255
+ return;
7256
+ }
7257
+ const parentKey = this.treeData.categoryEntityDef?.parentKey;
7258
+ if (!parentKey) {
7259
+ return; // No parent key means flat structure
7260
+ }
7261
+ // Use current selectedNodeIds signal value (may have been updated)
7262
+ const currentSelectedIds = this.selectedNodeIds();
7263
+ const selectedSet = new Set(currentSelectedIds);
7264
+ const processedParents = new Set();
7265
+ const parentsToSelect = new Set();
7266
+ // For each selected node, check its parent
7267
+ for (const selectedId of currentSelectedIds) {
7268
+ if (selectedId === 'all') {
7269
+ continue;
7270
+ }
7271
+ // Get parent ID from cached data
7272
+ const nodeData = this.nodeDataCache.get(selectedId);
7273
+ if (!nodeData) {
7274
+ continue;
7275
+ }
7276
+ const parentId = nodeData[parentKey];
7277
+ if (!parentId || parentId === 'all' || processedParents.has(String(parentId))) {
7278
+ continue;
7279
+ }
7280
+ const parentIdStr = String(parentId);
7281
+ processedParents.add(parentIdStr);
7282
+ // Load all children of this parent
7283
+ try {
7284
+ const childNodes = await this.datasource(parentIdStr);
7285
+ if (!childNodes || childNodes.length === 0) {
7286
+ continue;
7287
+ }
7288
+ // Check if all children are selected
7289
+ let allChildrenSelected = true;
7290
+ let hasChildren = false;
7291
+ for (const childNode of childNodes) {
7292
+ const childId = String(childNode['id'] ?? '');
7293
+ if (childId && childId !== 'all') {
7294
+ hasChildren = true;
7295
+ if (!selectedSet.has(childId)) {
7296
+ allChildrenSelected = false;
7297
+ break;
7298
+ }
7299
+ }
7300
+ }
7301
+ // If parent has children and all are selected, mark parent for selection
7302
+ if (hasChildren && allChildrenSelected) {
7303
+ parentsToSelect.add(parentIdStr);
7304
+ // Cache parent data if not already cached
7305
+ if (!this.nodeDataCache.has(parentIdStr)) {
7306
+ const parentData = await this.fetchItemById(parentIdStr);
7307
+ if (parentData) {
7308
+ this.nodeDataCache.set(parentIdStr, parentData);
7309
+ }
7310
+ }
7311
+ }
7312
+ }
7313
+ catch (error) {
7314
+ console.error(`Error checking parent ${parentIdStr}:`, error);
7315
+ }
7316
+ }
7317
+ // Add parents to selectedNodeIds
7318
+ if (parentsToSelect.size > 0) {
7319
+ const currentSelected = this.selectedNodeIds();
7320
+ const newSelected = [...currentSelected];
7321
+ let hasNewSelections = false;
7322
+ for (const parentId of parentsToSelect) {
7323
+ if (!newSelected.includes(parentId)) {
7324
+ newSelected.push(parentId);
7325
+ hasNewSelections = true;
7326
+ }
7327
+ }
7328
+ if (hasNewSelections) {
7329
+ this.selectedNodeIds.set(newSelected);
7330
+ // Recursively check parents of these parents
7331
+ const updatedSelected = this.selectedNodeIds();
7332
+ await this.selectParentsWithAllChildrenSelected(updatedSelected);
7333
+ }
7334
+ }
7335
+ }
7336
+ /**
7337
+ * Syncs selection state with the tree component
7338
+ * Handles cases where nodes might not be in the tree structure yet
7339
+ */
7340
+ async syncSelectionWithTree(selectedIds) {
7341
+ const treeComponent = this.tree();
7342
+ if (!treeComponent || selectedIds.length === 0) {
7343
+ return;
7344
+ }
7345
+ // Wait for tree to be fully initialized and rendered
7346
+ await new Promise((resolve) => setTimeout(resolve, 300));
7347
+ // Try multiple times to sync selection (nodes might load progressively)
7348
+ for (let attempt = 0; attempt < 3; attempt++) {
7349
+ let syncedCount = 0;
7350
+ selectedIds.forEach((id) => {
7351
+ if (id && id !== 'all') {
7352
+ try {
7353
+ const node = treeComponent.findNode(id);
7354
+ if (node) {
7355
+ // Node exists in tree, select it
7356
+ treeComponent.selectNode(id);
7357
+ syncedCount++;
7358
+ }
7359
+ }
7360
+ catch {
7361
+ // Node not in tree yet - will be selected when loaded via datasource callback
7362
+ }
7363
+ }
7364
+ });
7365
+ // If all nodes are synced, we're done
7366
+ if (syncedCount === selectedIds.length) {
7367
+ break;
7368
+ }
7369
+ // Wait a bit before next attempt
7370
+ if (attempt < 2) {
7371
+ await new Promise((resolve) => setTimeout(resolve, 100));
7372
+ }
7373
+ }
7374
+ // After syncing, read back from tree component to get any parents that were automatically selected
7375
+ // (due to intermediate-nested behavior when all children are selected)
7376
+ if (this.allowMultiple()) {
7377
+ try {
7378
+ const treeSelectedNodes = treeComponent.getSelectedNodes();
7379
+ const treeSelectedIds = treeSelectedNodes
7380
+ .map((node) => String(node['id'] ?? ''))
7381
+ .filter((id) => id && id !== 'all');
7382
+ // Update selectedNodeIds to match tree component's state (includes auto-selected parents)
7383
+ this.selectedNodeIds.set(treeSelectedIds);
7384
+ }
7385
+ catch {
7386
+ // Tree component might not be ready yet
7387
+ }
7388
+ }
7389
+ // Note: Selection state is maintained in selectedNodeIds signal
7390
+ // The tree component will sync selection state when nodes are loaded via datasource
7391
+ // We mark nodes as selected in the datasource callback by setting node.selected = true
7392
+ // Nodes that aren't in the tree yet will be selected when their parent is expanded
7393
+ }
7394
+ /**
7395
+ * Loads node data for IDs that are selected but not yet in the cache.
7396
+ * This is critical for pre-selected values in collapsed branches.
7397
+ */
7398
+ async loadMissingNodeData(selectedIds) {
7399
+ if (!this.treeData || !this.treeConfig || selectedIds.length === 0) {
7400
+ return;
7401
+ }
7402
+ // Find IDs that are selected but not in cache
7403
+ const missingIds = selectedIds.filter((id) => !this.nodeDataCache.has(id));
7404
+ if (missingIds.length === 0) {
7405
+ return;
7406
+ }
7407
+ try {
7408
+ const valueField = this.treeConfig.valueField || 'id';
7409
+ const categoryEntityQueryFunc = this.treeData.categoryEntityQueryFunc;
7410
+ if (!categoryEntityQueryFunc) {
7411
+ return;
7412
+ }
7413
+ // Query for missing nodes by their IDs
7414
+ const event = {
7415
+ ...this.treeData.basicQueryEvent,
7416
+ filter: {
7417
+ filters: missingIds.map((id) => ({
7418
+ field: valueField,
7419
+ value: id,
7420
+ operator: { type: 'equal' },
7421
+ })),
7422
+ logic: 'or',
7423
+ },
7424
+ };
7425
+ const res = await categoryEntityQueryFunc(event);
7426
+ if (res?.items) {
7427
+ // Cache the fetched node data
7428
+ res.items.forEach((item) => {
7429
+ const itemId = String(item[valueField] ?? '');
7430
+ if (itemId) {
7431
+ this.nodeDataCache.set(itemId, item);
7432
+ }
7433
+ });
7434
+ }
7435
+ }
7436
+ catch (error) {
7437
+ console.error('Error loading missing node data:', error);
7438
+ }
7439
+ }
7440
+ /**
7441
+ * Marks nodes as selected in the tree structure based on selectedNodeIds.
7442
+ * This ensures pre-selected nodes appear selected when the tree is rendered.
7443
+ */
7444
+ markNodesAsSelected(node) {
7445
+ const selectedIds = this.selectedNodeIds();
7446
+ if (selectedIds.length === 0) {
7447
+ return;
7448
+ }
7449
+ // Mark the node itself if it's selected
7450
+ this.markNodeAsSelectedIfNeeded(node);
7451
+ // Recursively mark children
7452
+ const nodeChildren = node['children'];
7453
+ if (nodeChildren) {
7454
+ nodeChildren.forEach((child) => {
7455
+ this.markNodesAsSelected(child);
7456
+ });
7457
+ }
7458
+ }
7459
+ /**
7460
+ * Marks a single node as selected if it's in the selectedNodeIds list.
7461
+ */
7462
+ markNodeAsSelectedIfNeeded(node) {
7463
+ const selectedIds = this.selectedNodeIds();
7464
+ const nodeId = String(node['id'] ?? '');
7465
+ if (nodeId && selectedIds.includes(nodeId)) {
7466
+ node['selected'] = true;
7467
+ }
7468
+ }
7469
+ /**
7470
+ * Marks a node and its children as disabled if the node ID matches the excluded ID.
7471
+ */
7472
+ markNodeAsDisabled(node, excludedId) {
7473
+ const nodeId = String(node['id'] ?? '');
7474
+ if (nodeId === excludedId) {
7475
+ node['disabled'] = true;
7476
+ }
7477
+ // Recursively mark children
7478
+ const nodeChildren = node['children'];
7479
+ if (nodeChildren) {
7480
+ nodeChildren.forEach((child) => {
7481
+ this.markNodeAsDisabled(child, excludedId);
7482
+ });
7483
+ }
7484
+ }
7485
+ /**
7486
+ * Processes root node: marks excluded as disabled, marks selected, and syncs selection with tree component
7487
+ */
7488
+ processRootNode(rootNode) {
7489
+ const excludedId = this.excludedNodeId();
7490
+ if (excludedId) {
7491
+ this.markNodeAsDisabled(rootNode, excludedId);
7492
+ }
7493
+ this.markNodesAsSelected(rootNode);
7494
+ // Sync selection with tree component after a short delay to ensure tree is rendered
7495
+ const treeComponent = this.tree();
7496
+ if (treeComponent) {
7497
+ setTimeout(() => {
7498
+ const selectedIds = this.selectedNodeIds();
7499
+ selectedIds.forEach((id) => {
7500
+ if (id && id !== 'all') {
7501
+ treeComponent.selectNode(id);
7502
+ }
7503
+ });
7504
+ }, 0);
7505
+ }
7506
+ }
7507
+ /**
7508
+ * Processes child nodes: marks excluded as disabled, marks selected, and syncs selection
7509
+ */
7510
+ processChildNodes(childNodes) {
7511
+ const excludedId = this.excludedNodeId();
7512
+ const selectedIds = this.selectedNodeIds();
7513
+ childNodes.forEach((node) => {
7514
+ const nodeId = String(node['id'] ?? '');
7515
+ if (excludedId && nodeId === excludedId) {
7516
+ node['disabled'] = true;
7517
+ }
7518
+ if (nodeId && selectedIds.includes(nodeId)) {
7519
+ node['selected'] = true;
7520
+ }
7521
+ });
7522
+ // Sync selection with tree component
7523
+ const treeComponent = this.tree();
7524
+ if (treeComponent) {
7525
+ setTimeout(() => {
6736
7526
  childNodes.forEach((node) => {
6737
7527
  const nodeId = String(node['id'] ?? '');
6738
7528
  if (nodeId && selectedIds.includes(nodeId) && nodeId !== 'all') {
@@ -6887,41 +7677,107 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
6887
7677
  const textField = this.treeConfig.textField || 'title';
6888
7678
  return String(nodeData[textField] ?? '');
6889
7679
  }
6890
- async getSelectedItems() {
6891
- // Use tree component's getSelectedNodes if available for more accurate selection
6892
- const treeComponent = this.tree();
6893
- if (treeComponent) {
6894
- const selectedNodes = treeComponent.getSelectedNodes();
6895
- const items = await Promise.all(selectedNodes.map(async (node) => {
6896
- const nodeId = String(node['id'] ?? '');
6897
- if (nodeId === 'all') {
6898
- return null;
6899
- }
6900
- const nodeData = node['data'] || node;
6901
- if (!nodeData) {
6902
- return null;
6903
- }
6904
- // Calculate path for this node
6905
- const path = await this.calculateNodePath(nodeId, nodeData);
6906
- return {
6907
- ...nodeData,
6908
- id: nodeId,
6909
- path: path,
6910
- };
6911
- }));
6912
- return items.filter((item) => item != null);
7680
+ /**
7681
+ * Checks if a node is a leaf node (has no children)
7682
+ */
7683
+ async isLeafNode(nodeId, treeComponent) {
7684
+ if (!treeComponent) {
7685
+ // If no tree component, check if node has children by querying
7686
+ return await this.checkIfNodeHasChildren(nodeId);
7687
+ }
7688
+ try {
7689
+ const node = treeComponent.findNode(nodeId);
7690
+ if (!node) {
7691
+ // Node not found in tree, check via query
7692
+ return await this.checkIfNodeHasChildren(nodeId);
7693
+ }
7694
+ // Check if node has children
7695
+ const children = node['children'];
7696
+ const childrenCount = node['childrenCount'];
7697
+ // If children are loaded, check the array
7698
+ if (children !== undefined) {
7699
+ return !children || children.length === 0;
7700
+ }
7701
+ // If childrenCount is available, use it
7702
+ if (childrenCount !== undefined) {
7703
+ return childrenCount === 0;
7704
+ }
7705
+ // If neither is available, try to check via query
7706
+ return await this.checkIfNodeHasChildren(nodeId);
7707
+ }
7708
+ catch {
7709
+ // If findNode fails, check via query
7710
+ return await this.checkIfNodeHasChildren(nodeId);
7711
+ }
7712
+ }
7713
+ /**
7714
+ * Checks if a node has children by querying the data source
7715
+ */
7716
+ async checkIfNodeHasChildren(nodeId) {
7717
+ if (!this.treeData?.categoryEntityQueryFunc || !this.treeConfig) {
7718
+ return true; // Assume leaf if we can't check
7719
+ }
7720
+ try {
7721
+ const parentKey = this.treeData.categoryEntityDef?.parentKey;
7722
+ if (!parentKey) {
7723
+ return true; // No parent key means flat structure, all nodes are leaves
7724
+ }
7725
+ const event = {
7726
+ ...this.treeData.basicQueryEvent,
7727
+ filter: {
7728
+ field: parentKey,
7729
+ value: nodeId,
7730
+ operator: { type: 'equal' },
7731
+ },
7732
+ take: 1, // Only need to check if any children exist
7733
+ };
7734
+ const res = await this.treeData.categoryEntityQueryFunc(event);
7735
+ return !res?.items || res.items.length === 0;
6913
7736
  }
6914
- // Fallback to cached data
7737
+ catch {
7738
+ return true; // Assume leaf on error
7739
+ }
7740
+ }
7741
+ async getSelectedItems() {
7742
+ // Always use selectedNodeIds as the source of truth
7743
+ // This ensures we get all selected nodes, even if they're not in the tree structure yet
6915
7744
  const selectedIds = this.selectedNodeIds();
6916
7745
  if (selectedIds.length === 0) {
6917
7746
  return [];
6918
7747
  }
7748
+ const treeComponent = this.tree();
6919
7749
  // Get node data from cache and calculate paths
7750
+ // For nodes not in cache, try to get from tree component
6920
7751
  const items = await Promise.all(selectedIds.map(async (id) => {
6921
- const nodeData = this.nodeDataCache.get(id);
7752
+ // First try to get from cache
7753
+ let nodeData = this.nodeDataCache.get(id);
7754
+ // If not in cache, try to get from tree component
7755
+ if (!nodeData && treeComponent) {
7756
+ try {
7757
+ const node = treeComponent.findNode(id);
7758
+ if (node) {
7759
+ nodeData = node['data'] || node;
7760
+ // Cache it for future use
7761
+ if (nodeData && typeof nodeData === 'object') {
7762
+ this.nodeDataCache.set(id, nodeData);
7763
+ }
7764
+ }
7765
+ }
7766
+ catch {
7767
+ // Node not found in tree, continue with cache lookup
7768
+ }
7769
+ }
7770
+ // If still no data, skip this node
6922
7771
  if (!nodeData) {
6923
7772
  return null;
6924
7773
  }
7774
+ // When selectionBehavior is intermediate-nested, only return leaf nodes
7775
+ if (this.allowMultiple()) {
7776
+ const isLeaf = await this.isLeafNode(id, treeComponent ?? null);
7777
+ if (!isLeaf) {
7778
+ return null; // Skip non-leaf nodes
7779
+ }
7780
+ }
6925
7781
  const path = await this.calculateNodePath(id, nodeData);
6926
7782
  return {
6927
7783
  ...nodeData,
@@ -6936,9 +7792,9 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
6936
7792
  <div class="ax-flex ax-flex-col ax-h-full">
6937
7793
  @if (loading()) {
6938
7794
  <div class="ax-p-4 ax-flex ax-flex-col ax-gap-3">
6939
- <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
6940
- <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
6941
- <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
7795
+ @for (i of [1, 2, 3, 4]; track i) {
7796
+ <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
7797
+ }
6942
7798
  </div>
6943
7799
  } @else if (treeData) {
6944
7800
  <div class="ax-flex ax-flex-col ax-flex-1 ax-min-h-0">
@@ -6976,14 +7832,14 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
6976
7832
  [datasource]="datasource"
6977
7833
  [dragBehavior]="'none'"
6978
7834
  [selectMode]="allowMultiple() ? 'multiple' : 'single'"
6979
- [selectionBehavior]="selectionBehavior()"
7835
+ [selectionBehavior]="allowMultiple() ? 'intermediate-nested' : 'all'"
6980
7836
  [showIcons]="true"
6981
7837
  [titleField]="textField()"
6982
7838
  [idField]="valueField()"
6983
- [nodeTemplate]="itemTemplate"
6984
7839
  (onNodeSelect)="onNodeSelect($event)"
6985
7840
  (onSelectionChange)="onSelectionChange($event)"
6986
7841
  (onNodeToggle)="onNodeToggle($event)"
7842
+ [nodeTemplate]="itemTemplate"
6987
7843
  #tree
6988
7844
  >
6989
7845
  </ax-tree-view>
@@ -6992,12 +7848,16 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
6992
7848
  @if (node) {
6993
7849
  @let item = node.data || node;
6994
7850
  <div class="ax-flex ax-items-center ax-gap-2 ax-w-full ax-overflow-hidden ax-p-2 ax-pe-0">
6995
- <!-- <ax-check-box
6996
- [ngModel]="isNodeSelected(node.id)"
6997
- (onValueChanged)="handleCheckboxChange(node.id, $event.value)"
6998
- (click)="$event.stopPropagation()"
6999
- [disabled]="node.disabled || node.id === 'all'"
7000
- ></ax-check-box> -->
7851
+ @if (allowMultiple()) {
7852
+ <ax-check-box
7853
+ [ngModel]="node['indeterminate'] ? null : node['selected'] || false"
7854
+ [indeterminate]="node['indeterminate'] || false"
7855
+ (onValueChanged)="handleCheckboxChange(node.id, $event.value)"
7856
+ (click)="$event.stopPropagation()"
7857
+ (pointerdown)="$event.stopPropagation()"
7858
+ [disabled]="node.disabled || node.id === 'all'"
7859
+ ></ax-check-box>
7860
+ }
7001
7861
  <ax-icon
7002
7862
  class="fas fa-folder"
7003
7863
  [style.color]="item.color ?? 'rgba(var(--ax-sys-color-warning-500), 1)'"
@@ -7036,7 +7896,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
7036
7896
  ></ax-button>
7037
7897
  </ax-suffix>
7038
7898
  </ax-footer>
7039
- `, 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: AXCheckBoxModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$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", "selectionBehavior", "dragArea", "dragBehavior", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "look", "nodeTemplate", "idField", "titleField", "tooltipField", "iconField", "expandedField", "selectedField", "indeterminateField", "disabledField", "hiddenField", "childrenField", "childrenCountField", "dataField", "inheritDisabled", "expandOnDoubleClick"], outputs: ["datasourceChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onNodeDoubleClick", "onNodeClick", "onSelectionChange", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "variant"] }, { kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7899
+ `, 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: AXCheckBoxModule }, { kind: "component", type: i2$1.AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "isLoading", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { 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: AXSearchBoxModule }, { kind: "component", type: i4$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: i5$1.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "component", type: AXTreeViewComponent, selector: "ax-tree-view", inputs: ["datasource", "selectMode", "selectionBehavior", "dragArea", "dragBehavior", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "look", "nodeTemplate", "idField", "titleField", "tooltipField", "iconField", "expandedField", "selectedField", "indeterminateField", "disabledField", "hiddenField", "childrenField", "childrenCountField", "dataField", "inheritDisabled", "expandOnDoubleClick"], outputs: ["datasourceChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onNodeDoubleClick", "onNodeClick", "onSelectionChange", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "variant"] }, { 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: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7040
7900
  }
7041
7901
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryTreeSelectorComponent, decorators: [{
7042
7902
  type: Component,
@@ -7046,9 +7906,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
7046
7906
  <div class="ax-flex ax-flex-col ax-h-full">
7047
7907
  @if (loading()) {
7048
7908
  <div class="ax-p-4 ax-flex ax-flex-col ax-gap-3">
7049
- <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
7050
- <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
7051
- <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
7909
+ @for (i of [1, 2, 3, 4]; track i) {
7910
+ <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
7911
+ }
7052
7912
  </div>
7053
7913
  } @else if (treeData) {
7054
7914
  <div class="ax-flex ax-flex-col ax-flex-1 ax-min-h-0">
@@ -7086,14 +7946,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
7086
7946
  [datasource]="datasource"
7087
7947
  [dragBehavior]="'none'"
7088
7948
  [selectMode]="allowMultiple() ? 'multiple' : 'single'"
7089
- [selectionBehavior]="selectionBehavior()"
7949
+ [selectionBehavior]="allowMultiple() ? 'intermediate-nested' : 'all'"
7090
7950
  [showIcons]="true"
7091
7951
  [titleField]="textField()"
7092
7952
  [idField]="valueField()"
7093
- [nodeTemplate]="itemTemplate"
7094
7953
  (onNodeSelect)="onNodeSelect($event)"
7095
7954
  (onSelectionChange)="onSelectionChange($event)"
7096
7955
  (onNodeToggle)="onNodeToggle($event)"
7956
+ [nodeTemplate]="itemTemplate"
7097
7957
  #tree
7098
7958
  >
7099
7959
  </ax-tree-view>
@@ -7102,12 +7962,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
7102
7962
  @if (node) {
7103
7963
  @let item = node.data || node;
7104
7964
  <div class="ax-flex ax-items-center ax-gap-2 ax-w-full ax-overflow-hidden ax-p-2 ax-pe-0">
7105
- <!-- <ax-check-box
7106
- [ngModel]="isNodeSelected(node.id)"
7107
- (onValueChanged)="handleCheckboxChange(node.id, $event.value)"
7108
- (click)="$event.stopPropagation()"
7109
- [disabled]="node.disabled || node.id === 'all'"
7110
- ></ax-check-box> -->
7965
+ @if (allowMultiple()) {
7966
+ <ax-check-box
7967
+ [ngModel]="node['indeterminate'] ? null : node['selected'] || false"
7968
+ [indeterminate]="node['indeterminate'] || false"
7969
+ (onValueChanged)="handleCheckboxChange(node.id, $event.value)"
7970
+ (click)="$event.stopPropagation()"
7971
+ (pointerdown)="$event.stopPropagation()"
7972
+ [disabled]="node.disabled || node.id === 'all'"
7973
+ ></ax-check-box>
7974
+ }
7111
7975
  <ax-icon
7112
7976
  class="fas fa-folder"
7113
7977
  [style.color]="item.color ?? 'rgba(var(--ax-sys-color-warning-500), 1)'"
@@ -7400,7 +8264,7 @@ class AXPEntityCategoryWidgetColumnComponent extends AXPColumnWidgetComponent {
7400
8264
  </div>
7401
8265
  }
7402
8266
  </div>
7403
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$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" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8267
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { 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" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7404
8268
  }
7405
8269
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetColumnComponent, decorators: [{
7406
8270
  type: Component,
@@ -7741,7 +8605,7 @@ class AXPTruncatedBreadcrumbComponent {
7741
8605
  }
7742
8606
  }
7743
8607
  </div>
7744
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
8608
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
7745
8609
  }
7746
8610
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPTruncatedBreadcrumbComponent, decorators: [{
7747
8611
  type: Component,
@@ -7858,6 +8722,8 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
7858
8722
  this.selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
7859
8723
  this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
7860
8724
  this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
8725
+ this.tagBox = viewChild('tagBoxComponent', ...(ngDevMode ? [{ debugName: "tagBox" }] : []));
8726
+ this.searchTerm = signal(null, ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
7861
8727
  //#endregion
7862
8728
  //#region ---- Private Properties ----
7863
8729
  this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : []));
@@ -7912,13 +8778,62 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
7912
8778
  handleAddClick(e) {
7913
8779
  this.showTreeSelector();
7914
8780
  }
7915
- handleRemoveItemClick(event, item) {
7916
- event.nativeEvent.stopPropagation();
7917
- this.removeItem(item);
8781
+ handleValueChange(e) {
8782
+ if (e.isUserInteraction) {
8783
+ if (isNil(e.value) || isEmpty(e.value)) {
8784
+ this.clear();
8785
+ }
8786
+ else {
8787
+ const items = Array.isArray(e.value) ? e.value : [e.value];
8788
+ this.setItems(items);
8789
+ }
8790
+ }
8791
+ }
8792
+ handleOnBlur(e) {
8793
+ setTimeout(() => {
8794
+ if (!this.isOpen()) {
8795
+ this.clearInput();
8796
+ }
8797
+ }, 100);
8798
+ }
8799
+ async handleKeyUp(e) {
8800
+ const keyEvent = e.nativeEvent;
8801
+ const value = this.tagBox()?.inputValue() ?? '';
8802
+ this.searchTerm.set(value);
8803
+ if ((keyEvent.code == 'Enter' || keyEvent.code == 'NumpadEnter') && value) {
8804
+ this.isLoading.set(true);
8805
+ // For category widget, always open selector on Enter
8806
+ this.showTreeSelector();
8807
+ this.isLoading.set(false);
8808
+ }
8809
+ if (keyEvent.code == 'ArrowDown') {
8810
+ this.showTreeSelector();
8811
+ }
7918
8812
  }
7919
8813
  handleClearClick() {
7920
8814
  this.clear();
7921
8815
  }
8816
+ async handleRemoveItem(event, index) {
8817
+ event.stopPropagation();
8818
+ if (this.disabled()) {
8819
+ return;
8820
+ }
8821
+ const currentItems = this.selectedItems();
8822
+ if (index < 0 || index >= currentItems.length) {
8823
+ return;
8824
+ }
8825
+ const filteredItems = currentItems.filter((_, i) => i !== index);
8826
+ if (filteredItems.length === 0) {
8827
+ this.clear();
8828
+ }
8829
+ else {
8830
+ await this.setItems(filteredItems);
8831
+ }
8832
+ }
8833
+ clearInput() {
8834
+ this.tagBox()?.inputValue.set('');
8835
+ this.searchTerm.set('');
8836
+ }
7922
8837
  async showTreeSelector() {
7923
8838
  this.isOpen.set(true);
7924
8839
  const currentValue = this.getValue();
@@ -7989,24 +8904,12 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
7989
8904
  }
7990
8905
  finally {
7991
8906
  this.isOpen.set(false);
7992
- }
7993
- }
7994
- async removeItem(item) {
7995
- if (this.disabled()) {
7996
- return;
7997
- }
7998
- const currentItems = this.selectedItems();
7999
- const itemId = get(item, this.valueField());
8000
- const filteredItems = currentItems.filter((i) => get(i, this.valueField()) !== itemId);
8001
- if (filteredItems.length === 0) {
8002
- this.clear();
8003
- }
8004
- else {
8005
- await this.setItems(filteredItems);
8907
+ this.tagBox()?.focus();
8006
8908
  }
8007
8909
  }
8008
8910
  clear() {
8009
8911
  this.setValue(null);
8912
+ this.clearInput();
8010
8913
  this.selectedItems.set([]);
8011
8914
  this.cdr.markForCheck();
8012
8915
  }
@@ -8088,6 +8991,7 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
8088
8991
  return;
8089
8992
  }
8090
8993
  items = castArray(items);
8994
+ this.clearInput();
8091
8995
  // Ensure all items have paths
8092
8996
  const itemsWithPaths = await Promise.all(items.map(async (item) => {
8093
8997
  // If item already has a path array, return it as is
@@ -8229,47 +9133,78 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
8229
9133
  return { ...item, path: pathArray };
8230
9134
  }
8231
9135
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetEditComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
8232
- 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: `
8233
- <div class="ax-flex ax-flex-col ax-gap-3">
8234
- @if (selectedItems().length > 0) {
8235
- <div class="ax-flex ax-flex-col ax-gap-2">
8236
- @for (item of selectedItems(); track getItemId(item)) {
8237
- <div class="ax-flex ax-items-center ax-gap-2 ax-p-2 ax-border ax-primary-lightest ax-rounded-xl">
8238
- <axp-truncated-breadcrumb
8239
- [sections]="getItemPath(item)"
8240
- [characterLimit]="characterLimit()"
8241
- [sectionLimit]="sectionLimit()"
8242
- class="ax-flex-1"
8243
- ></axp-truncated-breadcrumb>
8244
- <ax-button color="ghost" look="blank" class="ax-xs" (onClick)="handleRemoveItemClick($event, item)">
8245
- <ax-icon icon="ax-icon ax-icon-close"></ax-icon>
8246
- </ax-button>
8247
- </div>
8248
- }
8249
- </div>
9136
+ 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: "tagBox", first: true, predicate: ["tagBoxComponent"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
9137
+ <ax-tag-box
9138
+ #tagBoxComponent
9139
+ [tagTemplate]="tagTemplate"
9140
+ [ngModel]="selectedItems()"
9141
+ [textField]="displayField()"
9142
+ [valueField]="valueField()"
9143
+ (onValueChanged)="handleValueChange($event)"
9144
+ [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
9145
+ [addOnEnter]="false"
9146
+ [addOnComma]="false"
9147
+ [readonly]="true"
9148
+ [disabled]="disabled()"
9149
+ (onKeyUp)="handleKeyUp($event)"
9150
+ (onBlur)="handleOnBlur($event)"
9151
+ >
9152
+ @for (validation of validationRules(); track $index) {
9153
+ <ax-validation-rule
9154
+ [rule]="validation.rule"
9155
+ [message]="validation.options?.message"
9156
+ [options]="validation.options"
9157
+ ></ax-validation-rule>
9158
+ }
9159
+ @if (selectedItems().length > 1 || allowClear()) {
9160
+ <ax-clear-button (click)="handleClearClick()"></ax-clear-button>
8250
9161
  }
8251
9162
 
8252
- <div class="ax-flex ax-items-center ax-gap-2">
8253
- <ax-button
8254
- [text]="'@general:actions.add.title' | translate | async"
8255
- color="primary"
8256
- [disabled]="isLoading() || disabled()"
8257
- (onClick)="handleAddClick($event)"
8258
- >
9163
+ <ax-suffix>
9164
+ <ax-button color="ghost" look="blank" [disabled]="isLoading() || disabled()" (onClick)="handleAddClick($event)">
8259
9165
  @if (isLoading()) {
8260
9166
  <ax-loading></ax-loading>
8261
9167
  } @else {
8262
- <ax-icon icon="far fa-plus"></ax-icon>
9168
+ <ax-icon icon="far fa-search"></ax-icon>
8263
9169
  }
8264
9170
  </ax-button>
8265
-
8266
- @if (allowClear() && selectedItems().length > 0) {
8267
- <ax-button color="ghost" look="outline" [disabled]="disabled()" (onClick)="handleClearClick()">
8268
- Clear All
8269
- </ax-button>
8270
- }
9171
+ </ax-suffix>
9172
+ </ax-tag-box>
9173
+ <ng-template #tagTemplate let-item let-index="index">
9174
+ <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">
9175
+ <axp-truncated-breadcrumb
9176
+ [attr.data-color]="item.color"
9177
+ [sections]="getItemPath(item)"
9178
+ [characterLimit]="characterLimit()"
9179
+ [sectionLimit]="sectionLimit()"
9180
+ ></axp-truncated-breadcrumb>
9181
+ <button type="button" (click)="handleRemoveItem($event, index)">
9182
+ <ax-icon class="ax-icon ax-icon-close"></ax-icon>
9183
+ </button>
8271
9184
  </div>
8272
-
9185
+ </ng-template>
9186
+ `, 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$2.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: "component", type: AXPTruncatedBreadcrumbComponent, selector: "axp-truncated-breadcrumb", inputs: ["sections", "characterLimit", "sectionLimit", "separatorIcon", "ellipsisIcon", "eyeIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9187
+ }
9188
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetEditComponent, decorators: [{
9189
+ type: Component,
9190
+ args: [{
9191
+ selector: 'axp-entity-category-widget-edit',
9192
+ template: `
9193
+ <ax-tag-box
9194
+ #tagBoxComponent
9195
+ [tagTemplate]="tagTemplate"
9196
+ [ngModel]="selectedItems()"
9197
+ [textField]="displayField()"
9198
+ [valueField]="valueField()"
9199
+ (onValueChanged)="handleValueChange($event)"
9200
+ [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
9201
+ [addOnEnter]="false"
9202
+ [addOnComma]="false"
9203
+ [readonly]="true"
9204
+ [disabled]="disabled()"
9205
+ (onKeyUp)="handleKeyUp($event)"
9206
+ (onBlur)="handleOnBlur($event)"
9207
+ >
8273
9208
  @for (validation of validationRules(); track $index) {
8274
9209
  <ax-validation-rule
8275
9210
  [rule]="validation.rule"
@@ -8277,76 +9212,49 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
8277
9212
  [options]="validation.options"
8278
9213
  ></ax-validation-rule>
8279
9214
  }
8280
- </div>
8281
- `, 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: i2$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 }); }
8282
- }
8283
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetEditComponent, decorators: [{
8284
- type: Component,
8285
- args: [{
8286
- selector: 'axp-entity-category-widget-edit',
8287
- template: `
8288
- <div class="ax-flex ax-flex-col ax-gap-3">
8289
- @if (selectedItems().length > 0) {
8290
- <div class="ax-flex ax-flex-col ax-gap-2">
8291
- @for (item of selectedItems(); track getItemId(item)) {
8292
- <div class="ax-flex ax-items-center ax-gap-2 ax-p-2 ax-border ax-primary-lightest ax-rounded-xl">
8293
- <axp-truncated-breadcrumb
8294
- [sections]="getItemPath(item)"
8295
- [characterLimit]="characterLimit()"
8296
- [sectionLimit]="sectionLimit()"
8297
- class="ax-flex-1"
8298
- ></axp-truncated-breadcrumb>
8299
- <ax-button color="ghost" look="blank" class="ax-xs" (onClick)="handleRemoveItemClick($event, item)">
8300
- <ax-icon icon="ax-icon ax-icon-close"></ax-icon>
8301
- </ax-button>
8302
- </div>
8303
- }
8304
- </div>
9215
+ @if (selectedItems().length > 1 || allowClear()) {
9216
+ <ax-clear-button (click)="handleClearClick()"></ax-clear-button>
8305
9217
  }
8306
9218
 
8307
- <div class="ax-flex ax-items-center ax-gap-2">
8308
- <ax-button
8309
- [text]="'@general:actions.add.title' | translate | async"
8310
- color="primary"
8311
- [disabled]="isLoading() || disabled()"
8312
- (onClick)="handleAddClick($event)"
8313
- >
9219
+ <ax-suffix>
9220
+ <ax-button color="ghost" look="blank" [disabled]="isLoading() || disabled()" (onClick)="handleAddClick($event)">
8314
9221
  @if (isLoading()) {
8315
9222
  <ax-loading></ax-loading>
8316
9223
  } @else {
8317
- <ax-icon icon="far fa-plus"></ax-icon>
9224
+ <ax-icon icon="far fa-search"></ax-icon>
8318
9225
  }
8319
9226
  </ax-button>
8320
-
8321
- @if (allowClear() && selectedItems().length > 0) {
8322
- <ax-button color="ghost" look="outline" [disabled]="disabled()" (onClick)="handleClearClick()">
8323
- Clear All
8324
- </ax-button>
8325
- }
9227
+ </ax-suffix>
9228
+ </ax-tag-box>
9229
+ <ng-template #tagTemplate let-item let-index="index">
9230
+ <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">
9231
+ <axp-truncated-breadcrumb
9232
+ [attr.data-color]="item.color"
9233
+ [sections]="getItemPath(item)"
9234
+ [characterLimit]="characterLimit()"
9235
+ [sectionLimit]="sectionLimit()"
9236
+ ></axp-truncated-breadcrumb>
9237
+ <button type="button" (click)="handleRemoveItem($event, index)">
9238
+ <ax-icon class="ax-icon ax-icon-close"></ax-icon>
9239
+ </button>
8326
9240
  </div>
8327
-
8328
- @for (validation of validationRules(); track $index) {
8329
- <ax-validation-rule
8330
- [rule]="validation.rule"
8331
- [message]="validation.options?.message"
8332
- [options]="validation.options"
8333
- ></ax-validation-rule>
8334
- }
8335
- </div>
9241
+ </ng-template>
8336
9242
  `,
8337
9243
  changeDetection: ChangeDetectionStrategy.OnPush,
8338
9244
  imports: [
8339
9245
  CommonModule,
9246
+ FormsModule,
8340
9247
  AXButtonModule,
8341
9248
  AXDecoratorModule,
8342
9249
  AXLoadingModule,
8343
9250
  AXValidationModule,
8344
9251
  AXFormModule,
9252
+ AXTagBoxModule,
8345
9253
  AXTranslationModule,
8346
9254
  AXPTruncatedBreadcrumbComponent,
8347
9255
  ],
8348
9256
  }]
8349
- }] });
9257
+ }], propDecorators: { tagBox: [{ type: i0.ViewChild, args: ['tagBoxComponent', { isSignal: true }] }] } });
8350
9258
 
8351
9259
  var entityCategoryWidgetEdit_component = /*#__PURE__*/Object.freeze({
8352
9260
  __proto__: null,
@@ -8448,7 +9356,7 @@ class AXPEntityCategoryWidgetViewComponent extends AXPValueWidgetComponent {
8448
9356
  <span class="ax-text-muted">---</span>
8449
9357
  }
8450
9358
  }
8451
- `, 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$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9359
+ `, 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$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8452
9360
  }
8453
9361
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetViewComponent, decorators: [{
8454
9362
  type: Component,
@@ -8942,6 +9850,8 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
8942
9850
  this.entityListTableService = inject(AXPEntityListTableService);
8943
9851
  this.entityListToolbarService = inject(AXPEntityListToolbarService);
8944
9852
  this.deviceService = inject(AXPDeviceService);
9853
+ this.commandService = inject(AXPCommandService);
9854
+ this.eventService = inject(AXPBroadcastEventService);
8945
9855
  this.isMounted = signal(false, ...(ngDevMode ? [{ debugName: "isMounted" }] : []));
8946
9856
  this.entity = signal(null, ...(ngDevMode ? [{ debugName: "entity" }] : []));
8947
9857
  this.listNode = signal(null, ...(ngDevMode ? [{ debugName: "listNode" }] : []));
@@ -9024,17 +9934,21 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
9024
9934
  return actions;
9025
9935
  }, ...(ngDevMode ? [{ debugName: "secondaryActions" }] : []));
9026
9936
  //#region ---- Query Change Handler ----
9937
+ this.queries = undefined;
9027
9938
  this.#effect = effect(() => {
9028
- const queries = this.getValue()?.toolbar;
9939
+ //TODO: this is a temporary solution to handle the query changes; this should be removed when the query changes are handled in the widget core;
9940
+ if (this.getValue()?.toolbar) {
9941
+ this.queries = this.getValue()?.toolbar;
9942
+ }
9029
9943
  const listInstance = this.listWidget()?.instance;
9030
9944
  // const dataSource = this.listWidget()?.options()['dataSource'] as AXDataSource;
9031
9945
  const dataSource = listInstance?.options()?.['dataSource'];
9032
9946
  const isMounted = this.isMounted();
9033
- if (!this.hasRequiredDependencies(dataSource, queries, listInstance)) {
9947
+ if (!this.hasRequiredDependencies(dataSource, this.queries, listInstance)) {
9034
9948
  return;
9035
9949
  }
9036
9950
  untracked(() => {
9037
- this.handleQueryChanges(queries, dataSource, listInstance, isMounted);
9951
+ this.handleQueryChanges(this.queries, dataSource, listInstance, isMounted);
9038
9952
  });
9039
9953
  }, ...(ngDevMode ? [{ debugName: "#effect" }] : []));
9040
9954
  //#endregion
@@ -9067,23 +9981,43 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
9067
9981
  });
9068
9982
  const command = commandName.split('&')[0];
9069
9983
  // const options = await this.evaluateExpressions(action?.options, data);
9070
- await this.workflow.execute(command, {
9071
- entity: this.entitySource(),
9072
- entityInfo: {
9073
- name: this.entity()?.name,
9074
- module: this.entity()?.module,
9075
- title: this.entity()?.title,
9076
- parentKey: this.entity()?.parentKey,
9077
- source: `${this.entity()?.module}.${this.entity()?.name}`,
9078
- },
9079
- data: action?.scope == AXPEntityCommandScope.Selected
9080
- ? this.selectedItems()
9081
- : action?.options?.['process']?.data || null,
9082
- options: action?.options,
9083
- metadata: action?.metadata,
9084
- });
9984
+ if (this.commandService.exists(command)) {
9985
+ await this.commandService.execute(command, {
9986
+ __context__: {
9987
+ entity: this.entitySource(),
9988
+ entityInfo: {
9989
+ name: this.entity()?.name,
9990
+ module: this.entity()?.module,
9991
+ title: this.entity()?.title,
9992
+ parentKey: this.entity()?.parentKey,
9993
+ source: `${this.entity()?.module}.${this.entity()?.name}`,
9994
+ },
9995
+ data: action?.scope == AXPEntityCommandScope.Selected
9996
+ ? this.selectedItems()
9997
+ : action?.options?.['process']?.data || null,
9998
+ options: action?.options,
9999
+ metadata: action?.metadata,
10000
+ },
10001
+ });
10002
+ }
10003
+ else {
10004
+ await this.workflow.execute(command, {
10005
+ entity: this.entitySource(),
10006
+ entityInfo: {
10007
+ name: this.entity()?.name,
10008
+ module: this.entity()?.module,
10009
+ title: this.entity()?.title,
10010
+ parentKey: this.entity()?.parentKey,
10011
+ source: `${this.entity()?.module}.${this.entity()?.name}`,
10012
+ },
10013
+ data: action?.scope == AXPEntityCommandScope.Selected
10014
+ ? this.selectedItems()
10015
+ : action?.options?.['process']?.data || null,
10016
+ options: action?.options,
10017
+ metadata: action?.metadata,
10018
+ });
10019
+ }
9085
10020
  }
9086
- //#region ---- Query Change Handler ----
9087
10021
  #effect;
9088
10022
  /**
9089
10023
  * Validates that all required dependencies are available
@@ -9216,6 +10150,14 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
9216
10150
  this.listWidget()?.instance.call('refresh');
9217
10151
  }
9218
10152
  });
10153
+ this.eventService
10154
+ .listen(AXPEntityEventsKeys.REFRESH_LAYOUT)
10155
+ .pipe(takeUntil(this.destroyed))
10156
+ .subscribe((e) => {
10157
+ if (e.data.name == `${this.entity()?.module}.${this.entity()?.name}`) {
10158
+ this.listWidget()?.instance.call('refresh');
10159
+ }
10160
+ });
9219
10161
  const listWidget = (await this.layoutService.waitForWidget(`${this.entitySource()}-tab-list_table`, 500));
9220
10162
  if (listWidget?.api && typeof listWidget.api === 'function') {
9221
10163
  const onSelectionChange = listWidget.api()['onSelectionChange'];
@@ -9344,7 +10286,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
9344
10286
  ></ng-container>
9345
10287
  }
9346
10288
  </div>
9347
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$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 }); }
10289
+ `, 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 }); }
9348
10290
  }
9349
10291
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityListWidgetViewComponent, decorators: [{
9350
10292
  type: Component,
@@ -9915,7 +10857,7 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
9915
10857
  <span class="ax-text-muted">---</span>
9916
10858
  }
9917
10859
  }
9918
- `, 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$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10860
+ `, 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$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9919
10861
  }
9920
10862
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLookupWidgetViewComponent, decorators: [{
9921
10863
  type: Component,
@@ -10167,6 +11109,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
10167
11109
  this.disabled = computed(() => this.options()['disabled'], ...(ngDevMode ? [{ debugName: "disabled" }] : []));
10168
11110
  this.columns = computed(() => this.options()['columns'] ?? [], ...(ngDevMode ? [{ debugName: "columns" }] : []));
10169
11111
  this.textField = computed(() => this.options()['textField'] ?? '', ...(ngDevMode ? [{ debugName: "textField" }] : []));
11112
+ this.hasClearButton = computed(() => this.options()['hasClearButton'] ?? false, ...(ngDevMode ? [{ debugName: "hasClearButton" }] : []));
10170
11113
  this.customFilter = computed(() => this.options()['filter'], ...(ngDevMode ? [{ debugName: "customFilter" }] : []));
10171
11114
  this.multiple = computed(() => (this.options()['multiple'] ?? false), ...(ngDevMode ? [{ debugName: "multiple" }] : []));
10172
11115
  this.look = computed(() => this.options()['look'] ?? 'lookup', ...(ngDevMode ? [{ debugName: "look" }] : []));
@@ -10563,6 +11506,9 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
10563
11506
  [multiple]="multiple()"
10564
11507
  (onValueChanged)="selectBoxValueChange($event)"
10565
11508
  >
11509
+ @if (hasClearButton()) {
11510
+ <ax-clear-button></ax-clear-button>
11511
+ }
10566
11512
  <ax-search-box
10567
11513
  [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
10568
11514
  (onValueChanged)="handleSearchInputChange($event)"
@@ -10631,9 +11577,9 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
10631
11577
  </ng-template>
10632
11578
  }
10633
11579
  }
10634
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type:
11580
+ `, 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:
10635
11581
  //
10636
- 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: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i2$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 }); }
11582
+ 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$2.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 }); }
10637
11583
  }
10638
11584
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLookupWidgetEditComponent, decorators: [{
10639
11585
  type: Component,
@@ -10652,6 +11598,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
10652
11598
  [multiple]="multiple()"
10653
11599
  (onValueChanged)="selectBoxValueChange($event)"
10654
11600
  >
11601
+ @if (hasClearButton()) {
11602
+ <ax-clear-button></ax-clear-button>
11603
+ }
10655
11604
  <ax-search-box
10656
11605
  [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
10657
11606
  (onValueChanged)="handleSearchInputChange($event)"
@@ -11006,7 +11955,7 @@ class AXPWidgetSelectorWidgetEditComponent extends AXPValueWidgetComponent {
11006
11955
  <axp-widget-property-viewer [widget]="selectedWidgetNode()!" (onChanged)="handleChangeWidget($event)">
11007
11956
  </axp-widget-property-viewer>
11008
11957
  }
11009
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i2$3.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: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$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 }); }
11958
+ `, 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$3.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$2.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 }); }
11010
11959
  }
11011
11960
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWidgetSelectorWidgetEditComponent, decorators: [{
11012
11961
  type: Component,
@@ -11525,7 +12474,7 @@ class AXPEntityModule {
11525
12474
  },
11526
12475
  });
11527
12476
  }
11528
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityModule, deps: [{ token: i1$2.AXPAppStartUpService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.NgModule }); }
12477
+ 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 }); }
11529
12478
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityModule, imports: [RouterModule, i2$4.AXPWorkflowModule, i3$1.AXPWidgetCoreModule] }); }
11530
12479
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityModule, providers: [
11531
12480
  {
@@ -11550,11 +12499,11 @@ class AXPEntityModule {
11550
12499
  useValue: columnWidthMiddlewareProvider,
11551
12500
  multi: true,
11552
12501
  },
11553
- {
11554
- provide: AXP_ENTITY_MODIFIER,
11555
- useValue: layoutOrderingMiddlewareProvider,
11556
- multi: true,
11557
- },
12502
+ // {
12503
+ // provide: AXP_ENTITY_MODIFIER,
12504
+ // useValue: layoutOrderingMiddlewareProvider,
12505
+ // multi: true,
12506
+ // },
11558
12507
  provideCommandSetups([
11559
12508
  {
11560
12509
  key: 'Entity:OpenDetails',
@@ -11686,11 +12635,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
11686
12635
  useValue: columnWidthMiddlewareProvider,
11687
12636
  multi: true,
11688
12637
  },
11689
- {
11690
- provide: AXP_ENTITY_MODIFIER,
11691
- useValue: layoutOrderingMiddlewareProvider,
11692
- multi: true,
11693
- },
12638
+ // {
12639
+ // provide: AXP_ENTITY_MODIFIER,
12640
+ // useValue: layoutOrderingMiddlewareProvider,
12641
+ // multi: true,
12642
+ // },
11694
12643
  provideCommandSetups([
11695
12644
  {
11696
12645
  key: 'Entity:OpenDetails',
@@ -11717,7 +12666,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
11717
12666
  ]),
11718
12667
  ],
11719
12668
  }]
11720
- }], ctorParameters: () => [{ type: i1$2.AXPAppStartUpService }, { type: i0.Injector }] });
12669
+ }], ctorParameters: () => [{ type: i1$1.AXPAppStartUpService }, { type: i0.Injector }] });
11721
12670
 
11722
12671
  //#endregion
11723
12672
  //#region ---- Get Entity Details Query ----
@@ -11871,7 +12820,7 @@ function entityDetailsCreateActions(parentId) {
11871
12820
  return {
11872
12821
  title: '@general:actions.create.title',
11873
12822
  command: {
11874
- name: 'create-entity',
12823
+ name: 'Entity:Create',
11875
12824
  options: {
11876
12825
  process: {
11877
12826
  redirect: false,
@@ -11948,7 +12897,7 @@ function entityDetailsReferenceCreateActions(type) {
11948
12897
  {
11949
12898
  title: '@general:actions.create.title',
11950
12899
  command: {
11951
- name: 'create-entity',
12900
+ name: 'Entity:Create',
11952
12901
  options: {
11953
12902
  process: {
11954
12903
  redirect: false,