@acorex/platform 20.6.0-next.15 → 20.6.0-next.17

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,6 +1,6 @@
1
1
  import { AXPSessionService, AXPAuthGuard } from '@acorex/platform/auth';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, Injectable, input, viewChild, signal, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, InjectionToken, computed, Injector, runInInjectionContext, viewChildren, linkedSignal, effect, untracked, HostBinding, ViewChild, NgModule } from '@angular/core';
3
+ import { inject, Injectable, input, viewChild, signal, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, InjectionToken, computed, Injector, runInInjectionContext, ChangeDetectorRef, effect, viewChildren, linkedSignal, untracked, HostBinding, ViewChild, NgModule } from '@angular/core';
4
4
  import { Router, RouterModule, ROUTES } from '@angular/router';
5
5
  import * as i3 from '@acorex/components/button';
6
6
  import { AXButtonModule } from '@acorex/components/button';
@@ -11,17 +11,17 @@ import { AXPopoverModule } from '@acorex/components/popover';
11
11
  import * as i6 from '@acorex/core/translation';
12
12
  import { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';
13
13
  import * as i3$1 from '@acorex/platform/layout/widget-core';
14
- import { AXPWidgetsCatalog, AXPWidgetCoreModule, AXPPageStatus, AXPWidgetRegistryService, AXPValueWidgetComponent, AXPWidgetRendererDirective, AXPWidgetGroupEnum, AXPLayoutBaseWidgetComponent, AXPColumnWidgetComponent, AXP_WIDGETS_EDITOR_CATEGORY } from '@acorex/platform/layout/widget-core';
14
+ import { AXPWidgetsCatalog, AXPWidgetCoreModule, AXPPageStatus, AXPWidgetRegistryService, AXPColumnWidgetComponent, AXPValueWidgetComponent, AXPWidgetGroupEnum, AXPWidgetRendererDirective, AXPLayoutBaseWidgetComponent, AXP_WIDGETS_EDITOR_CATEGORY } from '@acorex/platform/layout/widget-core';
15
15
  import { AXPCommandService, AXPQueryService, provideCommandSetups, provideQuerySetups } from '@acorex/platform/runtime';
16
16
  import * as i5 from '@angular/common';
17
17
  import { CommonModule } from '@angular/common';
18
- import { castArray, get, cloneDeep, set, merge, orderBy, isEqual, isNil, isEmpty, sortBy } from 'lodash-es';
18
+ import { castArray, get, cloneDeep, set, merge, orderBy, isNil, isEqual, isEmpty, sortBy } from 'lodash-es';
19
19
  import { AXDataSource } from '@acorex/cdk/common';
20
20
  import { AXFormatService } from '@acorex/core/format';
21
21
  import * as i4$1 from '@acorex/platform/common';
22
22
  import { AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, getEntityInfo, AXPSettingService, AXPRefreshEvent, AXPReloadEvent, AXPCommonSettings, AXPCleanNestedFilters, AXPWorkflowNavigateAction, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER } from '@acorex/platform/common';
23
23
  import * as i1$1 from '@acorex/platform/core';
24
- import { resolveActionLook, AXPExpressionEvaluatorService, AXPDistributedEventListenerService, AXPBroadcastEventService, AXPPlatformScope, AXPDeviceService, getChangedPaths, extractValue, setSmart, AXPSystemActionType } from '@acorex/platform/core';
24
+ import { resolveActionLook, AXPExpressionEvaluatorService, AXPDistributedEventListenerService, AXPBroadcastEventService, AXPPlatformScope, extractValue, setSmart, AXPDeviceService, getChangedPaths, AXPSystemActionType } from '@acorex/platform/core';
25
25
  import * as i2$3 from '@acorex/platform/workflow';
26
26
  import { AXPWorkflowService, ofType, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowModule } from '@acorex/platform/workflow';
27
27
  import { AXPLayoutThemeService } from '@acorex/platform/themes/shared';
@@ -33,23 +33,28 @@ import { AXPopupService } from '@acorex/components/popup';
33
33
  import { AXPlatform } from '@acorex/core/platform';
34
34
  import * as i3$2 from '@acorex/components/decorators';
35
35
  import { AXDecoratorModule } from '@acorex/components/decorators';
36
- import * as i4$2 from '@acorex/components/dropdown';
37
- import { AXDropdownModule } from '@acorex/components/dropdown';
38
- import { AXP_NAME_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DISABLED_PROPERTY, AXP_ALLOW_CLEAR_PROPERTY, AXP_DATA_PROPERTY_GROUP, AXP_ALLOW_MULTIPLE_PROPERTY, AXPFileUploaderWidgetService } from '@acorex/platform/layout/widgets';
39
- import * as i1 from '@angular/forms';
40
- import { FormsModule } from '@angular/forms';
36
+ import { AXBasePageComponent } from '@acorex/components/page';
37
+ import * as i3$3 from '@acorex/components/search-box';
38
+ import { AXSearchBoxModule, AXSearchBoxComponent } from '@acorex/components/search-box';
39
+ import * as i4$2 from '@acorex/components/skeleton';
40
+ import { AXSkeletonModule } from '@acorex/components/skeleton';
41
+ import { AXTreeViewComponent } from '@acorex/components/tree-view';
42
+ import * as i2$1 from '@acorex/components/badge';
43
+ import { AXBadgeModule } from '@acorex/components/badge';
41
44
  import * as i5$1 from '@acorex/components/form';
42
45
  import { AXFormModule } from '@acorex/components/form';
43
46
  import * as i7 from '@acorex/components/select-box';
44
47
  import { AXSelectBoxModule } from '@acorex/components/select-box';
48
+ import * as i6$1 from '@acorex/components/tag-box';
49
+ import { AXTagBoxModule, AXTagBoxComponent } from '@acorex/components/tag-box';
50
+ import { AXValidationModule } from '@acorex/core/validation';
51
+ import * as i1 from '@angular/forms';
52
+ import { FormsModule } from '@angular/forms';
53
+ import { AXP_DISABLED_PROPERTY, AXP_ALLOW_CLEAR_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DATA_PROPERTY_GROUP, AXP_ALLOW_MULTIPLE_PROPERTY, AXP_NAME_PROPERTY, AXPFileUploaderWidgetService } from '@acorex/platform/layout/widgets';
54
+ import * as i4$3 from '@acorex/components/dropdown';
55
+ import { AXDropdownModule } from '@acorex/components/dropdown';
45
56
  import * as i2$2 from '@acorex/components/text-box';
46
57
  import { AXTextBoxModule, AXTextBoxComponent } from '@acorex/components/text-box';
47
- import { AXValidationModule } from '@acorex/core/validation';
48
- import * as i2$1 from '@acorex/components/badge';
49
- import { AXBadgeModule } from '@acorex/components/badge';
50
- import { AXSearchBoxComponent } from '@acorex/components/search-box';
51
- import * as i6$1 from '@acorex/components/tag-box';
52
- import { AXTagBoxComponent, AXTagBoxModule } from '@acorex/components/tag-box';
53
58
  import { AXPDataSelectorService, AXPWidgetPropertyViewerComponent } from '@acorex/platform/layout/components';
54
59
  import { AXPLayoutBuilderService } from '@acorex/platform/layout/builder';
55
60
  import { transform, isEqual as isEqual$1 } from 'lodash';
@@ -1393,7 +1398,7 @@ class AXPEntityCreateViewSectionViewModel {
1393
1398
  const { interfaces, properties } = this.entity;
1394
1399
  const createProps = interfaces?.master?.create?.properties ?? [];
1395
1400
  const createPropNames = new Set(createProps.map(({ name }) => name));
1396
- const filteredProperties = properties.filter(({ groupId, schema, name }) => groupId === this.group.id && !schema.hidden && createPropNames.has(name));
1401
+ const filteredProperties = properties.filter(({ groupId, schema, name }) => groupId === this.group.id && createPropNames.has(name));
1397
1402
  return filteredProperties.map((property) => {
1398
1403
  const createProp = createProps.find(({ name }) => name === property.name);
1399
1404
  return new AXPEntityCreateViewElementViewModel(this.entity, this, property, createProp);
@@ -1413,6 +1418,9 @@ class AXPEntityCreateViewElementViewModel {
1413
1418
  this.editable = computed(() => {
1414
1419
  return !(this.property.schema.readonly ?? false);
1415
1420
  }, ...(ngDevMode ? [{ debugName: "editable" }] : []));
1421
+ this.isHidden = computed(() => {
1422
+ return this.property.schema.hidden ?? false;
1423
+ }, ...(ngDevMode ? [{ debugName: "isHidden" }] : []));
1416
1424
  this.isRequired = computed(() => {
1417
1425
  return this.property.validations?.some((c) => c.rule == 'required') || false;
1418
1426
  }, ...(ngDevMode ? [{ debugName: "isRequired" }] : []));
@@ -1458,7 +1466,7 @@ class AXPEntityMasterCreateViewModel {
1458
1466
  this.sections = computed(() => {
1459
1467
  const { interfaces, properties } = this.entityDef;
1460
1468
  const createProps = interfaces?.master?.create?.properties?.map(({ name }) => name) ?? [];
1461
- const visibleProperties = properties.filter(({ groupId, schema, name }) => groupId && !schema.hidden && createProps.includes(name));
1469
+ const visibleProperties = properties.filter(({ groupId, schema, name }) => groupId && createProps.includes(name));
1462
1470
  const sections = interfaces?.master?.create?.sections?.filter(({ id }) => visibleProperties.some(({ groupId }) => groupId === id)) ?? [];
1463
1471
  console.log({ sections, visibleProperties });
1464
1472
  return sections.map((section) => new AXPEntityCreateViewSectionViewModel(this.entityDef, section));
@@ -3243,6 +3251,8 @@ class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
3243
3251
  const factory = new AXPRelatedEntityConverterFactory();
3244
3252
  const tabDetailTabs = await this.buildTabDetails(factory, tabDetailEntities ?? [], context);
3245
3253
  const tabListTabs = await this.buildTabLists(factory, tabListEntities ?? [], context);
3254
+ // Build actions from single interface
3255
+ const actions = this.buildActions(entityDef, helpers.singleInterface);
3246
3256
  return {
3247
3257
  id: entityDef?.name ?? '',
3248
3258
  title: `${context.rootTitle}`,
@@ -3250,12 +3260,73 @@ class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
3250
3260
  icon: relatedEntity.icon || entityDef.icon,
3251
3261
  settings: this.createPageSettings(),
3252
3262
  load: this.createLoadFunction(entityDef, relatedEntity, evaluateExpressions),
3253
- execute: this.createExecuteFunction(entityDef),
3263
+ execute: this.createExecuteFunction(entityDef, actions, evaluateExpressions, context),
3264
+ actions: await this.buildEvaluatedActions(actions, evaluateExpressions),
3254
3265
  // tabs: [...tabDetailTabs, ...tabListTabs],
3255
3266
  content: [await this.createGridLayoutStructure(helpers.singleInterface, helpers, evaluateExpressions)],
3256
3267
  };
3257
3268
  }
3258
3269
  //#region ---- Utility Methods ----
3270
+ buildActions(entityDef, singleInterface) {
3271
+ const actions = singleInterface?.actions ?? [];
3272
+ return actions.map((action) => new AXPEntityCommandTriggerViewModel(entityDef, action));
3273
+ }
3274
+ async buildEvaluatedActions(actions, evaluateExpressions) {
3275
+ const evaluatedActions = [];
3276
+ for (const action of actions) {
3277
+ // Evaluate disabled condition
3278
+ let disabled = action.disabled;
3279
+ if (disabled && typeof disabled === 'string' && evaluateExpressions) {
3280
+ try {
3281
+ const result = await evaluateExpressions({ disabled: disabled });
3282
+ disabled = result.disabled;
3283
+ }
3284
+ catch {
3285
+ disabled = false;
3286
+ }
3287
+ }
3288
+ // Evaluate hidden condition
3289
+ let hidden = action.hidden;
3290
+ if (hidden && typeof hidden === 'string' && evaluateExpressions) {
3291
+ try {
3292
+ const result = await evaluateExpressions({ hidden: hidden });
3293
+ hidden = result.hidden;
3294
+ }
3295
+ catch {
3296
+ hidden = false;
3297
+ }
3298
+ }
3299
+ // Skip if hidden
3300
+ if (hidden)
3301
+ continue;
3302
+ // Evaluate options
3303
+ let options = action.options;
3304
+ if (options && evaluateExpressions) {
3305
+ try {
3306
+ options = await evaluateExpressions(options);
3307
+ }
3308
+ catch {
3309
+ // Keep original options if evaluation fails
3310
+ }
3311
+ }
3312
+ evaluatedActions.push({
3313
+ name: action.name,
3314
+ title: action.title,
3315
+ icon: action.icon,
3316
+ color: action.color,
3317
+ disabled: disabled || false,
3318
+ zone: 'header',
3319
+ priority: action.priority,
3320
+ scope: action.scope === AXPEntityCommandScope.Individual ? AXPEntityCommandScope.TypeLevel : action.scope,
3321
+ command: {
3322
+ name: action.name,
3323
+ options: options,
3324
+ metadata: action.metadata,
3325
+ },
3326
+ });
3327
+ }
3328
+ return evaluatedActions;
3329
+ }
3259
3330
  createPageSettings() {
3260
3331
  return {
3261
3332
  commands: {
@@ -3284,20 +3355,70 @@ class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
3284
3355
  return { success: true, data: result };
3285
3356
  };
3286
3357
  }
3287
- createExecuteFunction(entityDef) {
3358
+ createExecuteFunction(entityDef, actions, evaluateExpressions, converterContext) {
3288
3359
  return async (e, context) => {
3289
- if (e.name === 'update-entity') {
3290
- const fn = entityDef?.commands?.update?.execute;
3291
- const result = await fn(context);
3292
- return { success: true, data: result };
3360
+ try {
3361
+ if (e.name === 'update-entity') {
3362
+ const fn = entityDef?.commands?.update?.execute;
3363
+ const result = await fn(context);
3364
+ return {
3365
+ success: true,
3366
+ data: result,
3367
+ };
3368
+ }
3369
+ else {
3370
+ // Find action in single interface actions
3371
+ const action = actions.find((a) => a.name === e.name);
3372
+ if (action && converterContext.workflowService) {
3373
+ // Evaluate action options with current context
3374
+ let evaluatedOptions = action.options;
3375
+ if (evaluateExpressions && action.options) {
3376
+ try {
3377
+ evaluatedOptions = await evaluateExpressions(action.options);
3378
+ }
3379
+ catch {
3380
+ // Keep original options if evaluation fails
3381
+ }
3382
+ }
3383
+ const commandName = e.name.split('&')[0];
3384
+ if (converterContext.workflowService.exists(commandName)) {
3385
+ await converterContext.workflowService.execute(commandName, {
3386
+ entity: getEntityInfo(entityDef).source,
3387
+ data: context,
3388
+ entityInfo: {
3389
+ name: entityDef.name,
3390
+ module: entityDef.module,
3391
+ title: entityDef.title,
3392
+ parentKey: entityDef.parentKey,
3393
+ source: `${entityDef.module}.${entityDef.name}`,
3394
+ },
3395
+ options: evaluatedOptions,
3396
+ metadata: action.metadata,
3397
+ });
3398
+ return {
3399
+ success: true,
3400
+ };
3401
+ }
3402
+ if (converterContext.commandService?.exists(commandName)) {
3403
+ // check options for evaluation
3404
+ await converterContext.commandService.execute(commandName, e.options);
3405
+ }
3406
+ }
3407
+ return {
3408
+ success: false,
3409
+ message: {
3410
+ code: 'invalid_command',
3411
+ text: 'Invalid command',
3412
+ },
3413
+ };
3414
+ }
3293
3415
  }
3294
- else {
3416
+ catch (error) {
3295
3417
  return {
3296
3418
  success: false,
3297
3419
  message: {
3298
- code: 'invalid_command',
3299
- text: 'Invalid command'
3300
- }
3420
+ text: error,
3421
+ },
3301
3422
  };
3302
3423
  }
3303
3424
  };
@@ -4164,7 +4285,7 @@ class AXPMainEntityContentBuilder {
4164
4285
  disabled: disabled || false,
4165
4286
  zone: 'header',
4166
4287
  priority: action.priority,
4167
- scope: action.scope,
4288
+ scope: action.scope === AXPEntityCommandScope.Individual ? AXPEntityCommandScope.TypeLevel : action.scope,
4168
4289
  command: {
4169
4290
  name: action.name,
4170
4291
  options: options,
@@ -4357,7 +4478,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
4357
4478
  }]
4358
4479
  }], ctorParameters: () => [{ type: AXPRelatedEntityConverterFactory }, { type: AXPMainEntityContentBuilder }, { type: AXPLayoutAdapterBuilder }, { type: i4$1.AXPFilterOperatorMiddlewareService }] });
4359
4480
 
4360
- const AXPLayoutDetailsViewRouteResolver = async (route, state, entityResolver = inject(AXPEntityDefinitionRegistryService), expressionEvaluator = inject(AXPExpressionEvaluatorService), session = inject(AXPSessionService), formatService = inject(AXFormatService), workflowService = inject(AXPWorkflowService), layoutAdapterFactory = inject(AXPLayoutAdapterFactory)) => {
4481
+ 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)) => {
4361
4482
  const moduleName = route.parent?.paramMap.get('module');
4362
4483
  const entityName = route.paramMap.get('entity');
4363
4484
  const id = route.paramMap.get('id');
@@ -4367,6 +4488,7 @@ const AXPLayoutDetailsViewRouteResolver = async (route, state, entityResolver =
4367
4488
  session,
4368
4489
  formatService,
4369
4490
  workflowService,
4491
+ commandService,
4370
4492
  };
4371
4493
  return await layoutAdapterFactory.createDetailsViewAdapter(entityResolver, moduleName, entityName, id, dependencies);
4372
4494
  };
@@ -4788,6 +4910,1468 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
4788
4910
  type: Injectable
4789
4911
  }] });
4790
4912
 
4913
+ //#endregion
4914
+ class AXPCategoryTreeService {
4915
+ constructor() {
4916
+ //#region ---- Services & Dependencies ----
4917
+ this.entityResolver = inject(AXPEntityResolver);
4918
+ this.translate = inject(AXTranslationService);
4919
+ }
4920
+ //#endregion
4921
+ //#region ---- Public Methods ----
4922
+ /**
4923
+ * Initialize category tree data source
4924
+ */
4925
+ async initializeCategoryTree(config) {
4926
+ const { entityKey } = config;
4927
+ if (!entityKey) {
4928
+ return null;
4929
+ }
4930
+ try {
4931
+ const [module, entity] = entityKey.split('.');
4932
+ if (!module || !entity) {
4933
+ return null;
4934
+ }
4935
+ const categoryEntityDef = await this.entityResolver.get(module, entity);
4936
+ if (!categoryEntityDef?.queries.list?.execute) {
4937
+ return null;
4938
+ }
4939
+ const categoryEntityQueryFunc = categoryEntityDef.queries.list.execute;
4940
+ const basicQueryEvent = {
4941
+ skip: 0,
4942
+ take: 1000,
4943
+ };
4944
+ return {
4945
+ categoryEntityDef,
4946
+ categoryEntityQueryFunc,
4947
+ basicQueryEvent,
4948
+ };
4949
+ }
4950
+ catch (error) {
4951
+ console.error('Error initializing category tree:', error);
4952
+ return null;
4953
+ }
4954
+ }
4955
+ /**
4956
+ * Create root node with children from items
4957
+ */
4958
+ async createRootNode(items, config) {
4959
+ const textField = config.textField ?? 'title';
4960
+ const valueField = config.valueField ?? 'id';
4961
+ const allItemsLabel = await this.translate.translateAsync('@general:terms.interface.selection.all-items');
4962
+ const rootNode = {
4963
+ id: 'all',
4964
+ label: allItemsLabel,
4965
+ icon: 'fa-solid fa-folder',
4966
+ childrenCount: items.length,
4967
+ expanded: true,
4968
+ data: { [valueField]: 'all', [textField]: allItemsLabel },
4969
+ };
4970
+ const childNodes = items.map((item) => this.convertToTreeNode(item, config));
4971
+ rootNode.children = childNodes;
4972
+ return rootNode;
4973
+ }
4974
+ /**
4975
+ * Convert entity item to AXTreeNode format
4976
+ */
4977
+ convertToTreeNode(item, config) {
4978
+ const textField = config.textField ?? 'title';
4979
+ const valueField = config.valueField ?? 'id';
4980
+ return {
4981
+ id: String(item[valueField] ?? ''),
4982
+ label: String(item[textField] ?? ''),
4983
+ icon: 'fa-solid fa-folder',
4984
+ childrenCount: item['childrenCount'] || item['children']?.length || 0,
4985
+ expanded: false,
4986
+ data: item,
4987
+ };
4988
+ }
4989
+ /**
4990
+ * Load root categories
4991
+ */
4992
+ async loadRootCategories(treeData, config) {
4993
+ if (!treeData.categoryEntityQueryFunc) {
4994
+ return null;
4995
+ }
4996
+ try {
4997
+ const res = await treeData.categoryEntityQueryFunc(treeData.basicQueryEvent);
4998
+ return res?.items ?? null;
4999
+ }
5000
+ catch (error) {
5001
+ console.error('Error loading root categories:', error);
5002
+ return null;
5003
+ }
5004
+ }
5005
+ /**
5006
+ * Load children for a given node
5007
+ */
5008
+ async loadChildren(node, treeData, config) {
5009
+ if (!treeData.categoryEntityQueryFunc || !treeData.categoryEntityDef?.parentKey) {
5010
+ return [];
5011
+ }
5012
+ try {
5013
+ const event = {
5014
+ ...treeData.basicQueryEvent,
5015
+ filter: {
5016
+ field: treeData.categoryEntityDef.parentKey,
5017
+ value: node.id,
5018
+ operator: { type: 'equal' },
5019
+ },
5020
+ };
5021
+ const res = await treeData.categoryEntityQueryFunc(event);
5022
+ if (!res?.items) {
5023
+ return [];
5024
+ }
5025
+ return res.items.map((item) => this.convertToTreeNode(item, config));
5026
+ }
5027
+ catch (error) {
5028
+ console.error('Error loading children:', error);
5029
+ return [];
5030
+ }
5031
+ }
5032
+ /**
5033
+ * Search categories
5034
+ */
5035
+ async searchCategories(searchValue, treeData, config) {
5036
+ if (!treeData.categoryEntityDef || !treeData.categoryEntityQueryFunc) {
5037
+ return null;
5038
+ }
5039
+ try {
5040
+ const categoryInlineFilters = treeData.categoryEntityDef.properties.filter((p) => p.options?.filter?.inline?.enabled);
5041
+ const event = {
5042
+ ...treeData.basicQueryEvent,
5043
+ filter: {
5044
+ filters: [
5045
+ {
5046
+ filters: categoryInlineFilters.map((cif) => ({
5047
+ field: cif.name,
5048
+ operator: {
5049
+ type: 'contains',
5050
+ },
5051
+ value: searchValue,
5052
+ })),
5053
+ logic: 'or',
5054
+ },
5055
+ {
5056
+ value: true,
5057
+ field: treeData.categoryEntityDef.parentKey,
5058
+ operator: {
5059
+ type: 'isEmpty',
5060
+ },
5061
+ },
5062
+ ],
5063
+ logic: 'and',
5064
+ },
5065
+ };
5066
+ const res = await treeData.categoryEntityQueryFunc(event);
5067
+ return res?.items ?? null;
5068
+ }
5069
+ catch (error) {
5070
+ console.error('Error searching categories:', error);
5071
+ return null;
5072
+ }
5073
+ }
5074
+ /**
5075
+ * Update children at a specific node in the tree
5076
+ */
5077
+ updateChildrenAtPath(nodes, targetId, childNodes) {
5078
+ return nodes.map((node) => {
5079
+ if (node.id === targetId) {
5080
+ return { ...node, children: childNodes, childrenCount: childNodes.length };
5081
+ }
5082
+ if (node.children?.length) {
5083
+ return { ...node, children: this.updateChildrenAtPath(node.children, targetId, childNodes) };
5084
+ }
5085
+ return node;
5086
+ });
5087
+ }
5088
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPCategoryTreeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5089
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPCategoryTreeService, providedIn: 'root' }); }
5090
+ }
5091
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPCategoryTreeService, decorators: [{
5092
+ type: Injectable,
5093
+ args: [{
5094
+ providedIn: 'root',
5095
+ }]
5096
+ }] });
5097
+
5098
+ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
5099
+ constructor() {
5100
+ super(...arguments);
5101
+ //#region ---- Services & Dependencies ----
5102
+ this.categoryTreeService = inject(AXPCategoryTreeService);
5103
+ //#endregion
5104
+ //#region ---- Properties (Set by popup service) ----
5105
+ this.entityKey = signal('', ...(ngDevMode ? [{ debugName: "entityKey" }] : []));
5106
+ this.textField = signal('title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
5107
+ this.valueField = signal('id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
5108
+ this.allowMultiple = signal(false, ...(ngDevMode ? [{ debugName: "allowMultiple" }] : []));
5109
+ this.selectedValues = signal([], ...(ngDevMode ? [{ debugName: "selectedValues" }] : []));
5110
+ this.searchPlaceholder = signal('@general:terms.interface.category.search.placeholder', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
5111
+ //#endregion
5112
+ //#region ---- View Queries ----
5113
+ this.tree = viewChild('tree', ...(ngDevMode ? [{ debugName: "tree" }] : []));
5114
+ //#endregion
5115
+ //#region ---- Component State ----
5116
+ this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
5117
+ this.selectedNodeIds = signal([], ...(ngDevMode ? [{ debugName: "selectedNodeIds" }] : []));
5118
+ //#endregion
5119
+ //#region ---- Private Properties ----
5120
+ this.treeData = null;
5121
+ this.treeConfig = null;
5122
+ this.searchResults = null;
5123
+ this.nodeDataCache = new Map(); // Cache node data by id for getSelectedItems
5124
+ /** Datasource callback for tree-view component. */
5125
+ this.datasource = async (id) => {
5126
+ if (!this.treeData || !this.treeConfig) {
5127
+ return [];
5128
+ }
5129
+ // If no id provided, return root nodes (or search results if available)
5130
+ if (!id) {
5131
+ // If we have search results, use them
5132
+ if (this.searchResults) {
5133
+ const rootNode = await this.categoryTreeService.createRootNode(this.searchResults, this.treeConfig);
5134
+ return [rootNode];
5135
+ }
5136
+ // Otherwise load root categories
5137
+ const items = await this.categoryTreeService.loadRootCategories(this.treeData, this.treeConfig);
5138
+ if (!items) {
5139
+ return [];
5140
+ }
5141
+ // Cache node data for getSelectedItems
5142
+ items.forEach((item) => {
5143
+ const itemId = item[this.treeConfig.valueField || 'id'];
5144
+ if (itemId) {
5145
+ this.nodeDataCache.set(itemId, item);
5146
+ }
5147
+ });
5148
+ const rootNode = await this.categoryTreeService.createRootNode(items, this.treeConfig);
5149
+ return [rootNode];
5150
+ }
5151
+ // Create a minimal node object with just the id (loadChildren only needs node.id)
5152
+ const targetNode = {
5153
+ id,
5154
+ label: '',
5155
+ data: {},
5156
+ };
5157
+ const childNodes = await this.categoryTreeService.loadChildren(targetNode, this.treeData, this.treeConfig);
5158
+ // Cache child node data for getSelectedItems
5159
+ childNodes.forEach((node) => {
5160
+ if (node.data && node.id) {
5161
+ this.nodeDataCache.set(node.id, node.data);
5162
+ }
5163
+ });
5164
+ return childNodes;
5165
+ };
5166
+ }
5167
+ //#endregion
5168
+ //#region ---- Lifecycle Methods ----
5169
+ ngOnInit() {
5170
+ super.ngOnInit();
5171
+ this.initializeTree();
5172
+ }
5173
+ //#endregion
5174
+ //#region ---- Private Methods ----
5175
+ async initializeTree() {
5176
+ if (!this.entityKey()) {
5177
+ this.loading.set(false);
5178
+ return;
5179
+ }
5180
+ this.loading.set(true);
5181
+ try {
5182
+ this.treeConfig = {
5183
+ entityKey: this.entityKey(),
5184
+ textField: this.textField(),
5185
+ valueField: this.valueField(),
5186
+ };
5187
+ this.treeData = await this.categoryTreeService.initializeCategoryTree(this.treeConfig);
5188
+ if (!this.treeData) {
5189
+ this.loading.set(false);
5190
+ return;
5191
+ }
5192
+ // Get parentKey from entity definition
5193
+ if (this.treeData.categoryEntityDef?.parentKey) {
5194
+ this.treeConfig.parentKey = this.treeData.categoryEntityDef.parentKey;
5195
+ }
5196
+ // Initialize selected nodes and load their data into cache
5197
+ await this.updateSelectedNodes(this.selectedValues());
5198
+ }
5199
+ catch (error) {
5200
+ console.error('Error loading entity definition:', error);
5201
+ }
5202
+ finally {
5203
+ this.loading.set(false);
5204
+ }
5205
+ }
5206
+ //#endregion
5207
+ //#region ---- Public Methods ----
5208
+ async handleSearchChange(e) {
5209
+ if (!this.treeData || !this.treeConfig) {
5210
+ return;
5211
+ }
5212
+ this.loading.set(true);
5213
+ try {
5214
+ const items = await this.categoryTreeService.searchCategories(e.value, this.treeData, this.treeConfig);
5215
+ if (!items) {
5216
+ this.searchResults = null;
5217
+ return;
5218
+ }
5219
+ // Store search results for datasource callback
5220
+ this.searchResults = items;
5221
+ // Cache node data for getSelectedItems
5222
+ items.forEach((item) => {
5223
+ const id = item[this.treeConfig.valueField || 'id'];
5224
+ if (id) {
5225
+ this.nodeDataCache.set(id, item);
5226
+ }
5227
+ });
5228
+ // Trigger tree refresh
5229
+ const treeComponent = this.tree();
5230
+ if (treeComponent) {
5231
+ treeComponent.refresh?.();
5232
+ }
5233
+ }
5234
+ catch (error) {
5235
+ console.error('Error searching categories:', error);
5236
+ }
5237
+ finally {
5238
+ this.loading.set(false);
5239
+ }
5240
+ }
5241
+ async onNodeToggle(event) {
5242
+ // Tree component handles lazy loading via datasource callback
5243
+ }
5244
+ async onNodeSelect(event) {
5245
+ const node = event.node;
5246
+ if (!node || node.id === 'all') {
5247
+ return;
5248
+ }
5249
+ // Cache node data for getSelectedItems
5250
+ if (node.data) {
5251
+ this.nodeDataCache.set(node.id, node.data);
5252
+ }
5253
+ const currentIds = this.selectedNodeIds();
5254
+ if (node.selected) {
5255
+ // Add to selection if not already selected
5256
+ if (!currentIds.includes(node.id)) {
5257
+ this.selectedNodeIds.set([...currentIds, node.id]);
5258
+ }
5259
+ }
5260
+ else {
5261
+ // Remove from selection
5262
+ this.selectedNodeIds.set(currentIds.filter((id) => id !== node.id));
5263
+ }
5264
+ }
5265
+ handleNodeClick(event) {
5266
+ // Extract node from event - could be { node: AXTreeNode } or just AXTreeNode
5267
+ const node = event?.node || event;
5268
+ if (!node || node.id === 'all') {
5269
+ return;
5270
+ }
5271
+ // Cache node data for getSelectedItems
5272
+ if (node.data) {
5273
+ this.nodeDataCache.set(node.id, node.data);
5274
+ }
5275
+ if (this.allowMultiple()) {
5276
+ // In multiple mode with checkboxes, clicking the node should toggle the checkbox
5277
+ // The checkbox state is handled by onNodeSelect, so we just sync the selection here
5278
+ const currentIds = this.selectedNodeIds();
5279
+ const isSelected = currentIds.includes(node.id);
5280
+ // Toggle selection state
5281
+ if (isSelected) {
5282
+ this.selectedNodeIds.set(currentIds.filter((id) => id !== node.id));
5283
+ }
5284
+ else {
5285
+ this.selectedNodeIds.set([...currentIds, node.id]);
5286
+ }
5287
+ }
5288
+ else {
5289
+ // Single selection - auto-confirm on click
5290
+ this.selectedNodeIds.set([node.id]);
5291
+ this.close({ selected: this.getSelectedItems() });
5292
+ }
5293
+ }
5294
+ async onConfirm() {
5295
+ this.close({ selected: this.getSelectedItems() });
5296
+ }
5297
+ async onCancel() {
5298
+ await this.close();
5299
+ }
5300
+ //#endregion
5301
+ async updateSelectedNodes(selectedIds) {
5302
+ if (!selectedIds || selectedIds.length === 0) {
5303
+ this.selectedNodeIds.set([]);
5304
+ return;
5305
+ }
5306
+ const ids = selectedIds.filter((id) => id && id !== 'all');
5307
+ this.selectedNodeIds.set(ids);
5308
+ // Fetch node data for pre-selected items that aren't in the cache
5309
+ // This ensures getSelectedItems() can retrieve them even if their branches aren't expanded
5310
+ await this.loadMissingNodeData(ids);
5311
+ // Note: Selection syncing is now handled by the tree component
5312
+ // The tree component should handle the selected state based on selectedNodeIds
5313
+ // If the tree component requires manual syncing, we may need to trigger a refresh
5314
+ }
5315
+ /**
5316
+ * Loads node data for IDs that are selected but not yet in the cache.
5317
+ * This is critical for pre-selected values in collapsed branches.
5318
+ */
5319
+ async loadMissingNodeData(selectedIds) {
5320
+ if (!this.treeData || !this.treeConfig || selectedIds.length === 0) {
5321
+ return;
5322
+ }
5323
+ // Find IDs that are selected but not in cache
5324
+ const missingIds = selectedIds.filter((id) => !this.nodeDataCache.has(id));
5325
+ if (missingIds.length === 0) {
5326
+ return;
5327
+ }
5328
+ try {
5329
+ const valueField = this.treeConfig.valueField || 'id';
5330
+ const categoryEntityQueryFunc = this.treeData.categoryEntityQueryFunc;
5331
+ if (!categoryEntityQueryFunc) {
5332
+ return;
5333
+ }
5334
+ // Query for missing nodes by their IDs
5335
+ const event = {
5336
+ ...this.treeData.basicQueryEvent,
5337
+ filter: {
5338
+ filters: missingIds.map((id) => ({
5339
+ field: valueField,
5340
+ value: id,
5341
+ operator: { type: 'equal' },
5342
+ })),
5343
+ logic: 'or',
5344
+ },
5345
+ };
5346
+ const res = await categoryEntityQueryFunc(event);
5347
+ if (res?.items) {
5348
+ // Cache the fetched node data
5349
+ res.items.forEach((item) => {
5350
+ const itemId = item[valueField];
5351
+ if (itemId) {
5352
+ this.nodeDataCache.set(itemId, item);
5353
+ }
5354
+ });
5355
+ }
5356
+ }
5357
+ catch (error) {
5358
+ console.error('Error loading missing node data:', error);
5359
+ }
5360
+ }
5361
+ getSelectedItems() {
5362
+ const selectedIds = this.selectedNodeIds();
5363
+ if (selectedIds.length === 0) {
5364
+ return [];
5365
+ }
5366
+ // Get node data from cache
5367
+ return selectedIds.map((id) => this.nodeDataCache.get(id)).filter((item) => item != null);
5368
+ }
5369
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryTreeSelectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
5370
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityCategoryTreeSelectorComponent, isStandalone: true, selector: "axp-entity-category-tree-selector", viewQueries: [{ propertyName: "tree", first: true, predicate: ["tree"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
5371
+ <div class="ax-flex ax-flex-col ax-h-full">
5372
+ @if (loading()) {
5373
+ <div class="ax-p-4 ax-flex ax-flex-col ax-gap-3">
5374
+ <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
5375
+ <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
5376
+ <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
5377
+ </div>
5378
+ } @else if (treeData) {
5379
+ <div class="ax-flex ax-flex-col ax-flex-1 ax-min-h-0">
5380
+ <div class="ax-p-4 ax-border-b">
5381
+ <ax-search-box
5382
+ (onValueChanged)="handleSearchChange($event)"
5383
+ [delayTime]="300"
5384
+ [placeholder]="searchPlaceholder()"
5385
+ ></ax-search-box>
5386
+ </div>
5387
+ <div class="ax-flex-1 ax-overflow-auto ax-p-4">
5388
+ <ax-tree-view
5389
+ [datasource]="datasource"
5390
+ [showCheckbox]="allowMultiple()"
5391
+ [showIcons]="true"
5392
+ (onNodeSelect)="onNodeSelect($event)"
5393
+ (onNodeToggle)="onNodeToggle($event)"
5394
+ (onNodeClick)="handleNodeClick($event)"
5395
+ #tree
5396
+ >
5397
+ </ax-tree-view>
5398
+ </div>
5399
+ </div>
5400
+ } @else {
5401
+ <div class="ax-p-4 ax-text-center ax-text-muted">
5402
+ <span>---</span>
5403
+ </div>
5404
+ }
5405
+ </div>
5406
+ @if (allowMultiple()) {
5407
+ <ax-footer>
5408
+ <ax-suffix>
5409
+ <ax-button
5410
+ look="solid"
5411
+ [text]="'@general:actions.cancel.title' | translate | async"
5412
+ (onClick)="onCancel()"
5413
+ ></ax-button>
5414
+ <ax-button
5415
+ look="solid"
5416
+ color="primary"
5417
+ [text]="'@general:actions.ok.title' | translate | async"
5418
+ (onClick)="onConfirm()"
5419
+ ></ax-button>
5420
+ </ax-suffix>
5421
+ </ax-footer>
5422
+ }
5423
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i3$3.AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i4$2.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "component", type: AXTreeViewComponent, selector: "ax-tree-view", inputs: ["datasource", "selectMode", "showCheckbox", "checkChildrenOnSelect", "intermediateState", "checkOnClick", "dragMode", "dragOperationType", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "nodeHeight", "look", "itemTemplate"], outputs: ["datasourceChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5424
+ }
5425
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryTreeSelectorComponent, decorators: [{
5426
+ type: Component,
5427
+ args: [{
5428
+ selector: 'axp-entity-category-tree-selector',
5429
+ template: `
5430
+ <div class="ax-flex ax-flex-col ax-h-full">
5431
+ @if (loading()) {
5432
+ <div class="ax-p-4 ax-flex ax-flex-col ax-gap-3">
5433
+ <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
5434
+ <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
5435
+ <ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
5436
+ </div>
5437
+ } @else if (treeData) {
5438
+ <div class="ax-flex ax-flex-col ax-flex-1 ax-min-h-0">
5439
+ <div class="ax-p-4 ax-border-b">
5440
+ <ax-search-box
5441
+ (onValueChanged)="handleSearchChange($event)"
5442
+ [delayTime]="300"
5443
+ [placeholder]="searchPlaceholder()"
5444
+ ></ax-search-box>
5445
+ </div>
5446
+ <div class="ax-flex-1 ax-overflow-auto ax-p-4">
5447
+ <ax-tree-view
5448
+ [datasource]="datasource"
5449
+ [showCheckbox]="allowMultiple()"
5450
+ [showIcons]="true"
5451
+ (onNodeSelect)="onNodeSelect($event)"
5452
+ (onNodeToggle)="onNodeToggle($event)"
5453
+ (onNodeClick)="handleNodeClick($event)"
5454
+ #tree
5455
+ >
5456
+ </ax-tree-view>
5457
+ </div>
5458
+ </div>
5459
+ } @else {
5460
+ <div class="ax-p-4 ax-text-center ax-text-muted">
5461
+ <span>---</span>
5462
+ </div>
5463
+ }
5464
+ </div>
5465
+ @if (allowMultiple()) {
5466
+ <ax-footer>
5467
+ <ax-suffix>
5468
+ <ax-button
5469
+ look="solid"
5470
+ [text]="'@general:actions.cancel.title' | translate | async"
5471
+ (onClick)="onCancel()"
5472
+ ></ax-button>
5473
+ <ax-button
5474
+ look="solid"
5475
+ color="primary"
5476
+ [text]="'@general:actions.ok.title' | translate | async"
5477
+ (onClick)="onConfirm()"
5478
+ ></ax-button>
5479
+ </ax-suffix>
5480
+ </ax-footer>
5481
+ }
5482
+ `,
5483
+ changeDetection: ChangeDetectionStrategy.OnPush,
5484
+ imports: [
5485
+ CommonModule,
5486
+ AXButtonModule,
5487
+ AXDecoratorModule,
5488
+ AXSearchBoxModule,
5489
+ AXSkeletonModule,
5490
+ AXTreeViewComponent,
5491
+ AXTranslationModule,
5492
+ ],
5493
+ }]
5494
+ }], propDecorators: { tree: [{ type: i0.ViewChild, args: ['tree', { isSignal: true }] }] } });
5495
+
5496
+ class AXPEntityCategoryWidgetColumnComponent extends AXPColumnWidgetComponent {
5497
+ constructor() {
5498
+ super(...arguments);
5499
+ //#region ---- Dependencies ----
5500
+ this.entityDetailPopoverService = inject(AXPEntityDetailPopoverService);
5501
+ this.formatService = inject(AXFormatService);
5502
+ //#endregion
5503
+ //#region ---- View Children ----
5504
+ this.moreButton = viewChild('moreButton', ...(ngDevMode ? [{ debugName: "moreButton" }] : []));
5505
+ this.morePopover = viewChild('morePopover', ...(ngDevMode ? [{ debugName: "morePopover" }] : []));
5506
+ //#endregion
5507
+ //#region ---- Properties ----
5508
+ this.host = inject(ElementRef);
5509
+ this.valueField = this.options['valueField'] ?? 'id';
5510
+ this.textField = this.options['textField'] ?? 'title';
5511
+ this.entity = this.options['entity'] ?? '';
5512
+ this.columnName = this.options['columnName'] ?? '';
5513
+ this.maxVisible = this.options['maxVisible'] ?? 2;
5514
+ //#endregion
5515
+ //#region ---- Signals ----
5516
+ this.isMorePopoverOpen = signal(false, ...(ngDevMode ? [{ debugName: "isMorePopoverOpen" }] : []));
5517
+ this.selectedItemIndex = signal(-1, ...(ngDevMode ? [{ debugName: "selectedItemIndex" }] : []));
5518
+ //#endregion
5519
+ //#region ---- Computed Properties ----
5520
+ this.displayItems = computed(() => isNil(this.rawValue)
5521
+ ? []
5522
+ : castArray(this.rawValue)
5523
+ .map((item) => this.extractItem(item))
5524
+ .filter((c) => c != null), ...(ngDevMode ? [{ debugName: "displayItems" }] : []));
5525
+ this.allItems = computed(() => this.displayItems(), ...(ngDevMode ? [{ debugName: "allItems" }] : []));
5526
+ this.visibleItems = computed(() => {
5527
+ const items = this.allItems();
5528
+ return items.slice(0, this.maxVisible);
5529
+ }, ...(ngDevMode ? [{ debugName: "visibleItems" }] : []));
5530
+ this.remainingItems = computed(() => {
5531
+ const items = this.allItems();
5532
+ return items.slice(this.maxVisible);
5533
+ }, ...(ngDevMode ? [{ debugName: "remainingItems" }] : []));
5534
+ this.hasMoreItems = computed(() => {
5535
+ return this.allItems().length > this.maxVisible;
5536
+ }, ...(ngDevMode ? [{ debugName: "hasMoreItems" }] : []));
5537
+ this.remainingItemsCount = computed(() => {
5538
+ return this.allItems().length - this.maxVisible;
5539
+ }, ...(ngDevMode ? [{ debugName: "remainingItemsCount" }] : []));
5540
+ }
5541
+ //#endregion
5542
+ //#region ---- Public Methods ----
5543
+ showMoreItems() {
5544
+ this.entityDetailPopoverService.hide();
5545
+ this.openMorePopover();
5546
+ }
5547
+ onMorePopoverOpenChange(event) {
5548
+ this.isMorePopoverOpen.set(event);
5549
+ }
5550
+ async showItemDetail(item, index) {
5551
+ const columnData = this.rowData[this.columnName];
5552
+ const id = Array.isArray(columnData) ? columnData[index] : columnData;
5553
+ this.selectedItemIndex.set(index);
5554
+ this.closeMorePopover();
5555
+ if (this.entity && id) {
5556
+ await this.entityDetailPopoverService.show(this.host, {
5557
+ entity: this.entity,
5558
+ id: id,
5559
+ textField: this.textField,
5560
+ valueField: this.valueField,
5561
+ item,
5562
+ });
5563
+ }
5564
+ }
5565
+ handleItemClick(index) {
5566
+ const items = this.allItems();
5567
+ if (index < items.length) {
5568
+ const item = items[index];
5569
+ this.showItemDetail(item, index);
5570
+ }
5571
+ }
5572
+ //#endregion
5573
+ //#region ---- Private Methods ----
5574
+ openMorePopover() {
5575
+ if (this.morePopover() && this.moreButton()) {
5576
+ this.morePopover().target = this.moreButton().nativeElement;
5577
+ this.morePopover().open();
5578
+ this.isMorePopoverOpen.set(true);
5579
+ }
5580
+ }
5581
+ closeMorePopover() {
5582
+ if (this.morePopover()) {
5583
+ this.morePopover().close();
5584
+ this.isMorePopoverOpen.set(false);
5585
+ }
5586
+ }
5587
+ extractItem(item) {
5588
+ if (isNil(item)) {
5589
+ return null;
5590
+ }
5591
+ if (typeof item === 'object') {
5592
+ return item;
5593
+ }
5594
+ return {
5595
+ [this.valueField]: item,
5596
+ [this.textField]: item,
5597
+ };
5598
+ }
5599
+ getDisplayText(item) {
5600
+ if (!item) {
5601
+ return '';
5602
+ }
5603
+ return item?.[this.textField] ?? String(item);
5604
+ }
5605
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetColumnComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
5606
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityCategoryWidgetColumnComponent, isStandalone: true, selector: "axp-entity-category-widget-column", inputs: { rawValue: "rawValue", rowData: "rowData" }, viewQueries: [{ propertyName: "moreButton", first: true, predicate: ["moreButton"], descendants: true, isSignal: true }, { propertyName: "morePopover", first: true, predicate: ["morePopover"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
5607
+ <div class="ax-flex ax-items-center ax-gap-1 ax-flex-wrap">
5608
+ @for (item of visibleItems(); track $index) {
5609
+ <ax-badge
5610
+ class="ax-p-0.5 ax-cursor-pointer"
5611
+ [text]="getDisplayText(item)"
5612
+ (click)="handleItemClick($index)"
5613
+ ></ax-badge>
5614
+ }
5615
+ @if (hasMoreItems()) {
5616
+ <span class="ax-cursor-pointer ax-px-1" (click)="showMoreItems()" #moreButton>
5617
+ <i class="fas fa-ellipsis-h"></i>
5618
+ </span>
5619
+ <ax-popover #morePopover [openOn]="'manual'" (openChange)="onMorePopoverOpenChange($event)">
5620
+ <div class="ax-p-2 ax-flex ax-flex-col ax-gap-1">
5621
+ @for (item of remainingItems(); track $index) {
5622
+ <ax-badge
5623
+ class="ax-p-0.5 ax-cursor-pointer"
5624
+ [text]="getDisplayText(item)"
5625
+ (click)="handleItemClick(visibleItems().length + $index)"
5626
+ ></ax-badge>
5627
+ }
5628
+ </div>
5629
+ </ax-popover>
5630
+ }
5631
+ </div>
5632
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXButtonModule }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5633
+ }
5634
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetColumnComponent, decorators: [{
5635
+ type: Component,
5636
+ args: [{
5637
+ selector: 'axp-entity-category-widget-column',
5638
+ template: `
5639
+ <div class="ax-flex ax-items-center ax-gap-1 ax-flex-wrap">
5640
+ @for (item of visibleItems(); track $index) {
5641
+ <ax-badge
5642
+ class="ax-p-0.5 ax-cursor-pointer"
5643
+ [text]="getDisplayText(item)"
5644
+ (click)="handleItemClick($index)"
5645
+ ></ax-badge>
5646
+ }
5647
+ @if (hasMoreItems()) {
5648
+ <span class="ax-cursor-pointer ax-px-1" (click)="showMoreItems()" #moreButton>
5649
+ <i class="fas fa-ellipsis-h"></i>
5650
+ </span>
5651
+ <ax-popover #morePopover [openOn]="'manual'" (openChange)="onMorePopoverOpenChange($event)">
5652
+ <div class="ax-p-2 ax-flex ax-flex-col ax-gap-1">
5653
+ @for (item of remainingItems(); track $index) {
5654
+ <ax-badge
5655
+ class="ax-p-0.5 ax-cursor-pointer"
5656
+ [text]="getDisplayText(item)"
5657
+ (click)="handleItemClick(visibleItems().length + $index)"
5658
+ ></ax-badge>
5659
+ }
5660
+ </div>
5661
+ </ax-popover>
5662
+ }
5663
+ </div>
5664
+ `,
5665
+ changeDetection: ChangeDetectionStrategy.OnPush,
5666
+ imports: [CommonModule, AXBadgeModule, AXButtonModule, AXPopoverModule],
5667
+ inputs: ['rawValue', 'rowData'],
5668
+ }]
5669
+ }], propDecorators: { moreButton: [{ type: i0.ViewChild, args: ['moreButton', { isSignal: true }] }], morePopover: [{ type: i0.ViewChild, args: ['morePopover', { isSignal: true }] }] } });
5670
+
5671
+ var entityCategoryWidgetColumn_component = /*#__PURE__*/Object.freeze({
5672
+ __proto__: null,
5673
+ AXPEntityCategoryWidgetColumnComponent: AXPEntityCategoryWidgetColumnComponent
5674
+ });
5675
+
5676
+ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
5677
+ constructor() {
5678
+ super(...arguments);
5679
+ //#region ---- Services & Dependencies ----
5680
+ this.entityResolver = inject(AXPEntityResolver);
5681
+ this.formatService = inject(AXFormatService);
5682
+ this.popupService = inject(AXPopupService);
5683
+ this.translateService = inject(AXTranslationService);
5684
+ this.cdr = inject(ChangeDetectorRef);
5685
+ //#endregion
5686
+ //#region ---- View Queries ----
5687
+ this.selectBox = viewChild('selectBox', ...(ngDevMode ? [{ debugName: "selectBox" }] : []));
5688
+ this.tagBox = viewChild('tagBoxComponent', ...(ngDevMode ? [{ debugName: "tagBox" }] : []));
5689
+ //#endregion
5690
+ //#region ---- Computed Properties ----
5691
+ this.entity = computed(() => this.options()['entity'] ?? '', ...(ngDevMode ? [{ debugName: "entity" }] : []));
5692
+ this.multiple = computed(() => (this.options()['multiple'] ?? false), ...(ngDevMode ? [{ debugName: "multiple" }] : []));
5693
+ this.disabled = computed(() => (this.options()['disabled'] ?? false), ...(ngDevMode ? [{ debugName: "disabled" }] : []));
5694
+ this.textField = computed(() => this.options()['textField'] ?? 'title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
5695
+ this.valueField = computed(() => this.options()['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
5696
+ this.expose = computed(() => this.options()['expose'], ...(ngDevMode ? [{ debugName: "expose" }] : []));
5697
+ this.allowClear = computed(() => (this.options()['allowClear'] ?? false), ...(ngDevMode ? [{ debugName: "allowClear" }] : []));
5698
+ this.look = computed(() => this.options()['look'] ?? 'lookup', ...(ngDevMode ? [{ debugName: "look" }] : []));
5699
+ this.defaultTextField = computed(() => {
5700
+ const textField = this.entityDef()?.formats.lookup ?? this.entityDef()?.properties.find((c) => c.name != 'id')?.name ?? 'title';
5701
+ return textField;
5702
+ }, ...(ngDevMode ? [{ debugName: "defaultTextField" }] : []));
5703
+ this.displayField = computed(() => {
5704
+ if (this.textField()) {
5705
+ return this.textField();
5706
+ }
5707
+ return this.defaultTextField();
5708
+ }, ...(ngDevMode ? [{ debugName: "displayField" }] : []));
5709
+ this.searchPlaceholderText = signal('', ...(ngDevMode ? [{ debugName: "searchPlaceholderText" }] : []));
5710
+ //#endregion
5711
+ //#region ---- Component State ----
5712
+ this.selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
5713
+ this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
5714
+ this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
5715
+ this.searchTerm = signal(null, ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
5716
+ //#endregion
5717
+ //#region ---- Private Properties ----
5718
+ this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : []));
5719
+ this.dataSource = computed(() => {
5720
+ const entity = this.entityDef();
5721
+ if (!entity)
5722
+ return null;
5723
+ return new AXDataSource({
5724
+ byKey: (key) => {
5725
+ const func = entity.queries.byKey.execute;
5726
+ return func();
5727
+ },
5728
+ load: (e) => {
5729
+ const func = entity.queries.list?.execute;
5730
+ return func(e);
5731
+ },
5732
+ pageSize: 10,
5733
+ key: 'id',
5734
+ });
5735
+ }, ...(ngDevMode ? [{ debugName: "dataSource" }] : []));
5736
+ //#endregion
5737
+ //#region ---- Effects ----
5738
+ this.#efEntity = effect(async () => {
5739
+ const entityKey = this.entity();
5740
+ if (!entityKey)
5741
+ return;
5742
+ const [module, entity] = entityKey.split('.');
5743
+ this.entityDef.set(await this.entityResolver.get(module, entity));
5744
+ }, ...(ngDevMode ? [{ debugName: "#efEntity" }] : []));
5745
+ this.#efValue = effect(() => {
5746
+ if (this.getValue()) {
5747
+ this.findByValue();
5748
+ }
5749
+ else {
5750
+ this.clear();
5751
+ }
5752
+ }, ...(ngDevMode ? [{ debugName: "#efValue" }] : []));
5753
+ this.#efSearchPlaceholder = effect(async () => {
5754
+ const entity = this.entityDef();
5755
+ if (!entity) {
5756
+ this.searchPlaceholderText.set('');
5757
+ return;
5758
+ }
5759
+ const displayFieldName = this.displayField();
5760
+ const displayProperty = entity.properties.find((property) => property.name === displayFieldName);
5761
+ if (displayProperty) {
5762
+ const translated = await this.translateService.translateAsync(displayProperty.title || displayProperty.name);
5763
+ this.searchPlaceholderText.set(translated ? `Search in ${translated}...` : '');
5764
+ }
5765
+ else {
5766
+ const fallback = await this.translateService.translateAsync('@general:actions.search.title');
5767
+ this.searchPlaceholderText.set(fallback ? `${fallback}...` : '');
5768
+ }
5769
+ }, ...(ngDevMode ? [{ debugName: "#efSearchPlaceholder" }] : []));
5770
+ }
5771
+ //#endregion
5772
+ //#region ---- Effects ----
5773
+ #efEntity;
5774
+ #efValue;
5775
+ #efSearchPlaceholder;
5776
+ //#endregion
5777
+ //#region ---- Public Methods ----
5778
+ handleOnClick(e) {
5779
+ this.showTreeSelector();
5780
+ }
5781
+ async showTreeSelector() {
5782
+ this.isOpen.set(true);
5783
+ const currentValue = this.getValue();
5784
+ const selectedIds = currentValue
5785
+ ? (this.multiple() ? castArray(currentValue) : [currentValue])
5786
+ .map((v) => String(extractValue(v, this.valueField())))
5787
+ .filter((id) => id && id !== 'all')
5788
+ : [];
5789
+ try {
5790
+ const result = await this.popupService.open(AXPEntityCategoryTreeSelectorComponent, {
5791
+ title: `${this.translateService.translateSync('@general:widgets.lookup.search')} ${this.translateService.translateSync(this.entityDef()?.formats.plural ?? '')}`,
5792
+ size: 'lg',
5793
+ data: {
5794
+ entityKey: signal(this.entity()),
5795
+ textField: signal(this.textField()),
5796
+ valueField: signal(this.valueField()),
5797
+ allowMultiple: signal(this.multiple() ?? false),
5798
+ selectedValues: signal(selectedIds),
5799
+ searchPlaceholder: signal(this.searchPlaceholderText()),
5800
+ },
5801
+ });
5802
+ if (result?.data?.selected && Array.isArray(result.data.selected)) {
5803
+ this.setItems(result.data.selected);
5804
+ }
5805
+ }
5806
+ catch (error) {
5807
+ console.error('Error opening category tree selector:', error);
5808
+ }
5809
+ finally {
5810
+ this.isOpen.set(false);
5811
+ this.selectBox()?.focus();
5812
+ }
5813
+ }
5814
+ selectBoxValueChange(e) {
5815
+ const items = e.component.selectedItems;
5816
+ this.setItems(items);
5817
+ }
5818
+ handleValueChange(e) {
5819
+ if (e.isUserInteraction) {
5820
+ if (isNil(e.value) || (Array.isArray(e.value) && e.value.length === 0)) {
5821
+ this.clear();
5822
+ }
5823
+ else {
5824
+ this.setValue(this.singleOrMultiple(e.value));
5825
+ }
5826
+ }
5827
+ }
5828
+ handleSearchInputChange(e) {
5829
+ if (e.isUserInteraction) {
5830
+ this.searchTerm.set(e.value ?? '');
5831
+ }
5832
+ }
5833
+ handleKeyUp(e) {
5834
+ const keyEvent = e.nativeEvent;
5835
+ if (keyEvent.code == 'ArrowDown') {
5836
+ this.showTreeSelector();
5837
+ }
5838
+ }
5839
+ handleOnBlur(e) {
5840
+ setTimeout(() => {
5841
+ if (!this.isOpen()) {
5842
+ this.clearInput();
5843
+ }
5844
+ }, 100);
5845
+ }
5846
+ handleClearClick() {
5847
+ this.clear();
5848
+ }
5849
+ clear() {
5850
+ this.setValue(null);
5851
+ this.clearInput();
5852
+ this.selectedItems.set([]);
5853
+ }
5854
+ clearInput() {
5855
+ this.tagBox()?.inputValue.set('');
5856
+ this.searchTerm.set('');
5857
+ }
5858
+ //#endregion
5859
+ //#region ---- Private Methods ----
5860
+ async findByValue() {
5861
+ this.isLoading.set(true);
5862
+ const rawValue = this.getValue();
5863
+ const values = castArray(rawValue);
5864
+ const byKey = this.entityDef()?.queries.byKey?.execute;
5865
+ if (byKey && values.length) {
5866
+ if (this.multiple()) {
5867
+ const items = await Promise.all(values.map((value) => byKey(extractValue(value, this.valueField()))));
5868
+ this.setItems(items);
5869
+ }
5870
+ else {
5871
+ const id = extractValue(values[0], this.valueField());
5872
+ const item = await byKey(id);
5873
+ this.setItems(item);
5874
+ }
5875
+ }
5876
+ else {
5877
+ this.setItems([]);
5878
+ }
5879
+ this.isLoading.set(false);
5880
+ }
5881
+ setItems(items) {
5882
+ if (!items || items.length == 0) {
5883
+ this.selectedItems.set([]);
5884
+ this.setValue(null);
5885
+ this.cdr.markForCheck();
5886
+ return;
5887
+ }
5888
+ items = castArray(items);
5889
+ this.clearInput();
5890
+ this.selectedItems.set(items);
5891
+ const keys = items.map((item) => get(item, this.valueField()));
5892
+ const text = items.map((item) => get(item, this.displayField()));
5893
+ // Extract data from valueField and set context by expose path
5894
+ if (this.expose()) {
5895
+ const exposeValue = castArray(this.expose());
5896
+ const itemToExpose = {};
5897
+ exposeValue.forEach((i) => {
5898
+ if (typeof i == 'string') {
5899
+ const values = items.map((item) => set({}, i, get(item, i)));
5900
+ setSmart(itemToExpose, i, this.singleOrMultiple(values));
5901
+ }
5902
+ else {
5903
+ // Extract data from item by source path and set context by target path
5904
+ const values = this.multiple()
5905
+ ? items.map((item) => set({}, i.source, get(item, i.source)))
5906
+ : items.map((item) => get(item, i.source));
5907
+ setSmart(itemToExpose, i.target, this.singleOrMultiple(values));
5908
+ }
5909
+ });
5910
+ this.contextService.patch(itemToExpose);
5911
+ // Fire triggers
5912
+ this.setValue(this.singleOrMultiple(keys));
5913
+ }
5914
+ else {
5915
+ this.setValue(this.singleOrMultiple(keys));
5916
+ }
5917
+ // Trigger change detection to update selectbox/tagbox
5918
+ this.cdr.markForCheck();
5919
+ }
5920
+ singleOrMultiple(values) {
5921
+ return this.multiple() ? values : values[0];
5922
+ }
5923
+ getTagLabel(item) {
5924
+ if (!item) {
5925
+ return '';
5926
+ }
5927
+ return get(item, this.displayField()) ?? '';
5928
+ }
5929
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetEditComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
5930
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityCategoryWidgetEditComponent, isStandalone: true, selector: "axp-entity-category-widget-edit", viewQueries: [{ propertyName: "selectBox", first: true, predicate: ["selectBox"], descendants: true, isSignal: true }, { propertyName: "tagBox", first: true, predicate: ["tagBoxComponent"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
5931
+ @if (dataSource()) {
5932
+ @if (look() == 'select') {
5933
+ <ax-select-box
5934
+ #selectBox
5935
+ [dataSource]="dataSource()!"
5936
+ [ngModel]="selectedItems()"
5937
+ [textField]="displayField()"
5938
+ [valueField]="valueField()"
5939
+ [disabled]="disabled()"
5940
+ [multiple]="multiple()"
5941
+ (onValueChanged)="selectBoxValueChange($event)"
5942
+ >
5943
+ <ax-search-box
5944
+ [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
5945
+ (onValueChanged)="handleSearchInputChange($event)"
5946
+ >
5947
+ <ax-clear-button></ax-clear-button>
5948
+ </ax-search-box>
5949
+ @for (validation of validationRules(); track $index) {
5950
+ <ax-validation-rule
5951
+ [rule]="validation.rule"
5952
+ [message]="validation.options?.message"
5953
+ [options]="validation.options"
5954
+ ></ax-validation-rule>
5955
+ }
5956
+ @if (allowClear()) {
5957
+ <ax-clear-button (click)="handleClearClick()"></ax-clear-button>
5958
+ }
5959
+ <ax-suffix>
5960
+ <ax-button
5961
+ color="ghost"
5962
+ look="blank"
5963
+ [disabled]="isLoading() || disabled()"
5964
+ (onClick)="handleOnClick($event)"
5965
+ >
5966
+ @if (isLoading()) {
5967
+ <ax-loading></ax-loading>
5968
+ } @else {
5969
+ <ax-icon icon="far fa-search"></ax-icon>
5970
+ }
5971
+ </ax-button>
5972
+ </ax-suffix>
5973
+ </ax-select-box>
5974
+ } @else {
5975
+ <ax-tag-box
5976
+ #tagBoxComponent
5977
+ [tagTemplate]="tagTemplate"
5978
+ [ngModel]="selectedItems()"
5979
+ [textField]="displayField()"
5980
+ [valueField]="valueField()"
5981
+ (onValueChanged)="handleValueChange($event)"
5982
+ [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
5983
+ [addOnEnter]="false"
5984
+ [addOnComma]="false"
5985
+ [disabled]="disabled()"
5986
+ (onKeyUp)="handleKeyUp($event)"
5987
+ (onBlur)="handleOnBlur($event)"
5988
+ >
5989
+ @for (validation of validationRules(); track $index) {
5990
+ <ax-validation-rule
5991
+ [rule]="validation.rule"
5992
+ [message]="validation.options?.message"
5993
+ [options]="validation.options"
5994
+ ></ax-validation-rule>
5995
+ }
5996
+ @if (selectedItems().length > 1 || allowClear()) {
5997
+ <ax-clear-button (click)="handleClearClick()"></ax-clear-button>
5998
+ }
5999
+
6000
+ <ax-suffix>
6001
+ <ax-button
6002
+ color="ghost"
6003
+ look="blank"
6004
+ [disabled]="isLoading() || disabled()"
6005
+ (onClick)="handleOnClick($event)"
6006
+ >
6007
+ @if (isLoading()) {
6008
+ <ax-loading></ax-loading>
6009
+ } @else {
6010
+ <ax-icon icon="far fa-search"></ax-icon>
6011
+ }
6012
+ </ax-button>
6013
+ </ax-suffix>
6014
+ </ax-tag-box>
6015
+ <ng-template #tagTemplate let-item let-index="index">
6016
+ <div class="ax-inline-flex ax-items-center ax-gap-1.5 ax-rounded-md ax-px-3 ax-py-1 ax-text-sm ax-surface">
6017
+ <span>{{ getTagLabel(item) }}</span>
6018
+ <button type="button" (click)="tagBoxComponent.removeItem(index)">
6019
+ <ax-icon class="ax-icon ax-icon-close"></ax-icon>
6020
+ </button>
6021
+ </div>
6022
+ </ng-template>
6023
+ }
6024
+ }
6025
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "directive", type: i5$1.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "ngmodule", type: AXTagBoxModule }, { kind: "component", type: i6$1.AXTagBoxComponent, selector: "ax-tag-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "allowNull", "type", "look", "addOnComma", "addOnEnter", "valueField", "textField", "readonlyField", "allowDuplicateValues", "tagTemplate"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onTagClick", "onTagDblClick", "onTagContextMenu"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "component", type: i7.AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "component", type: AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6026
+ }
6027
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetEditComponent, decorators: [{
6028
+ type: Component,
6029
+ args: [{
6030
+ selector: 'axp-entity-category-widget-edit',
6031
+ template: `
6032
+ @if (dataSource()) {
6033
+ @if (look() == 'select') {
6034
+ <ax-select-box
6035
+ #selectBox
6036
+ [dataSource]="dataSource()!"
6037
+ [ngModel]="selectedItems()"
6038
+ [textField]="displayField()"
6039
+ [valueField]="valueField()"
6040
+ [disabled]="disabled()"
6041
+ [multiple]="multiple()"
6042
+ (onValueChanged)="selectBoxValueChange($event)"
6043
+ >
6044
+ <ax-search-box
6045
+ [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
6046
+ (onValueChanged)="handleSearchInputChange($event)"
6047
+ >
6048
+ <ax-clear-button></ax-clear-button>
6049
+ </ax-search-box>
6050
+ @for (validation of validationRules(); track $index) {
6051
+ <ax-validation-rule
6052
+ [rule]="validation.rule"
6053
+ [message]="validation.options?.message"
6054
+ [options]="validation.options"
6055
+ ></ax-validation-rule>
6056
+ }
6057
+ @if (allowClear()) {
6058
+ <ax-clear-button (click)="handleClearClick()"></ax-clear-button>
6059
+ }
6060
+ <ax-suffix>
6061
+ <ax-button
6062
+ color="ghost"
6063
+ look="blank"
6064
+ [disabled]="isLoading() || disabled()"
6065
+ (onClick)="handleOnClick($event)"
6066
+ >
6067
+ @if (isLoading()) {
6068
+ <ax-loading></ax-loading>
6069
+ } @else {
6070
+ <ax-icon icon="far fa-search"></ax-icon>
6071
+ }
6072
+ </ax-button>
6073
+ </ax-suffix>
6074
+ </ax-select-box>
6075
+ } @else {
6076
+ <ax-tag-box
6077
+ #tagBoxComponent
6078
+ [tagTemplate]="tagTemplate"
6079
+ [ngModel]="selectedItems()"
6080
+ [textField]="displayField()"
6081
+ [valueField]="valueField()"
6082
+ (onValueChanged)="handleValueChange($event)"
6083
+ [placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
6084
+ [addOnEnter]="false"
6085
+ [addOnComma]="false"
6086
+ [disabled]="disabled()"
6087
+ (onKeyUp)="handleKeyUp($event)"
6088
+ (onBlur)="handleOnBlur($event)"
6089
+ >
6090
+ @for (validation of validationRules(); track $index) {
6091
+ <ax-validation-rule
6092
+ [rule]="validation.rule"
6093
+ [message]="validation.options?.message"
6094
+ [options]="validation.options"
6095
+ ></ax-validation-rule>
6096
+ }
6097
+ @if (selectedItems().length > 1 || allowClear()) {
6098
+ <ax-clear-button (click)="handleClearClick()"></ax-clear-button>
6099
+ }
6100
+
6101
+ <ax-suffix>
6102
+ <ax-button
6103
+ color="ghost"
6104
+ look="blank"
6105
+ [disabled]="isLoading() || disabled()"
6106
+ (onClick)="handleOnClick($event)"
6107
+ >
6108
+ @if (isLoading()) {
6109
+ <ax-loading></ax-loading>
6110
+ } @else {
6111
+ <ax-icon icon="far fa-search"></ax-icon>
6112
+ }
6113
+ </ax-button>
6114
+ </ax-suffix>
6115
+ </ax-tag-box>
6116
+ <ng-template #tagTemplate let-item let-index="index">
6117
+ <div class="ax-inline-flex ax-items-center ax-gap-1.5 ax-rounded-md ax-px-3 ax-py-1 ax-text-sm ax-surface">
6118
+ <span>{{ getTagLabel(item) }}</span>
6119
+ <button type="button" (click)="tagBoxComponent.removeItem(index)">
6120
+ <ax-icon class="ax-icon ax-icon-close"></ax-icon>
6121
+ </button>
6122
+ </div>
6123
+ </ng-template>
6124
+ }
6125
+ }
6126
+ `,
6127
+ changeDetection: ChangeDetectionStrategy.OnPush,
6128
+ imports: [
6129
+ CommonModule,
6130
+ FormsModule,
6131
+ AXButtonModule,
6132
+ AXDecoratorModule,
6133
+ AXLoadingModule,
6134
+ AXValidationModule,
6135
+ AXFormModule,
6136
+ AXTagBoxModule,
6137
+ AXTranslationModule,
6138
+ AXSelectBoxModule,
6139
+ AXSearchBoxComponent,
6140
+ ],
6141
+ }]
6142
+ }], propDecorators: { selectBox: [{ type: i0.ViewChild, args: ['selectBox', { isSignal: true }] }], tagBox: [{ type: i0.ViewChild, args: ['tagBoxComponent', { isSignal: true }] }] } });
6143
+
6144
+ var entityCategoryWidgetEdit_component = /*#__PURE__*/Object.freeze({
6145
+ __proto__: null,
6146
+ AXPEntityCategoryWidgetEditComponent: AXPEntityCategoryWidgetEditComponent
6147
+ });
6148
+
6149
+ class AXPEntityCategoryWidgetViewComponent extends AXPValueWidgetComponent {
6150
+ constructor() {
6151
+ super(...arguments);
6152
+ //#region ---- Services & Dependencies ----
6153
+ this.formatService = inject(AXFormatService);
6154
+ this.entityResolver = inject(AXPEntityResolver);
6155
+ //#endregion
6156
+ //#region ---- Computed Properties ----
6157
+ this.entity = computed(() => this.options()['entity'] ?? '', ...(ngDevMode ? [{ debugName: "entity" }] : []));
6158
+ this.multiple = computed(() => (this.options()['multiple'] ?? false), ...(ngDevMode ? [{ debugName: "multiple" }] : []));
6159
+ this.valueField = computed(() => this.options()['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
6160
+ this.textField = computed(() => this.options()['textField'] ?? 'title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
6161
+ this.badgeClass = computed(() => this.options()['badgeClass'] ?? 'ax-accent1', ...(ngDevMode ? [{ debugName: "badgeClass" }] : []));
6162
+ this.displayField = computed(() => {
6163
+ return (this.textField() ??
6164
+ this.entityDef()?.formats.lookup ??
6165
+ this.entityDef()?.properties.find((c) => c.name != 'id')?.name ??
6166
+ 'title');
6167
+ }, ...(ngDevMode ? [{ debugName: "displayField" }] : []));
6168
+ //#endregion
6169
+ //#region ---- Component State ----
6170
+ this.loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
6171
+ this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : []));
6172
+ this.displayItems = signal([], ...(ngDevMode ? [{ debugName: "displayItems" }] : []));
6173
+ //#endregion
6174
+ //#region ---- Effects ----
6175
+ this.efEntity = effect(async () => {
6176
+ const entityKey = this.entity();
6177
+ if (!entityKey) {
6178
+ return;
6179
+ }
6180
+ const [module, entity] = entityKey.split('.');
6181
+ if (!module || !entity) {
6182
+ return;
6183
+ }
6184
+ this.entityDef.set(await this.entityResolver.get(module, entity));
6185
+ }, ...(ngDevMode ? [{ debugName: "efEntity" }] : []));
6186
+ this.efDisplay = effect(async () => {
6187
+ const value = this.getValue();
6188
+ if (isNil(value)) {
6189
+ this.displayItems.set([]);
6190
+ }
6191
+ else {
6192
+ const items = castArray(value).map(async (item) => await this.extractItem(item));
6193
+ this.displayItems.set(await Promise.all(items));
6194
+ }
6195
+ }, ...(ngDevMode ? [{ debugName: "efDisplay" }] : []));
6196
+ }
6197
+ //#endregion
6198
+ //#region ---- Private Methods ----
6199
+ async extractItem(item) {
6200
+ if (typeof item == 'object') {
6201
+ return {
6202
+ id: item[this.valueField()],
6203
+ text: this.getDisplayText(item),
6204
+ };
6205
+ }
6206
+ const def = this.entityDef();
6207
+ const byKey = def?.queries.byKey?.execute;
6208
+ if (byKey) {
6209
+ this.loading.set(true);
6210
+ try {
6211
+ const fetchedItem = await byKey(item);
6212
+ return {
6213
+ id: fetchedItem[this.valueField()],
6214
+ text: this.getDisplayText(fetchedItem),
6215
+ };
6216
+ }
6217
+ finally {
6218
+ this.loading.set(false);
6219
+ }
6220
+ }
6221
+ return {
6222
+ id: item,
6223
+ text: String(item),
6224
+ };
6225
+ }
6226
+ getDisplayText(item) {
6227
+ return this.formatService.format(this.displayField(), 'string', item);
6228
+ }
6229
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
6230
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityCategoryWidgetViewComponent, isStandalone: true, selector: "axp-entity-category-widget-view", usesInheritance: true, ngImport: i0, template: `
6231
+ @if (loading()) {
6232
+ <ax-loading></ax-loading>
6233
+ } @else {
6234
+ @if (displayItems().length > 1) {
6235
+ @for (item of displayItems(); track $index) {
6236
+ <ax-badge class="ax-p-0.5 {{ badgeClass() }}" [text]="item.text"></ax-badge>
6237
+ }
6238
+ } @else if (displayItems().length == 1) {
6239
+ <ax-badge class="ax-p-0.5 {{ badgeClass() }}" [text]="displayItems()[0].text"></ax-badge>
6240
+ } @else {
6241
+ <span class="ax-text-muted">---</span>
6242
+ }
6243
+ }
6244
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6245
+ }
6246
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetViewComponent, decorators: [{
6247
+ type: Component,
6248
+ args: [{
6249
+ selector: 'axp-entity-category-widget-view',
6250
+ template: `
6251
+ @if (loading()) {
6252
+ <ax-loading></ax-loading>
6253
+ } @else {
6254
+ @if (displayItems().length > 1) {
6255
+ @for (item of displayItems(); track $index) {
6256
+ <ax-badge class="ax-p-0.5 {{ badgeClass() }}" [text]="item.text"></ax-badge>
6257
+ }
6258
+ } @else if (displayItems().length == 1) {
6259
+ <ax-badge class="ax-p-0.5 {{ badgeClass() }}" [text]="displayItems()[0].text"></ax-badge>
6260
+ } @else {
6261
+ <span class="ax-text-muted">---</span>
6262
+ }
6263
+ }
6264
+ `,
6265
+ changeDetection: ChangeDetectionStrategy.OnPush,
6266
+ imports: [AXLoadingModule, AXBadgeModule],
6267
+ }]
6268
+ }] });
6269
+
6270
+ var entityCategoryWidgetView_component = /*#__PURE__*/Object.freeze({
6271
+ __proto__: null,
6272
+ AXPEntityCategoryWidgetViewComponent: AXPEntityCategoryWidgetViewComponent
6273
+ });
6274
+
6275
+ const AXPEntityCategoryWidget = {
6276
+ name: 'entity-category-editor',
6277
+ title: 'Entity Category',
6278
+ categories: [],
6279
+ groups: [AXPWidgetGroupEnum.EntityWidget],
6280
+ defaultFilterWidgetName: 'lookup-filter',
6281
+ type: 'editor',
6282
+ icon: 'fa-light fa-sitemap',
6283
+ properties: [
6284
+ AXP_DISABLED_PROPERTY,
6285
+ AXP_ALLOW_CLEAR_PROPERTY,
6286
+ AXP_DATA_PATH_PROPERTY,
6287
+ {
6288
+ name: 'entity',
6289
+ title: 'Entity',
6290
+ group: AXP_DATA_PROPERTY_GROUP,
6291
+ schema: {
6292
+ dataType: 'string',
6293
+ interface: {
6294
+ name: 'entity',
6295
+ path: 'options.entity',
6296
+ type: AXPWidgetsCatalog.text,
6297
+ },
6298
+ },
6299
+ visible: true,
6300
+ },
6301
+ AXP_ALLOW_MULTIPLE_PROPERTY,
6302
+ {
6303
+ name: 'textField',
6304
+ title: 'Text Field',
6305
+ group: AXP_DATA_PROPERTY_GROUP,
6306
+ schema: {
6307
+ dataType: 'string',
6308
+ interface: {
6309
+ name: 'textField',
6310
+ path: 'options.textField',
6311
+ type: AXPWidgetsCatalog.text,
6312
+ },
6313
+ },
6314
+ visible: true,
6315
+ },
6316
+ {
6317
+ name: 'valueField',
6318
+ title: 'Value Field',
6319
+ group: AXP_DATA_PROPERTY_GROUP,
6320
+ schema: {
6321
+ dataType: 'string',
6322
+ interface: {
6323
+ name: 'valueField',
6324
+ path: 'options.valueField',
6325
+ type: AXPWidgetsCatalog.text,
6326
+ },
6327
+ },
6328
+ visible: true,
6329
+ },
6330
+ {
6331
+ name: 'parentKey',
6332
+ title: 'Parent Key',
6333
+ group: AXP_DATA_PROPERTY_GROUP,
6334
+ schema: {
6335
+ dataType: 'string',
6336
+ interface: {
6337
+ name: 'parentKey',
6338
+ path: 'options.parentKey',
6339
+ type: AXPWidgetsCatalog.text,
6340
+ },
6341
+ },
6342
+ visible: true,
6343
+ },
6344
+ {
6345
+ name: 'expose',
6346
+ title: 'Expose',
6347
+ group: AXP_DATA_PROPERTY_GROUP,
6348
+ schema: {
6349
+ dataType: 'string',
6350
+ interface: {
6351
+ name: 'expose',
6352
+ path: 'options.expose',
6353
+ type: AXPWidgetsCatalog.select,
6354
+ },
6355
+ },
6356
+ visible: true,
6357
+ },
6358
+ ],
6359
+ components: {
6360
+ view: {
6361
+ component: () => Promise.resolve().then(function () { return entityCategoryWidgetView_component; }).then((c) => c.AXPEntityCategoryWidgetViewComponent),
6362
+ },
6363
+ edit: {
6364
+ component: () => Promise.resolve().then(function () { return entityCategoryWidgetEdit_component; }).then((c) => c.AXPEntityCategoryWidgetEditComponent),
6365
+ },
6366
+ column: {
6367
+ component: () => Promise.resolve().then(function () { return entityCategoryWidgetColumn_component; }).then((c) => c.AXPEntityCategoryWidgetColumnComponent),
6368
+ },
6369
+ designer: {
6370
+ component: () => Promise.resolve().then(function () { return entityCategoryWidgetEdit_component; }).then((c) => c.AXPEntityCategoryWidgetEditComponent),
6371
+ },
6372
+ },
6373
+ };
6374
+
4791
6375
  //#region ---- Column Mapping Helpers ----
4792
6376
  /**
4793
6377
  * Maps an entity property to a list widget column configuration.
@@ -5553,7 +7137,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
5553
7137
  ></ng-container>
5554
7138
  }
5555
7139
  </div>
5556
- `, 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$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 }); }
7140
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i3.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i3.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i4$3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5557
7141
  }
5558
7142
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityListWidgetViewComponent, decorators: [{
5559
7143
  type: Component,
@@ -7815,6 +9399,7 @@ class AXPEntityModule {
7815
9399
  AXPWidgetSelectorWidget,
7816
9400
  AXPEntityListWidget,
7817
9401
  AXPEntityReferenceWidget,
9402
+ AXPEntityCategoryWidget,
7818
9403
  ],
7819
9404
  })] }); }
7820
9405
  }
@@ -7857,6 +9442,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
7857
9442
  AXPWidgetSelectorWidget,
7858
9443
  AXPEntityListWidget,
7859
9444
  AXPEntityReferenceWidget,
9445
+ AXPEntityCategoryWidget,
7860
9446
  ],
7861
9447
  }),
7862
9448
  ],
@@ -8465,5 +10051,5 @@ function detectEntityChanges(oldObj, newObj) {
8465
10051
  * Generated bundle index. Do not edit.
8466
10052
  */
8467
10053
 
8468
- export { AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEntityApplyUpdatesAction, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorService, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityDynamicDialogService, AXPEntityEventDispatcherService, AXPEntityListTableService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityReferenceWidget, AXPEntityReferenceWidgetColumnComponent, AXPEntityReferenceWidgetDesignerComponent, AXPEntityReferenceWidgetEditComponent, AXPEntityReferenceWidgetPrintComponent, AXPEntityReferenceWidgetViewComponent, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPGetEntityDetailsQuery, AXPLookupFilterWidget, AXPLookupFilterWidgetEditComponent, AXPLookupWidget, AXPLookupWidgetColumnComponent, AXPLookupWidgetEditComponent, AXPLookupWidgetViewComponent, AXPMiddlewareAbortError, AXPMiddlewareEntityStorageService, AXPModifyEntitySectionWorkflow, AXPOpenEntityDetailsCommand, AXPQuickEntityModifyPopupAction, AXPQuickModifyEntityWorkflow, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPWidgetSelectorWidget, AXPWidgetSelectorWidgetEditComponent, AXPWidgetSelectorWidgetViewComponent, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER, AXP_ENTITY_MODIFIER, AXP_ENTITY_STORAGE_BACKEND, AXP_ENTITY_STORAGE_MIDDLEWARE, DEFAULT_COLUMN_WIDTHS, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, actionExists, columnWidthMiddlewareFactory, columnWidthMiddlewareProvider, createColumnWidthMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, detectEntityChanges, ensureListActions, entityDetailsCreateActions, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, isAXPMiddlewareAbortError, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider };
10054
+ export { AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorService, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityDynamicDialogService, AXPEntityEventDispatcherService, AXPEntityListTableService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityReferenceWidget, AXPEntityReferenceWidgetColumnComponent, AXPEntityReferenceWidgetDesignerComponent, AXPEntityReferenceWidgetEditComponent, AXPEntityReferenceWidgetPrintComponent, AXPEntityReferenceWidgetViewComponent, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPGetEntityDetailsQuery, AXPLookupFilterWidget, AXPLookupFilterWidgetEditComponent, AXPLookupWidget, AXPLookupWidgetColumnComponent, AXPLookupWidgetEditComponent, AXPLookupWidgetViewComponent, AXPMiddlewareAbortError, AXPMiddlewareEntityStorageService, AXPModifyEntitySectionWorkflow, AXPOpenEntityDetailsCommand, AXPQuickEntityModifyPopupAction, AXPQuickModifyEntityWorkflow, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPWidgetSelectorWidget, AXPWidgetSelectorWidgetEditComponent, AXPWidgetSelectorWidgetViewComponent, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER, AXP_ENTITY_MODIFIER, AXP_ENTITY_STORAGE_BACKEND, AXP_ENTITY_STORAGE_MIDDLEWARE, DEFAULT_COLUMN_WIDTHS, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, actionExists, columnWidthMiddlewareFactory, columnWidthMiddlewareProvider, createColumnWidthMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, detectEntityChanges, ensureListActions, entityDetailsCreateActions, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, isAXPMiddlewareAbortError, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider };
8469
10055
  //# sourceMappingURL=acorex-platform-layout-entity.mjs.map