@acorex/platform 21.0.0-next.75 → 21.0.0-next.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/fesm2022/{acorex-platform-common-common-settings.provider-Ytey9uhY.mjs → acorex-platform-common-common-settings.provider-ChoT4m4k.mjs} +42 -1
  2. package/fesm2022/acorex-platform-common-common-settings.provider-ChoT4m4k.mjs.map +1 -0
  3. package/fesm2022/acorex-platform-common.mjs +1471 -606
  4. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  5. package/fesm2022/acorex-platform-contracts.mjs +1330 -1
  6. package/fesm2022/acorex-platform-contracts.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-core.mjs +208 -5
  8. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  10. package/fesm2022/acorex-platform-layout-entity.mjs +595 -439
  11. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  12. package/fesm2022/acorex-platform-layout-views.mjs +372 -171
  13. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  14. package/fesm2022/acorex-platform-layout-widget-core.mjs +3 -103
  15. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  16. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-CFyfix31.mjs +513 -0
  17. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-CFyfix31.mjs.map +1 -0
  18. package/fesm2022/acorex-platform-layout-widgets.mjs +11 -6
  19. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  20. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs → acorex-platform-themes-default-entity-master-single-view.component-DrUwqKKA.mjs} +2 -3
  21. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-DrUwqKKA.mjs.map +1 -0
  22. package/fesm2022/acorex-platform-themes-default.mjs +643 -52
  23. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  24. package/fesm2022/acorex-platform-workflow.mjs +5 -8
  25. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  26. package/package.json +1 -1
  27. package/types/acorex-platform-common.d.ts +337 -1056
  28. package/types/acorex-platform-contracts.d.ts +1679 -4
  29. package/types/acorex-platform-core.d.ts +92 -181
  30. package/types/acorex-platform-layout-components.d.ts +2 -1
  31. package/types/acorex-platform-layout-entity.d.ts +68 -176
  32. package/types/acorex-platform-layout-views.d.ts +39 -5
  33. package/types/acorex-platform-layout-widget-core.d.ts +2 -3
  34. package/types/acorex-platform-layout-widgets.d.ts +11 -4
  35. package/types/acorex-platform-themes-default.d.ts +120 -57
  36. package/types/acorex-platform-workflow.d.ts +5 -18
  37. package/fesm2022/acorex-platform-common-common-settings.provider-Ytey9uhY.mjs.map +0 -1
  38. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs +0 -116
  39. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs.map +0 -1
  40. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs.map +0 -1
@@ -1,27 +1,29 @@
1
1
  import { AXToastService } from '@acorex/components/toast';
2
2
  import * as i6 from '@acorex/core/translation';
3
- import { AXTranslationService, AXTranslationModule, resolveMultiLanguageString, translateSync } from '@acorex/core/translation';
3
+ import { AXTranslationService, resolveMultiLanguageString, AXTranslationModule, translateSync } from '@acorex/core/translation';
4
4
  import * as i4$3 from '@acorex/platform/common';
5
- import { AXPNotFoundError, AXPEntityCommandScope, axpNavigateAppPath, AXPSettingsService, AXPCommonSettings, normalizeEntityDisplayTemplate, isUnresolvedEntityDisplayTemplate, AXPFilterOperatorMiddlewareService, isCardFieldBadgeDisplay, resolveCardFieldBadgeColor, getEntityInfo, resolveEnabledMasterListLayouts, resolveDefaultMasterListLayout, AXPRefreshEvent, AXPReloadEvent, axpRedirectToNotFound, ENTITY_ROW_POPUP_TITLE_OPTION, AXPCleanNestedFilters, AXPFileTypeProviderService, AXPFileStorageService, resolveEntityRowDisplayTitle, AXPFileActionsService, axpIsEntityRecordNotFound, AXPDefaultMultiLanguageConfigService, withDefaultMultiLanguageOnWidgetNodeTree, AXPEntityQueryType, buildEntitySearchTitleContext, AXPWorkflowNavigateAction, AXP_NOT_FOUND_ROUTE, AXP_PROTECTED_ROUTE_GUARDS, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER, AXPMenuItemsDataSourceDefinition } from '@acorex/platform/common';
5
+ import { AXPNotFoundError, AXPEntityCommandScope, axpNavigateAppPath, AXPSettingsService, AXPCommonSettings, resolveEntityModifyPopupTitle, resolveSearchableText, normalizeEntityDisplayTemplate, evaluateEntityDisplayTemplate, sanitizeResolvedEntityDisplayTitle, isUnresolvedEntityDisplayTemplate, AXPFilterOperatorMiddlewareService, isCardFieldBadgeDisplay, resolveCardFieldBadgeColor, getEntityInfo, resolveEnabledMasterListLayouts, resolveDefaultMasterListLayout, AXPRefreshEvent, AXPReloadEvent, axpRedirectToNotFound, ENTITY_ROW_POPUP_TITLE_OPTION, AXPCleanNestedFilters, AXPFileTypeProviderService, AXPFileStorageService, resolveEntityRowDisplayTitle, AXPFileActionsService, axpIsEntityRecordNotFound, AXPDefaultMultiLanguageConfigService, withDefaultMultiLanguageOnWidgetNodeTree, AXPEntityQueryType, buildEntitySearchTitleContext, AXPWorkflowNavigateAction, AXP_NOT_FOUND_ROUTE, AXP_PROTECTED_ROUTE_GUARDS, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER, AXP_SEARCH_DEFINITION_LAZY_RESOLVER, AXPMenuItemsDataSourceDefinition } from '@acorex/platform/common';
6
6
  import * as i0 from '@angular/core';
7
- import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, input, viewChild, signal, computed, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, NgModule, ChangeDetectorRef, effect, Input, afterNextRender, untracked, ViewEncapsulation, viewChildren, linkedSignal, HostBinding, output, makeEnvironmentProviders } from '@angular/core';
7
+ import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, input, viewChild, signal, computed, effect, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, NgModule, ChangeDetectorRef, Input, afterNextRender, untracked, ViewEncapsulation, viewChildren, linkedSignal, HostBinding, output, makeEnvironmentProviders } from '@angular/core';
8
+ import { cloneDeep, merge, get, castArray, set, orderBy, omit, isNil, isEmpty, isEqual as isEqual$1, isArray, isString } from 'lodash-es';
8
9
  import { Subject, takeUntil } from 'rxjs';
9
10
  import { AXPLayoutBuilderService, LayoutBuilderModule } from '@acorex/platform/layout/builder';
10
11
  import * as i3 from '@acorex/platform/layout/widget-core';
11
12
  import { AXPWidgetsCatalog, AXPWidgetCoreModule, AXPPageStatus, AXPWidgetRegistryService, AXPColumnWidgetComponent, AXPValueWidgetComponent, AXPWidgetGroupEnum, createBooleanProperty, AXPWidgetRendererDirective, AXPBaseWidgetComponent, AXPWidgetStatus, createStringProperty, createNumberProperty, AXP_WIDGETS_ADVANCE_SUB_MEDIA, AXP_WIDGETS_ADVANCE_CATEGORY, createSelectProperty, AXP_WIDGETS_EDITOR_CATEGORY, AXP_WIDGET_DEFINITION_PROVIDER } from '@acorex/platform/layout/widget-core';
12
- import { AXPSystemActionType, AXPDeviceService, AXPExpressionEvaluatorService, AXPBroadcastEventService, applyFilterArray, applySortArray, resolveActionLook, AXPDistributedEventListenerService, AXPPlatformScope, AXHighlightService, extractValue, setSmart, getChangedPaths, objectKeyValueTransforms, AXPHookService, AXPDataGenerator, AXPComponentSlotModule, AXPContextStore, AXPColumnWidthService, AXPModuleManifestRegistry, defaultColumnWidthProvider, AXP_COLUMN_WIDTH_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPModuleManifestsDataSourceDefinition } from '@acorex/platform/core';
13
- import { cloneDeep, merge, get, castArray, set, orderBy, omit, isNil, isEmpty, isEqual as isEqual$1, isArray, isString } from 'lodash-es';
13
+ import { AXPDeviceService, AXPExpressionEvaluatorService, AXPContextEvalFactory, AXPBroadcastEventService, applyFilterArray, applySortArray, resolveActionLook, AXPDistributedEventListenerService, AXPPlatformScope, AXHighlightService, extractValue, setSmart, getChangedPaths, objectKeyValueTransforms, AXPHookService, AXPDataGenerator, AXPComponentSlotModule, AXPContextStore, AXPColumnWidthService, AXPModuleManifestRegistry, AXPSystemActionType, defaultColumnWidthProvider, AXP_COLUMN_WIDTH_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPModuleManifestsDataSourceDefinition } from '@acorex/platform/core';
14
+ import { mergeForeignKeyFieldIntoCreateActions, collectNestedCreateHiddenProperties, AXPEntityDataSourceKeys } from '@acorex/platform/contracts';
15
+ export { AXPEntityDataSourceKeys, collectNestedCreateHiddenProperties, entityDetailsCreateActions, entityDetailsCreateActionsDeferredParent, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, mergeForeignKeyFieldIntoCreateActions } from '@acorex/platform/contracts';
14
16
  import { transform, isEqual } from 'lodash';
15
17
  import { AXPSessionService, AXPPermissionDefinitionsDataSourceDefinition } from '@acorex/platform/auth';
16
18
  import { Router, ActivatedRoute, RouterModule, ROUTES } from '@angular/router';
17
19
  import { defineCommand, AXP_COMMAND_DEFINITION_CATEGORY_ENTITY, AXPCommandService, AXPQueryService, AXPQueryExecutor, AXPCommandExecutor, provideCommandSetups, provideQuerySetups, AXPCommandRegistry, AXPQueryRegistry } from '@acorex/platform/runtime';
20
+ import { AXFormatService } from '@acorex/core/format';
18
21
  import * as i1 from '@acorex/components/button';
19
22
  import { AXButtonModule } from '@acorex/components/button';
20
23
  import * as i4 from '@acorex/components/skeleton';
21
24
  import { AXSkeletonModule } from '@acorex/components/skeleton';
22
25
  import * as i2 from '@acorex/components/popover';
23
26
  import { AXPopoverModule } from '@acorex/components/popover';
24
- import { AXFormatService } from '@acorex/core/format';
25
27
  import * as i5 from '@angular/common';
26
28
  import { CommonModule, AsyncPipe, NgClass } from '@angular/common';
27
29
  import { AXPThemeLayoutBlockComponent, AXPPreloadFiltersComponent, AXP_PAGE_COMPONENT_PROVIDER, AXPStateMessageComponent, AXPColumnItemListComponent, AXPDataSelectorService, AXPPageComponentRegistryService } from '@acorex/platform/layout/components';
@@ -37,6 +39,7 @@ import { AXDialogService } from '@acorex/components/dialog';
37
39
  import { AXLoadingDialogService } from '@acorex/components/loading-dialog';
38
40
  import { AXPopupService } from '@acorex/components/popup';
39
41
  import { AXPlatform } from '@acorex/core/platform';
42
+ import { AXP_DISABLED_PROPERTY, AXP_ALLOW_CLEAR_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DATA_PROPERTY_GROUP, AXP_ALLOW_MULTIPLE_PROPERTY, AXP_NAME_PROPERTY, AXP_READONLY_PROPERTY, AXP_PLACEHOLDER_PROPERTY, AXP_BEHAVIOR_PROPERTY_GROUP, AXPProviderSelectWidgetEditBase, AXP_ROW_EXPR_PREFIX, AXP_DOWNLOADABLE_PROPERTY, AXP_DESCRIPTION_PROPERTY, AXP_REPEATER_ENTITY_BY_KEY_LOOKUP } from '@acorex/platform/layout/widgets';
40
43
  import * as i2$1 from '@acorex/components/badge';
41
44
  import { AXBadgeModule } from '@acorex/components/badge';
42
45
  import { AXCheckBoxModule } from '@acorex/components/check-box';
@@ -57,7 +60,6 @@ import { AXLoadingModule } from '@acorex/components/loading';
57
60
  import * as i6$1 from '@acorex/components/tag-box';
58
61
  import { AXTagBoxModule } from '@acorex/components/tag-box';
59
62
  import { AXValidationModule } from '@acorex/core/validation';
60
- import { AXP_DISABLED_PROPERTY, AXP_ALLOW_CLEAR_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DATA_PROPERTY_GROUP, AXP_ALLOW_MULTIPLE_PROPERTY, AXP_NAME_PROPERTY, AXP_READONLY_PROPERTY, AXP_PLACEHOLDER_PROPERTY, AXP_BEHAVIOR_PROPERTY_GROUP, AXPProviderSelectWidgetEditBase, AXP_ROW_EXPR_PREFIX, AXP_DOWNLOADABLE_PROPERTY, AXP_DESCRIPTION_PROPERTY } from '@acorex/platform/layout/widgets';
61
63
  import * as i2$2 from '@acorex/components/select-box';
62
64
  import { AXSelectBoxModule } from '@acorex/components/select-box';
63
65
  import * as i3$3 from '@acorex/components/dropdown';
@@ -852,276 +854,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
852
854
  }]
853
855
  }] });
854
856
 
855
- // #region Master
856
- function entityMasterCreateAction() {
857
- return {
858
- title: '@general:actions.create.title',
859
- command: {
860
- name: 'Entity:Create',
861
- },
862
- priority: 'primary',
863
- type: AXPSystemActionType.Create,
864
- scope: AXPEntityCommandScope.TypeLevel,
865
- };
866
- }
867
- function entityMasterEditAction() {
868
- return {
869
- title: '@general:actions.edit.title',
870
- command: 'Entity:Update',
871
- priority: 'secondary',
872
- type: AXPSystemActionType.Update,
873
- scope: AXPEntityCommandScope.Individual,
874
- default: true,
875
- };
876
- }
877
- function entityMasterBulkDeleteAction() {
878
- return {
879
- title: '@general:actions.delete-items.title',
880
- command: 'delete-entity',
881
- priority: 'primary',
882
- type: AXPSystemActionType.Delete,
883
- scope: AXPEntityCommandScope.Selected,
884
- order: 100,
885
- };
886
- }
887
- function entityMasterViewAction() {
888
- return {
889
- title: '@general:actions.view.title',
890
- command: 'open-entity',
891
- priority: 'secondary',
892
- type: AXPSystemActionType.View,
893
- scope: AXPEntityCommandScope.Individual,
894
- default: true,
895
- };
896
- }
897
- function entityMasterDeleteAction() {
898
- return {
899
- title: '@general:actions.delete.title',
900
- command: 'delete-entity',
901
- priority: 'secondary',
902
- type: AXPSystemActionType.Delete,
903
- scope: AXPEntityCommandScope.Individual,
904
- order: 100,
905
- shortcuts: ['ctrl+shift+delete'],
906
- };
907
- }
908
- function entityMasterCrudActions(options) {
909
- const opts = {
910
- create: true,
911
- delete: true,
912
- view: true,
913
- edit: false,
914
- ...options,
915
- };
916
- const actions = [];
917
- if (opts.create) {
918
- actions.push(entityMasterCreateAction());
919
- }
920
- if (opts.delete) {
921
- actions.push(entityMasterBulkDeleteAction());
922
- actions.push(entityMasterDeleteAction());
923
- }
924
- if (opts.view) {
925
- actions.push(entityMasterViewAction());
926
- }
927
- if (opts.edit) {
928
- actions.push(entityMasterEditAction());
929
- }
930
- return actions;
931
- }
932
- function entityMasterRecordActions() {
933
- return [entityMasterDeleteAction()];
934
- }
935
- // #endregion
936
- // #region Details
937
- function entityDetailsCreateActions(parentId) {
938
- return {
939
- title: '@general:actions.create.title',
940
- command: {
941
- name: 'Entity:Create',
942
- options: {
943
- process: {
944
- redirect: false,
945
- canCreateNewOne: true,
946
- data: {
947
- [parentId]: '{{context.eval("id")}}',
948
- },
949
- },
950
- },
951
- },
952
- priority: 'primary',
953
- type: AXPSystemActionType.Create,
954
- scope: AXPEntityCommandScope.TypeLevel,
955
- };
956
- }
957
- /**
958
- * Type-level Create with empty `process.data`; the FK is supplied from `relatedEntity.persistence.foreignKeyField`
959
- * when the related list is built (see `mergeForeignKeyFieldIntoCreateActions`).
960
- */
961
- function entityDetailsCreateActionsDeferredParent() {
962
- return {
963
- title: '@general:actions.create.title',
964
- command: {
965
- name: 'Entity:Create',
966
- options: {
967
- process: {
968
- redirect: false,
969
- canCreateNewOne: true,
970
- data: {},
971
- },
972
- },
973
- },
974
- priority: 'primary',
975
- type: AXPSystemActionType.Create,
976
- scope: AXPEntityCommandScope.TypeLevel,
977
- };
978
- }
979
- /**
980
- * Ensures each type-level `Entity:Create` action includes `process.data[foreignKeyField]` bound to the parent row id.
981
- */
982
- function mergeForeignKeyFieldIntoCreateActions(foreignKeyField, actions) {
983
- if (!foreignKeyField || !actions?.length) {
984
- return actions ?? [];
985
- }
986
- return actions.map((a) => {
987
- const cmd = a.command;
988
- if (typeof cmd !== 'object' ||
989
- !cmd ||
990
- cmd.name !== 'Entity:Create' ||
991
- a.scope !== AXPEntityCommandScope.TypeLevel) {
992
- return a;
993
- }
994
- const opts = (cmd.options ?? {});
995
- const proc = (opts['process'] ?? {});
996
- const data = { ...(proc['data'] ?? {}) };
997
- if (data[foreignKeyField] === undefined || data[foreignKeyField] === null || data[foreignKeyField] === '') {
998
- data[foreignKeyField] = '{{ context.eval("id") }}';
999
- }
1000
- return {
1001
- ...a,
1002
- command: {
1003
- ...cmd,
1004
- options: { ...opts, process: { ...proc, data } },
1005
- },
1006
- };
1007
- });
1008
- }
1009
- /** Property names hidden on nested Create from a related list (`excludeProperties` plus `foreignKeyField` when set). */
1010
- function collectNestedCreateHiddenProperties(relatedEntity) {
1011
- const fk = relatedEntity.persistence?.foreignKeyField;
1012
- const merged = [...(relatedEntity.excludeProperties ?? [])];
1013
- if (fk) {
1014
- merged.push(fk);
1015
- }
1016
- const unique = [...new Set(merged)];
1017
- return unique.length ? unique : undefined;
1018
- }
1019
- function entityDetailsSimpleCondition(fk) {
1020
- return {
1021
- name: fk,
1022
- operator: { type: 'equal' },
1023
- value: '{{context.eval("id")}}',
1024
- };
1025
- }
1026
- function entityDetailsReferenceCondition(type) {
1027
- return [
1028
- {
1029
- name: 'reference.id',
1030
- operator: { type: 'equal' },
1031
- value: '{{context.eval("id")}}',
1032
- },
1033
- {
1034
- name: 'reference.type',
1035
- operator: { type: 'equal' },
1036
- value: type,
1037
- },
1038
- ];
1039
- }
1040
- function entityDetailsEditAction() {
1041
- return {
1042
- title: '@general:actions.edit.title',
1043
- // command: 'quick-modify-entity',
1044
- command: 'Entity:Update',
1045
- priority: 'secondary',
1046
- type: AXPSystemActionType.Update,
1047
- default: true,
1048
- scope: AXPEntityCommandScope.Individual,
1049
- };
1050
- }
1051
- function entityDetailsNewEditAction() {
1052
- return {
1053
- title: 'New Edit',
1054
- command: {
1055
- name: 'Entity:Update',
1056
- },
1057
- priority: 'secondary',
1058
- type: AXPSystemActionType.Update,
1059
- default: true,
1060
- scope: AXPEntityCommandScope.Individual,
1061
- };
1062
- }
1063
- function entityOverrideDetailsViewAction() {
1064
- return {
1065
- title: '@general:actions.view.title',
1066
- command: 'open-entity',
1067
- priority: 'secondary',
1068
- hidden: true,
1069
- type: AXPSystemActionType.View,
1070
- scope: AXPEntityCommandScope.Individual,
1071
- };
1072
- }
1073
- function entityDetailsCrudActions(parentId, options) {
1074
- const opts = {
1075
- create: true,
1076
- delete: true,
1077
- view: true,
1078
- edit: true,
1079
- ...options,
1080
- };
1081
- const actions = [];
1082
- if (opts.create) {
1083
- if (parentId) {
1084
- actions.push(entityDetailsCreateActions(parentId));
1085
- }
1086
- else {
1087
- actions.push(entityDetailsCreateActionsDeferredParent());
1088
- }
1089
- }
1090
- if (opts.edit) {
1091
- actions.push(entityDetailsEditAction());
1092
- }
1093
- if (opts.view) {
1094
- actions.push(entityOverrideDetailsViewAction());
1095
- }
1096
- return actions;
1097
- }
1098
- function entityDetailsReferenceCreateActions(type) {
1099
- return [
1100
- {
1101
- title: '@general:actions.create.title',
1102
- command: {
1103
- name: 'Entity:Create',
1104
- options: {
1105
- process: {
1106
- redirect: false,
1107
- canCreateNewOne: true,
1108
- data: {
1109
- reference: {
1110
- id: '{{context.eval("id")}}',
1111
- type: type,
1112
- },
1113
- },
1114
- },
1115
- },
1116
- },
1117
- priority: 'primary',
1118
- type: AXPSystemActionType.Create,
1119
- scope: AXPEntityCommandScope.TypeLevel,
1120
- },
1121
- entityDetailsEditAction(),
1122
- entityOverrideDetailsViewAction(),
1123
- ];
1124
- }
1125
857
  /**
1126
858
  * Computes a diff between two plain objects with array-aware semantics.
1127
859
  * - For arrays of objects with an id field, computes added/removed by id.
@@ -1479,7 +1211,7 @@ class PropertyFilter {
1479
1211
  const viewLayout = mainViewLayoutMap.get(prop.name);
1480
1212
  const mergedProp = {
1481
1213
  ...prop,
1482
- __layout: viewLayout?.layout,
1214
+ __layout: viewLayout?.layout ? cloneDeep(viewLayout.layout) : undefined,
1483
1215
  __order: viewLayout?.layout?.order,
1484
1216
  };
1485
1217
  if (this.readonlyList?.has(prop.name)) {
@@ -1542,7 +1274,7 @@ class PropertyFilter {
1542
1274
  const mergedProp = {
1543
1275
  ...prop,
1544
1276
  __dataPath: dataPath,
1545
- __layout: viewLayout?.layout,
1277
+ __layout: viewLayout?.layout ? cloneDeep(viewLayout.layout) : undefined,
1546
1278
  __order: viewLayout?.layout?.order,
1547
1279
  };
1548
1280
  // Apply generic propertyOverrides extension (e.g. for identifier defaultValue on nested paths)
@@ -2051,6 +1783,9 @@ const GRID_COLUMNS = 12;
2051
1783
  function getColSpanAt(layout, breakpoint) {
2052
1784
  return layout?.positions?.[breakpoint]?.colSpan ?? GRID_COLUMNS;
2053
1785
  }
1786
+ function getColStartAt(layout, breakpoint) {
1787
+ return layout?.positions?.[breakpoint]?.colStart;
1788
+ }
2054
1789
  function setColSpanAt(layout, breakpoint, colSpan) {
2055
1790
  if (!layout)
2056
1791
  return;
@@ -2075,23 +1810,56 @@ function normalizeLayoutFillRowGaps(items, getLayout, getItemId) {
2075
1810
  if (items.length === 0)
2076
1811
  return scaleFactors;
2077
1812
  for (const breakpoint of LAYOUT_BREAKPOINTS) {
2078
- const colSpans = items.map((item) => getColSpanAt(getLayout(item), breakpoint));
2079
1813
  let i = 0;
2080
- while (i < colSpans.length) {
2081
- let rowSum = 0;
1814
+ while (i < items.length) {
2082
1815
  const rowStart = i;
2083
- while (i < colSpans.length && rowSum + colSpans[i] <= GRID_COLUMNS) {
2084
- rowSum += colSpans[i];
1816
+ let rowHasExplicitColStart = false;
1817
+ let sequentialRowSum = 0;
1818
+ let explicitRowEnd = 0;
1819
+ while (i < items.length) {
1820
+ const layout = getLayout(items[i]);
1821
+ const colStart = getColStartAt(layout, breakpoint);
1822
+ const colSpan = getColSpanAt(layout, breakpoint);
1823
+ // colStart: 1 begins a new row (except for the first item in the current row)
1824
+ if (colStart === 1 && i > rowStart) {
1825
+ break;
1826
+ }
1827
+ if (colStart != null) {
1828
+ rowHasExplicitColStart = true;
1829
+ const end = colStart + colSpan;
1830
+ if (end - 1 > GRID_COLUMNS) {
1831
+ i++;
1832
+ break;
1833
+ }
1834
+ explicitRowEnd = Math.max(explicitRowEnd, end);
1835
+ i++;
1836
+ if (explicitRowEnd >= GRID_COLUMNS) {
1837
+ break;
1838
+ }
1839
+ continue;
1840
+ }
1841
+ if (sequentialRowSum + colSpan > GRID_COLUMNS && i > rowStart) {
1842
+ break;
1843
+ }
1844
+ if (sequentialRowSum + colSpan > GRID_COLUMNS && i === rowStart) {
1845
+ sequentialRowSum = colSpan;
1846
+ i++;
1847
+ break;
1848
+ }
1849
+ sequentialRowSum += colSpan;
2085
1850
  i++;
1851
+ if (sequentialRowSum >= GRID_COLUMNS) {
1852
+ break;
1853
+ }
2086
1854
  }
2087
- if (i === rowStart) {
2088
- rowSum = colSpans[i];
2089
- i++;
1855
+ // Rows with explicit colStart (e.g. 4+4+4 at columns 1/5/9) keep intentional gaps
1856
+ if (rowHasExplicitColStart) {
1857
+ continue;
2090
1858
  }
2091
- if (rowSum < GRID_COLUMNS && rowSum > 0 && i > rowStart) {
1859
+ if (sequentialRowSum < GRID_COLUMNS && sequentialRowSum > 0 && i > rowStart) {
2092
1860
  const lastIdx = i - 1;
2093
- const oldColSpan = colSpans[lastIdx];
2094
- const fill = GRID_COLUMNS - rowSum;
1861
+ const oldColSpan = getColSpanAt(getLayout(items[lastIdx]), breakpoint);
1862
+ const fill = GRID_COLUMNS - sequentialRowSum;
2095
1863
  const newColSpan = Math.min(GRID_COLUMNS, oldColSpan + fill);
2096
1864
  const layout = getLayout(items[lastIdx]);
2097
1865
  if (layout) {
@@ -2586,7 +2354,7 @@ class AXPCreateEntityCommand {
2586
2354
  }
2587
2355
  const createFn = entityRef.commands?.create?.execute;
2588
2356
  const updateFn = entityRef.commands?.update?.execute;
2589
- const context = dialogRef.context();
2357
+ const context = merge({}, data, dialogRef.context());
2590
2358
  console.log('context', context);
2591
2359
  const hasPersistedId = hasPersistedRootId(context);
2592
2360
  const persistFn = hasPersistedId ? updateFn : createFn;
@@ -2742,6 +2510,9 @@ class AXPUpdateEntityCommand {
2742
2510
  this.entityService = inject(AXPEntityDefinitionRegistryService);
2743
2511
  this.toastService = inject(AXToastService);
2744
2512
  this.translationService = inject(AXTranslationService);
2513
+ this.formatService = inject(AXFormatService);
2514
+ this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
2515
+ this.contextEvalFactory = inject(AXPContextEvalFactory);
2745
2516
  this.eventService = inject(AXPBroadcastEventService);
2746
2517
  }
2747
2518
  //#endregion
@@ -2749,7 +2520,7 @@ class AXPUpdateEntityCommand {
2749
2520
  async execute(input) {
2750
2521
  const enableOperationToasts = await this.settingsService.get(AXPCommonSettings.EnableOperationToasts);
2751
2522
  const dialogSize = input['dialogSize'];
2752
- const { entity, entityInfo, data, options } = input.__context__;
2523
+ const { entity, data, options } = input.__context__;
2753
2524
  const excludeProperties = options?.excludeProperties;
2754
2525
  const includeProperties = options?.includeProperties;
2755
2526
  const decoration = options?.['decoration'];
@@ -2788,10 +2559,17 @@ class AXPUpdateEntityCommand {
2788
2559
  if (headerTitle) {
2789
2560
  chain = chain.title(headerTitle);
2790
2561
  }
2791
- else if (entityInfo?.title) {
2792
- const editText = await this.translationService.translateAsync('@general:actions.edit.title');
2793
- const translatedTitle = await this.translationService.translateAsync(entityInfo.title);
2794
- chain = chain.title(`${editText} ${translatedTitle}`);
2562
+ else {
2563
+ let recordData = {};
2564
+ const recordId = typeof data === 'string' ? data : (data?.id ?? data?._id);
2565
+ if (recordId) {
2566
+ recordData = await this.entityForm.getRecordById(`${moduleName}.${entityName}`, String(recordId));
2567
+ }
2568
+ else if (typeof data === 'object' && data != null) {
2569
+ recordData = data;
2570
+ }
2571
+ const title = await resolveEntityModifyPopupTitle(entityRef, recordData, this.translationService, this.formatService, this.expressionEvaluator, this.contextEvalFactory, '@general:actions.edit.title');
2572
+ chain = chain.title(title);
2795
2573
  }
2796
2574
  const finalSize = layoutSize || dialogSize;
2797
2575
  if (finalSize) {
@@ -2885,15 +2663,19 @@ var updateEntity_command = /*#__PURE__*/Object.freeze({
2885
2663
 
2886
2664
  class AXPViewEntityDetailsCommand {
2887
2665
  constructor() {
2888
- //#region ---- Services & Dependencies ----
2666
+ //#region ---- Services & Dependencies ----
2889
2667
  this.entityForm = inject(AXPEntityFormBuilderService);
2890
2668
  this.entityService = inject(AXPEntityDefinitionRegistryService);
2891
2669
  this.translationService = inject(AXTranslationService);
2670
+ this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
2671
+ this.contextEvalFactory = inject(AXPContextEvalFactory);
2892
2672
  }
2893
2673
  //#endregion
2894
- //#region ---- Command Execution ----
2674
+ //#region ---- Command Execution ----
2895
2675
  async execute(input) {
2896
- const excludeProperties = input['excludeProperties'];
2676
+ const excludeProperties = input['excludeProperties'] ??
2677
+ input?.options?.excludeProperties ??
2678
+ input?.__context__?.options?.excludeProperties;
2897
2679
  const { entity, entityInfo, data } = input.__context__;
2898
2680
  const [moduleName, entityName] = (entity || '').split('.');
2899
2681
  if (!moduleName || !entityName) {
@@ -2904,10 +2686,9 @@ class AXPViewEntityDetailsCommand {
2904
2686
  },
2905
2687
  };
2906
2688
  }
2907
- await this.entityService.resolve(moduleName, entityName);
2689
+ const entityDef = await this.entityService.resolve(moduleName, entityName);
2908
2690
  let dialogRef;
2909
2691
  try {
2910
- // Validate data type
2911
2692
  if (!data || (typeof data !== 'string' && typeof data !== 'object')) {
2912
2693
  return {
2913
2694
  success: false,
@@ -2916,22 +2697,18 @@ class AXPViewEntityDetailsCommand {
2916
2697
  },
2917
2698
  };
2918
2699
  }
2919
- // Pass data directly to single() - it handles string | object internally
2920
2700
  let chain = this.entityForm.entity(`${moduleName}.${entityName}`).single(data);
2921
2701
  if (excludeProperties && excludeProperties.length > 0) {
2922
2702
  chain = chain.exclude(...excludeProperties);
2923
2703
  }
2924
- if (entityInfo?.title) {
2925
- const detailText = await this.translationService.translateAsync('@general:actions.detail.title');
2926
- // const translatedTitle = await this.translationService.translateAsync(entityInfo.title);
2927
- chain = chain.title(`${detailText}`);
2704
+ const dialogTitle = await this.resolveDialogTitle(entityDef, data);
2705
+ if (dialogTitle) {
2706
+ chain = chain.title(dialogTitle);
2928
2707
  }
2929
2708
  chain = chain.actions((actions) => {
2930
2709
  actions.submit('@general:actions.ok.title');
2931
2710
  });
2932
2711
  dialogRef = await chain.show();
2933
- // For single/view mode, only close action is available
2934
- // No need to show any message when closing a read-only view
2935
2712
  dialogRef.close();
2936
2713
  return {
2937
2714
  success: true,
@@ -2951,11 +2728,62 @@ class AXPViewEntityDetailsCommand {
2951
2728
  };
2952
2729
  }
2953
2730
  finally {
2954
- if (dialogRef) {
2731
+ if (dialogRef && typeof dialogRef === 'object' && dialogRef !== null && 'setLoading' in dialogRef) {
2955
2732
  dialogRef.setLoading(false);
2956
2733
  }
2957
2734
  }
2958
2735
  }
2736
+ //#endregion
2737
+ //#region ---- Title resolution ----
2738
+ async resolveDialogTitle(entityDef, data) {
2739
+ const titleTemplate = entityDef.interfaces?.master?.single?.title ??
2740
+ entityDef.formats?.searchResult?.title ??
2741
+ entityDef.formats?.individual;
2742
+ if (!titleTemplate || typeof titleTemplate !== 'string') {
2743
+ return this.translationService.translateAsync('@general:actions.detail.title');
2744
+ }
2745
+ if (!titleTemplate.includes('{{')) {
2746
+ const translated = await this.translationService.translateAsync(titleTemplate);
2747
+ return resolveMultiLanguageString(translated, this.translationService.getActiveLang()).trim() || translated;
2748
+ }
2749
+ const recordContext = await this.loadRecordContext(`${entityDef.module}.${entityDef.name}`, data);
2750
+ const scope = {
2751
+ context: this.contextEvalFactory.createScope(recordContext),
2752
+ };
2753
+ const evaluated = await this.expressionEvaluator.evaluate(titleTemplate, scope);
2754
+ const locale = this.translationService.getActiveLang();
2755
+ const text = resolveMultiLanguageString(evaluated, locale).trim() || String(evaluated ?? '').trim();
2756
+ if (text) {
2757
+ return text;
2758
+ }
2759
+ return this.translationService.translateAsync('@general:actions.detail.title');
2760
+ }
2761
+ async loadRecordContext(entityFullName, data) {
2762
+ if (typeof data === 'object' && data !== null && !Array.isArray(data)) {
2763
+ const hasNestedFields = get(data, 'subject.title') != null ||
2764
+ get(data, 'recordType.title') != null ||
2765
+ get(data, 'occurredDate') != null;
2766
+ if (hasNestedFields) {
2767
+ return data;
2768
+ }
2769
+ }
2770
+ const recordId = typeof data === 'string' ? data : String(get(data, 'id') ?? '');
2771
+ if (!recordId) {
2772
+ return typeof data === 'object' && data !== null ? data : {};
2773
+ }
2774
+ try {
2775
+ const [moduleName, entityName] = entityFullName.split('.');
2776
+ const entity = await this.entityService.resolve(moduleName, entityName);
2777
+ const byKeyFn = entity?.queries?.byKey?.execute;
2778
+ if (typeof byKeyFn === 'function') {
2779
+ return (await byKeyFn(recordId)) ?? {};
2780
+ }
2781
+ }
2782
+ catch {
2783
+ // Fall back to list row payload below.
2784
+ }
2785
+ return typeof data === 'object' && data !== null ? data : {};
2786
+ }
2959
2787
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPViewEntityDetailsCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2960
2788
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPViewEntityDetailsCommand, providedIn: 'root' }); }
2961
2789
  }
@@ -2971,13 +2799,6 @@ var viewEntityDetails_command = /*#__PURE__*/Object.freeze({
2971
2799
  AXPViewEntityDetailsCommand: AXPViewEntityDetailsCommand
2972
2800
  });
2973
2801
 
2974
- //#region ---- Datasource keys ----
2975
- /** Platform entity layout datasource registry names. */
2976
- const AXPEntityDataSourceKeys = {
2977
- Entities: 'entities',
2978
- };
2979
- //#endregion
2980
-
2981
2802
  const AXPEntityEventsKeys = {
2982
2803
  REFRESH_LAYOUT: 'entity:refresh-layout',
2983
2804
  REFRESH_DATA: 'entity:refresh-data',
@@ -3016,10 +2837,44 @@ function buildAXPRecordWorkflowInfo(params) {
3016
2837
  ...(params.pinnedVersion != null ? { pinnedVersion: params.pinnedVersion } : {}),
3017
2838
  };
3018
2839
  }
2840
+ //#endregion
3019
2841
 
3020
2842
  //#region ---- Contracts barrel ----
3021
2843
  //#endregion
3022
2844
 
2845
+ /** Common keys on denormalized expose stubs (e.g. `{ id, displayName }` from lookup expose). */
2846
+ const LOOKUP_EXPOSE_STUB_DISPLAY_FIELDS = ['displayName', 'title', 'name', 'fullName', 'code'];
2847
+ function resolveLookupItemFieldValue(item, field) {
2848
+ const direct = get(item, field);
2849
+ if (direct != null && direct !== '') {
2850
+ return direct;
2851
+ }
2852
+ if (!field.includes('.')) {
2853
+ return direct;
2854
+ }
2855
+ for (const fallback of LOOKUP_EXPOSE_STUB_DISPLAY_FIELDS) {
2856
+ const candidate = get(item, fallback);
2857
+ if (candidate != null && candidate !== '') {
2858
+ return candidate;
2859
+ }
2860
+ }
2861
+ return direct;
2862
+ }
2863
+ function formatLookupFieldValue(raw, locale, translationService, resolveMultiLanguage) {
2864
+ if (raw == null || raw === '') {
2865
+ return '';
2866
+ }
2867
+ if (typeof raw === 'string' || typeof raw === 'number' || typeof raw === 'boolean') {
2868
+ return String(raw);
2869
+ }
2870
+ if (typeof raw === 'object' && !Array.isArray(raw)) {
2871
+ if (resolveMultiLanguage) {
2872
+ return resolveMultiLanguage(raw);
2873
+ }
2874
+ return resolveSearchableText(raw, locale, translationService);
2875
+ }
2876
+ return String(raw);
2877
+ }
3023
2878
  //#region ---- Template resolution ----
3024
2879
  /**
3025
2880
  * Resolves the display template for a lookup item.
@@ -3061,9 +2916,9 @@ function resolveLookupDisplayField(entity, options) {
3061
2916
  return found ?? 'title';
3062
2917
  }
3063
2918
  /**
3064
- * Formats a lookup row for display using template and/or field resolution.
2919
+ * Formats a lookup row for display using template and/or field resolution (display tier).
3065
2920
  */
3066
- function formatLookupItemDisplay(item, entity, options, formatService, resolveMultiLanguage) {
2921
+ async function formatLookupItemDisplayAsync(item, entity, options, formatService, displayDeps, resolveMultiLanguage) {
3067
2922
  if (item == null) {
3068
2923
  return '';
3069
2924
  }
@@ -3078,6 +2933,45 @@ function formatLookupItemDisplay(item, entity, options, formatService, resolveMu
3078
2933
  }
3079
2934
  const template = resolveLookupDisplayTemplate(entity, options);
3080
2935
  if (template) {
2936
+ if (template.includes('{{') || template.includes('context.eval')) {
2937
+ const evaluated = await evaluateEntityDisplayTemplate(template, item, displayDeps.expressionEvaluator, displayDeps.locale, displayDeps.translationService, displayDeps.contextEvalFactory);
2938
+ const text = sanitizeResolvedEntityDisplayTitle(resolveSearchableText(evaluated, displayDeps.locale, displayDeps.translationService));
2939
+ if (text && !isUnresolvedEntityDisplayTemplate(text)) {
2940
+ return text;
2941
+ }
2942
+ }
2943
+ else {
2944
+ const formatted = formatService.format(template, 'string', item);
2945
+ if (formatted) {
2946
+ const text = String(formatted);
2947
+ if (!isUnresolvedEntityDisplayTemplate(text)) {
2948
+ return text;
2949
+ }
2950
+ }
2951
+ }
2952
+ }
2953
+ const field = resolveLookupDisplayField(entity, options);
2954
+ const raw = typeof item === 'object' && item != null ? resolveLookupItemFieldValue(item, field) : undefined;
2955
+ return formatLookupFieldValue(raw, displayDeps.locale, displayDeps.translationService, resolveMultiLanguage);
2956
+ }
2957
+ /**
2958
+ * @deprecated Prefer {@link formatLookupItemDisplayAsync} for expression templates with `context.eval`.
2959
+ */
2960
+ function formatLookupItemDisplay(item, entity, options, formatService, resolveMultiLanguage) {
2961
+ if (item == null) {
2962
+ return '';
2963
+ }
2964
+ if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
2965
+ return String(item);
2966
+ }
2967
+ if (typeof item !== 'object') {
2968
+ return '';
2969
+ }
2970
+ if (options.isMultiLanguage?.(item) && resolveMultiLanguage) {
2971
+ return resolveMultiLanguage(item);
2972
+ }
2973
+ const template = resolveLookupDisplayTemplate(entity, options);
2974
+ if (template && !template.includes('context.eval') && !template.includes('{{')) {
3081
2975
  const formatted = formatService.format(template, 'string', item);
3082
2976
  if (formatted) {
3083
2977
  const text = String(formatted);
@@ -3087,8 +2981,8 @@ function formatLookupItemDisplay(item, entity, options, formatService, resolveMu
3087
2981
  }
3088
2982
  }
3089
2983
  const field = resolveLookupDisplayField(entity, options);
3090
- const raw = get(item, field);
3091
- if (raw == null) {
2984
+ const raw = typeof item === 'object' && item != null ? resolveLookupItemFieldValue(item, field) : undefined;
2985
+ if (raw == null || raw === '') {
3092
2986
  return '';
3093
2987
  }
3094
2988
  if (typeof raw === 'string' || typeof raw === 'number' || typeof raw === 'boolean') {
@@ -3111,6 +3005,8 @@ class AXPEntityDetailPopoverComponent {
3111
3005
  this.queryService = inject(AXPQueryService);
3112
3006
  this.formatService = inject(AXFormatService);
3113
3007
  this.translation = inject(AXTranslationService);
3008
+ this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
3009
+ this.contextEvalFactory = inject(AXPContextEvalFactory);
3114
3010
  //#endregion
3115
3011
  //#region ---- Inputs ----
3116
3012
  this.entity = input.required(...(ngDevMode ? [{ debugName: "entity" }] : /* istanbul ignore next */ []));
@@ -3128,31 +3024,10 @@ class AXPEntityDetailPopoverComponent {
3128
3024
  this.entityDetails = signal(null, ...(ngDevMode ? [{ debugName: "entityDetails" }] : /* istanbul ignore next */ []));
3129
3025
  this.isLoadingDetails = signal(false, ...(ngDevMode ? [{ debugName: "isLoadingDetails" }] : /* istanbul ignore next */ []));
3130
3026
  this.isDetailPopoverOpen = signal(false, ...(ngDevMode ? [{ debugName: "isDetailPopoverOpen" }] : /* istanbul ignore next */ []));
3027
+ this.headerTitleVersion = 0;
3131
3028
  /** Placeholder rows for the loading skeleton (matches typical property count). */
3132
3029
  this.loadingSkeletonRows = [1, 2, 3, 4, 5];
3133
- this.headerTitle = computed(() => {
3134
- const details = this.entityDetails();
3135
- const entityDefinition = details?.entityDefinition;
3136
- const data = details?.entityData;
3137
- if (data && entityDefinition) {
3138
- const fromDetails = this.resolveLookupDisplayLabel(data, entityDefinition);
3139
- if (fromDetails) {
3140
- return fromDetails;
3141
- }
3142
- }
3143
- const preset = this.displayTitle()?.trim();
3144
- if (preset && !isUnresolvedEntityDisplayTemplate(preset)) {
3145
- return preset;
3146
- }
3147
- const fallbackItem = this.item();
3148
- if (fallbackItem) {
3149
- const fromItem = this.resolveLookupDisplayLabel(fallbackItem, entityDefinition);
3150
- if (fromItem) {
3151
- return fromItem;
3152
- }
3153
- }
3154
- return preset ?? '';
3155
- }, ...(ngDevMode ? [{ debugName: "headerTitle" }] : /* istanbul ignore next */ []));
3030
+ this.headerTitle = signal('', ...(ngDevMode ? [{ debugName: "headerTitle" }] : /* istanbul ignore next */ []));
3156
3031
  /**
3157
3032
  * Stable list of property widgets for the template. Must be a signal (computed), not a method:
3158
3033
  * calling a method from the template rebuilds nodes every CD cycle and can make the widget renderer loop.
@@ -3165,6 +3040,18 @@ class AXPEntityDetailPopoverComponent {
3165
3040
  return [];
3166
3041
  return this.buildEntityPropertiesWithWidgets(data, entityDefinition, this.textField(), this.valueField());
3167
3042
  }, ...(ngDevMode ? [{ debugName: "entityPropertiesWithWidgets" }] : /* istanbul ignore next */ []));
3043
+ effect(() => {
3044
+ void this.translation.getActiveLang();
3045
+ const details = this.entityDetails();
3046
+ const preset = this.displayTitle();
3047
+ const fallbackItem = this.item();
3048
+ const version = ++this.headerTitleVersion;
3049
+ void this.resolveHeaderTitle(details?.entityDefinition, details?.entityData, preset, fallbackItem).then((title) => {
3050
+ if (version === this.headerTitleVersion) {
3051
+ this.headerTitle.set(title);
3052
+ }
3053
+ });
3054
+ });
3168
3055
  }
3169
3056
  //#endregion
3170
3057
  //#region ---- Public Methods ----
@@ -3237,10 +3124,34 @@ class AXPEntityDetailPopoverComponent {
3237
3124
  }
3238
3125
  //#endregion
3239
3126
  //#region ---- Helper Methods ----
3240
- resolveLookupDisplayLabel(item, entityDefinition) {
3241
- const label = formatLookupItemDisplay(item, entityDefinition, { textField: this.textField() }, this.formatService, (value) => this.translation.resolve(value));
3242
- const resolved = typeof label === 'string' ? label : this.translation.resolve(label);
3243
- return resolved && !isUnresolvedEntityDisplayTemplate(resolved) ? resolved : '';
3127
+ async resolveHeaderTitle(entityDefinition, data, preset, fallbackItem) {
3128
+ if (data && entityDefinition) {
3129
+ const fromDetails = await this.resolveLookupDisplayLabelAsync(data, entityDefinition);
3130
+ if (fromDetails) {
3131
+ return fromDetails;
3132
+ }
3133
+ }
3134
+ const presetTrimmed = preset?.trim();
3135
+ if (presetTrimmed && !isUnresolvedEntityDisplayTemplate(presetTrimmed)) {
3136
+ return presetTrimmed;
3137
+ }
3138
+ if (fallbackItem) {
3139
+ const fromItem = await this.resolveLookupDisplayLabelAsync(fallbackItem, entityDefinition);
3140
+ if (fromItem) {
3141
+ return fromItem;
3142
+ }
3143
+ }
3144
+ return presetTrimmed ?? '';
3145
+ }
3146
+ async resolveLookupDisplayLabelAsync(item, entityDefinition) {
3147
+ const locale = this.translation.getActiveLang() ?? 'en-US';
3148
+ const label = await formatLookupItemDisplayAsync(item, entityDefinition ?? null, { textField: this.textField() }, this.formatService, {
3149
+ expressionEvaluator: this.expressionEvaluator,
3150
+ contextEvalFactory: this.contextEvalFactory,
3151
+ translationService: this.translation,
3152
+ locale,
3153
+ }, (value) => this.translation.resolve(value));
3154
+ return label && !isUnresolvedEntityDisplayTemplate(label) ? label : '';
3244
3155
  }
3245
3156
  /**
3246
3157
  * Returns true if a value is meaningful for display (non-empty/non-null).
@@ -3405,14 +3316,24 @@ class AXPEntityDetailPopoverComponent {
3405
3316
  resolveDataPath(prop, data) {
3406
3317
  const iface = prop.schema?.interface;
3407
3318
  const expose = iface?.options?.['expose'];
3319
+ const textField = iface?.options?.['textField']?.trim();
3408
3320
  if (expose?.length) {
3409
- // Try expanded path first (e.g. personTitle for personTitle.title)
3410
3321
  const textTarget = expose.find((e) => e.source !== 'id');
3411
3322
  if (textTarget) {
3412
3323
  const expandedPath = textTarget.target.split('.')[0];
3413
3324
  const expandedValue = get(data, expandedPath);
3414
3325
  if (expandedValue != null && typeof expandedValue === 'object') {
3415
- return expandedPath;
3326
+ if (textField) {
3327
+ if (this.hasMeaningfulValue(get(expandedValue, textField))) {
3328
+ return expandedPath;
3329
+ }
3330
+ }
3331
+ else {
3332
+ const leaf = textTarget.target.split('.').pop();
3333
+ if (leaf && this.hasMeaningfulValue(get(expandedValue, leaf))) {
3334
+ return expandedPath;
3335
+ }
3336
+ }
3416
3337
  }
3417
3338
  }
3418
3339
  }
@@ -3424,7 +3345,7 @@ class AXPEntityDetailPopoverComponent {
3424
3345
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityDetailPopoverComponent, decorators: [{
3425
3346
  type: Component,
3426
3347
  args: [{ selector: 'axp-entity-detail-popover', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, AXButtonModule, AXPopoverModule, AXPWidgetCoreModule, AXTranslationModule, AXSkeletonModule], template: "<ax-popover [openOn]=\"'manual'\" #detailPopover (openChange)=\"onDetailPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface dark:ax-dark-surface ax-p-4 ax-w-[min(600px,calc(100vw-2rem))]\">\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 {{ headerTitle() }}\n </h3>\n @if (breadcrumb()) {\n <div class=\"ax-text-xs ax-text-neutral-500 ax-mt-1\">{{ breadcrumb() }}</div>\n }\n </div>\n @if (isLoadingDetails()) {\n <div class=\"ax-space-y-2 ax-mb-4\">\n @for (row of loadingSkeletonRows; track row) {\n <div class=\"ax-grid ax-grid-cols-[minmax(7rem,35%)_1fr] ax-gap-x-4 ax-items-start\">\n <ax-skeleton [animated]=\"true\" class=\"ax-h-4 ax-w-2/3 ax-rounded\"></ax-skeleton>\n @if (row === 2) {\n <ax-skeleton [animated]=\"true\" class=\"ax-h-16 ax-w-full ax-rounded\"></ax-skeleton>\n } @else {\n <ax-skeleton [animated]=\"true\" class=\"ax-h-4 ax-w-full ax-rounded\"></ax-skeleton>\n }\n </div>\n }\n </div>\n <div class=\"ax-flex ax-justify-end\">\n <ax-skeleton [animated]=\"true\" class=\"ax-h-9 ax-w-28 ax-rounded\"></ax-skeleton>\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 entityPropertiesWithWidgets(); track item.name) {\n <div class=\"ax-grid ax-grid-cols-[minmax(7rem,35%)_1fr] ax-gap-x-4 ax-gap-y-1 ax-items-start\">\n <span class=\"ax-text-sm ax-font-medium ax-shrink-0\">{{ item.title | translate | async\n }}:</span>\n <div class=\"ax-min-w-0 ax-text-sm\">\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]=\"'@general:actions.open-details.title' | translate | async\"\n (click)=\"navigateToDetails()\">\n </ax-button>\n </div>\n }\n </div>\n</ax-popover>" }]
3427
- }], propDecorators: { entity: [{ type: i0.Input, args: [{ isSignal: true, alias: "entity", required: true }] }], entityId: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityId", required: true }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], displayTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayTitle", required: false }] }], item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: false }] }], breadcrumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "breadcrumb", required: false }] }], detailPopover: [{ type: i0.ViewChild, args: ['detailPopover', { isSignal: true }] }] } });
3348
+ }], ctorParameters: () => [], propDecorators: { entity: [{ type: i0.Input, args: [{ isSignal: true, alias: "entity", required: true }] }], entityId: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityId", required: true }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], displayTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayTitle", required: false }] }], item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: false }] }], breadcrumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "breadcrumb", required: false }] }], detailPopover: [{ type: i0.ViewChild, args: ['detailPopover', { isSignal: true }] }] } });
3428
3349
 
3429
3350
  class AXPEntityDetailPopoverService {
3430
3351
  constructor() {
@@ -3976,7 +3897,6 @@ class AXPEntityPreloadFiltersContainerComponent extends AXPPageLayoutBaseCompone
3976
3897
  super(...arguments);
3977
3898
  //#region ---- Services & Dependencies ----
3978
3899
  this.route = inject(ActivatedRoute);
3979
- this.router = inject(Router);
3980
3900
  this.entityService = inject(AXPEntityService);
3981
3901
  this.filterOperatorMiddleware = inject(AXPFilterOperatorMiddlewareService);
3982
3902
  //#endregion
@@ -4395,7 +4315,7 @@ class AXPEntityCommandTriggerViewModel {
4395
4315
  this.priority = action.priority;
4396
4316
  this.title = action.title;
4397
4317
  this.separated = action.separated ?? false;
4398
- this.color = action.color ?? resolvedLook.color;
4318
+ this.color = (action.color ?? resolvedLook.color);
4399
4319
  this.icon = action.icon ?? resolvedLook.icon;
4400
4320
  this.hidden = action.hidden ?? false;
4401
4321
  this.disabled = action.disabled ?? false;
@@ -5265,7 +5185,7 @@ class AXPEntityMasterListViewModel {
5265
5185
  }
5266
5186
  }
5267
5187
  //#endregion
5268
- createExpressionScope(data) {
5188
+ createLogicExpressionScope(data) {
5269
5189
  return {
5270
5190
  context: {
5271
5191
  eval: (path) => get(data, path),
@@ -5276,11 +5196,20 @@ class AXPEntityMasterListViewModel {
5276
5196
  },
5277
5197
  };
5278
5198
  }
5199
+ createDisplayExpressionScope(data) {
5200
+ return {
5201
+ context: this.contextEvalFactory.createScope((data ?? {})),
5202
+ list: {
5203
+ view: () => this.view().name,
5204
+ views: () => this.views().map((v) => ({ name: v.name, title: v.title })),
5205
+ },
5206
+ };
5207
+ }
5279
5208
  async resolveCommandNameExpression(commandName, data) {
5280
5209
  if (!commandName || !commandName.includes('{{')) {
5281
5210
  return commandName;
5282
5211
  }
5283
- const scope = this.createExpressionScope(data);
5212
+ const scope = this.createLogicExpressionScope(data);
5284
5213
  const result = await this.expressionEvaluator.evaluate({ value: commandName }, scope);
5285
5214
  const resolved = result?.value;
5286
5215
  return typeof resolved === 'string' && resolved.trim() !== '' ? resolved : commandName;
@@ -5289,7 +5218,7 @@ class AXPEntityMasterListViewModel {
5289
5218
  if (!title || !title.includes('{{')) {
5290
5219
  return title;
5291
5220
  }
5292
- const scope = this.createExpressionScope(data);
5221
+ const scope = this.createDisplayExpressionScope(data);
5293
5222
  const result = await this.expressionEvaluator.evaluate({ value: title }, scope);
5294
5223
  const resolved = result?.value;
5295
5224
  return typeof resolved === 'string' && resolved.trim() !== '' ? resolved : title;
@@ -5304,7 +5233,7 @@ class AXPEntityMasterListViewModel {
5304
5233
  return '';
5305
5234
  }
5306
5235
  if (value.includes('{{')) {
5307
- const scope = this.createExpressionScope(rowData);
5236
+ const scope = this.createDisplayExpressionScope(rowData);
5308
5237
  const result = await this.expressionEvaluator.evaluate(value, scope);
5309
5238
  if (result === false) {
5310
5239
  return '';
@@ -5342,7 +5271,7 @@ class AXPEntityMasterListViewModel {
5342
5271
  if (color == null || color === '') {
5343
5272
  return 'default';
5344
5273
  }
5345
- const scope = this.createExpressionScope(rowData);
5274
+ const scope = this.createLogicExpressionScope(rowData);
5346
5275
  const result = await this.expressionEvaluator.evaluate(color, scope);
5347
5276
  if (result === false || result == null) {
5348
5277
  return 'default';
@@ -5390,6 +5319,7 @@ class AXPEntityMasterListViewModel {
5390
5319
  this.settings = this.injector.get(AXPSettingsService);
5391
5320
  this.widgetResolver = this.injector.get(AXPWidgetRegistryService);
5392
5321
  this.expressionEvaluator = this.injector.get(AXPExpressionEvaluatorService);
5322
+ this.contextEvalFactory = this.injector.get(AXPContextEvalFactory);
5393
5323
  this.translation = this.injector.get(AXTranslationService);
5394
5324
  this.commandService = this.injector.get(AXPCommandService);
5395
5325
  this.eventService = this.injector.get(AXPBroadcastEventService);
@@ -5612,7 +5542,7 @@ class AXPEntityMasterListViewModel {
5612
5542
  this.sortedFields = signal([], ...(ngDevMode ? [{ debugName: "sortedFields" }] : /* istanbul ignore next */ []));
5613
5543
  //#endregion
5614
5544
  this.evaluateExpressions = async (options, data) => {
5615
- const scope = this.createExpressionScope(data);
5545
+ const scope = this.createLogicExpressionScope(data);
5616
5546
  return await this.expressionEvaluator.evaluate(options, scope);
5617
5547
  };
5618
5548
  this.workflow.events$
@@ -6002,7 +5932,7 @@ class AXPEntityMasterListViewModel {
6002
5932
  this.selectedCategory.set(category);
6003
5933
  }
6004
5934
  async getPrimaryActions() {
6005
- const scope = this.createExpressionScope(null);
5935
+ const scope = this.createLogicExpressionScope(null);
6006
5936
  const actions = await Promise.all(this.allActions()
6007
5937
  .filter((a) => a.priority == 'primary' &&
6008
5938
  ((a.scope == AXPEntityCommandScope.Selected && this.hasSelectedItems()) ||
@@ -6019,7 +5949,7 @@ class AXPEntityMasterListViewModel {
6019
5949
  return actions.filter(Boolean);
6020
5950
  }
6021
5951
  async getSecondaryActions() {
6022
- const scope = this.createExpressionScope(null);
5952
+ const scope = this.createLogicExpressionScope(null);
6023
5953
  const actions = await Promise.all(this.allActions()
6024
5954
  .filter((a) => a.priority == 'secondary' &&
6025
5955
  ((a.scope == AXPEntityCommandScope.Selected && this.hasSelectedItems()) ||
@@ -6036,7 +5966,7 @@ class AXPEntityMasterListViewModel {
6036
5966
  return actions.filter(Boolean);
6037
5967
  }
6038
5968
  async secondaryRowActions(rowData) {
6039
- const scope = this.createExpressionScope(rowData);
5969
+ const scope = this.createLogicExpressionScope(rowData);
6040
5970
  const actions = await Promise.all(this.allActions()
6041
5971
  .filter((a) => a.scope === AXPEntityCommandScope.Individual && a.priority === 'secondary')
6042
5972
  .map(async (a) => {
@@ -7059,6 +6989,9 @@ class AXPEntityModifySectionPopupAction extends AXPWorkflowAction {
7059
6989
  this.popupService = inject(AXPopupService);
7060
6990
  this.platform = inject(AXPlatform);
7061
6991
  this.translateService = inject(AXTranslationService);
6992
+ this.formatService = inject(AXFormatService);
6993
+ this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
6994
+ this.contextEvalFactory = inject(AXPContextEvalFactory);
7062
6995
  this.entityRegistery = inject(AXPEntityDefinitionRegistryService);
7063
6996
  this.config = inject(AXP_ENTITY_CONFIG_TOKEN);
7064
6997
  this.factory = inject(AXPEntityMasterUpdateViewModelFactory);
@@ -7076,7 +7009,7 @@ class AXPEntityModifySectionPopupAction extends AXPWorkflowAction {
7076
7009
  title: headerTitle
7077
7010
  ? headerTitle
7078
7011
  : title ??
7079
- `${this.translateService.translateSync('entity.modify')} ${this.translateService.translateSync(entityRef.formats.individual)}`,
7012
+ (await resolveEntityModifyPopupTitle(entityRef, vm.context(), this.translateService, this.formatService, this.expressionEvaluator, this.contextEvalFactory)),
7080
7013
  size: this.platform.is('Mobile') || this.platform.is('SM') ? 'full' : 'md',
7081
7014
  data: {
7082
7015
  vm,
@@ -12313,6 +12246,7 @@ class AXPEntityListTableService {
12313
12246
  const evaluatedOptions = await this.evaluateExpressions(action?.options, data);
12314
12247
  const options = this.mergeRelatedListFormOptions(command, evaluatedOptions, relatedListExcludeProperties);
12315
12248
  if (this.commandService.exists(command)) {
12249
+ const excludeProperties = options['excludeProperties'];
12316
12250
  await this.commandService.execute(command, {
12317
12251
  __context__: {
12318
12252
  entity: getEntityInfo(entity).source,
@@ -12329,6 +12263,7 @@ class AXPEntityListTableService {
12329
12263
  },
12330
12264
  options,
12331
12265
  metadata: action?.metadata,
12266
+ ...(excludeProperties?.length ? { excludeProperties } : {}),
12332
12267
  });
12333
12268
  }
12334
12269
  else {
@@ -12354,7 +12289,7 @@ class AXPEntityListTableService {
12354
12289
  mergeRelatedListFormOptions(command, evaluatedOptions, relatedListExcludeProperties) {
12355
12290
  const exclusions = relatedListExcludeProperties?.filter(Boolean);
12356
12291
  if (!exclusions?.length ||
12357
- (command !== 'Entity:Create' && command !== 'Entity:Update')) {
12292
+ (command !== 'Entity:Create' && command !== 'Entity:Update' && command !== 'Entity:View')) {
12358
12293
  return evaluatedOptions;
12359
12294
  }
12360
12295
  return {
@@ -13898,6 +13833,8 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
13898
13833
  super(...arguments);
13899
13834
  this.formatService = inject(AXFormatService);
13900
13835
  this.translation = inject(AXTranslationService);
13836
+ this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
13837
+ this.contextEvalFactory = inject(AXPContextEvalFactory);
13901
13838
  this.entityResolver = inject(AXPEntityDefinitionRegistryService);
13902
13839
  this.entity = computed(() => this.options()['entity'], ...(ngDevMode ? [{ debugName: "entity" }] : /* istanbul ignore next */ []));
13903
13840
  this.multiple = computed(() => this.options()['multiple'], ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
@@ -13931,7 +13868,7 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
13931
13868
  if (typeof item == 'object') {
13932
13869
  return {
13933
13870
  id: item[this.valueField()],
13934
- text: this.getDisplayRaw(item),
13871
+ text: await this.getDisplayRaw(item),
13935
13872
  };
13936
13873
  }
13937
13874
  const def = this.entityDef();
@@ -13942,7 +13879,7 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
13942
13879
  this.loading.set(false);
13943
13880
  return {
13944
13881
  id: fetchedItem[this.valueField()],
13945
- text: this.getDisplayRaw(fetchedItem),
13882
+ text: await this.getDisplayRaw(fetchedItem),
13946
13883
  };
13947
13884
  }
13948
13885
  return {
@@ -13950,12 +13887,17 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
13950
13887
  text: item,
13951
13888
  };
13952
13889
  }
13953
- getDisplayRaw(item) {
13954
- const text = formatLookupItemDisplay(item, this.entityDef(), {
13890
+ async getDisplayRaw(item) {
13891
+ const locale = this.translation.getActiveLang() ?? 'en-US';
13892
+ return formatLookupItemDisplayAsync(item, this.entityDef(), {
13955
13893
  displayFormat: this.options()['displayFormat'],
13956
13894
  textField: this.textField(),
13957
- }, this.formatService, (value) => this.translation.resolve(value));
13958
- return text;
13895
+ }, this.formatService, {
13896
+ expressionEvaluator: this.expressionEvaluator,
13897
+ contextEvalFactory: this.contextEvalFactory,
13898
+ translationService: this.translation,
13899
+ locale,
13900
+ }, (value) => this.translation.resolve(value));
13959
13901
  }
13960
13902
  get __class() {
13961
13903
  const cls = {};
@@ -15105,6 +15047,8 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
15105
15047
  this.formatService = inject(AXFormatService);
15106
15048
  this.translateService = inject(AXTranslationService);
15107
15049
  this.entityDataSelectorService = inject(AXPEntityDataSelectorService);
15050
+ this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
15051
+ this.contextEvalFactory = inject(AXPContextEvalFactory);
15108
15052
  //#endregion
15109
15053
  //#region ---- Inputs ----
15110
15054
  this.selectedItems = input.required(...(ngDevMode ? [{ debugName: "selectedItems" }] : /* istanbul ignore next */ []));
@@ -15134,6 +15078,8 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
15134
15078
  //#region ---- Internal State ----
15135
15079
  this.searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []));
15136
15080
  this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
15081
+ this.itemLabels = signal({}, ...(ngDevMode ? [{ debugName: "itemLabels" }] : /* istanbul ignore next */ []));
15082
+ this.itemLabelsVersion = 0;
15137
15083
  //#endregion
15138
15084
  //#region ---- View Children ----
15139
15085
  this.tagBox = viewChild('tagBoxComponent', ...(ngDevMode ? [{ debugName: "tagBox" }] : /* istanbul ignore next */ []));
@@ -15156,6 +15102,31 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
15156
15102
  }
15157
15103
  }
15158
15104
  }, ...(ngDevMode ? [{ debugName: "#focusEffect" }] : /* istanbul ignore next */ []));
15105
+ this.#itemLabelsEffect = effect(() => {
15106
+ void this.translateService.getActiveLang();
15107
+ const items = this.selectedItemsValue();
15108
+ const entityDef = this.entityDef()();
15109
+ const valueField = this.valueFieldValue();
15110
+ const version = ++this.itemLabelsVersion;
15111
+ void Promise.all(items.map(async (item) => {
15112
+ const id = String(get(item, valueField) ?? '');
15113
+ const label = await formatLookupItemDisplayAsync(item, entityDef, {
15114
+ displayFormat: this.displayFormatValue(),
15115
+ textField: this.displayFieldValue(),
15116
+ }, this.formatService, {
15117
+ expressionEvaluator: this.expressionEvaluator,
15118
+ contextEvalFactory: this.contextEvalFactory,
15119
+ translationService: this.translateService,
15120
+ locale: this.translateService.getActiveLang() ?? 'en-US',
15121
+ }, (value) => this.translateService.resolve(value));
15122
+ return [id, label];
15123
+ })).then((entries) => {
15124
+ if (version !== this.itemLabelsVersion) {
15125
+ return;
15126
+ }
15127
+ this.itemLabels.set(Object.fromEntries(entries));
15128
+ });
15129
+ }, ...(ngDevMode ? [{ debugName: "#itemLabelsEffect" }] : /* istanbul ignore next */ []));
15159
15130
  //#endregion
15160
15131
  //#region ---- Computed Properties ----
15161
15132
  this.tagBoxComponent = computed(() => this.tagBox(), ...(ngDevMode ? [{ debugName: "tagBoxComponent" }] : /* istanbul ignore next */ []));
@@ -15171,6 +15142,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
15171
15142
  this.placeholderValue = computed(() => this.placeholder()?.() ?? '', ...(ngDevMode ? [{ debugName: "placeholderValue" }] : /* istanbul ignore next */ []));
15172
15143
  }
15173
15144
  #focusEffect;
15145
+ #itemLabelsEffect;
15174
15146
  focus() {
15175
15147
  this.shouldFocus.set(true);
15176
15148
  }
@@ -15236,11 +15208,9 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
15236
15208
  }
15237
15209
  //#endregion
15238
15210
  //#region ---- Utility Methods ----
15239
- getDisplayRaw(item) {
15240
- return formatLookupItemDisplay(item, this.entityDef()(), {
15241
- displayFormat: this.displayFormatValue(),
15242
- textField: this.displayFieldValue(),
15243
- }, this.formatService, (value) => this.translateService.resolve(value));
15211
+ getItemLabel(item) {
15212
+ const id = String(get(item, this.valueFieldValue()) ?? '');
15213
+ return this.itemLabels()[id] ?? '';
15244
15214
  }
15245
15215
  /**
15246
15216
  * Get current input value from tag box
@@ -15387,7 +15357,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
15387
15357
  </ax-tag-box>
15388
15358
  <ng-template #tagTemplate let-item let-index="index">
15389
15359
  <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">
15390
- <span>{{ getDisplayRaw(item) | translate | async }}</span>
15360
+ <span>{{ getItemLabel(item) }}</span>
15391
15361
  <button type="button" (click)="tagBoxComponent.removeItem(index)">
15392
15362
  <ax-icon class="ax-icon ax-icon-close"></ax-icon>
15393
15363
  </button>
@@ -15447,7 +15417,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
15447
15417
  </ax-tag-box>
15448
15418
  <ng-template #tagTemplate let-item let-index="index">
15449
15419
  <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">
15450
- <span>{{ getDisplayRaw(item) | translate | async }}</span>
15420
+ <span>{{ getItemLabel(item) }}</span>
15451
15421
  <button type="button" (click)="tagBoxComponent.removeItem(index)">
15452
15422
  <ax-icon class="ax-icon ax-icon-close"></ax-icon>
15453
15423
  </button>
@@ -15925,6 +15895,8 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
15925
15895
  this.entityService = inject(AXPEntityService);
15926
15896
  this.entityResolver = inject(AXPEntityDefinitionRegistryService);
15927
15897
  this.queryExecutor = inject(AXPQueryExecutor);
15898
+ this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
15899
+ this.contextEvalFactory = inject(AXPContextEvalFactory);
15928
15900
  //#endregion
15929
15901
  //#region ---- View Children ----
15930
15902
  this.moreButton = viewChild('moreButton', ...(ngDevMode ? [{ debugName: "moreButton" }] : /* istanbul ignore next */ []));
@@ -15962,11 +15934,16 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
15962
15934
  this.resolveError = signal(null, ...(ngDevMode ? [{ debugName: "resolveError" }] : /* istanbul ignore next */ []));
15963
15935
  this.summaryLabel = signal('', ...(ngDevMode ? [{ debugName: "summaryLabel" }] : /* istanbul ignore next */ []));
15964
15936
  this.popoverHeader = signal('', ...(ngDevMode ? [{ debugName: "popoverHeader" }] : /* istanbul ignore next */ []));
15937
+ this.mainItemLabels = signal([], ...(ngDevMode ? [{ debugName: "mainItemLabels" }] : /* istanbul ignore next */ []));
15938
+ this.lazyPopoverItemLabels = signal([], ...(ngDevMode ? [{ debugName: "lazyPopoverItemLabels" }] : /* istanbul ignore next */ []));
15965
15939
  this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : /* istanbul ignore next */ []));
15966
15940
  this.hydratedDisplayItems = signal(null, ...(ngDevMode ? [{ debugName: "hydratedDisplayItems" }] : /* istanbul ignore next */ []));
15967
15941
  this.hydrateRequestId = 0;
15942
+ this.mainLabelsVersion = 0;
15943
+ this.lazyPopoverLabelsVersion = 0;
15968
15944
  //#endregion
15969
15945
  //#region ---- Computed ----
15946
+ this.popoverItemLabels = computed(() => this.isHydratedStrategy() ? this.mainItemLabels() : this.lazyPopoverItemLabels(), ...(ngDevMode ? [{ debugName: "popoverItemLabels" }] : /* istanbul ignore next */ []));
15970
15947
  this.displayItems = computed(() => isNil(this.rawValue)
15971
15948
  ? []
15972
15949
  : castArray(this.rawValue)
@@ -16086,6 +16063,36 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
16086
16063
  }
16087
16064
  void this.hydrateScalarIds(entityKey, values);
16088
16065
  });
16066
+ effect(() => {
16067
+ void this.translation.getActiveLang();
16068
+ this.entityDef();
16069
+ const items = this.allItems();
16070
+ const version = ++this.mainLabelsVersion;
16071
+ void this.resolveLabelsForItems(items).then((labels) => {
16072
+ if (version === this.mainLabelsVersion) {
16073
+ this.mainItemLabels.set(labels);
16074
+ }
16075
+ });
16076
+ });
16077
+ effect(() => {
16078
+ if (this.isHydratedStrategy()) {
16079
+ return;
16080
+ }
16081
+ void this.translation.getActiveLang();
16082
+ this.entityDef();
16083
+ const status = this.resolveStatus();
16084
+ const items = this.resolvedPopoverItems();
16085
+ if (status !== 'ready') {
16086
+ this.lazyPopoverItemLabels.set([]);
16087
+ return;
16088
+ }
16089
+ const version = ++this.lazyPopoverLabelsVersion;
16090
+ void this.resolveLabelsForItems(items).then((labels) => {
16091
+ if (version === this.lazyPopoverLabelsVersion) {
16092
+ this.lazyPopoverItemLabels.set(labels);
16093
+ }
16094
+ });
16095
+ });
16089
16096
  }
16090
16097
  //#endregion
16091
16098
  //#region ---- Public methods ----
@@ -16140,7 +16147,9 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
16140
16147
  let resolvedTitle = '';
16141
16148
  if (headerItem != null && this.hasDisplayTextOnLookupValue(headerItem)) {
16142
16149
  resolvedTitle =
16143
- typeof headerItem === 'object' ? this.renderLookupLabel(headerItem) : this.formatDisplayValue(headerItem);
16150
+ typeof headerItem === 'object'
16151
+ ? await this.resolveItemLabel(headerItem)
16152
+ : this.formatDisplayValue(headerItem);
16144
16153
  }
16145
16154
  else if (!this.isMultiValueLookup()) {
16146
16155
  const rowText = this.getRowDisplayTextFromTextField();
@@ -16149,8 +16158,7 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
16149
16158
  }
16150
16159
  }
16151
16160
  if (!resolvedTitle) {
16152
- const displayTitle = formatLookupItemDisplay(headerItem, this.entityDef(), this.lookupDisplayOptions(), this.formatService, (value) => this.translation.resolve(value));
16153
- resolvedTitle = typeof displayTitle === 'string' ? displayTitle : this.translation.resolve(displayTitle);
16161
+ resolvedTitle = await this.resolveItemLabel(headerItem);
16154
16162
  if (isUnresolvedEntityDisplayTemplate(resolvedTitle)) {
16155
16163
  resolvedTitle = '';
16156
16164
  }
@@ -16210,8 +16218,22 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
16210
16218
  const values = castArray(raw).filter((value) => value != null && value !== '');
16211
16219
  return values.length > 0 && values.every((value) => this.hasDisplayTextOnLookupValue(value));
16212
16220
  }
16213
- getDisplayRaw(item) {
16214
- if (item != null && typeof item === 'object' && this.translation.isValidMultiLanguageObject(item)) {
16221
+ getItemLabel(index) {
16222
+ return this.mainItemLabels()[index] ?? '';
16223
+ }
16224
+ getPopoverItemLabel(index) {
16225
+ return this.popoverItemLabels()[index] ?? '';
16226
+ }
16227
+ //#endregion
16228
+ //#region ---- Private methods ----
16229
+ async resolveLabelsForItems(items) {
16230
+ return Promise.all(items.map((item) => this.resolveItemLabel(item)));
16231
+ }
16232
+ async resolveItemLabel(item) {
16233
+ if (item == null) {
16234
+ return '';
16235
+ }
16236
+ if (typeof item === 'object' && this.translation.isValidMultiLanguageObject(item)) {
16215
16237
  return this.translation.resolve(item);
16216
16238
  }
16217
16239
  if (!this.isMultiValueLookup()) {
@@ -16220,16 +16242,19 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
16220
16242
  return this.formatDisplayValue(rowText);
16221
16243
  }
16222
16244
  }
16223
- if (item != null && this.hasDisplayTextOnLookupValue(item)) {
16224
- if (typeof item === 'object') {
16225
- return this.renderLookupLabel(item);
16245
+ if (this.hasDisplayTextOnLookupValue(item)) {
16246
+ if (typeof item !== 'object') {
16247
+ return this.formatDisplayValue(item);
16226
16248
  }
16227
- return this.formatDisplayValue(item);
16228
16249
  }
16229
- return this.renderLookupLabel(item);
16250
+ const locale = this.translation.getActiveLang() ?? 'en-US';
16251
+ return formatLookupItemDisplayAsync(item, this.entityDef(), this.lookupDisplayOptions(), this.formatService, {
16252
+ expressionEvaluator: this.expressionEvaluator,
16253
+ contextEvalFactory: this.contextEvalFactory,
16254
+ translationService: this.translation,
16255
+ locale,
16256
+ }, (value) => this.translation.resolve(value));
16230
16257
  }
16231
- //#endregion
16232
- //#region ---- Private methods ----
16233
16258
  async refreshSummaryLabel(count) {
16234
16259
  const text = await this.translation.translateAsync('@general:widgets.lookup.column.items-count', {
16235
16260
  params: { count: String(count) },
@@ -16522,10 +16547,6 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
16522
16547
  return !isNil(candidate) && candidate !== '' && !this.isLikelyEntityId(candidate);
16523
16548
  });
16524
16549
  }
16525
- renderLookupLabel(value) {
16526
- const label = formatLookupItemDisplay(value, this.entityDef(), this.lookupDisplayOptions(), this.formatService, (item) => this.translation.resolve(item));
16527
- return typeof label === 'string' ? label : this.translation.resolve(label);
16528
- }
16529
16550
  formatDisplayValue(value) {
16530
16551
  if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
16531
16552
  return String(value);
@@ -16546,11 +16567,11 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
16546
16567
  return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value) || /^\d+$/.test(value);
16547
16568
  }
16548
16569
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLookupWidgetColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
16549
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLookupWidgetColumnComponent, isStandalone: true, selector: "ng-component", inputs: { rawValue: "rawValue", rowData: "rowData" }, viewQueries: [{ propertyName: "moreButton", first: true, predicate: ["moreButton"], descendants: true, isSignal: true }, { propertyName: "lazyTrigger", first: true, predicate: ["lazyTrigger"], descendants: true, isSignal: true }, { propertyName: "morePopover", first: true, predicate: ["morePopover"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (isHydratedStrategy()) {\n<div class=\"ax-relative ax-flex ax-min-w-0 ax-items-center ax-gap-1\">\n @for (item of visibleItems(); track $index) {\n @let label = getDisplayRaw(item);\n <span [class.ax-cursor-pointer]=\"detailPopoverEnabled()\" [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\" (click)=\"handleItemClick($index)\">\n {{ label }}\n </span>\n @if ($index < visibleItems().length - 1) { <span class=\"ax-text-muted\">\u2022</span>\n }\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n @if (hasMoreItems()) {\n <span\n class=\"ax-absolute ax-end-0 ax-flex ax-h-full ax-cursor-pointer ax-items-center ax-px-1 hover:ax-primary-lighter\"\n (click)=\"showMoreItems(); $event.stopPropagation()\" #moreButton>\n <i class=\"fa-light fa-ellipsis-vertical\"></i>\n </span>\n }\n</div>\n} @else {\n<div class=\"ax-flex ax-min-w-0 ax-items-center ax-gap-1\">\n @if (displayCount() > 0) {\n <span class=\"ax-cursor-pointer ax-text-primary hover:ax-underline\"\n (click)=\"openLazyPopover(); $event.stopPropagation()\" #lazyTrigger>\n {{ summaryLabel() }}\n </span>\n } @else {\n <span class=\"ax-text-muted\">---</span>\n }\n</div>\n}\n\n<ax-popover [openOn]=\"'manual'\" #morePopover (openChange)=\"onPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface dark:ax-dark-surface ax-min-w-[280px] ax-rounded-lg ax-border ax-p-4 ax-shadow-lg\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold\">{{ popoverHeader() }}</h3>\n </div>\n\n @if (!isHydratedStrategy() && resolveStatus() === 'loading') {\n <div class=\"ax-flex ax-min-h-[120px] ax-items-center ax-justify-center\">\n <ax-loading></ax-loading>\n </div>\n } @else if (!isHydratedStrategy() && resolveStatus() === 'error') {\n <div class=\"ax-text-danger ax-text-sm\">{{ resolveError() }}</div>\n } @else {\n <div class=\"ax-flex ax-max-h-64 ax-flex-col ax-gap-3\">\n @for (item of popoverListItems(); track $index) {\n @let label = getDisplayRaw(item);\n <span [class.ax-cursor-pointer]=\"detailPopoverEnabled()\" [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\" (click)=\"handlePopoverItemClick($index)\">\n {{ label }}\n </span>\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n </div>\n }\n </div>\n</ax-popover>", dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i1$2.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
16570
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLookupWidgetColumnComponent, isStandalone: true, selector: "ng-component", inputs: { rawValue: "rawValue", rowData: "rowData" }, viewQueries: [{ propertyName: "moreButton", first: true, predicate: ["moreButton"], descendants: true, isSignal: true }, { propertyName: "lazyTrigger", first: true, predicate: ["lazyTrigger"], descendants: true, isSignal: true }, { propertyName: "morePopover", first: true, predicate: ["morePopover"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (isHydratedStrategy()) {\n<div class=\"ax-relative ax-flex ax-min-w-0 ax-items-center ax-gap-1\">\n @for (item of visibleItems(); track $index) {\n <span [class.ax-cursor-pointer]=\"detailPopoverEnabled()\" [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\" (click)=\"handleItemClick($index)\">\n {{ getItemLabel($index) }}\n </span>\n @if ($index < visibleItems().length - 1) { <span class=\"ax-text-muted\">\u2022</span>\n }\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n @if (hasMoreItems()) {\n <span\n class=\"ax-absolute ax-end-0 ax-flex ax-h-full ax-cursor-pointer ax-items-center ax-px-1 hover:ax-primary-lighter\"\n (click)=\"showMoreItems(); $event.stopPropagation()\" #moreButton>\n <i class=\"fa-light fa-ellipsis-vertical\"></i>\n </span>\n }\n</div>\n} @else {\n<div class=\"ax-flex ax-min-w-0 ax-items-center ax-gap-1\">\n @if (displayCount() > 0) {\n <span class=\"ax-cursor-pointer ax-text-primary hover:ax-underline\"\n (click)=\"openLazyPopover(); $event.stopPropagation()\" #lazyTrigger>\n {{ summaryLabel() }}\n </span>\n } @else {\n <span class=\"ax-text-muted\">---</span>\n }\n</div>\n}\n\n<ax-popover [openOn]=\"'manual'\" #morePopover (openChange)=\"onPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface dark:ax-dark-surface ax-min-w-[280px] ax-rounded-lg ax-border ax-p-4 ax-shadow-lg\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold\">{{ popoverHeader() }}</h3>\n </div>\n\n @if (!isHydratedStrategy() && resolveStatus() === 'loading') {\n <div class=\"ax-flex ax-min-h-[120px] ax-items-center ax-justify-center\">\n <ax-loading></ax-loading>\n </div>\n } @else if (!isHydratedStrategy() && resolveStatus() === 'error') {\n <div class=\"ax-text-danger ax-text-sm\">{{ resolveError() }}</div>\n } @else {\n <div class=\"ax-flex ax-max-h-64 ax-flex-col ax-gap-3\">\n @for (item of popoverListItems(); track $index) {\n <span [class.ax-cursor-pointer]=\"detailPopoverEnabled()\" [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\" (click)=\"handlePopoverItemClick($index)\">\n {{ getPopoverItemLabel($index) }}\n </span>\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n </div>\n }\n </div>\n</ax-popover>", dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i1$2.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
16550
16571
  }
16551
16572
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLookupWidgetColumnComponent, decorators: [{
16552
16573
  type: Component,
16553
- args: [{ changeDetection: ChangeDetectionStrategy.OnPush, imports: [AXLoadingModule, AXPopoverModule], inputs: ['rawValue', 'rowData'], template: "@if (isHydratedStrategy()) {\n<div class=\"ax-relative ax-flex ax-min-w-0 ax-items-center ax-gap-1\">\n @for (item of visibleItems(); track $index) {\n @let label = getDisplayRaw(item);\n <span [class.ax-cursor-pointer]=\"detailPopoverEnabled()\" [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\" (click)=\"handleItemClick($index)\">\n {{ label }}\n </span>\n @if ($index < visibleItems().length - 1) { <span class=\"ax-text-muted\">\u2022</span>\n }\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n @if (hasMoreItems()) {\n <span\n class=\"ax-absolute ax-end-0 ax-flex ax-h-full ax-cursor-pointer ax-items-center ax-px-1 hover:ax-primary-lighter\"\n (click)=\"showMoreItems(); $event.stopPropagation()\" #moreButton>\n <i class=\"fa-light fa-ellipsis-vertical\"></i>\n </span>\n }\n</div>\n} @else {\n<div class=\"ax-flex ax-min-w-0 ax-items-center ax-gap-1\">\n @if (displayCount() > 0) {\n <span class=\"ax-cursor-pointer ax-text-primary hover:ax-underline\"\n (click)=\"openLazyPopover(); $event.stopPropagation()\" #lazyTrigger>\n {{ summaryLabel() }}\n </span>\n } @else {\n <span class=\"ax-text-muted\">---</span>\n }\n</div>\n}\n\n<ax-popover [openOn]=\"'manual'\" #morePopover (openChange)=\"onPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface dark:ax-dark-surface ax-min-w-[280px] ax-rounded-lg ax-border ax-p-4 ax-shadow-lg\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold\">{{ popoverHeader() }}</h3>\n </div>\n\n @if (!isHydratedStrategy() && resolveStatus() === 'loading') {\n <div class=\"ax-flex ax-min-h-[120px] ax-items-center ax-justify-center\">\n <ax-loading></ax-loading>\n </div>\n } @else if (!isHydratedStrategy() && resolveStatus() === 'error') {\n <div class=\"ax-text-danger ax-text-sm\">{{ resolveError() }}</div>\n } @else {\n <div class=\"ax-flex ax-max-h-64 ax-flex-col ax-gap-3\">\n @for (item of popoverListItems(); track $index) {\n @let label = getDisplayRaw(item);\n <span [class.ax-cursor-pointer]=\"detailPopoverEnabled()\" [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\" (click)=\"handlePopoverItemClick($index)\">\n {{ label }}\n </span>\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n </div>\n }\n </div>\n</ax-popover>" }]
16574
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, imports: [AXLoadingModule, AXPopoverModule], inputs: ['rawValue', 'rowData'], template: "@if (isHydratedStrategy()) {\n<div class=\"ax-relative ax-flex ax-min-w-0 ax-items-center ax-gap-1\">\n @for (item of visibleItems(); track $index) {\n <span [class.ax-cursor-pointer]=\"detailPopoverEnabled()\" [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\" (click)=\"handleItemClick($index)\">\n {{ getItemLabel($index) }}\n </span>\n @if ($index < visibleItems().length - 1) { <span class=\"ax-text-muted\">\u2022</span>\n }\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n @if (hasMoreItems()) {\n <span\n class=\"ax-absolute ax-end-0 ax-flex ax-h-full ax-cursor-pointer ax-items-center ax-px-1 hover:ax-primary-lighter\"\n (click)=\"showMoreItems(); $event.stopPropagation()\" #moreButton>\n <i class=\"fa-light fa-ellipsis-vertical\"></i>\n </span>\n }\n</div>\n} @else {\n<div class=\"ax-flex ax-min-w-0 ax-items-center ax-gap-1\">\n @if (displayCount() > 0) {\n <span class=\"ax-cursor-pointer ax-text-primary hover:ax-underline\"\n (click)=\"openLazyPopover(); $event.stopPropagation()\" #lazyTrigger>\n {{ summaryLabel() }}\n </span>\n } @else {\n <span class=\"ax-text-muted\">---</span>\n }\n</div>\n}\n\n<ax-popover [openOn]=\"'manual'\" #morePopover (openChange)=\"onPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface dark:ax-dark-surface ax-min-w-[280px] ax-rounded-lg ax-border ax-p-4 ax-shadow-lg\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold\">{{ popoverHeader() }}</h3>\n </div>\n\n @if (!isHydratedStrategy() && resolveStatus() === 'loading') {\n <div class=\"ax-flex ax-min-h-[120px] ax-items-center ax-justify-center\">\n <ax-loading></ax-loading>\n </div>\n } @else if (!isHydratedStrategy() && resolveStatus() === 'error') {\n <div class=\"ax-text-danger ax-text-sm\">{{ resolveError() }}</div>\n } @else {\n <div class=\"ax-flex ax-max-h-64 ax-flex-col ax-gap-3\">\n @for (item of popoverListItems(); track $index) {\n <span [class.ax-cursor-pointer]=\"detailPopoverEnabled()\" [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\" (click)=\"handlePopoverItemClick($index)\">\n {{ getPopoverItemLabel($index) }}\n </span>\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n </div>\n }\n </div>\n</ax-popover>" }]
16554
16575
  }], ctorParameters: () => [], propDecorators: { moreButton: [{ type: i0.ViewChild, args: ['moreButton', { isSignal: true }] }], lazyTrigger: [{ type: i0.ViewChild, args: ['lazyTrigger', { isSignal: true }] }], morePopover: [{ type: i0.ViewChild, args: ['morePopover', { isSignal: true }] }] } });
16555
16576
 
16556
16577
  var lookupWidgetColumn_component = /*#__PURE__*/Object.freeze({
@@ -21813,13 +21834,20 @@ class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
21813
21834
  const p = relatedEntity?.persistence || {};
21814
21835
  const strategy = p.strategy || 'embedded';
21815
21836
  const mappedTargets = Object.keys(p.map || {}).map((k) => (k || '').split('.')[0]);
21837
+ const excludeProperties = relatedEntity.excludeProperties && relatedEntity.excludeProperties.length > 0
21838
+ ? new Set(relatedEntity.excludeProperties)
21839
+ : undefined;
21816
21840
  const helpers = {
21817
21841
  ...baseHelpers,
21818
21842
  getPropertyByGroupId: (groupId) => {
21819
- const props = baseHelpers.getPropertyByGroupId(groupId) ?? [];
21820
- if (strategy !== 'referenced' || mappedTargets.length === 0)
21821
- return props;
21822
- return props.filter((prop) => !mappedTargets.includes(prop?.name));
21843
+ let props = baseHelpers.getPropertyByGroupId(groupId) ?? [];
21844
+ if (strategy === 'referenced' && mappedTargets.length > 0) {
21845
+ props = props.filter((prop) => !mappedTargets.includes(prop?.name ?? ''));
21846
+ }
21847
+ if (excludeProperties) {
21848
+ props = props.filter((prop) => !excludeProperties.has(prop.name ?? ''));
21849
+ }
21850
+ return props;
21823
21851
  },
21824
21852
  };
21825
21853
  const evaluateExpressions = async (actionData) => {
@@ -21937,18 +21965,70 @@ class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
21937
21965
  }
21938
21966
  createLoadFunction(entityDef, relatedEntity, evaluateExpressions) {
21939
21967
  return async (context) => {
21940
- const fn = entityDef?.queries.byKey?.execute;
21968
+ const conditions = relatedEntity.conditions ?? [];
21969
+ if (conditions.length > 0) {
21970
+ const evaluatedFilters = await Promise.all(conditions.map(async (c) => ({
21971
+ field: c.name,
21972
+ operator: c.operator,
21973
+ value: await evaluateExpressions(c.value),
21974
+ })));
21975
+ if (conditions.length === 1 && conditions[0].name === 'id') {
21976
+ const byKeyFn = entityDef?.queries?.byKey?.execute;
21977
+ const id = evaluatedFilters[0]?.value;
21978
+ const result = id ? await byKeyFn(id) : null;
21979
+ return { success: true, data: result ?? {} };
21980
+ }
21981
+ const listFn = entityDef?.queries?.list?.execute;
21982
+ const filter = evaluatedFilters.length === 1
21983
+ ? evaluatedFilters[0]
21984
+ : { logic: 'and', filters: evaluatedFilters };
21985
+ const page = await listFn({ skip: 0, take: 1, filter });
21986
+ const item = page?.items?.[0];
21987
+ const data = item ? { ...item } : {};
21988
+ if (!item) {
21989
+ for (const evaluated of evaluatedFilters) {
21990
+ if (evaluated.field) {
21991
+ set(data, evaluated.field, evaluated.value);
21992
+ }
21993
+ }
21994
+ }
21995
+ return { success: true, data };
21996
+ }
21997
+ const fn = entityDef?.queries?.byKey?.execute;
21941
21998
  const conditionValues = relatedEntity.conditions?.map((c) => c.value) ?? [];
21942
21999
  const evaluatedConditionValues = await Promise.all(conditionValues.map((c) => evaluateExpressions(c)));
21943
22000
  const id = evaluatedConditionValues[0];
21944
- const result = await fn(id);
21945
- return { success: true, data: result };
22001
+ const result = id ? await fn(id) : null;
22002
+ return { success: true, data: result ?? {} };
21946
22003
  };
21947
22004
  }
21948
22005
  createExecuteFunction(entityDef, actions, evaluateExpressions, converterContext) {
21949
22006
  return async (e, context) => {
21950
22007
  try {
21951
22008
  if (e.name === 'update-entity') {
22009
+ const recordId = context?.['id'];
22010
+ if (!recordId) {
22011
+ const createFn = entityDef?.commands?.create?.execute;
22012
+ const created = await createFn(context);
22013
+ if (created && typeof created === 'object' && 'success' in created) {
22014
+ const cmd = created;
22015
+ if (!cmd.success) {
22016
+ const errorText = commandMessageTextForError(cmd.message?.text) || 'Failed to create entity';
22017
+ return {
22018
+ success: false,
22019
+ message: cmd.message ?? { text: errorText },
22020
+ };
22021
+ }
22022
+ return {
22023
+ success: true,
22024
+ data: cmd.data ?? created,
22025
+ };
22026
+ }
22027
+ return {
22028
+ success: true,
22029
+ data: created,
22030
+ };
22031
+ }
21952
22032
  const fn = entityDef?.commands?.update?.execute;
21953
22033
  const result = await fn(context);
21954
22034
  if (result && typeof result === 'object' && 'success' in result) {
@@ -22210,11 +22290,16 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
22210
22290
  const excludeForUpdate = commandName === 'Entity:Update' &&
22211
22291
  relatedEntity.excludeProperties &&
22212
22292
  relatedEntity.excludeProperties.length > 0;
22293
+ const excludeForView = commandName === 'Entity:View' &&
22294
+ relatedEntity.excludeProperties &&
22295
+ relatedEntity.excludeProperties.length > 0;
22213
22296
  const mergedOptions = excludeForCreate
22214
22297
  ? { ...evaluatedOptions, excludeProperties: createExcludes }
22215
22298
  : excludeForUpdate
22216
22299
  ? { ...evaluatedOptions, excludeProperties: relatedEntity.excludeProperties }
22217
- : evaluatedOptions;
22300
+ : excludeForView
22301
+ ? { ...evaluatedOptions, excludeProperties: relatedEntity.excludeProperties }
22302
+ : evaluatedOptions;
22218
22303
  if (context.commandService.exists(commandName)) {
22219
22304
  // check options for evaluation
22220
22305
  await context.commandService.execute(commandName, {
@@ -22233,6 +22318,7 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
22233
22318
  },
22234
22319
  options: mergedOptions,
22235
22320
  metadata: action.metadata,
22321
+ ...(excludeForView ? { excludeProperties: relatedEntity.excludeProperties } : {}),
22236
22322
  });
22237
22323
  }
22238
22324
  else {
@@ -23143,6 +23229,7 @@ class AXPLayoutAdapterFactory {
23143
23229
  this.layoutAdapterBuilder = layoutAdapterBuilder;
23144
23230
  this.filterOperatorMiddleware = filterOperatorMiddleware;
23145
23231
  this.pageComponentConverter = inject(AXPPageComponentConverter);
23232
+ this.contextEvalFactory = inject(AXPContextEvalFactory);
23146
23233
  }
23147
23234
  async createDetailsViewAdapter(entityResolver, moduleName, entityName, id, dependencies) {
23148
23235
  const entity = await entityResolver.resolve(moduleName, entityName);
@@ -23196,9 +23283,7 @@ class AXPLayoutAdapterFactory {
23196
23283
  if (hidden && typeof hidden === 'string') {
23197
23284
  try {
23198
23285
  const scope = {
23199
- context: {
23200
- eval: (path) => get(rootContext, path),
23201
- },
23286
+ context: this.contextEvalFactory.createScope(rootContext),
23202
23287
  };
23203
23288
  const result = await dependencies.expressionEvaluator.evaluate({ hidden }, scope);
23204
23289
  hidden = result.hidden;
@@ -23360,9 +23445,7 @@ class AXPLayoutAdapterFactory {
23360
23445
  }
23361
23446
  const scope = {
23362
23447
  ...rootContext,
23363
- context: {
23364
- eval: (path) => get(rootContext, path),
23365
- },
23448
+ context: this.contextEvalFactory.createScope(rootContext),
23366
23449
  };
23367
23450
  const title = await dependencies.expressionEvaluator.evaluate(titleTemplate, scope);
23368
23451
  return title;
@@ -24171,7 +24254,7 @@ const AXPCrudModifier = {
24171
24254
  queries.list = {
24172
24255
  execute: async (e) => {
24173
24256
  const res = await dataService.query(e);
24174
- // console.log('query', res, ctx.module.get() + '.' + ctx.name.get(), e);
24257
+ //console.log('query', res, ctx.module.get() + '.' + ctx.name.get(), e);
24175
24258
  return res;
24176
24259
  },
24177
24260
  type: AXPEntityQueryType.List,
@@ -24204,6 +24287,68 @@ class AXPEntityCommandSearchDefinitionProvider {
24204
24287
  function moduleNameToI18nScope(moduleName) {
24205
24288
  return moduleName.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
24206
24289
  }
24290
+ //#region ---- Entity search definition builder ----
24291
+ function buildEntitySearchDefinition(entity, manifestRegistry) {
24292
+ const manifest = manifestRegistry.get(entity.module);
24293
+ const i18nScope = manifest?.i18n ?? moduleNameToI18nScope(entity.module);
24294
+ const searchTitleTemplate = entity.formats.searchResult?.title;
24295
+ const titleContext = buildEntitySearchTitleContext(entity, searchTitleTemplate);
24296
+ return {
24297
+ name: `Module.${entity.module}.${entity.name}`,
24298
+ title: `@${i18nScope}:module.title`,
24299
+ group: `Module.${entity.module}`,
24300
+ icon: entity.icon ?? 'fa-solid fa-objects-column',
24301
+ order: 4,
24302
+ format: {
24303
+ title: searchTitleTemplate,
24304
+ description: entity.formats.searchResult?.description ?? `${entity.module} / ${entity.title}`,
24305
+ id: '{{data.id}}',
24306
+ titleFallbackTemplates: titleContext.fallbackTemplates,
24307
+ titleFallbackFields: titleContext.fallbackFields,
24308
+ },
24309
+ actions: [
24310
+ {
24311
+ name: 'open-entity',
24312
+ type: AXPSystemActionType.View,
24313
+ priority: 'primary',
24314
+ },
24315
+ ],
24316
+ };
24317
+ }
24318
+ //#endregion
24319
+ //#region ---- Lazy resolver ----
24320
+ class AXPEntitySearchDefinitionLazyResolver {
24321
+ constructor() {
24322
+ this.entityResolver = inject(AXPEntityResolver);
24323
+ this.manifestRegistry = inject(AXPModuleManifestRegistry);
24324
+ this.resolved = new Map();
24325
+ }
24326
+ async resolve(definitionName) {
24327
+ const cached = this.resolved.get(definitionName);
24328
+ if (cached) {
24329
+ return cached;
24330
+ }
24331
+ const match = definitionName.match(/^Module\.([^.]+)\.(.+)$/);
24332
+ if (!match) {
24333
+ return null;
24334
+ }
24335
+ const [, moduleName, entityName] = match;
24336
+ await this.manifestRegistry.initialize();
24337
+ const entity = await this.entityResolver.get(moduleName, entityName);
24338
+ if (!entity) {
24339
+ return null;
24340
+ }
24341
+ const definition = buildEntitySearchDefinition(entity, this.manifestRegistry);
24342
+ this.resolved.set(definitionName, definition);
24343
+ return definition;
24344
+ }
24345
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntitySearchDefinitionLazyResolver, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
24346
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntitySearchDefinitionLazyResolver }); }
24347
+ }
24348
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntitySearchDefinitionLazyResolver, decorators: [{
24349
+ type: Injectable
24350
+ }] });
24351
+
24207
24352
  class AXPEntitySearchDefinitionProvider {
24208
24353
  constructor() {
24209
24354
  this.entityRegister = inject(AXPEntityDefinitionRegistryService);
@@ -24211,28 +24356,13 @@ class AXPEntitySearchDefinitionProvider {
24211
24356
  }
24212
24357
  async provide(context) {
24213
24358
  await this.manifestRegistry.initialize();
24214
- this.entityRegister.getAll().forEach((entity) => {
24215
- const manifest = this.manifestRegistry.get(entity.module);
24216
- const i18nScope = manifest?.i18n ?? moduleNameToI18nScope(entity.module);
24217
- const searchTitleTemplate = entity.formats.searchResult?.title;
24218
- const titleContext = buildEntitySearchTitleContext(entity, searchTitleTemplate);
24219
- context.addDefinition(`Module.${entity.module}.${entity.name}`, `@${i18nScope}:module.title`, `Module.${entity.module}`, entity.icon ?? 'fa-solid fa-objects-column', 4, {
24220
- actions: [
24221
- {
24222
- name: 'open-entity',
24223
- type: 'view',
24224
- priority: 'primary',
24225
- },
24226
- ],
24227
- format: {
24228
- title: searchTitleTemplate,
24229
- description: (entity.formats.searchResult?.description) ?? `${entity.module} / ${entity.title}`,
24230
- id: '{{data.id}}',
24231
- titleFallbackTemplates: titleContext.fallbackTemplates,
24232
- titleFallbackFields: titleContext.fallbackFields,
24233
- },
24359
+ for (const entity of this.entityRegister.getAll()) {
24360
+ const definition = buildEntitySearchDefinition(entity, this.manifestRegistry);
24361
+ context.addDefinition(definition.name, definition.title, definition.group, definition.icon, definition.order, {
24362
+ actions: definition.actions,
24363
+ format: definition.format,
24234
24364
  });
24235
- });
24365
+ }
24236
24366
  }
24237
24367
  }
24238
24368
 
@@ -24338,9 +24468,9 @@ class AXPMiddlewareEntityStorageService extends AXPEntityStorageService {
24338
24468
  ...init,
24339
24469
  };
24340
24470
  }
24341
- async initial(entityName, collection, options) {
24471
+ async initial(entityName, collection) {
24342
24472
  const ctx = this.createCtx('initial', entityName, { data: collection });
24343
- return this.run(ctx, () => this.backend.initial(ctx.entityName, ctx.data, options));
24473
+ return this.run(ctx, () => this.backend.initial(ctx.entityName, ctx.data));
24344
24474
  }
24345
24475
  async getOne(entityName, id) {
24346
24476
  const key = getDedupKey('getOne', entityName, { id });
@@ -24624,6 +24754,9 @@ class AXPQuickEntityModifyPopupAction extends AXPWorkflowAction {
24624
24754
  this.popupService = inject(AXPopupService);
24625
24755
  this.platform = inject(AXPlatform);
24626
24756
  this.translateService = inject(AXTranslationService);
24757
+ this.formatService = inject(AXFormatService);
24758
+ this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
24759
+ this.contextEvalFactory = inject(AXPContextEvalFactory);
24627
24760
  this.entityRegistery = inject(AXPEntityDefinitionRegistryService);
24628
24761
  this.config = inject(AXP_ENTITY_CONFIG_TOKEN);
24629
24762
  this.factory = inject(AXPEntityMasterUpdateViewModelFactory);
@@ -24633,10 +24766,8 @@ class AXPQuickEntityModifyPopupAction extends AXPWorkflowAction {
24633
24766
  const data = context.getVariable('data');
24634
24767
  const entityRef = await this.entityRegistery.resolve(moduleName, entityName);
24635
24768
  const { parentKey } = entityRef;
24636
- console.log(data);
24637
24769
  const { id } = data;
24638
- const { interfaces, title } = entityRef;
24639
- const properties = interfaces?.master?.update?.properties?.map((p) => p.name) || [];
24770
+ const properties = entityRef.interfaces?.master?.update?.properties?.map((p) => p.name) || [];
24640
24771
  const vm = await this.factory.create(moduleName, entityName, id, properties);
24641
24772
  const options = context.getVariable('options');
24642
24773
  const decoration = options?.['decoration'];
@@ -24646,12 +24777,11 @@ class AXPQuickEntityModifyPopupAction extends AXPWorkflowAction {
24646
24777
  if (parentKey) {
24647
24778
  context.setVariable('parentKey', parentKey);
24648
24779
  }
24649
- console.log(`${this.translateService.translateSync('entity.modify')}`);
24650
24780
  const com = await this.config.viewers.master.modify();
24651
24781
  const popup = await this.popupService.open(com, {
24652
24782
  title: headerTitle
24653
24783
  ? headerTitle
24654
- : `${this.translateService.translateSync('@general:actions.modify.title')} ${this.translateService.translateSync(entityRef.formats.individual)}`,
24784
+ : await resolveEntityModifyPopupTitle(entityRef, vm.context(), this.translateService, this.formatService, this.expressionEvaluator, this.contextEvalFactory),
24655
24785
  size: this.platform.is('Mobile') || this.platform.is('SM') ? 'full' : size ? size : 'md',
24656
24786
  data: {
24657
24787
  vm,
@@ -24958,7 +25088,7 @@ function routesFacory() {
24958
25088
  const refreshChanged = from.queryParams['_ts'] !== to.queryParams['_ts'];
24959
25089
  return entityChanged || idChanged || refreshChanged;
24960
25090
  },
24961
- data: { reuse: false },
25091
+ data: { reuse: 'queryParamsChange' },
24962
25092
  },
24963
25093
  {
24964
25094
  path: 'e/:entity/:id',
@@ -24991,6 +25121,15 @@ class AXPEntityModule {
24991
25121
  AXPAttachmentsPluginModule, i1$3.AXPWorkflowModule, AXPWidgetCoreModule,
24992
25122
  LayoutBuilderModule] }); }
24993
25123
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityModule, providers: [
25124
+ {
25125
+ provide: AXP_REPEATER_ENTITY_BY_KEY_LOOKUP,
25126
+ useFactory: () => {
25127
+ const entityService = inject(AXPEntityService);
25128
+ return {
25129
+ byKey: (entityKey, id) => entityService.withEntity(entityKey).data().byKey(id),
25130
+ };
25131
+ },
25132
+ },
24994
25133
  { provide: AXP_WIDGET_DEFINITION_PROVIDER, useClass: AXPEntityWidgetsProvider, multi: true },
24995
25134
  {
24996
25135
  provide: ROUTES,
@@ -25007,6 +25146,10 @@ class AXPEntityModule {
25007
25146
  useClass: AXPEntityCommandSearchDefinitionProvider,
25008
25147
  multi: true,
25009
25148
  },
25149
+ {
25150
+ provide: AXP_SEARCH_DEFINITION_LAZY_RESOLVER,
25151
+ useClass: AXPEntitySearchDefinitionLazyResolver,
25152
+ },
25010
25153
  // Bind the middleware wrapper as the public storage service
25011
25154
  { provide: AXPEntityStorageService, useClass: AXPMiddlewareEntityStorageService },
25012
25155
  {
@@ -25178,6 +25321,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
25178
25321
  exports: [],
25179
25322
  declarations: [],
25180
25323
  providers: [
25324
+ {
25325
+ provide: AXP_REPEATER_ENTITY_BY_KEY_LOOKUP,
25326
+ useFactory: () => {
25327
+ const entityService = inject(AXPEntityService);
25328
+ return {
25329
+ byKey: (entityKey, id) => entityService.withEntity(entityKey).data().byKey(id),
25330
+ };
25331
+ },
25332
+ },
25181
25333
  { provide: AXP_WIDGET_DEFINITION_PROVIDER, useClass: AXPEntityWidgetsProvider, multi: true },
25182
25334
  {
25183
25335
  provide: ROUTES,
@@ -25194,6 +25346,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
25194
25346
  useClass: AXPEntityCommandSearchDefinitionProvider,
25195
25347
  multi: true,
25196
25348
  },
25349
+ {
25350
+ provide: AXP_SEARCH_DEFINITION_LAZY_RESOLVER,
25351
+ useClass: AXPEntitySearchDefinitionLazyResolver,
25352
+ },
25197
25353
  // Bind the middleware wrapper as the public storage service
25198
25354
  { provide: AXPEntityStorageService, useClass: AXPMiddlewareEntityStorageService },
25199
25355
  {
@@ -25501,5 +25657,5 @@ var getEntityDetails_query = /*#__PURE__*/Object.freeze({
25501
25657
  * Generated bundle index. Do not edit.
25502
25658
  */
25503
25659
 
25504
- export { ATTACHMENTS_PAGE_COMPONENT_KEY, AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityCommand, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEditFileUploaderCommand, AXPEntitiesListDataSourceDefinition, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorRowActionsService, AXPEntityDataSelectorService, AXPEntityDataSourceKeys, AXPEntityDefinitionProviderWidget, AXPEntityDefinitionProviderWidgetEditComponent, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityEventDispatcherService, AXPEntityEventsKeys, AXPEntityFormBuilderService, AXPEntityListPersistenceModeDefault, AXPEntityListTableService, AXPEntityListToolbarService, AXPEntityListViewCardFieldViewModel, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListCardSelectActionName, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityPreloadFiltersContainerComponent, AXPEntityPreloadFiltersViewModel, AXPEntityPreloadFiltersViewModelResolver, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPFileListComponent, AXPFileUploaderLoadFilesQuery, AXPFileUploaderSaveFilesCommand, AXPFileUploaderWidget, AXPFileUploaderWidgetColumnComponent, AXPFileUploaderWidgetEditComponent, AXPFileUploaderWidgetService, AXPFileUploaderWidgetViewComponent, AXPGetEntityDetailsQuery, AXPLayoutOrderingConfigService, AXPLookupWidget, AXPLookupWidgetColumnComponent, AXPLookupWidgetEditComponent, AXPLookupWidgetViewComponent, AXPMiddlewareAbortError, AXPMiddlewareEntityStorageService, AXPModifyEntitySectionWorkflow, AXPMultiSourceDefinitionProviderContext, AXPMultiSourceDefinitionProviderService, AXPMultiSourceFederatedSearchService, AXPMultiSourceSelectorComponent, AXPMultiSourceSelectorService, AXPMultiSourceSelectorWidget, AXPMultiSourceSelectorWidgetColumnComponent, AXPMultiSourceSelectorWidgetEditComponent, AXPMultiSourceSelectorWidgetViewComponent, AXPMultiSourceType, AXPOpenEntityDetailsCommand, AXPQuickEntityModifyPopupAction, AXPQuickModifyEntityWorkflow, AXPRelatedColumnEnrichmentService, AXPRelatedColumnMetadataResolver, AXPSelectorStructureWidget, AXPSelectorStructureWidgetColumnComponent, AXPSelectorStructureWidgetEditComponent, AXPSelectorStructureWidgetViewComponent, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPTruncatedBreadcrumbComponent, AXPUpdateEntityCommand, AXPViewEntityDetailsCommand, AXP_CATEGORY_TREE_ROOT_TITLE_I18N_KEY, 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, AXP_MULTI_SOURCE_DEFINITION_PROVIDER, AXP_RECORD_WORKFLOW_INFO_CORRELATION_ID_FIELD, AXP_RECORD_WORKFLOW_INFO_DEFINITION_ID_FIELD, AXP_RECORD_WORKFLOW_INFO_INSTANCE_ID_FIELD, DEFAULT_COLUMN_ORDER, DEFAULT_PAIR_SPAN_RULES, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY, EntityBuilder, EntityDataAccessor, actionExists, applyDataSourcePagingWithoutLoad, attachmentFieldCount, attachmentsPlugin, attachmentsSemanticallyEqual, axpCreateEntityAiToolInputDefaults, axpCreateEntityCommandDefinition, buildAXPRecordWorkflowInfo, canPersistEntityListState, cloneLayoutArrays, collectEntityQuickSearchFieldPaths, collectNestedCreateHiddenProperties, collectNestedFieldPathsFromEntityColumns, collectQuickSearchPathsFromSingleEntityDefinition, columnOrderingMiddleware, columnOrderingMiddlewareProvider, columnWidthMiddleware, columnWidthMiddlewareProvider, commandMessageTextForError, committedAttachments, computeEntityAggregates, createColumnOrderingMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, defaultCardLayoutMiddleware, defaultCardLayoutMiddlewareProvider, defaultMultiLanguageMiddleware, defaultMultiLanguageMiddlewareProvider, detectEntityChanges, ensureLayoutPropertyView, ensureLayoutSection, ensureListActions, entityDetailsCreateActions, entityDetailsCreateActionsDeferredParent, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, filterSortEntityRows, findEntityListRowDataInTree, fingerprintAttachmentItem, fingerprintAttachments, formatLookupItemDisplay, getDataSourcePageIndex, getEntityListRowId, getMasterInterfacePropertySortKey, getRecordWorkflowCorrelationId, getRecordWorkflowInstanceId, hasFileUploaderTitleOrDescriptionFields, isAXPMiddlewareAbortError, isAttachmentListEntry, isCategoryEntity, isCategoryFilter, isFileListItem, isFileUploaderEditDialogAuto, isLegacyEntityDataSelectorOptions, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider, mapEntityStorageErrorToCommandResult, mapLegacyEntityDataSelectorOptions, mergeForeignKeyFieldIntoCreateActions, normalizeEntityDataSelectorOptions, normalizeEntityFieldToFileList, normalizeEntityListPersistenceMode, normalizeListPaging, persistedAttachments, provideEntity, resolveEntityPluginDetailPageOrder, resolveFileUploaderEditDialog, resolveFileUploaderEntityScope, resolveLookupDisplayField, resolveLookupDisplayTemplate, restoreEntityListExpandedRows, runEntityQuery, searchResultDescriptionMiddleware, searchResultDescriptionMiddlewareProvider, shouldLoadEntityListStateFromStorage, shouldResetEntityListStateOnRouteEntry };
25660
+ export { ATTACHMENTS_PAGE_COMPONENT_KEY, AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityCommand, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEditFileUploaderCommand, AXPEntitiesListDataSourceDefinition, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorRowActionsService, AXPEntityDataSelectorService, AXPEntityDefinitionProviderWidget, AXPEntityDefinitionProviderWidgetEditComponent, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityEventDispatcherService, AXPEntityEventsKeys, AXPEntityFormBuilderService, AXPEntityListPersistenceModeDefault, AXPEntityListTableService, AXPEntityListToolbarService, AXPEntityListViewCardFieldViewModel, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListCardSelectActionName, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityPreloadFiltersContainerComponent, AXPEntityPreloadFiltersViewModel, AXPEntityPreloadFiltersViewModelResolver, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPFileListComponent, AXPFileUploaderLoadFilesQuery, AXPFileUploaderSaveFilesCommand, AXPFileUploaderWidget, AXPFileUploaderWidgetColumnComponent, AXPFileUploaderWidgetEditComponent, AXPFileUploaderWidgetService, AXPFileUploaderWidgetViewComponent, AXPGetEntityDetailsQuery, AXPLayoutOrderingConfigService, AXPLookupWidget, AXPLookupWidgetColumnComponent, AXPLookupWidgetEditComponent, AXPLookupWidgetViewComponent, AXPMiddlewareAbortError, AXPMiddlewareEntityStorageService, AXPModifyEntitySectionWorkflow, AXPMultiSourceDefinitionProviderContext, AXPMultiSourceDefinitionProviderService, AXPMultiSourceFederatedSearchService, AXPMultiSourceSelectorComponent, AXPMultiSourceSelectorService, AXPMultiSourceSelectorWidget, AXPMultiSourceSelectorWidgetColumnComponent, AXPMultiSourceSelectorWidgetEditComponent, AXPMultiSourceSelectorWidgetViewComponent, AXPMultiSourceType, AXPOpenEntityDetailsCommand, AXPQuickEntityModifyPopupAction, AXPQuickModifyEntityWorkflow, AXPRelatedColumnEnrichmentService, AXPRelatedColumnMetadataResolver, AXPSelectorStructureWidget, AXPSelectorStructureWidgetColumnComponent, AXPSelectorStructureWidgetEditComponent, AXPSelectorStructureWidgetViewComponent, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPTruncatedBreadcrumbComponent, AXPUpdateEntityCommand, AXPViewEntityDetailsCommand, AXP_CATEGORY_TREE_ROOT_TITLE_I18N_KEY, 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, AXP_MULTI_SOURCE_DEFINITION_PROVIDER, AXP_RECORD_WORKFLOW_INFO_CORRELATION_ID_FIELD, AXP_RECORD_WORKFLOW_INFO_DEFINITION_ID_FIELD, AXP_RECORD_WORKFLOW_INFO_INSTANCE_ID_FIELD, DEFAULT_COLUMN_ORDER, DEFAULT_PAIR_SPAN_RULES, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY, EntityBuilder, EntityDataAccessor, actionExists, applyDataSourcePagingWithoutLoad, attachmentFieldCount, attachmentsPlugin, attachmentsSemanticallyEqual, axpCreateEntityAiToolInputDefaults, axpCreateEntityCommandDefinition, buildAXPRecordWorkflowInfo, canPersistEntityListState, cloneLayoutArrays, collectEntityQuickSearchFieldPaths, collectNestedFieldPathsFromEntityColumns, collectQuickSearchPathsFromSingleEntityDefinition, columnOrderingMiddleware, columnOrderingMiddlewareProvider, columnWidthMiddleware, columnWidthMiddlewareProvider, commandMessageTextForError, committedAttachments, computeEntityAggregates, createColumnOrderingMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, defaultCardLayoutMiddleware, defaultCardLayoutMiddlewareProvider, defaultMultiLanguageMiddleware, defaultMultiLanguageMiddlewareProvider, detectEntityChanges, ensureLayoutPropertyView, ensureLayoutSection, ensureListActions, eventDispatchMiddleware, filterSortEntityRows, findEntityListRowDataInTree, fingerprintAttachmentItem, fingerprintAttachments, formatLookupItemDisplay, formatLookupItemDisplayAsync, getDataSourcePageIndex, getEntityListRowId, getMasterInterfacePropertySortKey, getRecordWorkflowCorrelationId, getRecordWorkflowInstanceId, hasFileUploaderTitleOrDescriptionFields, isAXPMiddlewareAbortError, isAttachmentListEntry, isCategoryEntity, isCategoryFilter, isFileListItem, isFileUploaderEditDialogAuto, isLegacyEntityDataSelectorOptions, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider, mapEntityStorageErrorToCommandResult, mapLegacyEntityDataSelectorOptions, normalizeEntityDataSelectorOptions, normalizeEntityFieldToFileList, normalizeEntityListPersistenceMode, normalizeListPaging, persistedAttachments, provideEntity, resolveEntityPluginDetailPageOrder, resolveFileUploaderEditDialog, resolveFileUploaderEntityScope, resolveLookupDisplayField, resolveLookupDisplayTemplate, restoreEntityListExpandedRows, runEntityQuery, searchResultDescriptionMiddleware, searchResultDescriptionMiddlewareProvider, shouldLoadEntityListStateFromStorage, shouldResetEntityListStateOnRouteEntry };
25505
25661
  //# sourceMappingURL=acorex-platform-layout-entity.mjs.map