@acorex/platform 21.0.0-next.85 → 21.0.0-next.89
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.
- package/fesm2022/acorex-platform-auth.mjs +9 -3
- package/fesm2022/acorex-platform-auth.mjs.map +1 -1
- package/fesm2022/{acorex-platform-common-common-settings.provider-Ytey9uhY.mjs → acorex-platform-common-common-settings.provider-DilV4dql.mjs} +16 -3
- package/fesm2022/acorex-platform-common-common-settings.provider-DilV4dql.mjs.map +1 -0
- package/fesm2022/acorex-platform-common.mjs +3426 -2488
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-contracts.mjs +1160 -9
- package/fesm2022/acorex-platform-contracts.mjs.map +1 -1
- package/fesm2022/acorex-platform-core.mjs +826 -152
- package/fesm2022/acorex-platform-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-domain-contracts.mjs +58 -0
- package/fesm2022/acorex-platform-domain-contracts.mjs.map +1 -0
- package/fesm2022/acorex-platform-domain.mjs +2 -50
- package/fesm2022/acorex-platform-domain.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +98 -189
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/{acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs → acorex-platform-layout-components-binding-expression-editor-popup.component-RttFwaw9.mjs} +17 -4
- package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-RttFwaw9.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-components.mjs +181 -46
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs +7 -6
- package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity-attachments-page.component-CwG6n_Yb.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity-contracts.mjs +1208 -0
- package/fesm2022/acorex-platform-layout-entity-contracts.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-entity-file-list-popup.component--IeMZLIr.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +1080 -889
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +1150 -247
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +388 -207
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-CFyfix31.mjs +513 -0
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-CFyfix31.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-CZc2zFlg.mjs} +4 -4
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-CZc2zFlg.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-XWRUVoL4.mjs} +2 -2
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs.map → acorex-platform-layout-widgets-tabular-data-view-popup.component-XWRUVoL4.mjs.map} +1 -1
- package/fesm2022/acorex-platform-layout-widgets.mjs +1541 -394
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
- 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
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-DrUwqKKA.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default.mjs +956 -115
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs → acorex-platform-themes-shared-settings.provider-UyKdkeyk.mjs} +50 -3
- package/fesm2022/acorex-platform-themes-shared-settings.provider-UyKdkeyk.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared.mjs +104 -24
- package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
- package/fesm2022/acorex-platform-workflow.mjs +6 -8
- package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
- package/package.json +9 -5
- package/types/acorex-platform-auth.d.ts +3 -1
- package/types/acorex-platform-common.d.ts +655 -1268
- package/types/acorex-platform-contracts.d.ts +1791 -260
- package/types/acorex-platform-core.d.ts +2302 -2800
- package/types/acorex-platform-domain-contracts.d.ts +416 -0
- package/types/acorex-platform-domain.d.ts +4 -415
- package/types/acorex-platform-layout-builder.d.ts +11 -20
- package/types/acorex-platform-layout-components.d.ts +29 -5
- package/types/acorex-platform-layout-designer.d.ts +2 -1
- package/types/acorex-platform-layout-entity-contracts.d.ts +889 -0
- package/types/acorex-platform-layout-entity.d.ts +143 -275
- package/types/acorex-platform-layout-views.d.ts +147 -31
- package/types/acorex-platform-layout-widget-core.d.ts +74 -14
- package/types/acorex-platform-layout-widgets.d.ts +136 -38
- package/types/acorex-platform-runtime.d.ts +1 -1
- package/types/acorex-platform-themes-default.d.ts +227 -73
- package/types/acorex-platform-themes-shared.d.ts +4 -0
- package/types/acorex-platform-workflow.d.ts +5 -18
- package/fesm2022/acorex-platform-common-common-settings.provider-Ytey9uhY.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs +0 -116
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs.map +0 -1
- package/fesm2022/acorex-platform-native.mjs +0 -155
- package/fesm2022/acorex-platform-native.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs.map +0 -1
- package/native/README.md +0 -4
- package/types/acorex-platform-native.d.ts +0 -28
|
@@ -1,42 +1,47 @@
|
|
|
1
|
+
import { mergeForeignKeyFieldIntoCreateActions, collectNestedCreateHiddenProperties, normalizeEntityDisplayTemplate, sanitizeResolvedEntityDisplayTitle, isUnresolvedEntityDisplayTemplate, AXPEntityDataSourceKeys, AXPEntityEventsKeys, collectEntityListSortableFields, collectEntityListFilterDefinitions, parseDottedFieldPath, ENTITY_ROW_POPUP_TITLE_OPTION, buildEntitySearchTitleContext } from '@acorex/platform/layout/entity-contracts';
|
|
2
|
+
export * from '@acorex/platform/layout/entity-contracts';
|
|
3
|
+
export { collectNestedCreateHiddenProperties, entityDetailsCreateActions, entityDetailsCreateActionsDeferredParent, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, mergeForeignKeyFieldIntoCreateActions } from '@acorex/platform/layout/entity-contracts';
|
|
1
4
|
import { AXToastService } from '@acorex/components/toast';
|
|
2
5
|
import * as i3$1 from '@acorex/core/translation';
|
|
3
|
-
import { AXTranslationService,
|
|
6
|
+
import { AXTranslationService, resolveMultiLanguageString, AXTranslationModule, translateSync } from '@acorex/core/translation';
|
|
4
7
|
import * as i4$2 from '@acorex/platform/common';
|
|
5
|
-
import { AXPNotFoundError, AXPEntityCommandScope, axpNavigateAppPath, AXPSettingsService, AXPCommonSettings,
|
|
8
|
+
import { AXPNotFoundError, AXPEntityCommandScope, axpNavigateAppPath, AXPSettingsService, AXPCommonSettings, resolveEntityCreateListBehavior, AXPRefreshEvent, resolveEntityModifyPopupTitle, resolveSearchableText, evaluateEntityDisplayTemplate, AXPFilterOperatorMiddlewareService, isCardFieldBadgeDisplay, resolveCardFieldBadgeColor, getEntityInfo, resolveEnabledMasterListLayouts, resolveDefaultMasterListLayout, AXPReloadEvent, axpRedirectToNotFound, AXP_ENTITY_DELETED_WORKFLOW_EVENT_TYPE, AXPCleanNestedFilters, AXPFileTypeProviderService, AXPFileStorageService, resolveEntityRowDisplayTitle, AXPFileActionsService, axpIsEntityRecordNotFound, AXPDefaultMultiLanguageConfigService, withDefaultMultiLanguageOnWidgetNodeTree, AXPEntityQueryType, AXPWorkflowNavigateAction, AXP_NOT_FOUND_ROUTE, AXP_PROTECTED_ROUTE_GUARDS, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER, AXP_SEARCH_DEFINITION_LAZY_RESOLVER, AXPMenuItemsDataSourceDefinition } from '@acorex/platform/common';
|
|
9
|
+
import * as i1$3 from '@acorex/platform/workflow';
|
|
10
|
+
import { AXPWorkflowEventService, AXPWorkflowService, ofType, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowModule } from '@acorex/platform/workflow';
|
|
6
11
|
import * as i0 from '@angular/core';
|
|
7
|
-
import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, ChangeDetectorRef, input, signal, computed, ChangeDetectionStrategy, Component, ElementRef, NgModule, viewChild,
|
|
12
|
+
import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, ChangeDetectorRef, input, signal, computed, effect, ChangeDetectionStrategy, Component, ElementRef, NgModule, viewChild, Input, afterNextRender, untracked, ViewEncapsulation, viewChildren, linkedSignal, HostBinding, output, EnvironmentInjector, makeEnvironmentProviders } from '@angular/core';
|
|
13
|
+
import { cloneDeep, merge, get, castArray, set, orderBy, isNil, isEmpty, isEqual as isEqual$1, isObjectLike, isArray, has, isString } from 'lodash-es';
|
|
8
14
|
import { Subject, filter, takeUntil } from 'rxjs';
|
|
9
15
|
import { AXPLayoutBuilderService, LayoutBuilderModule } from '@acorex/platform/layout/builder';
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
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';
|
|
16
|
+
import { AXPWidgetsCatalog, AXPPlatformScope, AXPDataGenerator, AXPSystemActionType } from '@acorex/platform/contracts';
|
|
17
|
+
import { AXPDeviceService, AXPExpressionEvaluatorService, AXPContextEvalFactory, AXPBroadcastEventService, applyFilterArray, applySortArray, resolveActionLook, AXPDistributedEventListenerService, AXHighlightService, extractValue, setSmart, getChangedPaths, AXPContextStore, isSelectionValueEqual, AXPDebugService, FORM_DIRTY_TRACE_NS, objectKeyValueTransforms, setupPopupFooterKeyboardShortcuts, AXPHookService, AXPComponentSlotModule, AXPColumnWidthService, AXPModuleManifestRegistry, defaultColumnWidthProvider, AXP_COLUMN_WIDTH_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPModuleManifestsDataSourceDefinition } from '@acorex/platform/core';
|
|
14
18
|
import { transform, isEqual } from 'lodash';
|
|
15
19
|
import { AXPSessionService, AXPPermissionDefinitionsDataSourceDefinition } from '@acorex/platform/auth';
|
|
16
20
|
import { Router, NavigationStart, ActivatedRoute, RouterModule, ROUTES } from '@angular/router';
|
|
17
21
|
import { defineCommand, AXP_COMMAND_DEFINITION_CATEGORY_ENTITY, AXPCommandService, AXPQueryService, AXPQueryExecutor, AXPCommandExecutor, provideCommandSetups, provideQuerySetups, AXPCommandRegistry, AXPQueryRegistry } from '@acorex/platform/runtime';
|
|
22
|
+
import { AXFormatService } from '@acorex/core/format';
|
|
18
23
|
import * as i1 from '@acorex/components/button';
|
|
19
24
|
import { AXButtonModule } from '@acorex/components/button';
|
|
20
25
|
import * as i3 from '@acorex/components/skeleton';
|
|
21
26
|
import { AXSkeletonModule } from '@acorex/components/skeleton';
|
|
22
|
-
import
|
|
27
|
+
import * as i2 from '@acorex/platform/layout/widget-core';
|
|
28
|
+
import { 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';
|
|
23
29
|
import * as i5 from '@angular/common';
|
|
24
30
|
import { CommonModule, DOCUMENT, AsyncPipe, NgClass } from '@angular/common';
|
|
25
31
|
import { AXOverlayService } from '@acorex/cdk/overlay';
|
|
26
32
|
import { AXLocaleService } from '@acorex/core/locale';
|
|
27
33
|
import { AXPlatform } from '@acorex/core/platform';
|
|
28
34
|
import { AXPThemeLayoutBlockComponent, AXPPreloadFiltersComponent, AXP_PAGE_COMPONENT_PROVIDER, AXPStateMessageComponent, AXPColumnItemListComponent, AXPDataSelectorService, AXPPageComponentRegistryService } from '@acorex/platform/layout/components';
|
|
29
|
-
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageComponentRendererDirective, AXPPageComponentInstanceRegistryService, axpDetailsViewCanDeactivateGuard } from '@acorex/platform/layout/views';
|
|
35
|
+
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageComponentRendererDirective, AXPPageComponentInstanceRegistryService, AXP_LAYOUT_DETAILS_VIEW_ADAPTER_LOADER, axpDetailsViewCanDeactivateGuard } from '@acorex/platform/layout/views';
|
|
30
36
|
import { AXDataSource } from '@acorex/cdk/common';
|
|
31
37
|
import { AXP_ENTITY_CRUD_SETUP } from '@acorex/platform/domain';
|
|
32
38
|
export { AXP_ENTITY_DEFINITION_CRUD_SERVICE } from '@acorex/platform/domain';
|
|
33
|
-
import * as i1$3 from '@acorex/platform/workflow';
|
|
34
|
-
import { AXPWorkflowService, ofType, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowEventService, AXPWorkflowModule } from '@acorex/platform/workflow';
|
|
35
39
|
import { AXPLayoutThemeService } from '@acorex/platform/themes/shared';
|
|
36
40
|
import { moveItemInArray } from '@angular/cdk/drag-drop';
|
|
37
41
|
import { AXDialogService } from '@acorex/components/dialog';
|
|
38
42
|
import { AXLoadingDialogService } from '@acorex/components/loading-dialog';
|
|
39
43
|
import { AXPopupService } from '@acorex/components/popup';
|
|
44
|
+
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
45
|
import * as i2$1 from '@acorex/components/badge';
|
|
41
46
|
import { AXBadgeModule } from '@acorex/components/badge';
|
|
42
47
|
import { AXCheckBoxModule } from '@acorex/components/check-box';
|
|
@@ -57,7 +62,6 @@ import { AXLoadingModule } from '@acorex/components/loading';
|
|
|
57
62
|
import * as i6 from '@acorex/components/tag-box';
|
|
58
63
|
import { AXTagBoxModule } from '@acorex/components/tag-box';
|
|
59
64
|
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
65
|
import * as i2$2 from '@acorex/components/select-box';
|
|
62
66
|
import { AXSelectBoxModule } from '@acorex/components/select-box';
|
|
63
67
|
import * as i3$4 from '@acorex/components/dropdown';
|
|
@@ -854,276 +858,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
854
858
|
}]
|
|
855
859
|
}] });
|
|
856
860
|
|
|
857
|
-
// #region Master
|
|
858
|
-
function entityMasterCreateAction() {
|
|
859
|
-
return {
|
|
860
|
-
title: '@general:actions.create.title',
|
|
861
|
-
command: {
|
|
862
|
-
name: 'Entity:Create',
|
|
863
|
-
},
|
|
864
|
-
priority: 'primary',
|
|
865
|
-
type: AXPSystemActionType.Create,
|
|
866
|
-
scope: AXPEntityCommandScope.TypeLevel,
|
|
867
|
-
};
|
|
868
|
-
}
|
|
869
|
-
function entityMasterEditAction() {
|
|
870
|
-
return {
|
|
871
|
-
title: '@general:actions.edit.title',
|
|
872
|
-
command: 'Entity:Update',
|
|
873
|
-
priority: 'secondary',
|
|
874
|
-
type: AXPSystemActionType.Update,
|
|
875
|
-
scope: AXPEntityCommandScope.Individual,
|
|
876
|
-
default: true,
|
|
877
|
-
};
|
|
878
|
-
}
|
|
879
|
-
function entityMasterBulkDeleteAction() {
|
|
880
|
-
return {
|
|
881
|
-
title: '@general:actions.delete-items.title',
|
|
882
|
-
command: 'delete-entity',
|
|
883
|
-
priority: 'primary',
|
|
884
|
-
type: AXPSystemActionType.Delete,
|
|
885
|
-
scope: AXPEntityCommandScope.Selected,
|
|
886
|
-
order: 100,
|
|
887
|
-
};
|
|
888
|
-
}
|
|
889
|
-
function entityMasterViewAction() {
|
|
890
|
-
return {
|
|
891
|
-
title: '@general:actions.view.title',
|
|
892
|
-
command: 'open-entity',
|
|
893
|
-
priority: 'secondary',
|
|
894
|
-
type: AXPSystemActionType.View,
|
|
895
|
-
scope: AXPEntityCommandScope.Individual,
|
|
896
|
-
default: true,
|
|
897
|
-
};
|
|
898
|
-
}
|
|
899
|
-
function entityMasterDeleteAction() {
|
|
900
|
-
return {
|
|
901
|
-
title: '@general:actions.delete.title',
|
|
902
|
-
command: 'delete-entity',
|
|
903
|
-
priority: 'secondary',
|
|
904
|
-
type: AXPSystemActionType.Delete,
|
|
905
|
-
scope: AXPEntityCommandScope.Individual,
|
|
906
|
-
order: 100,
|
|
907
|
-
shortcuts: ['ctrl+shift+delete'],
|
|
908
|
-
};
|
|
909
|
-
}
|
|
910
|
-
function entityMasterCrudActions(options) {
|
|
911
|
-
const opts = {
|
|
912
|
-
create: true,
|
|
913
|
-
delete: true,
|
|
914
|
-
view: true,
|
|
915
|
-
edit: false,
|
|
916
|
-
...options,
|
|
917
|
-
};
|
|
918
|
-
const actions = [];
|
|
919
|
-
if (opts.create) {
|
|
920
|
-
actions.push(entityMasterCreateAction());
|
|
921
|
-
}
|
|
922
|
-
if (opts.delete) {
|
|
923
|
-
actions.push(entityMasterBulkDeleteAction());
|
|
924
|
-
actions.push(entityMasterDeleteAction());
|
|
925
|
-
}
|
|
926
|
-
if (opts.view) {
|
|
927
|
-
actions.push(entityMasterViewAction());
|
|
928
|
-
}
|
|
929
|
-
if (opts.edit) {
|
|
930
|
-
actions.push(entityMasterEditAction());
|
|
931
|
-
}
|
|
932
|
-
return actions;
|
|
933
|
-
}
|
|
934
|
-
function entityMasterRecordActions() {
|
|
935
|
-
return [entityMasterDeleteAction()];
|
|
936
|
-
}
|
|
937
|
-
// #endregion
|
|
938
|
-
// #region Details
|
|
939
|
-
function entityDetailsCreateActions(parentId) {
|
|
940
|
-
return {
|
|
941
|
-
title: '@general:actions.create.title',
|
|
942
|
-
command: {
|
|
943
|
-
name: 'Entity:Create',
|
|
944
|
-
options: {
|
|
945
|
-
process: {
|
|
946
|
-
redirect: false,
|
|
947
|
-
canCreateNewOne: true,
|
|
948
|
-
data: {
|
|
949
|
-
[parentId]: '{{context.eval("id")}}',
|
|
950
|
-
},
|
|
951
|
-
},
|
|
952
|
-
},
|
|
953
|
-
},
|
|
954
|
-
priority: 'primary',
|
|
955
|
-
type: AXPSystemActionType.Create,
|
|
956
|
-
scope: AXPEntityCommandScope.TypeLevel,
|
|
957
|
-
};
|
|
958
|
-
}
|
|
959
|
-
/**
|
|
960
|
-
* Type-level Create with empty `process.data`; the FK is supplied from `relatedEntity.persistence.foreignKeyField`
|
|
961
|
-
* when the related list is built (see `mergeForeignKeyFieldIntoCreateActions`).
|
|
962
|
-
*/
|
|
963
|
-
function entityDetailsCreateActionsDeferredParent() {
|
|
964
|
-
return {
|
|
965
|
-
title: '@general:actions.create.title',
|
|
966
|
-
command: {
|
|
967
|
-
name: 'Entity:Create',
|
|
968
|
-
options: {
|
|
969
|
-
process: {
|
|
970
|
-
redirect: false,
|
|
971
|
-
canCreateNewOne: true,
|
|
972
|
-
data: {},
|
|
973
|
-
},
|
|
974
|
-
},
|
|
975
|
-
},
|
|
976
|
-
priority: 'primary',
|
|
977
|
-
type: AXPSystemActionType.Create,
|
|
978
|
-
scope: AXPEntityCommandScope.TypeLevel,
|
|
979
|
-
};
|
|
980
|
-
}
|
|
981
|
-
/**
|
|
982
|
-
* Ensures each type-level `Entity:Create` action includes `process.data[foreignKeyField]` bound to the parent row id.
|
|
983
|
-
*/
|
|
984
|
-
function mergeForeignKeyFieldIntoCreateActions(foreignKeyField, actions) {
|
|
985
|
-
if (!foreignKeyField || !actions?.length) {
|
|
986
|
-
return actions ?? [];
|
|
987
|
-
}
|
|
988
|
-
return actions.map((a) => {
|
|
989
|
-
const cmd = a.command;
|
|
990
|
-
if (typeof cmd !== 'object' ||
|
|
991
|
-
!cmd ||
|
|
992
|
-
cmd.name !== 'Entity:Create' ||
|
|
993
|
-
a.scope !== AXPEntityCommandScope.TypeLevel) {
|
|
994
|
-
return a;
|
|
995
|
-
}
|
|
996
|
-
const opts = (cmd.options ?? {});
|
|
997
|
-
const proc = (opts['process'] ?? {});
|
|
998
|
-
const data = { ...(proc['data'] ?? {}) };
|
|
999
|
-
if (data[foreignKeyField] === undefined || data[foreignKeyField] === null || data[foreignKeyField] === '') {
|
|
1000
|
-
data[foreignKeyField] = '{{ context.eval("id") }}';
|
|
1001
|
-
}
|
|
1002
|
-
return {
|
|
1003
|
-
...a,
|
|
1004
|
-
command: {
|
|
1005
|
-
...cmd,
|
|
1006
|
-
options: { ...opts, process: { ...proc, data } },
|
|
1007
|
-
},
|
|
1008
|
-
};
|
|
1009
|
-
});
|
|
1010
|
-
}
|
|
1011
|
-
/** Property names hidden on nested Create from a related list (`excludeProperties` plus `foreignKeyField` when set). */
|
|
1012
|
-
function collectNestedCreateHiddenProperties(relatedEntity) {
|
|
1013
|
-
const fk = relatedEntity.persistence?.foreignKeyField;
|
|
1014
|
-
const merged = [...(relatedEntity.excludeProperties ?? [])];
|
|
1015
|
-
if (fk) {
|
|
1016
|
-
merged.push(fk);
|
|
1017
|
-
}
|
|
1018
|
-
const unique = [...new Set(merged)];
|
|
1019
|
-
return unique.length ? unique : undefined;
|
|
1020
|
-
}
|
|
1021
|
-
function entityDetailsSimpleCondition(fk) {
|
|
1022
|
-
return {
|
|
1023
|
-
name: fk,
|
|
1024
|
-
operator: { type: 'equal' },
|
|
1025
|
-
value: '{{context.eval("id")}}',
|
|
1026
|
-
};
|
|
1027
|
-
}
|
|
1028
|
-
function entityDetailsReferenceCondition(type) {
|
|
1029
|
-
return [
|
|
1030
|
-
{
|
|
1031
|
-
name: 'reference.id',
|
|
1032
|
-
operator: { type: 'equal' },
|
|
1033
|
-
value: '{{context.eval("id")}}',
|
|
1034
|
-
},
|
|
1035
|
-
{
|
|
1036
|
-
name: 'reference.type',
|
|
1037
|
-
operator: { type: 'equal' },
|
|
1038
|
-
value: type,
|
|
1039
|
-
},
|
|
1040
|
-
];
|
|
1041
|
-
}
|
|
1042
|
-
function entityDetailsEditAction() {
|
|
1043
|
-
return {
|
|
1044
|
-
title: '@general:actions.edit.title',
|
|
1045
|
-
// command: 'quick-modify-entity',
|
|
1046
|
-
command: 'Entity:Update',
|
|
1047
|
-
priority: 'secondary',
|
|
1048
|
-
type: AXPSystemActionType.Update,
|
|
1049
|
-
default: true,
|
|
1050
|
-
scope: AXPEntityCommandScope.Individual,
|
|
1051
|
-
};
|
|
1052
|
-
}
|
|
1053
|
-
function entityDetailsNewEditAction() {
|
|
1054
|
-
return {
|
|
1055
|
-
title: 'New Edit',
|
|
1056
|
-
command: {
|
|
1057
|
-
name: 'Entity:Update',
|
|
1058
|
-
},
|
|
1059
|
-
priority: 'secondary',
|
|
1060
|
-
type: AXPSystemActionType.Update,
|
|
1061
|
-
default: true,
|
|
1062
|
-
scope: AXPEntityCommandScope.Individual,
|
|
1063
|
-
};
|
|
1064
|
-
}
|
|
1065
|
-
function entityOverrideDetailsViewAction() {
|
|
1066
|
-
return {
|
|
1067
|
-
title: '@general:actions.view.title',
|
|
1068
|
-
command: 'open-entity',
|
|
1069
|
-
priority: 'secondary',
|
|
1070
|
-
hidden: true,
|
|
1071
|
-
type: AXPSystemActionType.View,
|
|
1072
|
-
scope: AXPEntityCommandScope.Individual,
|
|
1073
|
-
};
|
|
1074
|
-
}
|
|
1075
|
-
function entityDetailsCrudActions(parentId, options) {
|
|
1076
|
-
const opts = {
|
|
1077
|
-
create: true,
|
|
1078
|
-
delete: true,
|
|
1079
|
-
view: true,
|
|
1080
|
-
edit: true,
|
|
1081
|
-
...options,
|
|
1082
|
-
};
|
|
1083
|
-
const actions = [];
|
|
1084
|
-
if (opts.create) {
|
|
1085
|
-
if (parentId) {
|
|
1086
|
-
actions.push(entityDetailsCreateActions(parentId));
|
|
1087
|
-
}
|
|
1088
|
-
else {
|
|
1089
|
-
actions.push(entityDetailsCreateActionsDeferredParent());
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
if (opts.edit) {
|
|
1093
|
-
actions.push(entityDetailsEditAction());
|
|
1094
|
-
}
|
|
1095
|
-
if (opts.view) {
|
|
1096
|
-
actions.push(entityOverrideDetailsViewAction());
|
|
1097
|
-
}
|
|
1098
|
-
return actions;
|
|
1099
|
-
}
|
|
1100
|
-
function entityDetailsReferenceCreateActions(type) {
|
|
1101
|
-
return [
|
|
1102
|
-
{
|
|
1103
|
-
title: '@general:actions.create.title',
|
|
1104
|
-
command: {
|
|
1105
|
-
name: 'Entity:Create',
|
|
1106
|
-
options: {
|
|
1107
|
-
process: {
|
|
1108
|
-
redirect: false,
|
|
1109
|
-
canCreateNewOne: true,
|
|
1110
|
-
data: {
|
|
1111
|
-
reference: {
|
|
1112
|
-
id: '{{context.eval("id")}}',
|
|
1113
|
-
type: type,
|
|
1114
|
-
},
|
|
1115
|
-
},
|
|
1116
|
-
},
|
|
1117
|
-
},
|
|
1118
|
-
},
|
|
1119
|
-
priority: 'primary',
|
|
1120
|
-
type: AXPSystemActionType.Create,
|
|
1121
|
-
scope: AXPEntityCommandScope.TypeLevel,
|
|
1122
|
-
},
|
|
1123
|
-
entityDetailsEditAction(),
|
|
1124
|
-
entityOverrideDetailsViewAction(),
|
|
1125
|
-
];
|
|
1126
|
-
}
|
|
1127
861
|
/**
|
|
1128
862
|
* Computes a diff between two plain objects with array-aware semantics.
|
|
1129
863
|
* - For arrays of objects with an id field, computes added/removed by id.
|
|
@@ -1481,7 +1215,7 @@ class PropertyFilter {
|
|
|
1481
1215
|
const viewLayout = mainViewLayoutMap.get(prop.name);
|
|
1482
1216
|
const mergedProp = {
|
|
1483
1217
|
...prop,
|
|
1484
|
-
__layout: viewLayout?.layout,
|
|
1218
|
+
__layout: viewLayout?.layout ? cloneDeep(viewLayout.layout) : undefined,
|
|
1485
1219
|
__order: viewLayout?.layout?.order,
|
|
1486
1220
|
};
|
|
1487
1221
|
if (this.readonlyList?.has(prop.name)) {
|
|
@@ -1544,7 +1278,7 @@ class PropertyFilter {
|
|
|
1544
1278
|
const mergedProp = {
|
|
1545
1279
|
...prop,
|
|
1546
1280
|
__dataPath: dataPath,
|
|
1547
|
-
__layout: viewLayout?.layout,
|
|
1281
|
+
__layout: viewLayout?.layout ? cloneDeep(viewLayout.layout) : undefined,
|
|
1548
1282
|
__order: viewLayout?.layout?.order,
|
|
1549
1283
|
};
|
|
1550
1284
|
// Apply generic propertyOverrides extension (e.g. for identifier defaultValue on nested paths)
|
|
@@ -2053,6 +1787,9 @@ const GRID_COLUMNS = 12;
|
|
|
2053
1787
|
function getColSpanAt(layout, breakpoint) {
|
|
2054
1788
|
return layout?.positions?.[breakpoint]?.colSpan ?? GRID_COLUMNS;
|
|
2055
1789
|
}
|
|
1790
|
+
function getColStartAt(layout, breakpoint) {
|
|
1791
|
+
return layout?.positions?.[breakpoint]?.colStart;
|
|
1792
|
+
}
|
|
2056
1793
|
function setColSpanAt(layout, breakpoint, colSpan) {
|
|
2057
1794
|
if (!layout)
|
|
2058
1795
|
return;
|
|
@@ -2077,23 +1814,56 @@ function normalizeLayoutFillRowGaps(items, getLayout, getItemId) {
|
|
|
2077
1814
|
if (items.length === 0)
|
|
2078
1815
|
return scaleFactors;
|
|
2079
1816
|
for (const breakpoint of LAYOUT_BREAKPOINTS) {
|
|
2080
|
-
const colSpans = items.map((item) => getColSpanAt(getLayout(item), breakpoint));
|
|
2081
1817
|
let i = 0;
|
|
2082
|
-
while (i <
|
|
2083
|
-
let rowSum = 0;
|
|
1818
|
+
while (i < items.length) {
|
|
2084
1819
|
const rowStart = i;
|
|
2085
|
-
|
|
2086
|
-
|
|
1820
|
+
let rowHasExplicitColStart = false;
|
|
1821
|
+
let sequentialRowSum = 0;
|
|
1822
|
+
let explicitRowEnd = 0;
|
|
1823
|
+
while (i < items.length) {
|
|
1824
|
+
const layout = getLayout(items[i]);
|
|
1825
|
+
const colStart = getColStartAt(layout, breakpoint);
|
|
1826
|
+
const colSpan = getColSpanAt(layout, breakpoint);
|
|
1827
|
+
// colStart: 1 begins a new row (except for the first item in the current row)
|
|
1828
|
+
if (colStart === 1 && i > rowStart) {
|
|
1829
|
+
break;
|
|
1830
|
+
}
|
|
1831
|
+
if (colStart != null) {
|
|
1832
|
+
rowHasExplicitColStart = true;
|
|
1833
|
+
const end = colStart + colSpan;
|
|
1834
|
+
if (end - 1 > GRID_COLUMNS) {
|
|
1835
|
+
i++;
|
|
1836
|
+
break;
|
|
1837
|
+
}
|
|
1838
|
+
explicitRowEnd = Math.max(explicitRowEnd, end);
|
|
1839
|
+
i++;
|
|
1840
|
+
if (explicitRowEnd >= GRID_COLUMNS) {
|
|
1841
|
+
break;
|
|
1842
|
+
}
|
|
1843
|
+
continue;
|
|
1844
|
+
}
|
|
1845
|
+
if (sequentialRowSum + colSpan > GRID_COLUMNS && i > rowStart) {
|
|
1846
|
+
break;
|
|
1847
|
+
}
|
|
1848
|
+
if (sequentialRowSum + colSpan > GRID_COLUMNS && i === rowStart) {
|
|
1849
|
+
sequentialRowSum = colSpan;
|
|
1850
|
+
i++;
|
|
1851
|
+
break;
|
|
1852
|
+
}
|
|
1853
|
+
sequentialRowSum += colSpan;
|
|
2087
1854
|
i++;
|
|
1855
|
+
if (sequentialRowSum >= GRID_COLUMNS) {
|
|
1856
|
+
break;
|
|
1857
|
+
}
|
|
2088
1858
|
}
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
1859
|
+
// Rows with explicit colStart (e.g. 4+4+4 at columns 1/5/9) keep intentional gaps
|
|
1860
|
+
if (rowHasExplicitColStart) {
|
|
1861
|
+
continue;
|
|
2092
1862
|
}
|
|
2093
|
-
if (
|
|
1863
|
+
if (sequentialRowSum < GRID_COLUMNS && sequentialRowSum > 0 && i > rowStart) {
|
|
2094
1864
|
const lastIdx = i - 1;
|
|
2095
|
-
const oldColSpan =
|
|
2096
|
-
const fill = GRID_COLUMNS -
|
|
1865
|
+
const oldColSpan = getColSpanAt(getLayout(items[lastIdx]), breakpoint);
|
|
1866
|
+
const fill = GRID_COLUMNS - sequentialRowSum;
|
|
2097
1867
|
const newColSpan = Math.min(GRID_COLUMNS, oldColSpan + fill);
|
|
2098
1868
|
const layout = getLayout(items[lastIdx]);
|
|
2099
1869
|
if (layout) {
|
|
@@ -2532,6 +2302,7 @@ class AXPCreateEntityCommand {
|
|
|
2532
2302
|
this.translationService = inject(AXTranslationService);
|
|
2533
2303
|
this.settingsService = inject(AXPSettingsService);
|
|
2534
2304
|
this.openEntityDetailsCommand = inject(AXPOpenEntityDetailsCommand);
|
|
2305
|
+
this.workflowEventService = inject(AXPWorkflowEventService);
|
|
2535
2306
|
this.context = {};
|
|
2536
2307
|
}
|
|
2537
2308
|
async execute(input) {
|
|
@@ -2588,8 +2359,7 @@ class AXPCreateEntityCommand {
|
|
|
2588
2359
|
}
|
|
2589
2360
|
const createFn = entityRef.commands?.create?.execute;
|
|
2590
2361
|
const updateFn = entityRef.commands?.update?.execute;
|
|
2591
|
-
const context = dialogRef.context();
|
|
2592
|
-
console.log('context', context);
|
|
2362
|
+
const context = merge({}, data, dialogRef.context());
|
|
2593
2363
|
const hasPersistedId = hasPersistedRootId(context);
|
|
2594
2364
|
const persistFn = hasPersistedId ? updateFn : createFn;
|
|
2595
2365
|
const missingPersistHandlerMsg = hasPersistedId
|
|
@@ -2647,13 +2417,24 @@ class AXPCreateEntityCommand {
|
|
|
2647
2417
|
.show();
|
|
2648
2418
|
const commandResult = result;
|
|
2649
2419
|
const redirectOption = options?.process?.redirect;
|
|
2650
|
-
const shouldRedirect =
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
if (commandResult.success &&
|
|
2420
|
+
const { shouldRedirect, shouldHighlight } = await resolveEntityCreateListBehavior(this.settingsService, {
|
|
2421
|
+
redirect: redirectOption,
|
|
2422
|
+
});
|
|
2423
|
+
if (commandResult.success && commandResult.data) {
|
|
2654
2424
|
const createdItem = commandResult.data?.item ?? commandResult.data;
|
|
2655
|
-
const createdId = createdItem?.id;
|
|
2656
|
-
|
|
2425
|
+
const createdId = createdItem?.id ?? createdItem?._id;
|
|
2426
|
+
const refreshMeta = { resetPagination: true };
|
|
2427
|
+
if (createdId != null && shouldHighlight) {
|
|
2428
|
+
refreshMeta['highlightRowId'] = createdId;
|
|
2429
|
+
}
|
|
2430
|
+
if (entityRef.parentKey && createdItem?.[entityRef.parentKey]) {
|
|
2431
|
+
refreshMeta['refreshTargetId'] = createdItem[entityRef.parentKey];
|
|
2432
|
+
}
|
|
2433
|
+
this.workflowEventService.dispatch(AXPRefreshEvent({
|
|
2434
|
+
entity: `${moduleName}.${entityName}`,
|
|
2435
|
+
meta: refreshMeta,
|
|
2436
|
+
}));
|
|
2437
|
+
if (shouldRedirect && createdId != null) {
|
|
2657
2438
|
await this.openEntityDetailsCommand.execute({
|
|
2658
2439
|
entity: `${moduleName}.${entityName}`,
|
|
2659
2440
|
data: { id: String(createdId) },
|
|
@@ -2744,6 +2525,9 @@ class AXPUpdateEntityCommand {
|
|
|
2744
2525
|
this.entityService = inject(AXPEntityDefinitionRegistryService);
|
|
2745
2526
|
this.toastService = inject(AXToastService);
|
|
2746
2527
|
this.translationService = inject(AXTranslationService);
|
|
2528
|
+
this.formatService = inject(AXFormatService);
|
|
2529
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
2530
|
+
this.contextEvalFactory = inject(AXPContextEvalFactory);
|
|
2747
2531
|
this.eventService = inject(AXPBroadcastEventService);
|
|
2748
2532
|
}
|
|
2749
2533
|
//#endregion
|
|
@@ -2751,7 +2535,7 @@ class AXPUpdateEntityCommand {
|
|
|
2751
2535
|
async execute(input) {
|
|
2752
2536
|
const enableOperationToasts = await this.settingsService.get(AXPCommonSettings.EnableOperationToasts);
|
|
2753
2537
|
const dialogSize = input['dialogSize'];
|
|
2754
|
-
const { entity,
|
|
2538
|
+
const { entity, data, options } = input.__context__;
|
|
2755
2539
|
const excludeProperties = options?.excludeProperties;
|
|
2756
2540
|
const includeProperties = options?.includeProperties;
|
|
2757
2541
|
const decoration = options?.['decoration'];
|
|
@@ -2790,10 +2574,17 @@ class AXPUpdateEntityCommand {
|
|
|
2790
2574
|
if (headerTitle) {
|
|
2791
2575
|
chain = chain.title(headerTitle);
|
|
2792
2576
|
}
|
|
2793
|
-
else
|
|
2794
|
-
|
|
2795
|
-
const
|
|
2796
|
-
|
|
2577
|
+
else {
|
|
2578
|
+
let recordData = {};
|
|
2579
|
+
const recordId = typeof data === 'string' ? data : (data?.id ?? data?._id);
|
|
2580
|
+
if (recordId) {
|
|
2581
|
+
recordData = await this.entityForm.getRecordById(`${moduleName}.${entityName}`, String(recordId));
|
|
2582
|
+
}
|
|
2583
|
+
else if (typeof data === 'object' && data != null) {
|
|
2584
|
+
recordData = data;
|
|
2585
|
+
}
|
|
2586
|
+
const title = await resolveEntityModifyPopupTitle(entityRef, recordData, this.translationService, this.formatService, this.expressionEvaluator, this.contextEvalFactory, '@general:actions.edit.title');
|
|
2587
|
+
chain = chain.title(title);
|
|
2797
2588
|
}
|
|
2798
2589
|
const finalSize = layoutSize || dialogSize;
|
|
2799
2590
|
if (finalSize) {
|
|
@@ -2887,15 +2678,19 @@ var updateEntity_command = /*#__PURE__*/Object.freeze({
|
|
|
2887
2678
|
|
|
2888
2679
|
class AXPViewEntityDetailsCommand {
|
|
2889
2680
|
constructor() {
|
|
2890
|
-
//#region ----
|
|
2681
|
+
//#region ---- Services & Dependencies ----
|
|
2891
2682
|
this.entityForm = inject(AXPEntityFormBuilderService);
|
|
2892
2683
|
this.entityService = inject(AXPEntityDefinitionRegistryService);
|
|
2893
2684
|
this.translationService = inject(AXTranslationService);
|
|
2685
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
2686
|
+
this.contextEvalFactory = inject(AXPContextEvalFactory);
|
|
2894
2687
|
}
|
|
2895
2688
|
//#endregion
|
|
2896
|
-
//#region ----
|
|
2689
|
+
//#region ---- Command Execution ----
|
|
2897
2690
|
async execute(input) {
|
|
2898
|
-
const excludeProperties = input['excludeProperties']
|
|
2691
|
+
const excludeProperties = input['excludeProperties'] ??
|
|
2692
|
+
input?.options?.excludeProperties ??
|
|
2693
|
+
input?.__context__?.options?.excludeProperties;
|
|
2899
2694
|
const { entity, entityInfo, data } = input.__context__;
|
|
2900
2695
|
const [moduleName, entityName] = (entity || '').split('.');
|
|
2901
2696
|
if (!moduleName || !entityName) {
|
|
@@ -2906,10 +2701,9 @@ class AXPViewEntityDetailsCommand {
|
|
|
2906
2701
|
},
|
|
2907
2702
|
};
|
|
2908
2703
|
}
|
|
2909
|
-
await this.entityService.resolve(moduleName, entityName);
|
|
2704
|
+
const entityDef = await this.entityService.resolve(moduleName, entityName);
|
|
2910
2705
|
let dialogRef;
|
|
2911
2706
|
try {
|
|
2912
|
-
// Validate data type
|
|
2913
2707
|
if (!data || (typeof data !== 'string' && typeof data !== 'object')) {
|
|
2914
2708
|
return {
|
|
2915
2709
|
success: false,
|
|
@@ -2918,22 +2712,18 @@ class AXPViewEntityDetailsCommand {
|
|
|
2918
2712
|
},
|
|
2919
2713
|
};
|
|
2920
2714
|
}
|
|
2921
|
-
// Pass data directly to single() - it handles string | object internally
|
|
2922
2715
|
let chain = this.entityForm.entity(`${moduleName}.${entityName}`).single(data);
|
|
2923
2716
|
if (excludeProperties && excludeProperties.length > 0) {
|
|
2924
2717
|
chain = chain.exclude(...excludeProperties);
|
|
2925
2718
|
}
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
chain = chain.title(`${detailText}`);
|
|
2719
|
+
const dialogTitle = await this.resolveDialogTitle(entityDef, data);
|
|
2720
|
+
if (dialogTitle) {
|
|
2721
|
+
chain = chain.title(dialogTitle);
|
|
2930
2722
|
}
|
|
2931
2723
|
chain = chain.actions((actions) => {
|
|
2932
2724
|
actions.submit('@general:actions.ok.title');
|
|
2933
2725
|
});
|
|
2934
2726
|
dialogRef = await chain.show();
|
|
2935
|
-
// For single/view mode, only close action is available
|
|
2936
|
-
// No need to show any message when closing a read-only view
|
|
2937
2727
|
dialogRef.close();
|
|
2938
2728
|
return {
|
|
2939
2729
|
success: true,
|
|
@@ -2953,11 +2743,62 @@ class AXPViewEntityDetailsCommand {
|
|
|
2953
2743
|
};
|
|
2954
2744
|
}
|
|
2955
2745
|
finally {
|
|
2956
|
-
if (dialogRef) {
|
|
2746
|
+
if (dialogRef && typeof dialogRef === 'object' && dialogRef !== null && 'setLoading' in dialogRef) {
|
|
2957
2747
|
dialogRef.setLoading(false);
|
|
2958
2748
|
}
|
|
2959
2749
|
}
|
|
2960
2750
|
}
|
|
2751
|
+
//#endregion
|
|
2752
|
+
//#region ---- Title resolution ----
|
|
2753
|
+
async resolveDialogTitle(entityDef, data) {
|
|
2754
|
+
const titleTemplate = entityDef.interfaces?.master?.single?.title ??
|
|
2755
|
+
entityDef.formats?.searchResult?.title ??
|
|
2756
|
+
entityDef.formats?.individual;
|
|
2757
|
+
if (!titleTemplate || typeof titleTemplate !== 'string') {
|
|
2758
|
+
return this.translationService.translateAsync('@general:actions.detail.title');
|
|
2759
|
+
}
|
|
2760
|
+
if (!titleTemplate.includes('{{')) {
|
|
2761
|
+
const translated = await this.translationService.translateAsync(titleTemplate);
|
|
2762
|
+
return resolveMultiLanguageString(translated, this.translationService.getActiveLang()).trim() || translated;
|
|
2763
|
+
}
|
|
2764
|
+
const recordContext = await this.loadRecordContext(`${entityDef.module}.${entityDef.name}`, data);
|
|
2765
|
+
const scope = {
|
|
2766
|
+
context: this.contextEvalFactory.createScope(recordContext),
|
|
2767
|
+
};
|
|
2768
|
+
const evaluated = await this.expressionEvaluator.evaluate(titleTemplate, scope);
|
|
2769
|
+
const locale = this.translationService.getActiveLang();
|
|
2770
|
+
const text = resolveMultiLanguageString(evaluated, locale).trim() || String(evaluated ?? '').trim();
|
|
2771
|
+
if (text) {
|
|
2772
|
+
return text;
|
|
2773
|
+
}
|
|
2774
|
+
return this.translationService.translateAsync('@general:actions.detail.title');
|
|
2775
|
+
}
|
|
2776
|
+
async loadRecordContext(entityFullName, data) {
|
|
2777
|
+
if (typeof data === 'object' && data !== null && !Array.isArray(data)) {
|
|
2778
|
+
const hasNestedFields = get(data, 'subject.title') != null ||
|
|
2779
|
+
get(data, 'recordType.title') != null ||
|
|
2780
|
+
get(data, 'occurredDate') != null;
|
|
2781
|
+
if (hasNestedFields) {
|
|
2782
|
+
return data;
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
const recordId = typeof data === 'string' ? data : String(get(data, 'id') ?? '');
|
|
2786
|
+
if (!recordId) {
|
|
2787
|
+
return typeof data === 'object' && data !== null ? data : {};
|
|
2788
|
+
}
|
|
2789
|
+
try {
|
|
2790
|
+
const [moduleName, entityName] = entityFullName.split('.');
|
|
2791
|
+
const entity = await this.entityService.resolve(moduleName, entityName);
|
|
2792
|
+
const byKeyFn = entity?.queries?.byKey?.execute;
|
|
2793
|
+
if (typeof byKeyFn === 'function') {
|
|
2794
|
+
return (await byKeyFn(recordId)) ?? {};
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
catch {
|
|
2798
|
+
// Fall back to list row payload below.
|
|
2799
|
+
}
|
|
2800
|
+
return typeof data === 'object' && data !== null ? data : {};
|
|
2801
|
+
}
|
|
2961
2802
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPViewEntityDetailsCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2962
2803
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPViewEntityDetailsCommand, providedIn: 'root' }); }
|
|
2963
2804
|
}
|
|
@@ -2973,55 +2814,39 @@ var viewEntityDetails_command = /*#__PURE__*/Object.freeze({
|
|
|
2973
2814
|
AXPViewEntityDetailsCommand: AXPViewEntityDetailsCommand
|
|
2974
2815
|
});
|
|
2975
2816
|
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
const AXP_RECORD_WORKFLOW_INFO_CORRELATION_ID_FIELD = 'workflowInfo.correlationId';
|
|
2994
|
-
/** Entity query filter field for {@link AXPRecordWorkflowInfo.definitionId}. */
|
|
2995
|
-
const AXP_RECORD_WORKFLOW_INFO_DEFINITION_ID_FIELD = 'workflowInfo.definitionId';
|
|
2996
|
-
/** Returns a trimmed workflow instance id from a record, if present. */
|
|
2997
|
-
function getRecordWorkflowInstanceId(record) {
|
|
2998
|
-
const id = record?.workflowInfo?.instanceId?.trim();
|
|
2999
|
-
return id && id.length > 0 ? id : null;
|
|
3000
|
-
}
|
|
3001
|
-
/** Returns a trimmed workflow correlation id from a record, if present. */
|
|
3002
|
-
function getRecordWorkflowCorrelationId(record) {
|
|
3003
|
-
const id = record?.workflowInfo?.correlationId?.trim();
|
|
3004
|
-
return id && id.length > 0 ? id : null;
|
|
2817
|
+
/** Common keys on denormalized expose stubs (e.g. `{ id, displayName }` from lookup expose). */
|
|
2818
|
+
const LOOKUP_EXPOSE_STUB_DISPLAY_FIELDS = ['displayName', 'title', 'name', 'fullName', 'code'];
|
|
2819
|
+
function resolveLookupItemFieldValue(item, field) {
|
|
2820
|
+
const direct = get(item, field);
|
|
2821
|
+
if (direct != null && direct !== '') {
|
|
2822
|
+
return direct;
|
|
2823
|
+
}
|
|
2824
|
+
if (!field.includes('.')) {
|
|
2825
|
+
return direct;
|
|
2826
|
+
}
|
|
2827
|
+
for (const fallback of LOOKUP_EXPOSE_STUB_DISPLAY_FIELDS) {
|
|
2828
|
+
const candidate = get(item, fallback);
|
|
2829
|
+
if (candidate != null && candidate !== '') {
|
|
2830
|
+
return candidate;
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
return direct;
|
|
3005
2834
|
}
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
if (!instanceId) {
|
|
3010
|
-
return {};
|
|
2835
|
+
function formatLookupFieldValue(raw, locale, translationService, resolveMultiLanguage) {
|
|
2836
|
+
if (raw == null || raw === '') {
|
|
2837
|
+
return '';
|
|
3011
2838
|
}
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
2839
|
+
if (typeof raw === 'string' || typeof raw === 'number' || typeof raw === 'boolean') {
|
|
2840
|
+
return String(raw);
|
|
2841
|
+
}
|
|
2842
|
+
if (typeof raw === 'object' && !Array.isArray(raw)) {
|
|
2843
|
+
if (resolveMultiLanguage) {
|
|
2844
|
+
return resolveMultiLanguage(raw);
|
|
2845
|
+
}
|
|
2846
|
+
return resolveSearchableText(raw, locale, translationService);
|
|
2847
|
+
}
|
|
2848
|
+
return String(raw);
|
|
3020
2849
|
}
|
|
3021
|
-
|
|
3022
|
-
//#region ---- Contracts barrel ----
|
|
3023
|
-
//#endregion
|
|
3024
|
-
|
|
3025
2850
|
//#region ---- Template resolution ----
|
|
3026
2851
|
/**
|
|
3027
2852
|
* Resolves the display template for a lookup item.
|
|
@@ -3063,9 +2888,9 @@ function resolveLookupDisplayField(entity, options) {
|
|
|
3063
2888
|
return found ?? 'title';
|
|
3064
2889
|
}
|
|
3065
2890
|
/**
|
|
3066
|
-
* Formats a lookup row for display using template and/or field resolution.
|
|
2891
|
+
* Formats a lookup row for display using template and/or field resolution (display tier).
|
|
3067
2892
|
*/
|
|
3068
|
-
function
|
|
2893
|
+
async function formatLookupItemDisplayAsync(item, entity, options, formatService, displayDeps, resolveMultiLanguage) {
|
|
3069
2894
|
if (item == null) {
|
|
3070
2895
|
return '';
|
|
3071
2896
|
}
|
|
@@ -3080,6 +2905,45 @@ function formatLookupItemDisplay(item, entity, options, formatService, resolveMu
|
|
|
3080
2905
|
}
|
|
3081
2906
|
const template = resolveLookupDisplayTemplate(entity, options);
|
|
3082
2907
|
if (template) {
|
|
2908
|
+
if (template.includes('{{') || template.includes('context.eval')) {
|
|
2909
|
+
const evaluated = await evaluateEntityDisplayTemplate(template, item, displayDeps.expressionEvaluator, displayDeps.locale, displayDeps.translationService, displayDeps.contextEvalFactory);
|
|
2910
|
+
const text = sanitizeResolvedEntityDisplayTitle(resolveSearchableText(evaluated, displayDeps.locale, displayDeps.translationService));
|
|
2911
|
+
if (text && !isUnresolvedEntityDisplayTemplate(text)) {
|
|
2912
|
+
return text;
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
else {
|
|
2916
|
+
const formatted = formatService.format(template, 'string', item);
|
|
2917
|
+
if (formatted) {
|
|
2918
|
+
const text = String(formatted);
|
|
2919
|
+
if (!isUnresolvedEntityDisplayTemplate(text)) {
|
|
2920
|
+
return text;
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
const field = resolveLookupDisplayField(entity, options);
|
|
2926
|
+
const raw = typeof item === 'object' && item != null ? resolveLookupItemFieldValue(item, field) : undefined;
|
|
2927
|
+
return formatLookupFieldValue(raw, displayDeps.locale, displayDeps.translationService, resolveMultiLanguage);
|
|
2928
|
+
}
|
|
2929
|
+
/**
|
|
2930
|
+
* @deprecated Prefer {@link formatLookupItemDisplayAsync} for expression templates with `context.eval`.
|
|
2931
|
+
*/
|
|
2932
|
+
function formatLookupItemDisplay(item, entity, options, formatService, resolveMultiLanguage) {
|
|
2933
|
+
if (item == null) {
|
|
2934
|
+
return '';
|
|
2935
|
+
}
|
|
2936
|
+
if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
|
|
2937
|
+
return String(item);
|
|
2938
|
+
}
|
|
2939
|
+
if (typeof item !== 'object') {
|
|
2940
|
+
return '';
|
|
2941
|
+
}
|
|
2942
|
+
if (options.isMultiLanguage?.(item) && resolveMultiLanguage) {
|
|
2943
|
+
return resolveMultiLanguage(item);
|
|
2944
|
+
}
|
|
2945
|
+
const template = resolveLookupDisplayTemplate(entity, options);
|
|
2946
|
+
if (template && !template.includes('context.eval') && !template.includes('{{')) {
|
|
3083
2947
|
const formatted = formatService.format(template, 'string', item);
|
|
3084
2948
|
if (formatted) {
|
|
3085
2949
|
const text = String(formatted);
|
|
@@ -3089,8 +2953,8 @@ function formatLookupItemDisplay(item, entity, options, formatService, resolveMu
|
|
|
3089
2953
|
}
|
|
3090
2954
|
}
|
|
3091
2955
|
const field = resolveLookupDisplayField(entity, options);
|
|
3092
|
-
const raw =
|
|
3093
|
-
if (raw == null) {
|
|
2956
|
+
const raw = typeof item === 'object' && item != null ? resolveLookupItemFieldValue(item, field) : undefined;
|
|
2957
|
+
if (raw == null || raw === '') {
|
|
3094
2958
|
return '';
|
|
3095
2959
|
}
|
|
3096
2960
|
if (typeof raw === 'string' || typeof raw === 'number' || typeof raw === 'boolean') {
|
|
@@ -3113,6 +2977,8 @@ class AXPEntityDetailPopoverComponent {
|
|
|
3113
2977
|
this.queryService = inject(AXPQueryService);
|
|
3114
2978
|
this.formatService = inject(AXFormatService);
|
|
3115
2979
|
this.translation = inject(AXTranslationService);
|
|
2980
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
2981
|
+
this.contextEvalFactory = inject(AXPContextEvalFactory);
|
|
3116
2982
|
this.changeDetectorRef = inject(ChangeDetectorRef);
|
|
3117
2983
|
//#endregion
|
|
3118
2984
|
//#region ---- Inputs ----
|
|
@@ -3128,31 +2994,10 @@ class AXPEntityDetailPopoverComponent {
|
|
|
3128
2994
|
//#region ---- Signals ----
|
|
3129
2995
|
this.entityDetails = signal(null, ...(ngDevMode ? [{ debugName: "entityDetails" }] : /* istanbul ignore next */ []));
|
|
3130
2996
|
this.isLoadingDetails = signal(false, ...(ngDevMode ? [{ debugName: "isLoadingDetails" }] : /* istanbul ignore next */ []));
|
|
2997
|
+
this.headerTitleVersion = 0;
|
|
3131
2998
|
/** Placeholder rows for the loading skeleton (matches typical property count). */
|
|
3132
2999
|
this.loadingSkeletonRows = [1, 2, 3, 4, 5];
|
|
3133
|
-
this.headerTitle =
|
|
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 */ []));
|
|
3000
|
+
this.headerTitle = signal('', ...(ngDevMode ? [{ debugName: "headerTitle" }] : /* istanbul ignore next */ []));
|
|
3156
3001
|
/**
|
|
3157
3002
|
* Stable list of property widgets for the template. Must be a signal (computed), not a method:
|
|
3158
3003
|
* calling a method from the template rebuilds nodes every CD cycle and can make the widget renderer loop.
|
|
@@ -3165,6 +3010,18 @@ class AXPEntityDetailPopoverComponent {
|
|
|
3165
3010
|
return [];
|
|
3166
3011
|
return this.buildEntityPropertiesWithWidgets(data, entityDefinition, this.textField(), this.valueField());
|
|
3167
3012
|
}, ...(ngDevMode ? [{ debugName: "entityPropertiesWithWidgets" }] : /* istanbul ignore next */ []));
|
|
3013
|
+
effect(() => {
|
|
3014
|
+
void this.translation.getActiveLang();
|
|
3015
|
+
const details = this.entityDetails();
|
|
3016
|
+
const preset = this.displayTitle();
|
|
3017
|
+
const fallbackItem = this.item();
|
|
3018
|
+
const version = ++this.headerTitleVersion;
|
|
3019
|
+
void this.resolveHeaderTitle(details?.entityDefinition, details?.entityData, preset, fallbackItem).then((title) => {
|
|
3020
|
+
if (version === this.headerTitleVersion) {
|
|
3021
|
+
this.headerTitle.set(title);
|
|
3022
|
+
}
|
|
3023
|
+
});
|
|
3024
|
+
});
|
|
3168
3025
|
}
|
|
3169
3026
|
//#endregion
|
|
3170
3027
|
//#region ---- Public Methods ----
|
|
@@ -3201,10 +3058,34 @@ class AXPEntityDetailPopoverComponent {
|
|
|
3201
3058
|
}
|
|
3202
3059
|
//#endregion
|
|
3203
3060
|
//#region ---- Helper Methods ----
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3061
|
+
async resolveHeaderTitle(entityDefinition, data, preset, fallbackItem) {
|
|
3062
|
+
if (data && entityDefinition) {
|
|
3063
|
+
const fromDetails = await this.resolveLookupDisplayLabelAsync(data, entityDefinition);
|
|
3064
|
+
if (fromDetails) {
|
|
3065
|
+
return fromDetails;
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
3068
|
+
const presetTrimmed = preset?.trim();
|
|
3069
|
+
if (presetTrimmed && !isUnresolvedEntityDisplayTemplate(presetTrimmed)) {
|
|
3070
|
+
return presetTrimmed;
|
|
3071
|
+
}
|
|
3072
|
+
if (fallbackItem) {
|
|
3073
|
+
const fromItem = await this.resolveLookupDisplayLabelAsync(fallbackItem, entityDefinition);
|
|
3074
|
+
if (fromItem) {
|
|
3075
|
+
return fromItem;
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3078
|
+
return presetTrimmed ?? '';
|
|
3079
|
+
}
|
|
3080
|
+
async resolveLookupDisplayLabelAsync(item, entityDefinition) {
|
|
3081
|
+
const locale = this.translation.getActiveLang() ?? 'en-US';
|
|
3082
|
+
const label = await formatLookupItemDisplayAsync(item, entityDefinition ?? null, { textField: this.textField() }, this.formatService, {
|
|
3083
|
+
expressionEvaluator: this.expressionEvaluator,
|
|
3084
|
+
contextEvalFactory: this.contextEvalFactory,
|
|
3085
|
+
translationService: this.translation,
|
|
3086
|
+
locale,
|
|
3087
|
+
}, (value) => this.translation.resolve(value));
|
|
3088
|
+
return label && !isUnresolvedEntityDisplayTemplate(label) ? label : '';
|
|
3208
3089
|
}
|
|
3209
3090
|
/**
|
|
3210
3091
|
* Returns true if a value is meaningful for display (non-empty/non-null).
|
|
@@ -3369,14 +3250,24 @@ class AXPEntityDetailPopoverComponent {
|
|
|
3369
3250
|
resolveDataPath(prop, data) {
|
|
3370
3251
|
const iface = prop.schema?.interface;
|
|
3371
3252
|
const expose = iface?.options?.['expose'];
|
|
3253
|
+
const textField = iface?.options?.['textField']?.trim();
|
|
3372
3254
|
if (expose?.length) {
|
|
3373
|
-
// Try expanded path first (e.g. personTitle for personTitle.title)
|
|
3374
3255
|
const textTarget = expose.find((e) => e.source !== 'id');
|
|
3375
3256
|
if (textTarget) {
|
|
3376
3257
|
const expandedPath = textTarget.target.split('.')[0];
|
|
3377
3258
|
const expandedValue = get(data, expandedPath);
|
|
3378
3259
|
if (expandedValue != null && typeof expandedValue === 'object') {
|
|
3379
|
-
|
|
3260
|
+
if (textField) {
|
|
3261
|
+
if (this.hasMeaningfulValue(get(expandedValue, textField))) {
|
|
3262
|
+
return expandedPath;
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
else {
|
|
3266
|
+
const leaf = textTarget.target.split('.').pop();
|
|
3267
|
+
if (leaf && this.hasMeaningfulValue(get(expandedValue, leaf))) {
|
|
3268
|
+
return expandedPath;
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3380
3271
|
}
|
|
3381
3272
|
}
|
|
3382
3273
|
}
|
|
@@ -3388,7 +3279,7 @@ class AXPEntityDetailPopoverComponent {
|
|
|
3388
3279
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityDetailPopoverComponent, decorators: [{
|
|
3389
3280
|
type: Component,
|
|
3390
3281
|
args: [{ selector: 'axp-entity-detail-popover', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, AXButtonModule, AXPWidgetCoreModule, AXTranslationModule, AXSkeletonModule], template: "<div\n class=\"ax-lightest-surface dark:ax-dark-surface ax-p-4 ax-w-[min(600px,calc(100vw-2rem))] ax-rounded-lg ax-shadow-lg\"\n>\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 @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 }}:</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\n [color]=\"'primary'\"\n [look]=\"'solid'\"\n [text]=\"'@general:actions.open-details.title' | translate | async\"\n (click)=\"navigateToDetails()\"\n >\n </ax-button>\n </div>\n }\n</div>\n" }]
|
|
3391
|
-
}], 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 }] }], requestClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestClose", required: false }] }] } });
|
|
3282
|
+
}], 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 }] }], requestClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestClose", required: false }] }] } });
|
|
3392
3283
|
|
|
3393
3284
|
class AXPEntityDetailPopoverService {
|
|
3394
3285
|
constructor() {
|
|
@@ -3402,6 +3293,7 @@ class AXPEntityDetailPopoverService {
|
|
|
3402
3293
|
//#region ---- Private Properties ----
|
|
3403
3294
|
this.overlayRef = null;
|
|
3404
3295
|
this.componentRef = null;
|
|
3296
|
+
this.anchorElement = null;
|
|
3405
3297
|
this.outsideClickHandler = null;
|
|
3406
3298
|
this.keydownHandler = null;
|
|
3407
3299
|
this.routerSubscription = null;
|
|
@@ -3458,6 +3350,7 @@ class AXPEntityDetailPopoverService {
|
|
|
3458
3350
|
});
|
|
3459
3351
|
this.overlayRef = ref;
|
|
3460
3352
|
this.componentRef = ref.instance;
|
|
3353
|
+
this.anchorElement = anchorElement;
|
|
3461
3354
|
setTimeout(() => {
|
|
3462
3355
|
ref.updatePosition();
|
|
3463
3356
|
this.bindDismissHandlers(ref.overlayElement, anchorElement);
|
|
@@ -3559,6 +3452,7 @@ class AXPEntityDetailPopoverService {
|
|
|
3559
3452
|
this.removeDismissHandlers();
|
|
3560
3453
|
this.overlayRef = null;
|
|
3561
3454
|
this.componentRef = null;
|
|
3455
|
+
this.anchorElement = null;
|
|
3562
3456
|
}
|
|
3563
3457
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityDetailPopoverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3564
3458
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityDetailPopoverService, providedIn: 'root' }); }
|
|
@@ -3817,16 +3711,27 @@ function commandMessageTextForError(value) {
|
|
|
3817
3711
|
* 2. Falls back to CRUD service if not defined
|
|
3818
3712
|
*/
|
|
3819
3713
|
class EntityDataAccessor {
|
|
3820
|
-
constructor(module, entity, entityRegistry, queryExecutor, commandService) {
|
|
3714
|
+
constructor(module, entity, entityRegistry, queryExecutor, commandService, injector) {
|
|
3821
3715
|
this.module = module;
|
|
3822
3716
|
this.entity = entity;
|
|
3823
3717
|
this.entityRegistry = entityRegistry;
|
|
3824
3718
|
this.queryExecutor = queryExecutor;
|
|
3825
3719
|
this.commandService = commandService;
|
|
3720
|
+
this.injector = injector;
|
|
3826
3721
|
this.crudService = null;
|
|
3827
3722
|
this.entityDef = null;
|
|
3828
3723
|
this.entityDefPromise = null;
|
|
3829
3724
|
}
|
|
3725
|
+
/**
|
|
3726
|
+
* Lazily creates the CRUD fallback inside an injection context so {@link AXMEntityCrudServiceImpl}
|
|
3727
|
+
* can resolve {@link AXPEntityStorageService} via `inject()`.
|
|
3728
|
+
*/
|
|
3729
|
+
ensureCrudService() {
|
|
3730
|
+
if (!this.crudService) {
|
|
3731
|
+
this.crudService = runInInjectionContext(this.injector, () => new AXMEntityCrudServiceImpl(`${this.module}.${this.entity}`));
|
|
3732
|
+
}
|
|
3733
|
+
return this.crudService;
|
|
3734
|
+
}
|
|
3830
3735
|
/**
|
|
3831
3736
|
* Resolves the entity definition lazily and caches it.
|
|
3832
3737
|
* @returns The resolved entity definition
|
|
@@ -3859,10 +3764,7 @@ class EntityDataAccessor {
|
|
|
3859
3764
|
return await this.queryExecutor.fetch(execute, key);
|
|
3860
3765
|
}
|
|
3861
3766
|
// Fallback to CRUD service
|
|
3862
|
-
|
|
3863
|
-
this.crudService = new AXMEntityCrudServiceImpl(`${this.module}.${this.entity}`);
|
|
3864
|
-
}
|
|
3865
|
-
return await this.crudService.getOne(key);
|
|
3767
|
+
return await this.ensureCrudService().getOne(key);
|
|
3866
3768
|
}
|
|
3867
3769
|
/**
|
|
3868
3770
|
* Queries a list of entities.
|
|
@@ -3885,20 +3787,14 @@ class EntityDataAccessor {
|
|
|
3885
3787
|
return result;
|
|
3886
3788
|
}
|
|
3887
3789
|
// Fallback to CRUD service
|
|
3888
|
-
|
|
3889
|
-
this.crudService = new AXMEntityCrudServiceImpl(`${this.module}.${this.entity}`);
|
|
3890
|
-
}
|
|
3891
|
-
return await this.crudService.query(queryRequest);
|
|
3790
|
+
return await this.ensureCrudService().query(queryRequest);
|
|
3892
3791
|
}
|
|
3893
3792
|
/**
|
|
3894
3793
|
* Queries category entities linked to this entity (`{module}.{entity}Category`).
|
|
3895
3794
|
* Falls back to CRUD category storage (same as {@link AXMEntityCrudServiceImpl.getCategoriesList}).
|
|
3896
3795
|
*/
|
|
3897
3796
|
async getCategoriesList(request = { skip: 0, take: 1000 }) {
|
|
3898
|
-
|
|
3899
|
-
this.crudService = new AXMEntityCrudServiceImpl(`${this.module}.${this.entity}`);
|
|
3900
|
-
}
|
|
3901
|
-
return await this.crudService.getCategoriesList(request);
|
|
3797
|
+
return await this.ensureCrudService().getCategoriesList(request);
|
|
3902
3798
|
}
|
|
3903
3799
|
/**
|
|
3904
3800
|
* Creates a new entity.
|
|
@@ -3920,10 +3816,7 @@ class EntityDataAccessor {
|
|
|
3920
3816
|
return result.data?.id || result.data;
|
|
3921
3817
|
}
|
|
3922
3818
|
// Fallback to CRUD service
|
|
3923
|
-
|
|
3924
|
-
this.crudService = new AXMEntityCrudServiceImpl(`${this.module}.${this.entity}`);
|
|
3925
|
-
}
|
|
3926
|
-
return await this.crudService.insertOne(data);
|
|
3819
|
+
return await this.ensureCrudService().insertOne(data);
|
|
3927
3820
|
}
|
|
3928
3821
|
/**
|
|
3929
3822
|
* Updates an existing entity.
|
|
@@ -3946,10 +3839,7 @@ class EntityDataAccessor {
|
|
|
3946
3839
|
return result.data;
|
|
3947
3840
|
}
|
|
3948
3841
|
// Fallback to CRUD service
|
|
3949
|
-
|
|
3950
|
-
this.crudService = new AXMEntityCrudServiceImpl(`${this.module}.${this.entity}`);
|
|
3951
|
-
}
|
|
3952
|
-
return await this.crudService.updateOne(id, data);
|
|
3842
|
+
return await this.ensureCrudService().updateOne(id, data);
|
|
3953
3843
|
}
|
|
3954
3844
|
/**
|
|
3955
3845
|
* Deletes an entity.
|
|
@@ -3970,10 +3860,7 @@ class EntityDataAccessor {
|
|
|
3970
3860
|
return;
|
|
3971
3861
|
}
|
|
3972
3862
|
// Fallback to CRUD service
|
|
3973
|
-
|
|
3974
|
-
this.crudService = new AXMEntityCrudServiceImpl(`${this.module}.${this.entity}`);
|
|
3975
|
-
}
|
|
3976
|
-
return await this.crudService.deleteOne(id);
|
|
3863
|
+
return await this.ensureCrudService().deleteOne(id);
|
|
3977
3864
|
}
|
|
3978
3865
|
}
|
|
3979
3866
|
//#endregion
|
|
@@ -3983,11 +3870,12 @@ class EntityDataAccessor {
|
|
|
3983
3870
|
* Provides methods to create paths and access entity data.
|
|
3984
3871
|
*/
|
|
3985
3872
|
class EntityBuilder {
|
|
3986
|
-
constructor(module, entity, sessionService, entityRegistry, queryExecutor, commandService) {
|
|
3873
|
+
constructor(module, entity, sessionService, entityRegistry, queryExecutor, commandService, injector) {
|
|
3987
3874
|
this.sessionService = sessionService;
|
|
3988
3875
|
this.entityRegistry = entityRegistry;
|
|
3989
3876
|
this.queryExecutor = queryExecutor;
|
|
3990
3877
|
this.commandService = commandService;
|
|
3878
|
+
this.injector = injector;
|
|
3991
3879
|
this.module = module;
|
|
3992
3880
|
this.entity = entity;
|
|
3993
3881
|
}
|
|
@@ -4005,7 +3893,7 @@ class EntityBuilder {
|
|
|
4005
3893
|
* @returns An EntityDataAccessor instance
|
|
4006
3894
|
*/
|
|
4007
3895
|
data() {
|
|
4008
|
-
return new EntityDataAccessor(this.module, this.entity, this.entityRegistry, this.queryExecutor, this.commandService);
|
|
3896
|
+
return new EntityDataAccessor(this.module, this.entity, this.entityRegistry, this.queryExecutor, this.commandService, this.injector);
|
|
4009
3897
|
}
|
|
4010
3898
|
}
|
|
4011
3899
|
//#endregion
|
|
@@ -4015,6 +3903,7 @@ class AXPEntityService {
|
|
|
4015
3903
|
this.entityRegistry = inject(AXPEntityDefinitionRegistryService);
|
|
4016
3904
|
this.queryExecutor = inject(AXPQueryExecutor);
|
|
4017
3905
|
this.commandService = inject(AXPCommandService);
|
|
3906
|
+
this.injector = inject(Injector);
|
|
4018
3907
|
}
|
|
4019
3908
|
/**
|
|
4020
3909
|
* @deprecated Use `withEntity(module, entity).createPath(path)` instead.
|
|
@@ -4040,7 +3929,7 @@ class AXPEntityService {
|
|
|
4040
3929
|
module = moduleOrEntityKey.substring(0, dotIndex);
|
|
4041
3930
|
entityName = moduleOrEntityKey.substring(dotIndex + 1);
|
|
4042
3931
|
}
|
|
4043
|
-
return new EntityBuilder(module, entityName, this.sessionService, this.entityRegistry, this.queryExecutor, this.commandService);
|
|
3932
|
+
return new EntityBuilder(module, entityName, this.sessionService, this.entityRegistry, this.queryExecutor, this.commandService, this.injector);
|
|
4044
3933
|
}
|
|
4045
3934
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4046
3935
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityService, providedIn: 'root' }); }
|
|
@@ -4055,7 +3944,6 @@ class AXPEntityPreloadFiltersContainerComponent extends AXPPageLayoutBaseCompone
|
|
|
4055
3944
|
super(...arguments);
|
|
4056
3945
|
//#region ---- Services & Dependencies ----
|
|
4057
3946
|
this.route = inject(ActivatedRoute);
|
|
4058
|
-
this.router = inject(Router);
|
|
4059
3947
|
this.entityService = inject(AXPEntityService);
|
|
4060
3948
|
this.filterOperatorMiddleware = inject(AXPFilterOperatorMiddlewareService);
|
|
4061
3949
|
//#endregion
|
|
@@ -4345,7 +4233,8 @@ const PLUGIN_SLOT_INDEX = {
|
|
|
4345
4233
|
attachments: 1,
|
|
4346
4234
|
documents: 2,
|
|
4347
4235
|
comments: 3,
|
|
4348
|
-
|
|
4236
|
+
dashboard: 4,
|
|
4237
|
+
history: 5,
|
|
4349
4238
|
};
|
|
4350
4239
|
//#endregion
|
|
4351
4240
|
//#region ---- Helpers ----
|
|
@@ -4474,7 +4363,7 @@ class AXPEntityCommandTriggerViewModel {
|
|
|
4474
4363
|
this.priority = action.priority;
|
|
4475
4364
|
this.title = action.title;
|
|
4476
4365
|
this.separated = action.separated ?? false;
|
|
4477
|
-
this.color = action.color ?? resolvedLook.color;
|
|
4366
|
+
this.color = (action.color ?? resolvedLook.color);
|
|
4478
4367
|
this.icon = action.icon ?? resolvedLook.icon;
|
|
4479
4368
|
this.hidden = action.hidden ?? false;
|
|
4480
4369
|
this.disabled = action.disabled ?? false;
|
|
@@ -4566,6 +4455,7 @@ class AXPEntityDetailListViewModel {
|
|
|
4566
4455
|
this.settingsService = this.injector.get(AXPSettingsService);
|
|
4567
4456
|
this.destroyed = new Subject();
|
|
4568
4457
|
this.showRowIndexColumnEnabled = signal(false, ...(ngDevMode ? [{ debugName: "showRowIndexColumnEnabled" }] : /* istanbul ignore next */ []));
|
|
4458
|
+
this.lastAppliedFilterKey = null;
|
|
4569
4459
|
/** Whether the row index column is shown (user setting). */
|
|
4570
4460
|
this.showIndexColumn = computed(() => this.showRowIndexColumnEnabled(), ...(ngDevMode ? [{ debugName: "showIndexColumn" }] : /* istanbul ignore next */ []));
|
|
4571
4461
|
this.dataSource = new AXDataSource({
|
|
@@ -4759,10 +4649,6 @@ class AXPEntityDetailListViewModel {
|
|
|
4759
4649
|
this.applyFilterAndSort();
|
|
4760
4650
|
}
|
|
4761
4651
|
async applyFilterAndSort() {
|
|
4762
|
-
this.dataSource.clearFilter();
|
|
4763
|
-
//
|
|
4764
|
-
//this.dataSource.sort(...this.detailEntity.().map(s => ({ dir: s.dir, field: s.name } as AXDataSourceSortOption)));
|
|
4765
|
-
//
|
|
4766
4652
|
const parentFilters = (await Promise.all(this.detailEntityConfig.conditions?.map(async (c) => {
|
|
4767
4653
|
return {
|
|
4768
4654
|
field: c.name,
|
|
@@ -4780,22 +4666,30 @@ class AXPEntityDetailListViewModel {
|
|
|
4780
4666
|
//
|
|
4781
4667
|
const inline = this.inlineFilters.filters?.length ?? 0;
|
|
4782
4668
|
const parent = parentFilterWrapper.filters?.length ?? 0;
|
|
4783
|
-
|
|
4784
|
-
if (inline) {
|
|
4785
|
-
this.
|
|
4786
|
-
}
|
|
4787
|
-
else if (!inline && parent) {
|
|
4788
|
-
this.dataSource.filter(this.filterOperatorMiddleware.transformFilter(parentFilterWrapper));
|
|
4789
|
-
}
|
|
4790
|
-
else if (inline && parent) {
|
|
4791
|
-
this.dataSource.filter(this.filterOperatorMiddleware.transformFilter({
|
|
4669
|
+
let effectiveFilter;
|
|
4670
|
+
if (inline && parent) {
|
|
4671
|
+
effectiveFilter = this.filterOperatorMiddleware.transformFilter({
|
|
4792
4672
|
field: null,
|
|
4793
4673
|
logic: 'and',
|
|
4794
4674
|
operator: null,
|
|
4795
4675
|
filters: [this.inlineFilters, parentFilterWrapper],
|
|
4796
|
-
})
|
|
4676
|
+
});
|
|
4677
|
+
}
|
|
4678
|
+
else if (inline) {
|
|
4679
|
+
effectiveFilter = this.filterOperatorMiddleware.transformFilter(this.inlineFilters);
|
|
4680
|
+
}
|
|
4681
|
+
else if (parent) {
|
|
4682
|
+
effectiveFilter = this.filterOperatorMiddleware.transformFilter(parentFilterWrapper);
|
|
4683
|
+
}
|
|
4684
|
+
const filterKey = JSON.stringify(effectiveFilter ?? null);
|
|
4685
|
+
if (filterKey === this.lastAppliedFilterKey) {
|
|
4686
|
+
return;
|
|
4687
|
+
}
|
|
4688
|
+
this.lastAppliedFilterKey = filterKey;
|
|
4689
|
+
this.dataSource.clearFilter();
|
|
4690
|
+
if (effectiveFilter) {
|
|
4691
|
+
this.dataSource.filter(effectiveFilter);
|
|
4797
4692
|
}
|
|
4798
|
-
//
|
|
4799
4693
|
this.dataSource.refresh();
|
|
4800
4694
|
}
|
|
4801
4695
|
//****************** Commands ******************//
|
|
@@ -5344,7 +5238,7 @@ class AXPEntityMasterListViewModel {
|
|
|
5344
5238
|
}
|
|
5345
5239
|
}
|
|
5346
5240
|
//#endregion
|
|
5347
|
-
|
|
5241
|
+
createLogicExpressionScope(data) {
|
|
5348
5242
|
return {
|
|
5349
5243
|
context: {
|
|
5350
5244
|
eval: (path) => get(data, path),
|
|
@@ -5355,11 +5249,20 @@ class AXPEntityMasterListViewModel {
|
|
|
5355
5249
|
},
|
|
5356
5250
|
};
|
|
5357
5251
|
}
|
|
5252
|
+
createDisplayExpressionScope(data) {
|
|
5253
|
+
return {
|
|
5254
|
+
context: this.contextEvalFactory.createScope((data ?? {})),
|
|
5255
|
+
list: {
|
|
5256
|
+
view: () => this.view().name,
|
|
5257
|
+
views: () => this.views().map((v) => ({ name: v.name, title: v.title })),
|
|
5258
|
+
},
|
|
5259
|
+
};
|
|
5260
|
+
}
|
|
5358
5261
|
async resolveCommandNameExpression(commandName, data) {
|
|
5359
5262
|
if (!commandName || !commandName.includes('{{')) {
|
|
5360
5263
|
return commandName;
|
|
5361
5264
|
}
|
|
5362
|
-
const scope = this.
|
|
5265
|
+
const scope = this.createLogicExpressionScope(data);
|
|
5363
5266
|
const result = await this.expressionEvaluator.evaluate({ value: commandName }, scope);
|
|
5364
5267
|
const resolved = result?.value;
|
|
5365
5268
|
return typeof resolved === 'string' && resolved.trim() !== '' ? resolved : commandName;
|
|
@@ -5368,7 +5271,7 @@ class AXPEntityMasterListViewModel {
|
|
|
5368
5271
|
if (!title || !title.includes('{{')) {
|
|
5369
5272
|
return title;
|
|
5370
5273
|
}
|
|
5371
|
-
const scope = this.
|
|
5274
|
+
const scope = this.createDisplayExpressionScope(data);
|
|
5372
5275
|
const result = await this.expressionEvaluator.evaluate({ value: title }, scope);
|
|
5373
5276
|
const resolved = result?.value;
|
|
5374
5277
|
return typeof resolved === 'string' && resolved.trim() !== '' ? resolved : title;
|
|
@@ -5383,7 +5286,7 @@ class AXPEntityMasterListViewModel {
|
|
|
5383
5286
|
return '';
|
|
5384
5287
|
}
|
|
5385
5288
|
if (value.includes('{{')) {
|
|
5386
|
-
const scope = this.
|
|
5289
|
+
const scope = this.createDisplayExpressionScope(rowData);
|
|
5387
5290
|
const result = await this.expressionEvaluator.evaluate(value, scope);
|
|
5388
5291
|
if (result === false) {
|
|
5389
5292
|
return '';
|
|
@@ -5421,7 +5324,7 @@ class AXPEntityMasterListViewModel {
|
|
|
5421
5324
|
if (color == null || color === '') {
|
|
5422
5325
|
return 'default';
|
|
5423
5326
|
}
|
|
5424
|
-
const scope = this.
|
|
5327
|
+
const scope = this.createLogicExpressionScope(rowData);
|
|
5425
5328
|
const result = await this.expressionEvaluator.evaluate(color, scope);
|
|
5426
5329
|
if (result === false || result == null) {
|
|
5427
5330
|
return 'default';
|
|
@@ -5469,6 +5372,7 @@ class AXPEntityMasterListViewModel {
|
|
|
5469
5372
|
this.settings = this.injector.get(AXPSettingsService);
|
|
5470
5373
|
this.widgetResolver = this.injector.get(AXPWidgetRegistryService);
|
|
5471
5374
|
this.expressionEvaluator = this.injector.get(AXPExpressionEvaluatorService);
|
|
5375
|
+
this.contextEvalFactory = this.injector.get(AXPContextEvalFactory);
|
|
5472
5376
|
this.translation = this.injector.get(AXTranslationService);
|
|
5473
5377
|
this.commandService = this.injector.get(AXPCommandService);
|
|
5474
5378
|
this.eventService = this.injector.get(AXPBroadcastEventService);
|
|
@@ -5582,8 +5486,11 @@ class AXPEntityMasterListViewModel {
|
|
|
5582
5486
|
return this._viewDef.description ?? null;
|
|
5583
5487
|
}, ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
|
|
5584
5488
|
//****************** Inline filter ******************//
|
|
5489
|
+
this.filterDefinitions = signal([], ...(ngDevMode ? [{ debugName: "filterDefinitions" }] : /* istanbul ignore next */ []));
|
|
5585
5490
|
this.inlineFiltersPlaceholders = computed(() => {
|
|
5586
|
-
return this.
|
|
5491
|
+
return this.filterDefinitions()
|
|
5492
|
+
.filter((f) => f.filterType.inline)
|
|
5493
|
+
.map((c) => c.title ?? c.field);
|
|
5587
5494
|
}, ...(ngDevMode ? [{ debugName: "inlineFiltersPlaceholders" }] : /* istanbul ignore next */ []));
|
|
5588
5495
|
this.hasInlineFilters = computed(() => {
|
|
5589
5496
|
return this.inlineFiltersPlaceholders().length > 0;
|
|
@@ -5623,7 +5530,6 @@ class AXPEntityMasterListViewModel {
|
|
|
5623
5530
|
this.primaryRowActions = computed(() => this.allActions().filter((a) => a.scope == AXPEntityCommandScope.Individual && a.priority === 'primary'), ...(ngDevMode ? [{ debugName: "primaryRowActions" }] : /* istanbul ignore next */ []));
|
|
5624
5531
|
//****************** Filter ******************//
|
|
5625
5532
|
this.filterQueries = signal([], ...(ngDevMode ? [{ debugName: "filterQueries" }] : /* istanbul ignore next */ []));
|
|
5626
|
-
//****************** Columns ******************//
|
|
5627
5533
|
this.allAvailableColumns = () => {
|
|
5628
5534
|
const { columns = [], properties } = this.entityDef;
|
|
5629
5535
|
// const visibleProperties = properties.filter(({ schema }) => schema?.visible !== false);
|
|
@@ -5631,13 +5537,15 @@ class AXPEntityMasterListViewModel {
|
|
|
5631
5537
|
return columns
|
|
5632
5538
|
.filter(({ name, showAs, options }) => (propNames.has(name) || showAs) && options?.visible !== false)
|
|
5633
5539
|
.map((column) => {
|
|
5540
|
+
const relatedProperty = this.resolveMergeDetailProperty(column.name);
|
|
5634
5541
|
if (column.showAs) {
|
|
5635
5542
|
const widgetConfig = this.widgetResolver.resolve(column.showAs.type);
|
|
5636
5543
|
const { title: _wcTitle, description: _wcDescription, ...widgetRest } = widgetConfig;
|
|
5637
5544
|
const property = {
|
|
5638
5545
|
...widgetRest,
|
|
5639
5546
|
name: column.name,
|
|
5640
|
-
title: column.title ?? '',
|
|
5547
|
+
title: column.title ?? relatedProperty?.title ?? '',
|
|
5548
|
+
options: relatedProperty?.options,
|
|
5641
5549
|
schema: {
|
|
5642
5550
|
dataType: 'string',
|
|
5643
5551
|
interface: {
|
|
@@ -5666,18 +5574,16 @@ class AXPEntityMasterListViewModel {
|
|
|
5666
5574
|
};
|
|
5667
5575
|
this.cardFields = signal([], ...(ngDevMode ? [{ debugName: "cardFields" }] : /* istanbul ignore next */ []));
|
|
5668
5576
|
//****************** Sort ******************//
|
|
5577
|
+
this.sortableFieldDefinitions = signal([], ...(ngDevMode ? [{ debugName: "sortableFieldDefinitions" }] : /* istanbul ignore next */ []));
|
|
5669
5578
|
this.sortableFields = () => {
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
dir: undefined,
|
|
5676
|
-
};
|
|
5677
|
-
});
|
|
5579
|
+
return this.sortableFieldDefinitions().map((field) => ({
|
|
5580
|
+
name: field.name,
|
|
5581
|
+
title: field.title,
|
|
5582
|
+
dir: undefined,
|
|
5583
|
+
}));
|
|
5678
5584
|
};
|
|
5679
5585
|
this.sortableFieldsCount = () => {
|
|
5680
|
-
return this.
|
|
5586
|
+
return this.sortableFieldDefinitions().length;
|
|
5681
5587
|
};
|
|
5682
5588
|
this.canSort = () => {
|
|
5683
5589
|
return this.sortableFieldsCount() > 0;
|
|
@@ -5691,7 +5597,7 @@ class AXPEntityMasterListViewModel {
|
|
|
5691
5597
|
this.sortedFields = signal([], ...(ngDevMode ? [{ debugName: "sortedFields" }] : /* istanbul ignore next */ []));
|
|
5692
5598
|
//#endregion
|
|
5693
5599
|
this.evaluateExpressions = async (options, data) => {
|
|
5694
|
-
const scope = this.
|
|
5600
|
+
const scope = this.createLogicExpressionScope(data);
|
|
5695
5601
|
return await this.expressionEvaluator.evaluate(options, scope);
|
|
5696
5602
|
};
|
|
5697
5603
|
this.workflow.events$
|
|
@@ -6081,7 +5987,7 @@ class AXPEntityMasterListViewModel {
|
|
|
6081
5987
|
this.selectedCategory.set(category);
|
|
6082
5988
|
}
|
|
6083
5989
|
async getPrimaryActions() {
|
|
6084
|
-
const scope = this.
|
|
5990
|
+
const scope = this.createLogicExpressionScope(null);
|
|
6085
5991
|
const actions = await Promise.all(this.allActions()
|
|
6086
5992
|
.filter((a) => a.priority == 'primary' &&
|
|
6087
5993
|
((a.scope == AXPEntityCommandScope.Selected && this.hasSelectedItems()) ||
|
|
@@ -6098,7 +6004,7 @@ class AXPEntityMasterListViewModel {
|
|
|
6098
6004
|
return actions.filter(Boolean);
|
|
6099
6005
|
}
|
|
6100
6006
|
async getSecondaryActions() {
|
|
6101
|
-
const scope = this.
|
|
6007
|
+
const scope = this.createLogicExpressionScope(null);
|
|
6102
6008
|
const actions = await Promise.all(this.allActions()
|
|
6103
6009
|
.filter((a) => a.priority == 'secondary' &&
|
|
6104
6010
|
((a.scope == AXPEntityCommandScope.Selected && this.hasSelectedItems()) ||
|
|
@@ -6115,7 +6021,7 @@ class AXPEntityMasterListViewModel {
|
|
|
6115
6021
|
return actions.filter(Boolean);
|
|
6116
6022
|
}
|
|
6117
6023
|
async secondaryRowActions(rowData) {
|
|
6118
|
-
const scope = this.
|
|
6024
|
+
const scope = this.createLogicExpressionScope(rowData);
|
|
6119
6025
|
const actions = await Promise.all(this.allActions()
|
|
6120
6026
|
.filter((a) => a.scope === AXPEntityCommandScope.Individual && a.priority === 'secondary')
|
|
6121
6027
|
.map(async (a) => {
|
|
@@ -6276,38 +6182,27 @@ class AXPEntityMasterListViewModel {
|
|
|
6276
6182
|
}
|
|
6277
6183
|
return false;
|
|
6278
6184
|
}
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
operator: {
|
|
6293
|
-
type: 'contains',
|
|
6294
|
-
},
|
|
6295
|
-
widget: { ...omit(iface, 'triggers'), path: e.name, type },
|
|
6296
|
-
filters: [],
|
|
6297
|
-
isParametric: false,
|
|
6298
|
-
icon: widgetConfig?.icon,
|
|
6299
|
-
filterType: {
|
|
6300
|
-
advance: e.options?.filter?.advance?.enabled ?? false,
|
|
6301
|
-
inline: e.options?.filter?.inline?.enabled ?? false,
|
|
6302
|
-
preload: e.options?.filter?.preload,
|
|
6303
|
-
},
|
|
6304
|
-
// `interface.options.disabled` is for edit forms only; do not gray out advance filters.
|
|
6305
|
-
triggers: e.schema.interface?.triggers,
|
|
6306
|
-
};
|
|
6185
|
+
/**
|
|
6186
|
+
* Loads host and merge-detail related sortable field definitions (async registry resolution).
|
|
6187
|
+
*/
|
|
6188
|
+
async loadSortableFields() {
|
|
6189
|
+
const fields = await collectEntityListSortableFields(this.entityDef, (moduleName, entityName) => this.entityDefinitionRegistry.resolve(moduleName, entityName).catch(() => null));
|
|
6190
|
+
this.sortableFieldDefinitions.set(fields);
|
|
6191
|
+
}
|
|
6192
|
+
/**
|
|
6193
|
+
* Loads host and merge-detail related filter definitions (async registry resolution).
|
|
6194
|
+
*/
|
|
6195
|
+
async loadFilterDefinitions() {
|
|
6196
|
+
const definitions = await collectEntityListFilterDefinitions(this.entityDef, (moduleName, entityName) => this.entityDefinitionRegistry.resolve(moduleName, entityName).catch(() => null), {
|
|
6197
|
+
resolveWidget: (type) => this.widgetResolver.resolve(type),
|
|
6307
6198
|
});
|
|
6199
|
+
this.filterDefinitions.set(definitions);
|
|
6200
|
+
}
|
|
6201
|
+
get filtersDef() {
|
|
6202
|
+
return this.filterDefinitions();
|
|
6308
6203
|
}
|
|
6309
6204
|
get preloadFiltersDef() {
|
|
6310
|
-
return this.
|
|
6205
|
+
return this.filterDefinitions().filter((f) => f.filterType.preload?.enabled);
|
|
6311
6206
|
}
|
|
6312
6207
|
// const viewFilters = this.view().conditions.map((f) => ({
|
|
6313
6208
|
// field: f.name,
|
|
@@ -6337,7 +6232,13 @@ class AXPEntityMasterListViewModel {
|
|
|
6337
6232
|
.map((s) => ({ name: s.name, dir: s.dir }));
|
|
6338
6233
|
const filters = this.filterQueries();
|
|
6339
6234
|
const sortKey = JSON.stringify(sorts);
|
|
6340
|
-
const
|
|
6235
|
+
const transformedFilter = this.filterOperatorMiddleware.transformFilter({
|
|
6236
|
+
field: null,
|
|
6237
|
+
logic: 'and',
|
|
6238
|
+
operator: null,
|
|
6239
|
+
filters: filters,
|
|
6240
|
+
});
|
|
6241
|
+
const filterKey = JSON.stringify(transformedFilter);
|
|
6341
6242
|
if (sortKey === this.lastAppliedSortKey && filterKey === this.lastAppliedFilterKey) {
|
|
6342
6243
|
return; // No effective change; avoid redundant refresh
|
|
6343
6244
|
}
|
|
@@ -6349,14 +6250,23 @@ class AXPEntityMasterListViewModel {
|
|
|
6349
6250
|
}
|
|
6350
6251
|
this.dataSource.clearFilter();
|
|
6351
6252
|
this.dataSource.sort(...sorts.map((s) => ({ dir: s.dir, field: s.name })));
|
|
6352
|
-
this.dataSource.filter(
|
|
6353
|
-
field: null,
|
|
6354
|
-
logic: 'and',
|
|
6355
|
-
operator: null,
|
|
6356
|
-
filters: filters,
|
|
6357
|
-
}));
|
|
6253
|
+
this.dataSource.filter(transformedFilter);
|
|
6358
6254
|
this.events$.next({ action: 'refresh', meta: { resetPagination: filtersChanged } });
|
|
6359
6255
|
}
|
|
6256
|
+
//****************** Columns ******************//
|
|
6257
|
+
resolveMergeDetailProperty(columnName) {
|
|
6258
|
+
const parsed = parseDottedFieldPath(columnName);
|
|
6259
|
+
if (!parsed) {
|
|
6260
|
+
return null;
|
|
6261
|
+
}
|
|
6262
|
+
const { dataPath, propertyName } = parsed;
|
|
6263
|
+
const related = this.entityDef.relatedEntities?.find((entry) => entry.layout?.type === 'merge-detail' && entry.persistence?.dataPath?.trim() === dataPath);
|
|
6264
|
+
if (!related?.entity) {
|
|
6265
|
+
return null;
|
|
6266
|
+
}
|
|
6267
|
+
const relatedDef = this.getRegisteredEntity(related.entity);
|
|
6268
|
+
return relatedDef?.properties?.find((property) => property.name === propertyName) ?? null;
|
|
6269
|
+
}
|
|
6360
6270
|
resetColumns() {
|
|
6361
6271
|
this.applyViewColumns();
|
|
6362
6272
|
}
|
|
@@ -6751,6 +6661,8 @@ class AXPEntityListViewModelFactory {
|
|
|
6751
6661
|
const config = await this.entityService.resolve(moduleName, entityName);
|
|
6752
6662
|
this.layout.setNavigationLoading(false);
|
|
6753
6663
|
const vm = new AXPEntityMasterListViewModel(this.injector, config);
|
|
6664
|
+
await vm.loadFilterDefinitions();
|
|
6665
|
+
await vm.loadSortableFields();
|
|
6754
6666
|
await vm.initializeListPersistence();
|
|
6755
6667
|
return vm;
|
|
6756
6668
|
}
|
|
@@ -6785,7 +6697,7 @@ const AXPEntityListViewModelResolver = async (route, state, service = inject(AXP
|
|
|
6785
6697
|
}
|
|
6786
6698
|
};
|
|
6787
6699
|
|
|
6788
|
-
const AXPEntityDeletedEvent = createWorkFlowEvent(
|
|
6700
|
+
const AXPEntityDeletedEvent = createWorkFlowEvent(AXP_ENTITY_DELETED_WORKFLOW_EVENT_TYPE);
|
|
6789
6701
|
class AXPEntityPerformDeleteAction extends AXPWorkflowAction {
|
|
6790
6702
|
constructor() {
|
|
6791
6703
|
super(...arguments);
|
|
@@ -7138,6 +7050,9 @@ class AXPEntityModifySectionPopupAction extends AXPWorkflowAction {
|
|
|
7138
7050
|
this.popupService = inject(AXPopupService);
|
|
7139
7051
|
this.platform = inject(AXPlatform);
|
|
7140
7052
|
this.translateService = inject(AXTranslationService);
|
|
7053
|
+
this.formatService = inject(AXFormatService);
|
|
7054
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
7055
|
+
this.contextEvalFactory = inject(AXPContextEvalFactory);
|
|
7141
7056
|
this.entityRegistery = inject(AXPEntityDefinitionRegistryService);
|
|
7142
7057
|
this.config = inject(AXP_ENTITY_CONFIG_TOKEN);
|
|
7143
7058
|
this.factory = inject(AXPEntityMasterUpdateViewModelFactory);
|
|
@@ -7155,7 +7070,7 @@ class AXPEntityModifySectionPopupAction extends AXPWorkflowAction {
|
|
|
7155
7070
|
title: headerTitle
|
|
7156
7071
|
? headerTitle
|
|
7157
7072
|
: title ??
|
|
7158
|
-
|
|
7073
|
+
(await resolveEntityModifyPopupTitle(entityRef, vm.context(), this.translateService, this.formatService, this.expressionEvaluator, this.contextEvalFactory)),
|
|
7159
7074
|
size: this.platform.is('Mobile') || this.platform.is('SM') ? 'full' : 'md',
|
|
7160
7075
|
data: {
|
|
7161
7076
|
vm,
|
|
@@ -7516,6 +7431,8 @@ class AXPEntityPreloadFiltersViewModel {
|
|
|
7516
7431
|
this.config = config;
|
|
7517
7432
|
this.entityDef = cloneDeep(this.config);
|
|
7518
7433
|
this.widgetResolver = this.injector.get(AXPWidgetRegistryService);
|
|
7434
|
+
this.entityRegistry = this.injector.get(AXPEntityDefinitionRegistryService);
|
|
7435
|
+
this.filterDefinitions = signal([], ...(ngDevMode ? [{ debugName: "filterDefinitions" }] : /* istanbul ignore next */ []));
|
|
7519
7436
|
//#endregion
|
|
7520
7437
|
//#region ---- Computed Properties ----
|
|
7521
7438
|
/**
|
|
@@ -7534,46 +7451,7 @@ class AXPEntityPreloadFiltersViewModel {
|
|
|
7534
7451
|
* All filter definitions for properties with preload enabled
|
|
7535
7452
|
*/
|
|
7536
7453
|
this.preloadFiltersDef = computed(() => {
|
|
7537
|
-
|
|
7538
|
-
return props.map((e) => {
|
|
7539
|
-
const widgetConfig = this.widgetResolver.resolve(e.schema.interface?.type);
|
|
7540
|
-
const type = e.schema.interface?.type;
|
|
7541
|
-
// Merge validations with existing options
|
|
7542
|
-
const validations = e.options?.filter?.preload?.required
|
|
7543
|
-
? [
|
|
7544
|
-
{
|
|
7545
|
-
rule: 'required',
|
|
7546
|
-
message: 'This field is required',
|
|
7547
|
-
options: {},
|
|
7548
|
-
},
|
|
7549
|
-
]
|
|
7550
|
-
: [];
|
|
7551
|
-
const mergedOptions = {
|
|
7552
|
-
...e.schema.interface?.options,
|
|
7553
|
-
validations,
|
|
7554
|
-
};
|
|
7555
|
-
return {
|
|
7556
|
-
title: e.title,
|
|
7557
|
-
field: e.name,
|
|
7558
|
-
operator: {
|
|
7559
|
-
type: 'contains',
|
|
7560
|
-
},
|
|
7561
|
-
widget: {
|
|
7562
|
-
...e.schema.interface,
|
|
7563
|
-
path: e.name,
|
|
7564
|
-
type,
|
|
7565
|
-
options: mergedOptions,
|
|
7566
|
-
},
|
|
7567
|
-
filters: [],
|
|
7568
|
-
isParametric: false,
|
|
7569
|
-
icon: widgetConfig?.icon,
|
|
7570
|
-
filterType: {
|
|
7571
|
-
advance: false,
|
|
7572
|
-
inline: false,
|
|
7573
|
-
preload: e.options?.filter?.preload,
|
|
7574
|
-
},
|
|
7575
|
-
};
|
|
7576
|
-
});
|
|
7454
|
+
return this.filterDefinitions().filter((definition) => definition.filterType.preload?.enabled);
|
|
7577
7455
|
}, ...(ngDevMode ? [{ debugName: "preloadFiltersDef" }] : /* istanbul ignore next */ []));
|
|
7578
7456
|
/**
|
|
7579
7457
|
* Required filter definitions only
|
|
@@ -7582,7 +7460,14 @@ class AXPEntityPreloadFiltersViewModel {
|
|
|
7582
7460
|
return this.preloadFiltersDef().filter((c) => c.filterType.preload?.required);
|
|
7583
7461
|
}, ...(ngDevMode ? [{ debugName: "requiredFiltersDef" }] : /* istanbul ignore next */ []));
|
|
7584
7462
|
}
|
|
7463
|
+
//#endregion
|
|
7585
7464
|
//#region ---- Methods ----
|
|
7465
|
+
async loadFilterDefinitions() {
|
|
7466
|
+
const definitions = await collectEntityListFilterDefinitions(this.entityDef, (moduleName, entityName) => this.entityRegistry.resolve(moduleName, entityName).catch(() => null), {
|
|
7467
|
+
resolveWidget: (type) => this.widgetResolver.resolve(type),
|
|
7468
|
+
});
|
|
7469
|
+
this.filterDefinitions.set(definitions);
|
|
7470
|
+
}
|
|
7586
7471
|
/**
|
|
7587
7472
|
* Serialize filter values to plain objects (remove signals, functions, etc.)
|
|
7588
7473
|
*/
|
|
@@ -7599,159 +7484,17 @@ const AXPEntityPreloadFiltersViewModelResolver = async (route, state) => {
|
|
|
7599
7484
|
const entityName = route.paramMap.get('entity');
|
|
7600
7485
|
try {
|
|
7601
7486
|
const entity = await entityRegistry.resolve(moduleName, entityName);
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
}
|
|
7610
|
-
};
|
|
7611
|
-
//#endregion
|
|
7612
|
-
|
|
7613
|
-
//#endregion
|
|
7614
|
-
//#region ---- Quick search: schema-driven field paths ----
|
|
7615
|
-
const NON_TEXT_DATATYPES = new Set([
|
|
7616
|
-
'number',
|
|
7617
|
-
'integer',
|
|
7618
|
-
'int',
|
|
7619
|
-
'long',
|
|
7620
|
-
'float',
|
|
7621
|
-
'double',
|
|
7622
|
-
'decimal',
|
|
7623
|
-
'money',
|
|
7624
|
-
'currency',
|
|
7625
|
-
'boolean',
|
|
7626
|
-
'bool',
|
|
7627
|
-
'date',
|
|
7628
|
-
'datetime',
|
|
7629
|
-
'time',
|
|
7630
|
-
'object',
|
|
7631
|
-
'array',
|
|
7632
|
-
'json',
|
|
7633
|
-
'image',
|
|
7634
|
-
'file',
|
|
7635
|
-
'binary',
|
|
7636
|
-
]);
|
|
7637
|
-
/**
|
|
7638
|
-
* Whether an entity property likely stores free text worth a `contains` quick-search clause.
|
|
7639
|
-
*/
|
|
7640
|
-
function isTextLikeDataType(dataType) {
|
|
7641
|
-
const dt = (dataType ?? 'string').toLowerCase().trim();
|
|
7642
|
-
if (!dt || NON_TEXT_DATATYPES.has(dt)) {
|
|
7643
|
-
return false;
|
|
7644
|
-
}
|
|
7645
|
-
return true;
|
|
7646
|
-
}
|
|
7647
|
-
/**
|
|
7648
|
-
* Lodash-get paths for quick search from a single entity definition: string-like property names
|
|
7649
|
-
* plus lookup `expose[].target` paths (e.g. `brand.title`).
|
|
7650
|
-
*/
|
|
7651
|
-
function collectQuickSearchPathsFromSingleEntityDefinition(entity) {
|
|
7652
|
-
if (!entity?.properties?.length) {
|
|
7653
|
-
return [];
|
|
7654
|
-
}
|
|
7655
|
-
const paths = new Set();
|
|
7656
|
-
for (const p of entity.properties) {
|
|
7657
|
-
if (isTextLikeDataType(p.schema?.dataType)) {
|
|
7658
|
-
paths.add(p.name);
|
|
7659
|
-
}
|
|
7660
|
-
const opts = p.schema?.interface?.options;
|
|
7661
|
-
const expose = opts?.['expose'];
|
|
7662
|
-
if (!Array.isArray(expose)) {
|
|
7663
|
-
continue;
|
|
7664
|
-
}
|
|
7665
|
-
for (const row of expose) {
|
|
7666
|
-
if (row && typeof row === 'object' && typeof row.target === 'string') {
|
|
7667
|
-
const t = (row.target).trim();
|
|
7668
|
-
if (t) {
|
|
7669
|
-
paths.add(t);
|
|
7670
|
-
}
|
|
7671
|
-
}
|
|
7672
|
-
}
|
|
7673
|
-
}
|
|
7674
|
-
return [...paths];
|
|
7675
|
-
}
|
|
7676
|
-
//#endregion
|
|
7677
|
-
//#region ---- Column-derived nested paths ----
|
|
7678
|
-
/**
|
|
7679
|
-
* Adds dotted paths from master columns (`name` or `options.dataPath`), e.g. `person.fullName`, `jobDefinition.title`.
|
|
7680
|
-
*/
|
|
7681
|
-
function collectNestedFieldPathsFromEntityColumns(entity) {
|
|
7682
|
-
if (!entity?.columns?.length) {
|
|
7683
|
-
return [];
|
|
7684
|
-
}
|
|
7685
|
-
const paths = new Set();
|
|
7686
|
-
for (const col of entity.columns) {
|
|
7687
|
-
const name = col.name.trim();
|
|
7688
|
-
if (name.includes('.')) {
|
|
7689
|
-
paths.add(name);
|
|
7690
|
-
}
|
|
7691
|
-
const rawDp = col.options?.['dataPath'];
|
|
7692
|
-
if (typeof rawDp === 'string') {
|
|
7693
|
-
const dp = rawDp.trim();
|
|
7694
|
-
if (dp.includes('.')) {
|
|
7695
|
-
paths.add(dp);
|
|
7696
|
-
}
|
|
7697
|
-
}
|
|
7698
|
-
}
|
|
7699
|
-
return [...paths];
|
|
7700
|
-
}
|
|
7701
|
-
//#endregion
|
|
7702
|
-
//#region ---- Related merge-detail paths ----
|
|
7703
|
-
function parseRelatedEntityFullName(fullName) {
|
|
7704
|
-
const t = fullName.trim();
|
|
7705
|
-
const idx = t.indexOf('.');
|
|
7706
|
-
if (idx <= 0 || idx >= t.length - 1) {
|
|
7707
|
-
return null;
|
|
7708
|
-
}
|
|
7709
|
-
return {
|
|
7710
|
-
moduleName: t.slice(0, idx),
|
|
7711
|
-
entityName: t.slice(idx + 1),
|
|
7712
|
-
};
|
|
7713
|
-
}
|
|
7714
|
-
//#endregion
|
|
7715
|
-
//#region ---- Public API ----
|
|
7716
|
-
/**
|
|
7717
|
-
* Collects lodash-get field paths used for mock/API quick search (`contains` / OR filters):
|
|
7718
|
-
* host properties and lookup expose targets, dotted column paths, and merge-detail related entities
|
|
7719
|
-
* prefixed with the related entity merge `persistence.dataPath` (e.g. `person.firstName`).
|
|
7720
|
-
*/
|
|
7721
|
-
async function collectEntityQuickSearchFieldPaths(entity, resolveRelatedDefinition) {
|
|
7722
|
-
if (!entity) {
|
|
7723
|
-
return [];
|
|
7724
|
-
}
|
|
7725
|
-
const paths = new Set();
|
|
7726
|
-
for (const p of collectQuickSearchPathsFromSingleEntityDefinition(entity)) {
|
|
7727
|
-
paths.add(p);
|
|
7728
|
-
}
|
|
7729
|
-
for (const p of collectNestedFieldPathsFromEntityColumns(entity)) {
|
|
7730
|
-
paths.add(p);
|
|
7731
|
-
}
|
|
7732
|
-
const related = entity.relatedEntities ?? [];
|
|
7733
|
-
for (const rel of related) {
|
|
7734
|
-
const dataPath = rel.persistence?.dataPath?.trim();
|
|
7735
|
-
if (!dataPath || rel.layout?.type !== 'merge-detail') {
|
|
7736
|
-
continue;
|
|
7737
|
-
}
|
|
7738
|
-
const parsed = rel.entity ? parseRelatedEntityFullName(rel.entity) : null;
|
|
7739
|
-
if (!parsed) {
|
|
7740
|
-
continue;
|
|
7741
|
-
}
|
|
7742
|
-
const relatedDef = await resolveRelatedDefinition(parsed.moduleName, parsed.entityName);
|
|
7743
|
-
if (!relatedDef) {
|
|
7744
|
-
continue;
|
|
7745
|
-
}
|
|
7746
|
-
for (const p of collectQuickSearchPathsFromSingleEntityDefinition(relatedDef)) {
|
|
7747
|
-
paths.add(`${dataPath}.${p}`);
|
|
7748
|
-
}
|
|
7749
|
-
for (const p of collectNestedFieldPathsFromEntityColumns(relatedDef)) {
|
|
7750
|
-
paths.add(`${dataPath}.${p}`);
|
|
7487
|
+
const vm = new AXPEntityPreloadFiltersViewModel(injector, entity);
|
|
7488
|
+
await vm.loadFilterDefinitions();
|
|
7489
|
+
return vm;
|
|
7490
|
+
}
|
|
7491
|
+
catch (error) {
|
|
7492
|
+
if (error instanceof AXPNotFoundError) {
|
|
7493
|
+
return axpRedirectToNotFound(router);
|
|
7751
7494
|
}
|
|
7495
|
+
throw error;
|
|
7752
7496
|
}
|
|
7753
|
-
|
|
7754
|
-
}
|
|
7497
|
+
};
|
|
7755
7498
|
//#endregion
|
|
7756
7499
|
|
|
7757
7500
|
//#region ---- Path / numeric helpers ----
|
|
@@ -10149,7 +9892,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
10149
9892
|
></ax-button>
|
|
10150
9893
|
</ax-suffix>
|
|
10151
9894
|
</ax-footer>
|
|
10152
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i4.AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i3.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "component", type: AXTreeViewComponent, selector: "ax-tree-view", inputs: ["datasource", "selectMode", "selectionBehavior", "dragArea", "dragBehavior", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "look", "nodeTemplate", "idField", "titleField", "tooltipField", "iconField", "expandedField", "selectedField", "indeterminateField", "disabledField", "hiddenField", "childrenField", "childrenCountField", "dataField", "inheritDisabled", "expandOnDoubleClick", "doubleClickDuration", "tooltipDelay", "controlledSelection", "selectedIds"], outputs: ["datasourceChange", "selectedIdsChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onNodeDoubleClick", "onNodeClick", "onSelectionChange", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "look"] }, { kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9895
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$1.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i4.AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i3.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "component", type: AXTreeViewComponent, selector: "ax-tree-view", inputs: ["datasource", "selectMode", "selectionBehavior", "dragArea", "dragBehavior", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "look", "nodeTemplate", "idField", "titleField", "tooltipField", "iconField", "expandedField", "selectedField", "indeterminateField", "disabledField", "hiddenField", "childrenField", "childrenCountField", "dataField", "inheritDisabled", "expandOnDoubleClick", "doubleClickDuration", "tooltipDelay", "controlledSelection", "selectedIds"], outputs: ["datasourceChange", "selectedIdsChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onNodeDoubleClick", "onNodeClick", "onSelectionChange", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
10153
9896
|
}
|
|
10154
9897
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityCategoryTreeSelectorComponent, decorators: [{
|
|
10155
9898
|
type: Component,
|
|
@@ -12392,6 +12135,7 @@ class AXPEntityListTableService {
|
|
|
12392
12135
|
const evaluatedOptions = await this.evaluateExpressions(action?.options, data);
|
|
12393
12136
|
const options = this.mergeRelatedListFormOptions(command, evaluatedOptions, relatedListExcludeProperties);
|
|
12394
12137
|
if (this.commandService.exists(command)) {
|
|
12138
|
+
const excludeProperties = options['excludeProperties'];
|
|
12395
12139
|
await this.commandService.execute(command, {
|
|
12396
12140
|
__context__: {
|
|
12397
12141
|
entity: getEntityInfo(entity).source,
|
|
@@ -12408,6 +12152,7 @@ class AXPEntityListTableService {
|
|
|
12408
12152
|
},
|
|
12409
12153
|
options,
|
|
12410
12154
|
metadata: action?.metadata,
|
|
12155
|
+
...(excludeProperties?.length ? { excludeProperties } : {}),
|
|
12411
12156
|
});
|
|
12412
12157
|
}
|
|
12413
12158
|
else {
|
|
@@ -12433,7 +12178,7 @@ class AXPEntityListTableService {
|
|
|
12433
12178
|
mergeRelatedListFormOptions(command, evaluatedOptions, relatedListExcludeProperties) {
|
|
12434
12179
|
const exclusions = relatedListExcludeProperties?.filter(Boolean);
|
|
12435
12180
|
if (!exclusions?.length ||
|
|
12436
|
-
(command !== 'Entity:Create' && command !== 'Entity:Update')) {
|
|
12181
|
+
(command !== 'Entity:Create' && command !== 'Entity:Update' && command !== 'Entity:View')) {
|
|
12437
12182
|
return evaluatedOptions;
|
|
12438
12183
|
}
|
|
12439
12184
|
return {
|
|
@@ -12484,6 +12229,7 @@ class AXPEntityListToolbarService {
|
|
|
12484
12229
|
constructor() {
|
|
12485
12230
|
//#region ---- Services & Dependencies ----
|
|
12486
12231
|
this.widgetResolver = inject(AXPWidgetRegistryService);
|
|
12232
|
+
this.entityRegistry = inject(AXPEntityDefinitionRegistryService);
|
|
12487
12233
|
}
|
|
12488
12234
|
//#endregion
|
|
12489
12235
|
//#region ---- Public Methods ----
|
|
@@ -12491,11 +12237,11 @@ class AXPEntityListToolbarService {
|
|
|
12491
12237
|
* Convert Entity to Toolbar Options
|
|
12492
12238
|
*/
|
|
12493
12239
|
async convertEntityToolbarOptions(entity, options) {
|
|
12494
|
-
const baseFilters = this.createFilterDefinitions(entity);
|
|
12240
|
+
const baseFilters = await this.createFilterDefinitions(entity);
|
|
12495
12241
|
const toolbarOptions = {
|
|
12496
12242
|
filterDefinitions: this.mergeFilterDefinitions(baseFilters, options?.customFilterDefinitions),
|
|
12497
12243
|
columnDefinitions: this.createColumnDefinitions(entity, options),
|
|
12498
|
-
sortDefinitions: this.createSortDefinitions(entity),
|
|
12244
|
+
sortDefinitions: await this.createSortDefinitions(entity),
|
|
12499
12245
|
canFilter: true,
|
|
12500
12246
|
canColumns: true,
|
|
12501
12247
|
canSort: true,
|
|
@@ -12571,30 +12317,9 @@ class AXPEntityListToolbarService {
|
|
|
12571
12317
|
/**
|
|
12572
12318
|
* Create Filter Definitions for Toolbar
|
|
12573
12319
|
*/
|
|
12574
|
-
createFilterDefinitions(entity) {
|
|
12575
|
-
|
|
12576
|
-
|
|
12577
|
-
const widgetConfig = this.widgetResolver.resolve(e.schema.interface?.type);
|
|
12578
|
-
const type = (e.options?.filter?.advance?.widgetType ||
|
|
12579
|
-
widgetConfig?.defaultFilterWidgetName ||
|
|
12580
|
-
e.schema.interface?.type);
|
|
12581
|
-
const iface = e.schema.interface ?? {};
|
|
12582
|
-
return {
|
|
12583
|
-
title: e.title,
|
|
12584
|
-
field: e.name,
|
|
12585
|
-
operator: {
|
|
12586
|
-
type: 'contains',
|
|
12587
|
-
},
|
|
12588
|
-
widget: { ...omit(iface, 'triggers'), path: e.name, type },
|
|
12589
|
-
filters: [],
|
|
12590
|
-
isParametric: false,
|
|
12591
|
-
icon: widgetConfig?.icon,
|
|
12592
|
-
filterType: {
|
|
12593
|
-
advance: e.options?.filter?.advance?.enabled ?? false,
|
|
12594
|
-
inline: e.options?.filter?.inline?.enabled ?? false,
|
|
12595
|
-
},
|
|
12596
|
-
triggers: e.schema.interface?.triggers,
|
|
12597
|
-
};
|
|
12320
|
+
async createFilterDefinitions(entity) {
|
|
12321
|
+
return collectEntityListFilterDefinitions(entity, (moduleName, entityName) => this.entityRegistry.resolve(moduleName, entityName).catch(() => null), {
|
|
12322
|
+
resolveWidget: (type) => this.widgetResolver.resolve(type),
|
|
12598
12323
|
});
|
|
12599
12324
|
}
|
|
12600
12325
|
/**
|
|
@@ -12642,23 +12367,14 @@ class AXPEntityListToolbarService {
|
|
|
12642
12367
|
}
|
|
12643
12368
|
/**
|
|
12644
12369
|
* Create Sort Definitions for Toolbar.
|
|
12645
|
-
* Includes
|
|
12370
|
+
* Includes host properties and merge-detail related fields with sort enabled.
|
|
12646
12371
|
*/
|
|
12647
|
-
createSortDefinitions(entity) {
|
|
12648
|
-
const
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
.filter((col) => col.name.includes('.') && col.title)
|
|
12654
|
-
.map((col) => ({ name: col.name, title: col.title ?? col.name }));
|
|
12655
|
-
const seen = new Set();
|
|
12656
|
-
return [...fromProperties, ...fromColumns].filter((s) => {
|
|
12657
|
-
if (seen.has(s.name))
|
|
12658
|
-
return false;
|
|
12659
|
-
seen.add(s.name);
|
|
12660
|
-
return true;
|
|
12661
|
-
});
|
|
12372
|
+
async createSortDefinitions(entity) {
|
|
12373
|
+
const fields = await collectEntityListSortableFields(entity, (moduleName, entityName) => this.entityRegistry.resolve(moduleName, entityName).catch(() => null));
|
|
12374
|
+
return fields.map((field) => ({
|
|
12375
|
+
name: field.name,
|
|
12376
|
+
title: field.title,
|
|
12377
|
+
}));
|
|
12662
12378
|
}
|
|
12663
12379
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityListToolbarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
12664
12380
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityListToolbarService }); }
|
|
@@ -13693,7 +13409,7 @@ class AXPPageComponentWidgetViewComponent extends AXPBaseWidgetComponent {
|
|
|
13693
13409
|
return;
|
|
13694
13410
|
}
|
|
13695
13411
|
for (const [path, value] of Object.entries(partial)) {
|
|
13696
|
-
this.contextService.update(path, value);
|
|
13412
|
+
this.contextService.update(path, value, { origin: 'user' });
|
|
13697
13413
|
}
|
|
13698
13414
|
}
|
|
13699
13415
|
//#endregion
|
|
@@ -13977,6 +13693,8 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
13977
13693
|
super(...arguments);
|
|
13978
13694
|
this.formatService = inject(AXFormatService);
|
|
13979
13695
|
this.translation = inject(AXTranslationService);
|
|
13696
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
13697
|
+
this.contextEvalFactory = inject(AXPContextEvalFactory);
|
|
13980
13698
|
this.entityResolver = inject(AXPEntityDefinitionRegistryService);
|
|
13981
13699
|
this.entity = computed(() => this.options()['entity'], ...(ngDevMode ? [{ debugName: "entity" }] : /* istanbul ignore next */ []));
|
|
13982
13700
|
this.multiple = computed(() => this.options()['multiple'], ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
|
|
@@ -14010,7 +13728,7 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
14010
13728
|
if (typeof item == 'object') {
|
|
14011
13729
|
return {
|
|
14012
13730
|
id: item[this.valueField()],
|
|
14013
|
-
text: this.getDisplayRaw(item),
|
|
13731
|
+
text: await this.getDisplayRaw(item),
|
|
14014
13732
|
};
|
|
14015
13733
|
}
|
|
14016
13734
|
const def = this.entityDef();
|
|
@@ -14021,7 +13739,7 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
14021
13739
|
this.loading.set(false);
|
|
14022
13740
|
return {
|
|
14023
13741
|
id: fetchedItem[this.valueField()],
|
|
14024
|
-
text: this.getDisplayRaw(fetchedItem),
|
|
13742
|
+
text: await this.getDisplayRaw(fetchedItem),
|
|
14025
13743
|
};
|
|
14026
13744
|
}
|
|
14027
13745
|
return {
|
|
@@ -14029,12 +13747,17 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
14029
13747
|
text: item,
|
|
14030
13748
|
};
|
|
14031
13749
|
}
|
|
14032
|
-
getDisplayRaw(item) {
|
|
14033
|
-
const
|
|
13750
|
+
async getDisplayRaw(item) {
|
|
13751
|
+
const locale = this.translation.getActiveLang() ?? 'en-US';
|
|
13752
|
+
return formatLookupItemDisplayAsync(item, this.entityDef(), {
|
|
14034
13753
|
displayFormat: this.options()['displayFormat'],
|
|
14035
13754
|
textField: this.textField(),
|
|
14036
|
-
}, this.formatService,
|
|
14037
|
-
|
|
13755
|
+
}, this.formatService, {
|
|
13756
|
+
expressionEvaluator: this.expressionEvaluator,
|
|
13757
|
+
contextEvalFactory: this.contextEvalFactory,
|
|
13758
|
+
translationService: this.translation,
|
|
13759
|
+
locale,
|
|
13760
|
+
}, (value) => this.translation.resolve(value));
|
|
14038
13761
|
}
|
|
14039
13762
|
get __class() {
|
|
14040
13763
|
const cls = {};
|
|
@@ -14097,6 +13820,108 @@ var lookupWidgetView_component = /*#__PURE__*/Object.freeze({
|
|
|
14097
13820
|
AXPLookupWidgetViewComponent: AXPLookupWidgetViewComponent
|
|
14098
13821
|
});
|
|
14099
13822
|
|
|
13823
|
+
//#region ---- Expression Scope ----
|
|
13824
|
+
/**
|
|
13825
|
+
* Builds the expression scope used to evaluate lookup `create.context` templates.
|
|
13826
|
+
* Matches widget-renderer `context.eval` / `context.set` semantics.
|
|
13827
|
+
*/
|
|
13828
|
+
function buildLookupExpressionScope(contextService, parentPath) {
|
|
13829
|
+
return {
|
|
13830
|
+
context: {
|
|
13831
|
+
eval: (path) => {
|
|
13832
|
+
const fullPath = path.startsWith('>') && parentPath ? `${parentPath}.${path.substring(1)}` : path;
|
|
13833
|
+
return contextService.getValue(fullPath);
|
|
13834
|
+
},
|
|
13835
|
+
set: (path, value) => {
|
|
13836
|
+
contextService.update(path, value, { origin: 'user' });
|
|
13837
|
+
},
|
|
13838
|
+
data: () => contextService.data(),
|
|
13839
|
+
isDirty: () => {
|
|
13840
|
+
if (!contextService.isSavedCommitted()) {
|
|
13841
|
+
return false;
|
|
13842
|
+
}
|
|
13843
|
+
return contextService.isDirty();
|
|
13844
|
+
},
|
|
13845
|
+
options: (path) => {
|
|
13846
|
+
if (path == null || path === '') {
|
|
13847
|
+
return contextService.getValue('options');
|
|
13848
|
+
}
|
|
13849
|
+
return contextService.getValue(`options.${path}`);
|
|
13850
|
+
},
|
|
13851
|
+
},
|
|
13852
|
+
events: {},
|
|
13853
|
+
widget: {},
|
|
13854
|
+
methods: {},
|
|
13855
|
+
vars: {},
|
|
13856
|
+
};
|
|
13857
|
+
}
|
|
13858
|
+
//#endregion
|
|
13859
|
+
//#region ---- Create Context Evaluation ----
|
|
13860
|
+
/**
|
|
13861
|
+
* Deep-evaluates expression strings inside lookup `create.context` (e.g. parentId from context).
|
|
13862
|
+
*/
|
|
13863
|
+
async function evaluateLookupCreateContext(template, expressionEvaluator, scope) {
|
|
13864
|
+
if (!template || !isObjectLike(template)) {
|
|
13865
|
+
return {};
|
|
13866
|
+
}
|
|
13867
|
+
return (await evaluateLookupCreateContextValue(template, expressionEvaluator, scope));
|
|
13868
|
+
}
|
|
13869
|
+
async function evaluateLookupCreateContextValue(value, expressionEvaluator, scope) {
|
|
13870
|
+
if (typeof value === 'string' && expressionEvaluator.isExpression(value)) {
|
|
13871
|
+
return expressionEvaluator.evaluate(value, scope);
|
|
13872
|
+
}
|
|
13873
|
+
if (isArray(value)) {
|
|
13874
|
+
const results = await Promise.all(value.map((entry) => evaluateLookupCreateContextValue(entry, expressionEvaluator, scope)));
|
|
13875
|
+
return results;
|
|
13876
|
+
}
|
|
13877
|
+
if (isObjectLike(value)) {
|
|
13878
|
+
const result = {};
|
|
13879
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
13880
|
+
result[key] = await evaluateLookupCreateContextValue(entry, expressionEvaluator, scope);
|
|
13881
|
+
}
|
|
13882
|
+
return result;
|
|
13883
|
+
}
|
|
13884
|
+
return value;
|
|
13885
|
+
}
|
|
13886
|
+
/**
|
|
13887
|
+
* Removes null/undefined entries from resolved create context before Entity:Create.
|
|
13888
|
+
*/
|
|
13889
|
+
function compactLookupCreateContext(data) {
|
|
13890
|
+
const result = {};
|
|
13891
|
+
for (const [key, value] of Object.entries(cloneDeep(data))) {
|
|
13892
|
+
if (!isNil(value) && value !== '') {
|
|
13893
|
+
result[key] = value;
|
|
13894
|
+
}
|
|
13895
|
+
}
|
|
13896
|
+
return result;
|
|
13897
|
+
}
|
|
13898
|
+
//#endregion
|
|
13899
|
+
|
|
13900
|
+
//#endregion
|
|
13901
|
+
//#region ---- Resolution ----
|
|
13902
|
+
/**
|
|
13903
|
+
* Resolves lookup create options from `create` and legacy `allowCreate` (mode).
|
|
13904
|
+
*/
|
|
13905
|
+
function resolveLookupWidgetCreateOptions(options) {
|
|
13906
|
+
const create = options.create;
|
|
13907
|
+
const legacyMode = options.allowCreate;
|
|
13908
|
+
const context = create?.context;
|
|
13909
|
+
if (create?.enable !== undefined) {
|
|
13910
|
+
if (!create.enable) {
|
|
13911
|
+
return { enabled: false, mode: 'none', context };
|
|
13912
|
+
}
|
|
13913
|
+
const mode = legacyMode && legacyMode !== 'none' ? legacyMode : 'quick';
|
|
13914
|
+
return { enabled: true, mode, context };
|
|
13915
|
+
}
|
|
13916
|
+
const mode = legacyMode ?? 'none';
|
|
13917
|
+
return {
|
|
13918
|
+
enabled: mode !== 'none',
|
|
13919
|
+
mode,
|
|
13920
|
+
context,
|
|
13921
|
+
};
|
|
13922
|
+
}
|
|
13923
|
+
//#endregion
|
|
13924
|
+
|
|
14100
13925
|
//#endregion
|
|
14101
13926
|
class AXPEntityDataSelectorRowActionsService {
|
|
14102
13927
|
constructor() {
|
|
@@ -14373,11 +14198,20 @@ function mapLegacyEntityDataSelectorOptions(legacy) {
|
|
|
14373
14198
|
normalized.category = { enabled: legacy.showCategoryFilter };
|
|
14374
14199
|
}
|
|
14375
14200
|
if (legacy.allowCreate !== undefined) {
|
|
14376
|
-
normalized.create = {
|
|
14201
|
+
normalized.create = {
|
|
14202
|
+
...(legacy.allowCreate !== undefined && {
|
|
14203
|
+
enable: legacy.allowCreate !== 'none',
|
|
14204
|
+
mode: legacy.allowCreate,
|
|
14205
|
+
}),
|
|
14206
|
+
...normalized.create,
|
|
14207
|
+
};
|
|
14377
14208
|
}
|
|
14378
14209
|
if (legacy.rowActions !== undefined) {
|
|
14379
14210
|
normalized.rowActions = legacy.rowActions;
|
|
14380
14211
|
}
|
|
14212
|
+
if (legacy.contextStore !== undefined) {
|
|
14213
|
+
normalized.contextStore = legacy.contextStore;
|
|
14214
|
+
}
|
|
14381
14215
|
return normalized;
|
|
14382
14216
|
}
|
|
14383
14217
|
/**
|
|
@@ -14413,6 +14247,9 @@ function normalizeEntityDataSelectorOptions(options) {
|
|
|
14413
14247
|
if (nested.create) {
|
|
14414
14248
|
normalized.create = { ...normalized.create, ...nested.create };
|
|
14415
14249
|
}
|
|
14250
|
+
if (nested.contextStore !== undefined) {
|
|
14251
|
+
normalized.contextStore = nested.contextStore;
|
|
14252
|
+
}
|
|
14416
14253
|
if (nested.rowActions !== undefined) {
|
|
14417
14254
|
normalized.rowActions = nested.rowActions;
|
|
14418
14255
|
}
|
|
@@ -14430,9 +14267,21 @@ class AXPEntityDataSelectorService {
|
|
|
14430
14267
|
this.categoryTreeService = inject(AXPCategoryTreeService);
|
|
14431
14268
|
this.translationService = inject(AXTranslationService);
|
|
14432
14269
|
this.rowActionsService = inject(AXPEntityDataSelectorRowActionsService);
|
|
14270
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
14433
14271
|
}
|
|
14434
14272
|
//#endregion
|
|
14435
14273
|
//#region ---- Public Methods ----
|
|
14274
|
+
/**
|
|
14275
|
+
* Resolves lookup `create.context` templates using the provided form context store.
|
|
14276
|
+
*/
|
|
14277
|
+
async resolveCreateContext(template, contextStore) {
|
|
14278
|
+
if (!template || !contextStore) {
|
|
14279
|
+
return {};
|
|
14280
|
+
}
|
|
14281
|
+
const scope = buildLookupExpressionScope(contextStore);
|
|
14282
|
+
const resolved = await evaluateLookupCreateContext(template, this.expressionEvaluator, scope);
|
|
14283
|
+
return compactLookupCreateContext(resolved);
|
|
14284
|
+
}
|
|
14436
14285
|
/**
|
|
14437
14286
|
* Open entity data selector popup.
|
|
14438
14287
|
* Accepts nested {@link AXPEntityDataSelectorOpenOptions} or deprecated flat {@link AXPEntityDataSelectorOptions}.
|
|
@@ -14448,8 +14297,8 @@ class AXPEntityDataSelectorService {
|
|
|
14448
14297
|
* Execute Entity:Create and return created item.
|
|
14449
14298
|
* Used by lookup widget and data selector for inline create.
|
|
14450
14299
|
*/
|
|
14451
|
-
async executeEntityCreate(entity, mode) {
|
|
14452
|
-
return this.executeCreate(entity, mode);
|
|
14300
|
+
async executeEntityCreate(entity, mode, initialData = {}) {
|
|
14301
|
+
return this.executeCreate(entity, mode, initialData);
|
|
14453
14302
|
}
|
|
14454
14303
|
/**
|
|
14455
14304
|
* Normalize item's phones/emails for expose/display.
|
|
@@ -14512,7 +14361,16 @@ class AXPEntityDataSelectorService {
|
|
|
14512
14361
|
const dataSource = this.createDataSource(options);
|
|
14513
14362
|
const columns = this.createColumns(options);
|
|
14514
14363
|
const searchFields = this.getSearchFields(options);
|
|
14515
|
-
const
|
|
14364
|
+
const hasCreateConfig = options.create !== undefined;
|
|
14365
|
+
const resolvedCreate = resolveLookupWidgetCreateOptions({
|
|
14366
|
+
create: options.create,
|
|
14367
|
+
allowCreate: options.create?.mode,
|
|
14368
|
+
});
|
|
14369
|
+
const allowCreate = hasCreateConfig
|
|
14370
|
+
? resolvedCreate.enabled
|
|
14371
|
+
? resolvedCreate.mode
|
|
14372
|
+
: 'none'
|
|
14373
|
+
: this.getAllowCreate(options.entity);
|
|
14516
14374
|
const rowActions = options.rowActions
|
|
14517
14375
|
? this.rowActionsService.createHandler(options.entity, options.rowActions)
|
|
14518
14376
|
: undefined;
|
|
@@ -14537,7 +14395,12 @@ class AXPEntityDataSelectorService {
|
|
|
14537
14395
|
filter: options.filter?.value ? { value: options.filter.value } : undefined,
|
|
14538
14396
|
create: {
|
|
14539
14397
|
mode: allowCreate,
|
|
14540
|
-
onCreate: allowCreate !== 'none'
|
|
14398
|
+
onCreate: allowCreate !== 'none'
|
|
14399
|
+
? async (mode) => {
|
|
14400
|
+
const data = await this.resolveCreateContext(resolvedCreate.context, options.contextStore);
|
|
14401
|
+
return this.executeCreate(options.entity, mode, data);
|
|
14402
|
+
}
|
|
14403
|
+
: undefined,
|
|
14541
14404
|
},
|
|
14542
14405
|
rowActions,
|
|
14543
14406
|
};
|
|
@@ -14685,7 +14548,7 @@ class AXPEntityDataSelectorService {
|
|
|
14685
14548
|
/**
|
|
14686
14549
|
* Execute Entity:Create and return created item
|
|
14687
14550
|
*/
|
|
14688
|
-
async executeCreate(entity, mode) {
|
|
14551
|
+
async executeCreate(entity, mode, initialData = {}) {
|
|
14689
14552
|
const quickCreate = entity.interfaces?.master?.create?.quickCreate;
|
|
14690
14553
|
const options = {};
|
|
14691
14554
|
if (mode === 'quick' && quickCreate) {
|
|
@@ -14709,7 +14572,7 @@ class AXPEntityDataSelectorService {
|
|
|
14709
14572
|
title: entity.title,
|
|
14710
14573
|
parentKey: entity.parentKey,
|
|
14711
14574
|
},
|
|
14712
|
-
data:
|
|
14575
|
+
data: initialData,
|
|
14713
14576
|
options,
|
|
14714
14577
|
},
|
|
14715
14578
|
});
|
|
@@ -15184,6 +15047,9 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
15184
15047
|
this.formatService = inject(AXFormatService);
|
|
15185
15048
|
this.translateService = inject(AXTranslationService);
|
|
15186
15049
|
this.entityDataSelectorService = inject(AXPEntityDataSelectorService);
|
|
15050
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
15051
|
+
this.contextEvalFactory = inject(AXPContextEvalFactory);
|
|
15052
|
+
this.contextStore = inject(AXPContextStore, { optional: true });
|
|
15187
15053
|
//#endregion
|
|
15188
15054
|
//#region ---- Inputs ----
|
|
15189
15055
|
this.selectedItems = input.required(...(ngDevMode ? [{ debugName: "selectedItems" }] : /* istanbul ignore next */ []));
|
|
@@ -15196,7 +15062,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
15196
15062
|
this.validationRules = input.required(...(ngDevMode ? [{ debugName: "validationRules" }] : /* istanbul ignore next */ []));
|
|
15197
15063
|
this.placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
15198
15064
|
this.hasClearButton = input(false, ...(ngDevMode ? [{ debugName: "hasClearButton" }] : /* istanbul ignore next */ []));
|
|
15199
|
-
this.
|
|
15065
|
+
this.resolvedCreate = input({ enabled: false, mode: 'none' }, ...(ngDevMode ? [{ debugName: "resolvedCreate" }] : /* istanbul ignore next */ []));
|
|
15200
15066
|
this.allowUnselect = input(true, ...(ngDevMode ? [{ debugName: "allowUnselect" }] : /* istanbul ignore next */ []));
|
|
15201
15067
|
// Entity and configuration data (for showSelector and searchByValue)
|
|
15202
15068
|
this.entityDef = input.required(...(ngDevMode ? [{ debugName: "entityDef" }] : /* istanbul ignore next */ []));
|
|
@@ -15213,6 +15079,8 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
15213
15079
|
//#region ---- Internal State ----
|
|
15214
15080
|
this.searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []));
|
|
15215
15081
|
this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
15082
|
+
this.itemLabels = signal({}, ...(ngDevMode ? [{ debugName: "itemLabels" }] : /* istanbul ignore next */ []));
|
|
15083
|
+
this.itemLabelsVersion = 0;
|
|
15216
15084
|
//#endregion
|
|
15217
15085
|
//#region ---- View Children ----
|
|
15218
15086
|
this.tagBox = viewChild('tagBoxComponent', ...(ngDevMode ? [{ debugName: "tagBox" }] : /* istanbul ignore next */ []));
|
|
@@ -15235,6 +15103,31 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
15235
15103
|
}
|
|
15236
15104
|
}
|
|
15237
15105
|
}, ...(ngDevMode ? [{ debugName: "#focusEffect" }] : /* istanbul ignore next */ []));
|
|
15106
|
+
this.#itemLabelsEffect = effect(() => {
|
|
15107
|
+
void this.translateService.getActiveLang();
|
|
15108
|
+
const items = this.selectedItemsValue();
|
|
15109
|
+
const entityDef = this.entityDef()();
|
|
15110
|
+
const valueField = this.valueFieldValue();
|
|
15111
|
+
const version = ++this.itemLabelsVersion;
|
|
15112
|
+
void Promise.all(items.map(async (item) => {
|
|
15113
|
+
const id = String(get(item, valueField) ?? '');
|
|
15114
|
+
const label = await formatLookupItemDisplayAsync(item, entityDef, {
|
|
15115
|
+
displayFormat: this.displayFormatValue(),
|
|
15116
|
+
textField: this.displayFieldValue(),
|
|
15117
|
+
}, this.formatService, {
|
|
15118
|
+
expressionEvaluator: this.expressionEvaluator,
|
|
15119
|
+
contextEvalFactory: this.contextEvalFactory,
|
|
15120
|
+
translationService: this.translateService,
|
|
15121
|
+
locale: this.translateService.getActiveLang() ?? 'en-US',
|
|
15122
|
+
}, (value) => this.translateService.resolve(value));
|
|
15123
|
+
return [id, label];
|
|
15124
|
+
})).then((entries) => {
|
|
15125
|
+
if (version !== this.itemLabelsVersion) {
|
|
15126
|
+
return;
|
|
15127
|
+
}
|
|
15128
|
+
this.itemLabels.set(Object.fromEntries(entries));
|
|
15129
|
+
});
|
|
15130
|
+
}, ...(ngDevMode ? [{ debugName: "#itemLabelsEffect" }] : /* istanbul ignore next */ []));
|
|
15238
15131
|
//#endregion
|
|
15239
15132
|
//#region ---- Computed Properties ----
|
|
15240
15133
|
this.tagBoxComponent = computed(() => this.tagBox(), ...(ngDevMode ? [{ debugName: "tagBoxComponent" }] : /* istanbul ignore next */ []));
|
|
@@ -15250,6 +15143,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
15250
15143
|
this.placeholderValue = computed(() => this.placeholder()?.() ?? '', ...(ngDevMode ? [{ debugName: "placeholderValue" }] : /* istanbul ignore next */ []));
|
|
15251
15144
|
}
|
|
15252
15145
|
#focusEffect;
|
|
15146
|
+
#itemLabelsEffect;
|
|
15253
15147
|
focus() {
|
|
15254
15148
|
this.shouldFocus.set(true);
|
|
15255
15149
|
}
|
|
@@ -15315,11 +15209,9 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
15315
15209
|
}
|
|
15316
15210
|
//#endregion
|
|
15317
15211
|
//#region ---- Utility Methods ----
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
textField: this.displayFieldValue(),
|
|
15322
|
-
}, this.formatService, (value) => this.translateService.resolve(value));
|
|
15212
|
+
getItemLabel(item) {
|
|
15213
|
+
const id = String(get(item, this.valueFieldValue()) ?? '');
|
|
15214
|
+
return this.itemLabels()[id] ?? '';
|
|
15323
15215
|
}
|
|
15324
15216
|
/**
|
|
15325
15217
|
* Get current input value from tag box
|
|
@@ -15379,6 +15271,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
15379
15271
|
.map((item) => get(item, this.valueField()()))
|
|
15380
15272
|
.filter((id) => id != null);
|
|
15381
15273
|
try {
|
|
15274
|
+
const createOptions = this.resolvedCreate();
|
|
15382
15275
|
const result = await this.entityDataSelectorService.open({
|
|
15383
15276
|
entity,
|
|
15384
15277
|
title: `${this.translateService.translateSync(entity.formats.plural ?? '')}`,
|
|
@@ -15387,7 +15280,12 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
15387
15280
|
filters: this.customFilter()(),
|
|
15388
15281
|
parentFilters: this.parentFilters(),
|
|
15389
15282
|
columns: this.columns()(),
|
|
15390
|
-
|
|
15283
|
+
create: {
|
|
15284
|
+
enable: createOptions.enabled,
|
|
15285
|
+
mode: createOptions.mode,
|
|
15286
|
+
context: createOptions.context,
|
|
15287
|
+
},
|
|
15288
|
+
contextStore: this.contextStore ?? undefined,
|
|
15391
15289
|
initialSearchTerm: searchTerm,
|
|
15392
15290
|
selectedItemIds: selectedItemIds.length > 0 ? selectedItemIds : undefined,
|
|
15393
15291
|
rowActions: this.rowActions(),
|
|
@@ -15413,7 +15311,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
15413
15311
|
this.clear();
|
|
15414
15312
|
}
|
|
15415
15313
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLookupWidgetTagboxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
15416
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLookupWidgetTagboxComponent, isStandalone: true, selector: "axp-lookup-widget-tagbox", inputs: { selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: true, transformFunction: null }, displayField: { classPropertyName: "displayField", publicName: "displayField", isSignal: true, isRequired: true, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: true, transformFunction: null }, displayFormat: { classPropertyName: "displayFormat", publicName: "displayFormat", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: true, transformFunction: null }, validationRules: { classPropertyName: "validationRules", publicName: "validationRules", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hasClearButton: { classPropertyName: "hasClearButton", publicName: "hasClearButton", isSignal: true, isRequired: false, transformFunction: null },
|
|
15314
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLookupWidgetTagboxComponent, isStandalone: true, selector: "axp-lookup-widget-tagbox", inputs: { selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: true, transformFunction: null }, displayField: { classPropertyName: "displayField", publicName: "displayField", isSignal: true, isRequired: true, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: true, transformFunction: null }, displayFormat: { classPropertyName: "displayFormat", publicName: "displayFormat", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: true, transformFunction: null }, validationRules: { classPropertyName: "validationRules", publicName: "validationRules", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hasClearButton: { classPropertyName: "hasClearButton", publicName: "hasClearButton", isSignal: true, isRequired: false, transformFunction: null }, resolvedCreate: { classPropertyName: "resolvedCreate", publicName: "resolvedCreate", isSignal: true, isRequired: false, transformFunction: null }, allowUnselect: { classPropertyName: "allowUnselect", publicName: "allowUnselect", isSignal: true, isRequired: false, transformFunction: null }, entityDef: { classPropertyName: "entityDef", publicName: "entityDef", isSignal: true, isRequired: true, transformFunction: null }, customFilter: { classPropertyName: "customFilter", publicName: "customFilter", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, parentFilters: { classPropertyName: "parentFilters", publicName: "parentFilters", isSignal: true, isRequired: false, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, onSetLoading: { classPropertyName: "onSetLoading", publicName: "onSetLoading", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { valueChanged: "valueChanged" }, providers: [
|
|
15417
15315
|
{
|
|
15418
15316
|
provide: LookupWidgetLookBase,
|
|
15419
15317
|
useExisting: AXPLookupWidgetTagboxComponent,
|
|
@@ -15466,7 +15364,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
15466
15364
|
</ax-tag-box>
|
|
15467
15365
|
<ng-template #tagTemplate let-item let-index="index">
|
|
15468
15366
|
<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">
|
|
15469
|
-
<span>{{
|
|
15367
|
+
<span>{{ getItemLabel(item) }}</span>
|
|
15470
15368
|
<button type="button" (click)="tagBoxComponent.removeItem(index)">
|
|
15471
15369
|
<ax-icon class="ax-icon ax-icon-close"></ax-icon>
|
|
15472
15370
|
</button>
|
|
@@ -15526,7 +15424,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
15526
15424
|
</ax-tag-box>
|
|
15527
15425
|
<ng-template #tagTemplate let-item let-index="index">
|
|
15528
15426
|
<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">
|
|
15529
|
-
<span>{{
|
|
15427
|
+
<span>{{ getItemLabel(item) }}</span>
|
|
15530
15428
|
<button type="button" (click)="tagBoxComponent.removeItem(index)">
|
|
15531
15429
|
<ax-icon class="ax-icon ax-icon-close"></ax-icon>
|
|
15532
15430
|
</button>
|
|
@@ -15552,7 +15450,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
15552
15450
|
},
|
|
15553
15451
|
],
|
|
15554
15452
|
}]
|
|
15555
|
-
}], propDecorators: { selectedItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItems", required: true }] }], displayField: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayField", required: true }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: true }] }], displayFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayFormat", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: true }] }], validationRules: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationRules", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hasClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasClearButton", required: false }] }],
|
|
15453
|
+
}], propDecorators: { selectedItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItems", required: true }] }], displayField: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayField", required: true }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: true }] }], displayFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayFormat", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: true }] }], validationRules: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationRules", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hasClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasClearButton", required: false }] }], resolvedCreate: [{ type: i0.Input, args: [{ isSignal: true, alias: "resolvedCreate", required: false }] }], allowUnselect: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowUnselect", required: false }] }], entityDef: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityDef", required: true }] }], customFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "customFilter", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], parentFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentFilters", required: false }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], onSetLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "onSetLoading", required: true }] }], valueChanged: [{ type: i0.Output, args: ["valueChanged"] }], tagBox: [{ type: i0.ViewChild, args: ['tagBoxComponent', { isSignal: true }] }] } });
|
|
15556
15454
|
|
|
15557
15455
|
class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
15558
15456
|
constructor() {
|
|
@@ -15595,7 +15493,10 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15595
15493
|
this.allowUnselect = computed(() => this.options()['allowUnselect'] ?? true, ...(ngDevMode ? [{ debugName: "allowUnselect" }] : /* istanbul ignore next */ []));
|
|
15596
15494
|
this.look = computed(() => this.options()['look'] ?? 'lookup', ...(ngDevMode ? [{ debugName: "look" }] : /* istanbul ignore next */ []));
|
|
15597
15495
|
this.displayField = computed(() => resolveLookupDisplayField(this.entityDef(), { textField: this.textField() }), ...(ngDevMode ? [{ debugName: "displayField" }] : /* istanbul ignore next */ []));
|
|
15598
|
-
this.
|
|
15496
|
+
this.resolvedCreate = computed(() => resolveLookupWidgetCreateOptions({
|
|
15497
|
+
create: this.options()['create'],
|
|
15498
|
+
allowCreate: this.options()['allowCreate'],
|
|
15499
|
+
}), ...(ngDevMode ? [{ debugName: "resolvedCreate" }] : /* istanbul ignore next */ []));
|
|
15599
15500
|
this.selectorRowActions = computed(() => this.options()['selectorRowActions'], ...(ngDevMode ? [{ debugName: "selectorRowActions" }] : /* istanbul ignore next */ []));
|
|
15600
15501
|
this.valueField = computed(() => this.entityDef()?.properties.find((c) => c.name == 'id')?.name ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
|
|
15601
15502
|
this.displayFormat = computed(() => resolveLookupDisplayTemplate(this.entityDef(), {
|
|
@@ -15641,6 +15542,12 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15641
15542
|
//#region ---- Business Logic Methods (Passed to Dumb Components) ----
|
|
15642
15543
|
this.setLoading = (loading) => {
|
|
15643
15544
|
this.isLoading.set(loading);
|
|
15545
|
+
if (loading) {
|
|
15546
|
+
this.beginHydration();
|
|
15547
|
+
}
|
|
15548
|
+
else {
|
|
15549
|
+
this.endHydration();
|
|
15550
|
+
}
|
|
15644
15551
|
};
|
|
15645
15552
|
/** @param syncContext When false, only updates UI (hydration/revert); skips context writes. */
|
|
15646
15553
|
this.setItems = (items, syncContext = true) => {
|
|
@@ -15650,6 +15557,8 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15650
15557
|
items = items.filter((item) => item != null);
|
|
15651
15558
|
// Normalize phones/emails from repeater nested structure to { value: string }
|
|
15652
15559
|
items = items.map((item) => this.entityDataSelectorService.normalizeItemContactArrays(item));
|
|
15560
|
+
/** Preserve raw entity fields (e.g. MLS maps) before display-field resolution for expose writes. */
|
|
15561
|
+
const itemsForExpose = cloneDeep(items);
|
|
15653
15562
|
const displayField = this.displayField();
|
|
15654
15563
|
items = items.map((item) => {
|
|
15655
15564
|
const raw = get(item, displayField);
|
|
@@ -15664,10 +15573,32 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15664
15573
|
}
|
|
15665
15574
|
const keys = items.map((item) => get(item, this.valueField()));
|
|
15666
15575
|
const text = items.map((item) => this.mlsResolver.resolve(get(item, displayField)));
|
|
15576
|
+
const newValue = this.singleOrMultiple(keys);
|
|
15577
|
+
const widgetPath = this.fullPath();
|
|
15578
|
+
const savedWidgetValue = widgetPath ? this.contextService.getSavedValue(widgetPath) : undefined;
|
|
15579
|
+
const selectionMatchesSaved = this.contextService.isSavedCommitted() &&
|
|
15580
|
+
widgetPath != null &&
|
|
15581
|
+
isSelectionValueEqual(newValue, savedWidgetValue);
|
|
15667
15582
|
if (this.expose()) {
|
|
15668
|
-
|
|
15583
|
+
AXPDebugService.instance?.trace(FORM_DIRTY_TRACE_NS, 'lookup-widget', 'setItems expose', () => ({
|
|
15584
|
+
path: this.fullPath(),
|
|
15585
|
+
items: items.map((item) => get(item, this.valueField())),
|
|
15586
|
+
expose: this.expose(),
|
|
15587
|
+
selectionMatchesSaved,
|
|
15588
|
+
}));
|
|
15589
|
+
if (selectionMatchesSaved) {
|
|
15590
|
+
this.syncExposePathsToSavedBaseline();
|
|
15591
|
+
}
|
|
15592
|
+
else {
|
|
15593
|
+
this.expoesItems(itemsForExpose);
|
|
15594
|
+
}
|
|
15669
15595
|
}
|
|
15670
|
-
|
|
15596
|
+
AXPDebugService.instance?.trace(FORM_DIRTY_TRACE_NS, 'lookup-widget', 'setItems setValue', () => ({
|
|
15597
|
+
path: this.fullPath(),
|
|
15598
|
+
newValue,
|
|
15599
|
+
keys,
|
|
15600
|
+
syncContext,
|
|
15601
|
+
}));
|
|
15671
15602
|
if (this.filterMode()) {
|
|
15672
15603
|
this.setValue({
|
|
15673
15604
|
value: newValue,
|
|
@@ -15680,12 +15611,16 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15680
15611
|
else {
|
|
15681
15612
|
this.setValue(newValue);
|
|
15682
15613
|
}
|
|
15614
|
+
if (this.expose() && selectionMatchesSaved) {
|
|
15615
|
+
this.syncExposePathsToSavedBaseline();
|
|
15616
|
+
}
|
|
15683
15617
|
};
|
|
15684
15618
|
}
|
|
15685
15619
|
#efEntity;
|
|
15686
15620
|
#efValue;
|
|
15687
15621
|
async findByValue() {
|
|
15688
15622
|
this.isLoading.set(true);
|
|
15623
|
+
this.beginHydration();
|
|
15689
15624
|
const rawValue = this.getValue();
|
|
15690
15625
|
// When multiple is true, ensure we always work with arrays
|
|
15691
15626
|
const values = this.multiple()
|
|
@@ -15694,6 +15629,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15694
15629
|
if (!values.length) {
|
|
15695
15630
|
this.setItems([], false);
|
|
15696
15631
|
this.isLoading.set(false);
|
|
15632
|
+
this.endHydration();
|
|
15697
15633
|
return;
|
|
15698
15634
|
}
|
|
15699
15635
|
try {
|
|
@@ -15726,6 +15662,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15726
15662
|
}
|
|
15727
15663
|
finally {
|
|
15728
15664
|
this.isLoading.set(false);
|
|
15665
|
+
this.endHydration();
|
|
15729
15666
|
}
|
|
15730
15667
|
}
|
|
15731
15668
|
//#region ---- Event Handlers from Dumb Components ----
|
|
@@ -15736,7 +15673,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15736
15673
|
const entity = this.entityDef();
|
|
15737
15674
|
if (!entity || !entity.commands?.create?.execute)
|
|
15738
15675
|
return;
|
|
15739
|
-
const mode = this.
|
|
15676
|
+
const { mode } = this.resolvedCreate();
|
|
15740
15677
|
if (mode !== 'full' && mode !== 'quick')
|
|
15741
15678
|
return;
|
|
15742
15679
|
await this.executeCreate(mode);
|
|
@@ -15746,8 +15683,11 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15746
15683
|
if (!entity || !entity.commands?.create?.execute)
|
|
15747
15684
|
return;
|
|
15748
15685
|
this.isLoading.set(true);
|
|
15686
|
+
this.beginHydration();
|
|
15749
15687
|
try {
|
|
15750
|
-
const
|
|
15688
|
+
const { context } = this.resolvedCreate();
|
|
15689
|
+
const createData = await this.entityDataSelectorService.resolveCreateContext(context, this.contextService);
|
|
15690
|
+
const createdItem = await this.entityDataSelectorService.executeEntityCreate(entity, mode, createData);
|
|
15751
15691
|
if (createdItem) {
|
|
15752
15692
|
const currentItems = this.selectedItems();
|
|
15753
15693
|
const valueField = this.valueField();
|
|
@@ -15767,6 +15707,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15767
15707
|
}
|
|
15768
15708
|
finally {
|
|
15769
15709
|
this.isLoading.set(false);
|
|
15710
|
+
this.endHydration();
|
|
15770
15711
|
}
|
|
15771
15712
|
}
|
|
15772
15713
|
/**
|
|
@@ -15775,9 +15716,31 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15775
15716
|
* so e.g. `{ person: { educationLevel: { id, title } } }` would replace the entire `person`
|
|
15776
15717
|
* object and drop sibling fields like `person.educationLevelId`, causing a value/effect loop.
|
|
15777
15718
|
*/
|
|
15778
|
-
|
|
15719
|
+
syncExposePathsToSavedBaseline() {
|
|
15779
15720
|
const exposeValue = castArray(this.expose());
|
|
15780
|
-
const
|
|
15721
|
+
const parentPaths = new Set();
|
|
15722
|
+
exposeValue.forEach((item) => {
|
|
15723
|
+
const target = typeof item === 'string' ? item : item.target;
|
|
15724
|
+
if (target.includes('.')) {
|
|
15725
|
+
parentPaths.add(target.split('.').slice(0, -1).join('.'));
|
|
15726
|
+
}
|
|
15727
|
+
this.contextService.syncPathToSavedBaseline(target, { origin: 'system' });
|
|
15728
|
+
});
|
|
15729
|
+
const saved = this.contextService.saved();
|
|
15730
|
+
parentPaths.forEach((parentPath) => {
|
|
15731
|
+
if (!has(saved, parentPath)) {
|
|
15732
|
+
this.contextService.syncPathToSavedBaseline(parentPath, { origin: 'system' });
|
|
15733
|
+
}
|
|
15734
|
+
});
|
|
15735
|
+
AXPDebugService.instance?.trace(FORM_DIRTY_TRACE_NS, 'lookup-widget', 'syncExposePathsToSavedBaseline', () => ({
|
|
15736
|
+
path: this.fullPath(),
|
|
15737
|
+
expose: this.expose(),
|
|
15738
|
+
parentPaths: [...parentPaths],
|
|
15739
|
+
}));
|
|
15740
|
+
}
|
|
15741
|
+
expoesItems(sourceItems) {
|
|
15742
|
+
const exposeValue = castArray(this.expose());
|
|
15743
|
+
const items = sourceItems ?? this.selectedItems();
|
|
15781
15744
|
const isEmpty = !items || items.length === 0;
|
|
15782
15745
|
if (isEmpty) {
|
|
15783
15746
|
const parentPaths = new Set();
|
|
@@ -15788,7 +15751,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15788
15751
|
parentPaths.add(pathParts.slice(0, -1).join('.'));
|
|
15789
15752
|
}
|
|
15790
15753
|
else {
|
|
15791
|
-
this.contextService.update(i, null);
|
|
15754
|
+
this.contextService.update(i, null, { origin: 'user' });
|
|
15792
15755
|
}
|
|
15793
15756
|
}
|
|
15794
15757
|
else {
|
|
@@ -15797,25 +15760,25 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15797
15760
|
parentPaths.add(pathParts.slice(0, -1).join('.'));
|
|
15798
15761
|
}
|
|
15799
15762
|
else {
|
|
15800
|
-
this.contextService.update(i.target, null);
|
|
15763
|
+
this.contextService.update(i.target, null, { origin: 'user' });
|
|
15801
15764
|
}
|
|
15802
15765
|
}
|
|
15803
15766
|
});
|
|
15804
15767
|
parentPaths.forEach((parentPath) => {
|
|
15805
|
-
this.contextService.update(parentPath, null);
|
|
15768
|
+
this.contextService.update(parentPath, null, { origin: 'user' });
|
|
15806
15769
|
});
|
|
15807
15770
|
return;
|
|
15808
15771
|
}
|
|
15809
15772
|
exposeValue.forEach((i) => {
|
|
15810
15773
|
if (typeof i === 'string') {
|
|
15811
15774
|
const values = items.map((item) => set({}, i, get(item, i)));
|
|
15812
|
-
this.contextService.update(i, this.singleOrMultiple(values));
|
|
15775
|
+
this.contextService.update(i, this.singleOrMultiple(values), { origin: 'user' });
|
|
15813
15776
|
}
|
|
15814
15777
|
else {
|
|
15815
15778
|
const values = this.multiple()
|
|
15816
15779
|
? items.map((item) => set({}, i.source, get(item, i.source)))
|
|
15817
15780
|
: items.map((item) => get(item, i.source));
|
|
15818
|
-
this.contextService.update(i.target, this.singleOrMultiple(values));
|
|
15781
|
+
this.contextService.update(i.target, this.singleOrMultiple(values), { origin: 'user' });
|
|
15819
15782
|
}
|
|
15820
15783
|
});
|
|
15821
15784
|
}
|
|
@@ -15858,7 +15821,6 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15858
15821
|
[placeholder]="placeholder"
|
|
15859
15822
|
[validationRules]="validationRules"
|
|
15860
15823
|
[hasClearButton]="hasClearButton()"
|
|
15861
|
-
[allowCreate]="allowCreate()"
|
|
15862
15824
|
[showItemTooltip]="showItemTooltip()"
|
|
15863
15825
|
[isItemTruncated]="isItemTruncated()"
|
|
15864
15826
|
(valueChanged)="handleComponentValueChanged($event)"
|
|
@@ -15877,7 +15839,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15877
15839
|
[isLoading]="isLoading"
|
|
15878
15840
|
[validationRules]="validationRules"
|
|
15879
15841
|
[hasClearButton]="hasClearButton()"
|
|
15880
|
-
[
|
|
15842
|
+
[resolvedCreate]="resolvedCreate()"
|
|
15881
15843
|
[allowUnselect]="allowUnselect()"
|
|
15882
15844
|
[entityDef]="entityDef"
|
|
15883
15845
|
[customFilter]="customFilter"
|
|
@@ -15889,7 +15851,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15889
15851
|
/>
|
|
15890
15852
|
}
|
|
15891
15853
|
}
|
|
15892
|
-
@if (
|
|
15854
|
+
@if (resolvedCreate().enabled) {
|
|
15893
15855
|
<div class="ax-sm">
|
|
15894
15856
|
<ax-button
|
|
15895
15857
|
color="primary"
|
|
@@ -15904,7 +15866,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
15904
15866
|
}
|
|
15905
15867
|
</div>
|
|
15906
15868
|
}
|
|
15907
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPLookupWidgetSelectComponent, selector: "axp-lookup-widget-select", inputs: ["entityDef", "customFilter", "selectedItems", "displayField", "valueField", "disabled", "multiple", "validationRules", "placeholder", "hasClearButton", "allowCreate", "showItemTooltip", "isItemTruncated"], outputs: ["valueChanged"] }, { kind: "component", type: AXPLookupWidgetTagboxComponent, selector: "axp-lookup-widget-tagbox", inputs: ["selectedItems", "displayField", "valueField", "displayFormat", "disabled", "multiple", "isLoading", "validationRules", "placeholder", "hasClearButton", "
|
|
15869
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPLookupWidgetSelectComponent, selector: "axp-lookup-widget-select", inputs: ["entityDef", "customFilter", "selectedItems", "displayField", "valueField", "disabled", "multiple", "validationRules", "placeholder", "hasClearButton", "allowCreate", "showItemTooltip", "isItemTruncated"], outputs: ["valueChanged"] }, { kind: "component", type: AXPLookupWidgetTagboxComponent, selector: "axp-lookup-widget-tagbox", inputs: ["selectedItems", "displayField", "valueField", "displayFormat", "disabled", "multiple", "isLoading", "validationRules", "placeholder", "hasClearButton", "resolvedCreate", "allowUnselect", "entityDef", "customFilter", "columns", "parentFilters", "rowActions", "onSetLoading"], outputs: ["valueChanged"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
15908
15870
|
}
|
|
15909
15871
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLookupWidgetEditComponent, decorators: [{
|
|
15910
15872
|
type: Component,
|
|
@@ -15927,7 +15889,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
15927
15889
|
[placeholder]="placeholder"
|
|
15928
15890
|
[validationRules]="validationRules"
|
|
15929
15891
|
[hasClearButton]="hasClearButton()"
|
|
15930
|
-
[allowCreate]="allowCreate()"
|
|
15931
15892
|
[showItemTooltip]="showItemTooltip()"
|
|
15932
15893
|
[isItemTruncated]="isItemTruncated()"
|
|
15933
15894
|
(valueChanged)="handleComponentValueChanged($event)"
|
|
@@ -15946,7 +15907,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
15946
15907
|
[isLoading]="isLoading"
|
|
15947
15908
|
[validationRules]="validationRules"
|
|
15948
15909
|
[hasClearButton]="hasClearButton()"
|
|
15949
|
-
[
|
|
15910
|
+
[resolvedCreate]="resolvedCreate()"
|
|
15950
15911
|
[allowUnselect]="allowUnselect()"
|
|
15951
15912
|
[entityDef]="entityDef"
|
|
15952
15913
|
[customFilter]="customFilter"
|
|
@@ -15958,7 +15919,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
15958
15919
|
/>
|
|
15959
15920
|
}
|
|
15960
15921
|
}
|
|
15961
|
-
@if (
|
|
15922
|
+
@if (resolvedCreate().enabled) {
|
|
15962
15923
|
<div class="ax-sm">
|
|
15963
15924
|
<ax-button
|
|
15964
15925
|
color="primary"
|
|
@@ -16004,6 +15965,8 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
16004
15965
|
this.entityService = inject(AXPEntityService);
|
|
16005
15966
|
this.entityResolver = inject(AXPEntityDefinitionRegistryService);
|
|
16006
15967
|
this.queryExecutor = inject(AXPQueryExecutor);
|
|
15968
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
15969
|
+
this.contextEvalFactory = inject(AXPContextEvalFactory);
|
|
16007
15970
|
//#endregion
|
|
16008
15971
|
//#region ---- View Children ----
|
|
16009
15972
|
this.moreButton = viewChild('moreButton', ...(ngDevMode ? [{ debugName: "moreButton" }] : /* istanbul ignore next */ []));
|
|
@@ -16041,11 +16004,16 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
16041
16004
|
this.resolveError = signal(null, ...(ngDevMode ? [{ debugName: "resolveError" }] : /* istanbul ignore next */ []));
|
|
16042
16005
|
this.summaryLabel = signal('', ...(ngDevMode ? [{ debugName: "summaryLabel" }] : /* istanbul ignore next */ []));
|
|
16043
16006
|
this.popoverHeader = signal('', ...(ngDevMode ? [{ debugName: "popoverHeader" }] : /* istanbul ignore next */ []));
|
|
16007
|
+
this.mainItemLabels = signal([], ...(ngDevMode ? [{ debugName: "mainItemLabels" }] : /* istanbul ignore next */ []));
|
|
16008
|
+
this.lazyPopoverItemLabels = signal([], ...(ngDevMode ? [{ debugName: "lazyPopoverItemLabels" }] : /* istanbul ignore next */ []));
|
|
16044
16009
|
this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : /* istanbul ignore next */ []));
|
|
16045
16010
|
this.hydratedDisplayItems = signal(null, ...(ngDevMode ? [{ debugName: "hydratedDisplayItems" }] : /* istanbul ignore next */ []));
|
|
16046
16011
|
this.hydrateRequestId = 0;
|
|
16012
|
+
this.mainLabelsVersion = 0;
|
|
16013
|
+
this.lazyPopoverLabelsVersion = 0;
|
|
16047
16014
|
//#endregion
|
|
16048
16015
|
//#region ---- Computed ----
|
|
16016
|
+
this.popoverItemLabels = computed(() => this.isHydratedStrategy() ? this.mainItemLabels() : this.lazyPopoverItemLabels(), ...(ngDevMode ? [{ debugName: "popoverItemLabels" }] : /* istanbul ignore next */ []));
|
|
16049
16017
|
this.displayItems = computed(() => isNil(this.rawValue)
|
|
16050
16018
|
? []
|
|
16051
16019
|
: castArray(this.rawValue)
|
|
@@ -16165,6 +16133,36 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
16165
16133
|
}
|
|
16166
16134
|
void this.hydrateScalarIds(entityKey, values);
|
|
16167
16135
|
});
|
|
16136
|
+
effect(() => {
|
|
16137
|
+
void this.translation.getActiveLang();
|
|
16138
|
+
this.entityDef();
|
|
16139
|
+
const items = this.allItems();
|
|
16140
|
+
const version = ++this.mainLabelsVersion;
|
|
16141
|
+
void this.resolveLabelsForItems(items).then((labels) => {
|
|
16142
|
+
if (version === this.mainLabelsVersion) {
|
|
16143
|
+
this.mainItemLabels.set(labels);
|
|
16144
|
+
}
|
|
16145
|
+
});
|
|
16146
|
+
});
|
|
16147
|
+
effect(() => {
|
|
16148
|
+
if (this.isHydratedStrategy()) {
|
|
16149
|
+
return;
|
|
16150
|
+
}
|
|
16151
|
+
void this.translation.getActiveLang();
|
|
16152
|
+
this.entityDef();
|
|
16153
|
+
const status = this.resolveStatus();
|
|
16154
|
+
const items = this.resolvedPopoverItems();
|
|
16155
|
+
if (status !== 'ready') {
|
|
16156
|
+
this.lazyPopoverItemLabels.set([]);
|
|
16157
|
+
return;
|
|
16158
|
+
}
|
|
16159
|
+
const version = ++this.lazyPopoverLabelsVersion;
|
|
16160
|
+
void this.resolveLabelsForItems(items).then((labels) => {
|
|
16161
|
+
if (version === this.lazyPopoverLabelsVersion) {
|
|
16162
|
+
this.lazyPopoverItemLabels.set(labels);
|
|
16163
|
+
}
|
|
16164
|
+
});
|
|
16165
|
+
});
|
|
16168
16166
|
}
|
|
16169
16167
|
//#endregion
|
|
16170
16168
|
//#region ---- Public methods ----
|
|
@@ -16220,7 +16218,9 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
16220
16218
|
let resolvedTitle = '';
|
|
16221
16219
|
if (headerItem != null && this.hasDisplayTextOnLookupValue(headerItem)) {
|
|
16222
16220
|
resolvedTitle =
|
|
16223
|
-
typeof headerItem === 'object'
|
|
16221
|
+
typeof headerItem === 'object'
|
|
16222
|
+
? await this.resolveItemLabel(headerItem)
|
|
16223
|
+
: this.formatDisplayValue(headerItem);
|
|
16224
16224
|
}
|
|
16225
16225
|
else if (!this.isMultiValueLookup()) {
|
|
16226
16226
|
const rowText = this.getRowDisplayTextFromTextField();
|
|
@@ -16229,8 +16229,7 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
16229
16229
|
}
|
|
16230
16230
|
}
|
|
16231
16231
|
if (!resolvedTitle) {
|
|
16232
|
-
|
|
16233
|
-
resolvedTitle = typeof displayTitle === 'string' ? displayTitle : this.translation.resolve(displayTitle);
|
|
16232
|
+
resolvedTitle = await this.resolveItemLabel(headerItem);
|
|
16234
16233
|
if (isUnresolvedEntityDisplayTemplate(resolvedTitle)) {
|
|
16235
16234
|
resolvedTitle = '';
|
|
16236
16235
|
}
|
|
@@ -16296,8 +16295,22 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
16296
16295
|
const values = castArray(raw).filter((value) => value != null && value !== '');
|
|
16297
16296
|
return values.length > 0 && values.every((value) => this.hasDisplayTextOnLookupValue(value));
|
|
16298
16297
|
}
|
|
16299
|
-
|
|
16300
|
-
|
|
16298
|
+
getItemLabel(index) {
|
|
16299
|
+
return this.mainItemLabels()[index] ?? '';
|
|
16300
|
+
}
|
|
16301
|
+
getPopoverItemLabel(index) {
|
|
16302
|
+
return this.popoverItemLabels()[index] ?? '';
|
|
16303
|
+
}
|
|
16304
|
+
//#endregion
|
|
16305
|
+
//#region ---- Private methods ----
|
|
16306
|
+
async resolveLabelsForItems(items) {
|
|
16307
|
+
return Promise.all(items.map((item) => this.resolveItemLabel(item)));
|
|
16308
|
+
}
|
|
16309
|
+
async resolveItemLabel(item) {
|
|
16310
|
+
if (item == null) {
|
|
16311
|
+
return '';
|
|
16312
|
+
}
|
|
16313
|
+
if (typeof item === 'object' && this.translation.isValidMultiLanguageObject(item)) {
|
|
16301
16314
|
return this.translation.resolve(item);
|
|
16302
16315
|
}
|
|
16303
16316
|
if (!this.isMultiValueLookup()) {
|
|
@@ -16306,16 +16319,19 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
16306
16319
|
return this.formatDisplayValue(rowText);
|
|
16307
16320
|
}
|
|
16308
16321
|
}
|
|
16309
|
-
if (
|
|
16310
|
-
if (typeof item
|
|
16311
|
-
return this.
|
|
16322
|
+
if (this.hasDisplayTextOnLookupValue(item)) {
|
|
16323
|
+
if (typeof item !== 'object') {
|
|
16324
|
+
return this.formatDisplayValue(item);
|
|
16312
16325
|
}
|
|
16313
|
-
return this.formatDisplayValue(item);
|
|
16314
16326
|
}
|
|
16315
|
-
|
|
16327
|
+
const locale = this.translation.getActiveLang() ?? 'en-US';
|
|
16328
|
+
return formatLookupItemDisplayAsync(item, this.entityDef(), this.lookupDisplayOptions(), this.formatService, {
|
|
16329
|
+
expressionEvaluator: this.expressionEvaluator,
|
|
16330
|
+
contextEvalFactory: this.contextEvalFactory,
|
|
16331
|
+
translationService: this.translation,
|
|
16332
|
+
locale,
|
|
16333
|
+
}, (value) => this.translation.resolve(value));
|
|
16316
16334
|
}
|
|
16317
|
-
//#endregion
|
|
16318
|
-
//#region ---- Private methods ----
|
|
16319
16335
|
async refreshSummaryLabel(count) {
|
|
16320
16336
|
const text = await this.translation.translateAsync('@general:widgets.lookup.column.items-count', {
|
|
16321
16337
|
params: { count: String(count) },
|
|
@@ -16639,10 +16655,6 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
16639
16655
|
return !isNil(candidate) && candidate !== '' && !this.isLikelyEntityId(candidate);
|
|
16640
16656
|
});
|
|
16641
16657
|
}
|
|
16642
|
-
renderLookupLabel(value) {
|
|
16643
|
-
const label = formatLookupItemDisplay(value, this.entityDef(), this.lookupDisplayOptions(), this.formatService, (item) => this.translation.resolve(item));
|
|
16644
|
-
return typeof label === 'string' ? label : this.translation.resolve(label);
|
|
16645
|
-
}
|
|
16646
16658
|
formatDisplayValue(value) {
|
|
16647
16659
|
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
16648
16660
|
return String(value);
|
|
@@ -16663,11 +16675,11 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
16663
16675
|
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);
|
|
16664
16676
|
}
|
|
16665
16677
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLookupWidgetColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
16666
|
-
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
|
|
16678
|
+
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\n [class.ax-cursor-pointer]=\"detailPopoverEnabled()\"\n [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\"\n (click)=\"handleItemClick($index, $event)\"\n >\n {{ getItemLabel($index) }}\n </span>\n @if ($index < visibleItems().length - 1) {\n <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()\"\n #moreButton\n >\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\n class=\"ax-cursor-pointer ax-text-primary hover:ax-underline\"\n (click)=\"openLazyPopover(); $event.stopPropagation()\"\n #lazyTrigger\n >\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-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\n [class.ax-cursor-pointer]=\"detailPopoverEnabled()\"\n [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\"\n (click)=\"handlePopoverItemClick($index, $event)\"\n >\n {{ getPopoverItemLabel($index) }}\n </span>\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n </div>\n }\n </div>\n</ax-popover>\n", 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$3.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 }); }
|
|
16667
16679
|
}
|
|
16668
16680
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLookupWidgetColumnComponent, decorators: [{
|
|
16669
16681
|
type: Component,
|
|
16670
|
-
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
|
|
16682
|
+
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\n [class.ax-cursor-pointer]=\"detailPopoverEnabled()\"\n [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\"\n (click)=\"handleItemClick($index, $event)\"\n >\n {{ getItemLabel($index) }}\n </span>\n @if ($index < visibleItems().length - 1) {\n <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()\"\n #moreButton\n >\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\n class=\"ax-cursor-pointer ax-text-primary hover:ax-underline\"\n (click)=\"openLazyPopover(); $event.stopPropagation()\"\n #lazyTrigger\n >\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-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\n [class.ax-cursor-pointer]=\"detailPopoverEnabled()\"\n [class.hover:ax-text-primary]=\"detailPopoverEnabled()\"\n [class.hover:ax-underline]=\"detailPopoverEnabled()\"\n (click)=\"handlePopoverItemClick($index, $event)\"\n >\n {{ getPopoverItemLabel($index) }}\n </span>\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n </div>\n }\n </div>\n</ax-popover>\n" }]
|
|
16671
16683
|
}], 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 }] }] } });
|
|
16672
16684
|
|
|
16673
16685
|
var lookupWidgetColumn_component = /*#__PURE__*/Object.freeze({
|
|
@@ -17220,8 +17232,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
17220
17232
|
* Multi-source selector popup component
|
|
17221
17233
|
*/
|
|
17222
17234
|
class AXPMultiSourceSelectorComponent extends AXBasePageComponent {
|
|
17235
|
+
//#endregion
|
|
17223
17236
|
constructor() {
|
|
17224
|
-
super(
|
|
17237
|
+
super();
|
|
17225
17238
|
//#region ---- Services & Dependencies ----
|
|
17226
17239
|
this.entityDataSelectorService = inject(AXPEntityDataSelectorService);
|
|
17227
17240
|
this.entityResolver = inject(AXPEntityDefinitionRegistryService);
|
|
@@ -17244,8 +17257,20 @@ class AXPMultiSourceSelectorComponent extends AXBasePageComponent {
|
|
|
17244
17257
|
}, ...(ngDevMode ? [{ debugName: "activeSource" }] : /* istanbul ignore next */ []));
|
|
17245
17258
|
this.selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : /* istanbul ignore next */ []));
|
|
17246
17259
|
this.AXPMultiSourceType = AXPMultiSourceType;
|
|
17260
|
+
setupPopupFooterKeyboardShortcuts(() => [
|
|
17261
|
+
{
|
|
17262
|
+
title: '@general:actions.cancel.title',
|
|
17263
|
+
command: 'cancel',
|
|
17264
|
+
handler: () => this.handleCancel(),
|
|
17265
|
+
},
|
|
17266
|
+
{
|
|
17267
|
+
title: '@general:actions.select.title',
|
|
17268
|
+
command: 'select',
|
|
17269
|
+
disabled: () => this.selectedItems().length === 0,
|
|
17270
|
+
handler: () => this.handleConfirm(),
|
|
17271
|
+
},
|
|
17272
|
+
], { id: 'multi-source-selector-popup' });
|
|
17247
17273
|
}
|
|
17248
|
-
//#endregion
|
|
17249
17274
|
//#region ---- Lifecycle ----
|
|
17250
17275
|
ngOnInit() {
|
|
17251
17276
|
super.ngOnInit();
|
|
@@ -17322,7 +17347,7 @@ class AXPMultiSourceSelectorComponent extends AXBasePageComponent {
|
|
|
17322
17347
|
items: this.selectedItems(),
|
|
17323
17348
|
});
|
|
17324
17349
|
}
|
|
17325
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMultiSourceSelectorComponent, deps:
|
|
17350
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMultiSourceSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
17326
17351
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPMultiSourceSelectorComponent, isStandalone: true, selector: "axp-multi-source-selector", usesInheritance: true, ngImport: i0, template: `
|
|
17327
17352
|
<div class="ax-flex ax-flex-col ax-h-full ax-overflow-hidden">
|
|
17328
17353
|
@if (definition().searchStrategy === 'tabs') {
|
|
@@ -17471,7 +17496,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
17471
17496
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
17472
17497
|
imports: [CommonModule, AXButtonModule, AXTabsModule, AXDecoratorModule, AXTranslationModule],
|
|
17473
17498
|
}]
|
|
17474
|
-
}] });
|
|
17499
|
+
}], ctorParameters: () => [] });
|
|
17475
17500
|
|
|
17476
17501
|
var multiSourceSelector_component = /*#__PURE__*/Object.freeze({
|
|
17477
17502
|
__proto__: null,
|
|
@@ -18906,7 +18931,7 @@ class AXPFileListComponent {
|
|
|
18906
18931
|
// ACoreX
|
|
18907
18932
|
AXFormModule }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXLabelModule }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type:
|
|
18908
18933
|
// Platform
|
|
18909
|
-
AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "look"] }, { kind: "pipe", type:
|
|
18934
|
+
AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "pipe", type:
|
|
18910
18935
|
// Angular
|
|
18911
18936
|
AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }] }); }
|
|
18912
18937
|
}
|
|
@@ -21930,13 +21955,20 @@ class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
|
|
|
21930
21955
|
const p = relatedEntity?.persistence || {};
|
|
21931
21956
|
const strategy = p.strategy || 'embedded';
|
|
21932
21957
|
const mappedTargets = Object.keys(p.map || {}).map((k) => (k || '').split('.')[0]);
|
|
21958
|
+
const excludeProperties = relatedEntity.excludeProperties && relatedEntity.excludeProperties.length > 0
|
|
21959
|
+
? new Set(relatedEntity.excludeProperties)
|
|
21960
|
+
: undefined;
|
|
21933
21961
|
const helpers = {
|
|
21934
21962
|
...baseHelpers,
|
|
21935
21963
|
getPropertyByGroupId: (groupId) => {
|
|
21936
|
-
|
|
21937
|
-
if (strategy
|
|
21938
|
-
|
|
21939
|
-
|
|
21964
|
+
let props = baseHelpers.getPropertyByGroupId(groupId) ?? [];
|
|
21965
|
+
if (strategy === 'referenced' && mappedTargets.length > 0) {
|
|
21966
|
+
props = props.filter((prop) => !mappedTargets.includes(prop?.name ?? ''));
|
|
21967
|
+
}
|
|
21968
|
+
if (excludeProperties) {
|
|
21969
|
+
props = props.filter((prop) => !excludeProperties.has(prop.name ?? ''));
|
|
21970
|
+
}
|
|
21971
|
+
return props;
|
|
21940
21972
|
},
|
|
21941
21973
|
};
|
|
21942
21974
|
const evaluateExpressions = async (actionData) => {
|
|
@@ -22054,18 +22086,70 @@ class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
|
|
|
22054
22086
|
}
|
|
22055
22087
|
createLoadFunction(entityDef, relatedEntity, evaluateExpressions) {
|
|
22056
22088
|
return async (context) => {
|
|
22057
|
-
const
|
|
22089
|
+
const conditions = relatedEntity.conditions ?? [];
|
|
22090
|
+
if (conditions.length > 0) {
|
|
22091
|
+
const evaluatedFilters = await Promise.all(conditions.map(async (c) => ({
|
|
22092
|
+
field: c.name,
|
|
22093
|
+
operator: c.operator,
|
|
22094
|
+
value: await evaluateExpressions(c.value),
|
|
22095
|
+
})));
|
|
22096
|
+
if (conditions.length === 1 && conditions[0].name === 'id') {
|
|
22097
|
+
const byKeyFn = entityDef?.queries?.byKey?.execute;
|
|
22098
|
+
const id = evaluatedFilters[0]?.value;
|
|
22099
|
+
const result = id ? await byKeyFn(id) : null;
|
|
22100
|
+
return { success: true, data: result ?? {} };
|
|
22101
|
+
}
|
|
22102
|
+
const listFn = entityDef?.queries?.list?.execute;
|
|
22103
|
+
const filter = evaluatedFilters.length === 1
|
|
22104
|
+
? evaluatedFilters[0]
|
|
22105
|
+
: { logic: 'and', filters: evaluatedFilters };
|
|
22106
|
+
const page = await listFn({ skip: 0, take: 1, filter });
|
|
22107
|
+
const item = page?.items?.[0];
|
|
22108
|
+
const data = item ? { ...item } : {};
|
|
22109
|
+
if (!item) {
|
|
22110
|
+
for (const evaluated of evaluatedFilters) {
|
|
22111
|
+
if (evaluated.field) {
|
|
22112
|
+
set(data, evaluated.field, evaluated.value);
|
|
22113
|
+
}
|
|
22114
|
+
}
|
|
22115
|
+
}
|
|
22116
|
+
return { success: true, data };
|
|
22117
|
+
}
|
|
22118
|
+
const fn = entityDef?.queries?.byKey?.execute;
|
|
22058
22119
|
const conditionValues = relatedEntity.conditions?.map((c) => c.value) ?? [];
|
|
22059
22120
|
const evaluatedConditionValues = await Promise.all(conditionValues.map((c) => evaluateExpressions(c)));
|
|
22060
22121
|
const id = evaluatedConditionValues[0];
|
|
22061
|
-
const result = await fn(id);
|
|
22062
|
-
return { success: true, data: result };
|
|
22122
|
+
const result = id ? await fn(id) : null;
|
|
22123
|
+
return { success: true, data: result ?? {} };
|
|
22063
22124
|
};
|
|
22064
22125
|
}
|
|
22065
22126
|
createExecuteFunction(entityDef, actions, evaluateExpressions, converterContext) {
|
|
22066
22127
|
return async (e, context) => {
|
|
22067
22128
|
try {
|
|
22068
22129
|
if (e.name === 'update-entity') {
|
|
22130
|
+
const recordId = context?.['id'];
|
|
22131
|
+
if (!recordId) {
|
|
22132
|
+
const createFn = entityDef?.commands?.create?.execute;
|
|
22133
|
+
const created = await createFn(context);
|
|
22134
|
+
if (created && typeof created === 'object' && 'success' in created) {
|
|
22135
|
+
const cmd = created;
|
|
22136
|
+
if (!cmd.success) {
|
|
22137
|
+
const errorText = commandMessageTextForError(cmd.message?.text) || 'Failed to create entity';
|
|
22138
|
+
return {
|
|
22139
|
+
success: false,
|
|
22140
|
+
message: cmd.message ?? { text: errorText },
|
|
22141
|
+
};
|
|
22142
|
+
}
|
|
22143
|
+
return {
|
|
22144
|
+
success: true,
|
|
22145
|
+
data: cmd.data ?? created,
|
|
22146
|
+
};
|
|
22147
|
+
}
|
|
22148
|
+
return {
|
|
22149
|
+
success: true,
|
|
22150
|
+
data: created,
|
|
22151
|
+
};
|
|
22152
|
+
}
|
|
22069
22153
|
const fn = entityDef?.commands?.update?.execute;
|
|
22070
22154
|
const result = await fn(context);
|
|
22071
22155
|
if (result && typeof result === 'object' && 'success' in result) {
|
|
@@ -22327,11 +22411,16 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
22327
22411
|
const excludeForUpdate = commandName === 'Entity:Update' &&
|
|
22328
22412
|
relatedEntity.excludeProperties &&
|
|
22329
22413
|
relatedEntity.excludeProperties.length > 0;
|
|
22414
|
+
const excludeForView = commandName === 'Entity:View' &&
|
|
22415
|
+
relatedEntity.excludeProperties &&
|
|
22416
|
+
relatedEntity.excludeProperties.length > 0;
|
|
22330
22417
|
const mergedOptions = excludeForCreate
|
|
22331
22418
|
? { ...evaluatedOptions, excludeProperties: createExcludes }
|
|
22332
22419
|
: excludeForUpdate
|
|
22333
22420
|
? { ...evaluatedOptions, excludeProperties: relatedEntity.excludeProperties }
|
|
22334
|
-
:
|
|
22421
|
+
: excludeForView
|
|
22422
|
+
? { ...evaluatedOptions, excludeProperties: relatedEntity.excludeProperties }
|
|
22423
|
+
: evaluatedOptions;
|
|
22335
22424
|
if (context.commandService.exists(commandName)) {
|
|
22336
22425
|
// check options for evaluation
|
|
22337
22426
|
await context.commandService.execute(commandName, {
|
|
@@ -22350,6 +22439,7 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
22350
22439
|
},
|
|
22351
22440
|
options: mergedOptions,
|
|
22352
22441
|
metadata: action.metadata,
|
|
22442
|
+
...(excludeForView ? { excludeProperties: relatedEntity.excludeProperties } : {}),
|
|
22353
22443
|
});
|
|
22354
22444
|
}
|
|
22355
22445
|
else {
|
|
@@ -22880,6 +22970,7 @@ class AXPMainEntityContentBuilder {
|
|
|
22880
22970
|
const tabListTabs = await this.buildTabLists(tabListEntities ?? [], rootContext, dependencies);
|
|
22881
22971
|
// Build actions from single interface
|
|
22882
22972
|
const actions = this.buildActions(entity, singleInterface);
|
|
22973
|
+
let cachedRootContext = rootContext;
|
|
22883
22974
|
//console.log({ rootContext, dependencies });
|
|
22884
22975
|
return {
|
|
22885
22976
|
id: entity?.name ?? '',
|
|
@@ -22916,14 +23007,15 @@ class AXPMainEntityContentBuilder {
|
|
|
22916
23007
|
},
|
|
22917
23008
|
load: async (params) => {
|
|
22918
23009
|
if (params?.forceRefresh) {
|
|
23010
|
+
cachedRootContext = await dependencies.reloadRootContext();
|
|
22919
23011
|
return {
|
|
22920
23012
|
success: true,
|
|
22921
|
-
data:
|
|
23013
|
+
data: cachedRootContext,
|
|
22922
23014
|
};
|
|
22923
23015
|
}
|
|
22924
23016
|
return {
|
|
22925
23017
|
success: true,
|
|
22926
|
-
data:
|
|
23018
|
+
data: cachedRootContext,
|
|
22927
23019
|
};
|
|
22928
23020
|
},
|
|
22929
23021
|
execute: async (e, context) => {
|
|
@@ -23260,6 +23352,7 @@ class AXPLayoutAdapterFactory {
|
|
|
23260
23352
|
this.layoutAdapterBuilder = layoutAdapterBuilder;
|
|
23261
23353
|
this.filterOperatorMiddleware = filterOperatorMiddleware;
|
|
23262
23354
|
this.pageComponentConverter = inject(AXPPageComponentConverter);
|
|
23355
|
+
this.contextEvalFactory = inject(AXPContextEvalFactory);
|
|
23263
23356
|
}
|
|
23264
23357
|
async createDetailsViewAdapter(entityResolver, moduleName, entityName, id, dependencies) {
|
|
23265
23358
|
const entity = await entityResolver.resolve(moduleName, entityName);
|
|
@@ -23313,9 +23406,7 @@ class AXPLayoutAdapterFactory {
|
|
|
23313
23406
|
if (hidden && typeof hidden === 'string') {
|
|
23314
23407
|
try {
|
|
23315
23408
|
const scope = {
|
|
23316
|
-
context:
|
|
23317
|
-
eval: (path) => get(rootContext, path),
|
|
23318
|
-
},
|
|
23409
|
+
context: this.contextEvalFactory.createScope(rootContext),
|
|
23319
23410
|
};
|
|
23320
23411
|
const result = await dependencies.expressionEvaluator.evaluate({ hidden }, scope);
|
|
23321
23412
|
hidden = result.hidden;
|
|
@@ -23477,9 +23568,7 @@ class AXPLayoutAdapterFactory {
|
|
|
23477
23568
|
}
|
|
23478
23569
|
const scope = {
|
|
23479
23570
|
...rootContext,
|
|
23480
|
-
context:
|
|
23481
|
-
eval: (path) => get(rootContext, path),
|
|
23482
|
-
},
|
|
23571
|
+
context: this.contextEvalFactory.createScope(rootContext),
|
|
23483
23572
|
};
|
|
23484
23573
|
const title = await dependencies.expressionEvaluator.evaluate(titleTemplate, scope);
|
|
23485
23574
|
return title;
|
|
@@ -23494,27 +23583,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
23494
23583
|
}]
|
|
23495
23584
|
}], ctorParameters: () => [{ type: AXPRelatedEntityConverterFactory }, { type: AXPMainEntityContentBuilder }, { type: AXPLayoutAdapterBuilder }, { type: i4$2.AXPFilterOperatorMiddlewareService }] });
|
|
23496
23585
|
|
|
23497
|
-
|
|
23498
|
-
|
|
23499
|
-
|
|
23500
|
-
|
|
23501
|
-
|
|
23502
|
-
|
|
23503
|
-
expressionEvaluator
|
|
23504
|
-
session
|
|
23505
|
-
formatService
|
|
23506
|
-
workflowService
|
|
23507
|
-
commandService
|
|
23508
|
-
};
|
|
23509
|
-
try {
|
|
23510
|
-
return await layoutAdapterFactory.createDetailsViewAdapter(entityResolver, moduleName, entityName, id, dependencies);
|
|
23586
|
+
//#region ---- Entity Details View Adapter Loader ----
|
|
23587
|
+
class AXPEntityDetailsViewAdapterLoader {
|
|
23588
|
+
constructor() {
|
|
23589
|
+
//#region ---- Services & Dependencies ----
|
|
23590
|
+
this.entityResolver = inject(AXPEntityDefinitionRegistryService);
|
|
23591
|
+
this.layoutAdapterFactory = inject(AXPLayoutAdapterFactory);
|
|
23592
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
23593
|
+
this.session = inject(AXPSessionService);
|
|
23594
|
+
this.formatService = inject(AXFormatService);
|
|
23595
|
+
this.workflowService = inject(AXPWorkflowService);
|
|
23596
|
+
this.commandService = inject(AXPCommandService);
|
|
23511
23597
|
}
|
|
23512
|
-
|
|
23513
|
-
|
|
23514
|
-
|
|
23515
|
-
|
|
23516
|
-
|
|
23598
|
+
//#endregion
|
|
23599
|
+
/**
|
|
23600
|
+
* Builds the details-view adapter for an entity record (definition, layout pages, root context).
|
|
23601
|
+
*/
|
|
23602
|
+
async load(params) {
|
|
23603
|
+
const { moduleName, entityName, id } = params;
|
|
23604
|
+
const dependencies = {
|
|
23605
|
+
entityResolver: this.entityResolver,
|
|
23606
|
+
expressionEvaluator: this.expressionEvaluator,
|
|
23607
|
+
session: this.session,
|
|
23608
|
+
formatService: this.formatService,
|
|
23609
|
+
workflowService: this.workflowService,
|
|
23610
|
+
commandService: this.commandService,
|
|
23611
|
+
};
|
|
23612
|
+
return this.layoutAdapterFactory.createDetailsViewAdapter(this.entityResolver, moduleName, entityName, id, dependencies);
|
|
23517
23613
|
}
|
|
23614
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityDetailsViewAdapterLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
23615
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityDetailsViewAdapterLoader, providedIn: 'root' }); }
|
|
23616
|
+
}
|
|
23617
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityDetailsViewAdapterLoader, decorators: [{
|
|
23618
|
+
type: Injectable,
|
|
23619
|
+
args: [{ providedIn: 'root' }]
|
|
23620
|
+
}] });
|
|
23621
|
+
const AXP_ENTITY_DETAILS_VIEW_ADAPTER_LOADER_PROVIDER = {
|
|
23622
|
+
provide: AXP_LAYOUT_DETAILS_VIEW_ADAPTER_LOADER,
|
|
23623
|
+
useExisting: AXPEntityDetailsViewAdapterLoader,
|
|
23518
23624
|
};
|
|
23519
23625
|
|
|
23520
23626
|
class AXPEntityPreloadFilterGuard {
|
|
@@ -23577,9 +23683,7 @@ const eventDispatchMiddleware = {
|
|
|
23577
23683
|
if (ctx.op === 'create') {
|
|
23578
23684
|
const createdData = ctx.result ? { ...ctx.data, id: ctx.result } : ctx.data;
|
|
23579
23685
|
await dispatcher.dispatchInserted(ctx.entityName, { refType: ctx.entityName, data: createdData });
|
|
23580
|
-
|
|
23581
|
-
entity: ctx.entityName,
|
|
23582
|
-
}));
|
|
23686
|
+
// List refresh is dispatched after create UI closes (Entity:Create command / create-entity workflow).
|
|
23583
23687
|
}
|
|
23584
23688
|
else if (ctx.op === 'update') {
|
|
23585
23689
|
await dispatcher.dispatchUpdated(ctx.entityName, {
|
|
@@ -24244,8 +24348,8 @@ const AXPCrudModifier = {
|
|
|
24244
24348
|
if (!command?.create) {
|
|
24245
24349
|
command.create = {
|
|
24246
24350
|
execute: async (data) => {
|
|
24247
|
-
console.log('create', ctx.module.get() + '.' + ctx.name.get(), data);
|
|
24248
24351
|
const res = await dataService.insertOne(data);
|
|
24352
|
+
//await delay(2000);
|
|
24249
24353
|
return { id: res };
|
|
24250
24354
|
},
|
|
24251
24355
|
};
|
|
@@ -24265,7 +24369,9 @@ const AXPCrudModifier = {
|
|
|
24265
24369
|
if (id == null || id === '') {
|
|
24266
24370
|
throw new Error(`Update requires entity id (${entityKey})`);
|
|
24267
24371
|
}
|
|
24268
|
-
|
|
24372
|
+
const updated = await dataService.updateOne(id, patch);
|
|
24373
|
+
//await delay(2000);
|
|
24374
|
+
return updated;
|
|
24269
24375
|
},
|
|
24270
24376
|
};
|
|
24271
24377
|
}
|
|
@@ -24279,6 +24385,7 @@ const AXPCrudModifier = {
|
|
|
24279
24385
|
queries.byKey = {
|
|
24280
24386
|
execute: async (id) => {
|
|
24281
24387
|
const data = await dataService.getOne(id);
|
|
24388
|
+
//await delay(1000);
|
|
24282
24389
|
return data;
|
|
24283
24390
|
},
|
|
24284
24391
|
type: AXPEntityQueryType.Single,
|
|
@@ -24288,7 +24395,7 @@ const AXPCrudModifier = {
|
|
|
24288
24395
|
queries.list = {
|
|
24289
24396
|
execute: async (e) => {
|
|
24290
24397
|
const res = await dataService.query(e);
|
|
24291
|
-
//
|
|
24398
|
+
//console.log('query', res, ctx.module.get() + '.' + ctx.name.get(), e);
|
|
24292
24399
|
return res;
|
|
24293
24400
|
},
|
|
24294
24401
|
type: AXPEntityQueryType.List,
|
|
@@ -24321,6 +24428,68 @@ class AXPEntityCommandSearchDefinitionProvider {
|
|
|
24321
24428
|
function moduleNameToI18nScope(moduleName) {
|
|
24322
24429
|
return moduleName.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
|
|
24323
24430
|
}
|
|
24431
|
+
//#region ---- Entity search definition builder ----
|
|
24432
|
+
function buildEntitySearchDefinition(entity, manifestRegistry) {
|
|
24433
|
+
const manifest = manifestRegistry.get(entity.module);
|
|
24434
|
+
const i18nScope = manifest?.i18n ?? moduleNameToI18nScope(entity.module);
|
|
24435
|
+
const searchTitleTemplate = entity.formats.searchResult?.title;
|
|
24436
|
+
const titleContext = buildEntitySearchTitleContext(entity, searchTitleTemplate);
|
|
24437
|
+
return {
|
|
24438
|
+
name: `Module.${entity.module}.${entity.name}`,
|
|
24439
|
+
title: `@${i18nScope}:module.title`,
|
|
24440
|
+
group: `Module.${entity.module}`,
|
|
24441
|
+
icon: entity.icon ?? 'fa-solid fa-objects-column',
|
|
24442
|
+
order: 4,
|
|
24443
|
+
format: {
|
|
24444
|
+
title: searchTitleTemplate,
|
|
24445
|
+
description: entity.formats.searchResult?.description ?? `${entity.module} / ${entity.title}`,
|
|
24446
|
+
id: '{{data.id}}',
|
|
24447
|
+
titleFallbackTemplates: titleContext.fallbackTemplates,
|
|
24448
|
+
titleFallbackFields: titleContext.fallbackFields,
|
|
24449
|
+
},
|
|
24450
|
+
actions: [
|
|
24451
|
+
{
|
|
24452
|
+
name: 'open-entity',
|
|
24453
|
+
type: AXPSystemActionType.View,
|
|
24454
|
+
priority: 'primary',
|
|
24455
|
+
},
|
|
24456
|
+
],
|
|
24457
|
+
};
|
|
24458
|
+
}
|
|
24459
|
+
//#endregion
|
|
24460
|
+
//#region ---- Lazy resolver ----
|
|
24461
|
+
class AXPEntitySearchDefinitionLazyResolver {
|
|
24462
|
+
constructor() {
|
|
24463
|
+
this.entityResolver = inject(AXPEntityResolver);
|
|
24464
|
+
this.manifestRegistry = inject(AXPModuleManifestRegistry);
|
|
24465
|
+
this.resolved = new Map();
|
|
24466
|
+
}
|
|
24467
|
+
async resolve(definitionName) {
|
|
24468
|
+
const cached = this.resolved.get(definitionName);
|
|
24469
|
+
if (cached) {
|
|
24470
|
+
return cached;
|
|
24471
|
+
}
|
|
24472
|
+
const match = definitionName.match(/^Module\.([^.]+)\.(.+)$/);
|
|
24473
|
+
if (!match) {
|
|
24474
|
+
return null;
|
|
24475
|
+
}
|
|
24476
|
+
const [, moduleName, entityName] = match;
|
|
24477
|
+
await this.manifestRegistry.initialize();
|
|
24478
|
+
const entity = await this.entityResolver.get(moduleName, entityName);
|
|
24479
|
+
if (!entity) {
|
|
24480
|
+
return null;
|
|
24481
|
+
}
|
|
24482
|
+
const definition = buildEntitySearchDefinition(entity, this.manifestRegistry);
|
|
24483
|
+
this.resolved.set(definitionName, definition);
|
|
24484
|
+
return definition;
|
|
24485
|
+
}
|
|
24486
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntitySearchDefinitionLazyResolver, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
24487
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntitySearchDefinitionLazyResolver }); }
|
|
24488
|
+
}
|
|
24489
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntitySearchDefinitionLazyResolver, decorators: [{
|
|
24490
|
+
type: Injectable
|
|
24491
|
+
}] });
|
|
24492
|
+
|
|
24324
24493
|
class AXPEntitySearchDefinitionProvider {
|
|
24325
24494
|
constructor() {
|
|
24326
24495
|
this.entityRegister = inject(AXPEntityDefinitionRegistryService);
|
|
@@ -24328,28 +24497,13 @@ class AXPEntitySearchDefinitionProvider {
|
|
|
24328
24497
|
}
|
|
24329
24498
|
async provide(context) {
|
|
24330
24499
|
await this.manifestRegistry.initialize();
|
|
24331
|
-
this.entityRegister.getAll()
|
|
24332
|
-
const
|
|
24333
|
-
|
|
24334
|
-
|
|
24335
|
-
|
|
24336
|
-
context.addDefinition(`Module.${entity.module}.${entity.name}`, `@${i18nScope}:module.title`, `Module.${entity.module}`, entity.icon ?? 'fa-solid fa-objects-column', 4, {
|
|
24337
|
-
actions: [
|
|
24338
|
-
{
|
|
24339
|
-
name: 'open-entity',
|
|
24340
|
-
type: 'view',
|
|
24341
|
-
priority: 'primary',
|
|
24342
|
-
},
|
|
24343
|
-
],
|
|
24344
|
-
format: {
|
|
24345
|
-
title: searchTitleTemplate,
|
|
24346
|
-
description: (entity.formats.searchResult?.description) ?? `${entity.module} / ${entity.title}`,
|
|
24347
|
-
id: '{{data.id}}',
|
|
24348
|
-
titleFallbackTemplates: titleContext.fallbackTemplates,
|
|
24349
|
-
titleFallbackFields: titleContext.fallbackFields,
|
|
24350
|
-
},
|
|
24500
|
+
for (const entity of this.entityRegister.getAll()) {
|
|
24501
|
+
const definition = buildEntitySearchDefinition(entity, this.manifestRegistry);
|
|
24502
|
+
context.addDefinition(definition.name, definition.title, definition.group, definition.icon, definition.order, {
|
|
24503
|
+
actions: definition.actions,
|
|
24504
|
+
format: definition.format,
|
|
24351
24505
|
});
|
|
24352
|
-
}
|
|
24506
|
+
}
|
|
24353
24507
|
}
|
|
24354
24508
|
}
|
|
24355
24509
|
|
|
@@ -24455,9 +24609,9 @@ class AXPMiddlewareEntityStorageService extends AXPEntityStorageService {
|
|
|
24455
24609
|
...init,
|
|
24456
24610
|
};
|
|
24457
24611
|
}
|
|
24458
|
-
async initial(entityName, collection
|
|
24612
|
+
async initial(entityName, collection) {
|
|
24459
24613
|
const ctx = this.createCtx('initial', entityName, { data: collection });
|
|
24460
|
-
return this.run(ctx, () => this.backend.initial(ctx.entityName, ctx.data
|
|
24614
|
+
return this.run(ctx, () => this.backend.initial(ctx.entityName, ctx.data));
|
|
24461
24615
|
}
|
|
24462
24616
|
async getOne(entityName, id) {
|
|
24463
24617
|
const key = getDedupKey('getOne', entityName, { id });
|
|
@@ -24641,6 +24795,7 @@ class AXPEntityCreatePopupAction extends AXPWorkflowAction {
|
|
|
24641
24795
|
this.factory = inject(AXPEntityCreateViewModelFactory);
|
|
24642
24796
|
this.config = inject(AXP_ENTITY_CONFIG_TOKEN);
|
|
24643
24797
|
this.translateService = inject(AXTranslationService);
|
|
24798
|
+
this.settingsService = inject(AXPSettingsService);
|
|
24644
24799
|
}
|
|
24645
24800
|
async execute(context) {
|
|
24646
24801
|
const [module, entity] = context.getVariable('entity').split('.');
|
|
@@ -24672,8 +24827,22 @@ class AXPEntityCreatePopupAction extends AXPWorkflowAction {
|
|
|
24672
24827
|
const prevData = context.getVariable('data');
|
|
24673
24828
|
const prevMeta = context.getVariable('meta');
|
|
24674
24829
|
context.setVariable('data', { ...prevData, ...result.data.item });
|
|
24675
|
-
|
|
24676
|
-
|
|
24830
|
+
const createdItem = result.data.item;
|
|
24831
|
+
const highlightRowId = createdItem?.id ?? createdItem?._id;
|
|
24832
|
+
const { shouldRedirect, shouldHighlight } = await resolveEntityCreateListBehavior(this.settingsService, {
|
|
24833
|
+
redirect: process?.redirect,
|
|
24834
|
+
});
|
|
24835
|
+
context.setVariable('shouldRedirect', shouldRedirect);
|
|
24836
|
+
const meta = {
|
|
24837
|
+
...prevMeta,
|
|
24838
|
+
resetPagination: true,
|
|
24839
|
+
...(shouldHighlight && highlightRowId != null ? { highlightRowId } : {}),
|
|
24840
|
+
...(entityRef.parentKey && createdItem[entityRef.parentKey]
|
|
24841
|
+
? { refreshTargetId: createdItem[entityRef.parentKey] }
|
|
24842
|
+
: {}),
|
|
24843
|
+
};
|
|
24844
|
+
if (Object.keys(meta).length > 0) {
|
|
24845
|
+
context.setVariable('meta', meta);
|
|
24677
24846
|
}
|
|
24678
24847
|
}
|
|
24679
24848
|
}
|
|
@@ -24724,7 +24893,7 @@ const AXPCreateEntityWorkflow = {
|
|
|
24724
24893
|
action: 'AXPEntityCreateSubmittedAction',
|
|
24725
24894
|
nextSteps: [
|
|
24726
24895
|
{
|
|
24727
|
-
conditions: [{ type: 'SINGLE', expression: 'context.getVariable("
|
|
24896
|
+
conditions: [{ type: 'SINGLE', expression: 'context.getVariable("shouldRedirect") == true' }],
|
|
24728
24897
|
nextStepId: 'show-entity',
|
|
24729
24898
|
},
|
|
24730
24899
|
],
|
|
@@ -24741,6 +24910,9 @@ class AXPQuickEntityModifyPopupAction extends AXPWorkflowAction {
|
|
|
24741
24910
|
this.popupService = inject(AXPopupService);
|
|
24742
24911
|
this.platform = inject(AXPlatform);
|
|
24743
24912
|
this.translateService = inject(AXTranslationService);
|
|
24913
|
+
this.formatService = inject(AXFormatService);
|
|
24914
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
24915
|
+
this.contextEvalFactory = inject(AXPContextEvalFactory);
|
|
24744
24916
|
this.entityRegistery = inject(AXPEntityDefinitionRegistryService);
|
|
24745
24917
|
this.config = inject(AXP_ENTITY_CONFIG_TOKEN);
|
|
24746
24918
|
this.factory = inject(AXPEntityMasterUpdateViewModelFactory);
|
|
@@ -24750,10 +24922,8 @@ class AXPQuickEntityModifyPopupAction extends AXPWorkflowAction {
|
|
|
24750
24922
|
const data = context.getVariable('data');
|
|
24751
24923
|
const entityRef = await this.entityRegistery.resolve(moduleName, entityName);
|
|
24752
24924
|
const { parentKey } = entityRef;
|
|
24753
|
-
console.log(data);
|
|
24754
24925
|
const { id } = data;
|
|
24755
|
-
const
|
|
24756
|
-
const properties = interfaces?.master?.update?.properties?.map((p) => p.name) || [];
|
|
24926
|
+
const properties = entityRef.interfaces?.master?.update?.properties?.map((p) => p.name) || [];
|
|
24757
24927
|
const vm = await this.factory.create(moduleName, entityName, id, properties);
|
|
24758
24928
|
const options = context.getVariable('options');
|
|
24759
24929
|
const decoration = options?.['decoration'];
|
|
@@ -24763,12 +24933,11 @@ class AXPQuickEntityModifyPopupAction extends AXPWorkflowAction {
|
|
|
24763
24933
|
if (parentKey) {
|
|
24764
24934
|
context.setVariable('parentKey', parentKey);
|
|
24765
24935
|
}
|
|
24766
|
-
console.log(`${this.translateService.translateSync('entity.modify')}`);
|
|
24767
24936
|
const com = await this.config.viewers.master.modify();
|
|
24768
24937
|
const popup = await this.popupService.open(com, {
|
|
24769
24938
|
title: headerTitle
|
|
24770
24939
|
? headerTitle
|
|
24771
|
-
:
|
|
24940
|
+
: await resolveEntityModifyPopupTitle(entityRef, vm.context(), this.translateService, this.formatService, this.expressionEvaluator, this.contextEvalFactory),
|
|
24772
24941
|
size: this.platform.is('Mobile') || this.platform.is('SM') ? 'full' : size ? size : 'md',
|
|
24773
24942
|
data: {
|
|
24774
24943
|
vm,
|
|
@@ -25031,6 +25200,7 @@ function routesFacory() {
|
|
|
25031
25200
|
return config.viewers.root();
|
|
25032
25201
|
},
|
|
25033
25202
|
canActivate: [...AXP_PROTECTED_ROUTE_GUARDS],
|
|
25203
|
+
data: { rootLayout: true },
|
|
25034
25204
|
children: [
|
|
25035
25205
|
{
|
|
25036
25206
|
path: ':module',
|
|
@@ -25064,18 +25234,11 @@ function routesFacory() {
|
|
|
25064
25234
|
// },
|
|
25065
25235
|
{
|
|
25066
25236
|
path: 'e/:entity/:id/view',
|
|
25067
|
-
resolve: { adapter: AXPLayoutDetailsViewRouteResolver },
|
|
25068
25237
|
loadComponent: () => {
|
|
25069
25238
|
return config.viewers.master.details();
|
|
25070
25239
|
},
|
|
25071
25240
|
canDeactivate: [axpDetailsViewCanDeactivateGuard],
|
|
25072
|
-
|
|
25073
|
-
const entityChanged = from.params['module'] !== to.params['module'] || from.params['entity'] !== to.params['entity'];
|
|
25074
|
-
const idChanged = from.params['id'] !== to.params['id'];
|
|
25075
|
-
const refreshChanged = from.queryParams['_ts'] !== to.queryParams['_ts'];
|
|
25076
|
-
return entityChanged || idChanged || refreshChanged;
|
|
25077
|
-
},
|
|
25078
|
-
data: { reuse: false },
|
|
25241
|
+
data: { reuse: 'queryParamsChange' },
|
|
25079
25242
|
},
|
|
25080
25243
|
{
|
|
25081
25244
|
path: 'e/:entity/:id',
|
|
@@ -25108,6 +25271,16 @@ class AXPEntityModule {
|
|
|
25108
25271
|
AXPAttachmentsPluginModule, i1$3.AXPWorkflowModule, AXPWidgetCoreModule,
|
|
25109
25272
|
LayoutBuilderModule] }); }
|
|
25110
25273
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityModule, providers: [
|
|
25274
|
+
AXP_ENTITY_DETAILS_VIEW_ADAPTER_LOADER_PROVIDER,
|
|
25275
|
+
{
|
|
25276
|
+
provide: AXP_REPEATER_ENTITY_BY_KEY_LOOKUP,
|
|
25277
|
+
useFactory: () => {
|
|
25278
|
+
const entityService = inject(AXPEntityService);
|
|
25279
|
+
return {
|
|
25280
|
+
byKey: (entityKey, id) => entityService.withEntity(entityKey).data().byKey(id),
|
|
25281
|
+
};
|
|
25282
|
+
},
|
|
25283
|
+
},
|
|
25111
25284
|
{ provide: AXP_WIDGET_DEFINITION_PROVIDER, useClass: AXPEntityWidgetsProvider, multi: true },
|
|
25112
25285
|
{
|
|
25113
25286
|
provide: ROUTES,
|
|
@@ -25124,6 +25297,10 @@ class AXPEntityModule {
|
|
|
25124
25297
|
useClass: AXPEntityCommandSearchDefinitionProvider,
|
|
25125
25298
|
multi: true,
|
|
25126
25299
|
},
|
|
25300
|
+
{
|
|
25301
|
+
provide: AXP_SEARCH_DEFINITION_LAZY_RESOLVER,
|
|
25302
|
+
useClass: AXPEntitySearchDefinitionLazyResolver,
|
|
25303
|
+
},
|
|
25127
25304
|
// Bind the middleware wrapper as the public storage service
|
|
25128
25305
|
{ provide: AXPEntityStorageService, useClass: AXPMiddlewareEntityStorageService },
|
|
25129
25306
|
{
|
|
@@ -25295,6 +25472,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
25295
25472
|
exports: [],
|
|
25296
25473
|
declarations: [],
|
|
25297
25474
|
providers: [
|
|
25475
|
+
AXP_ENTITY_DETAILS_VIEW_ADAPTER_LOADER_PROVIDER,
|
|
25476
|
+
{
|
|
25477
|
+
provide: AXP_REPEATER_ENTITY_BY_KEY_LOOKUP,
|
|
25478
|
+
useFactory: () => {
|
|
25479
|
+
const entityService = inject(AXPEntityService);
|
|
25480
|
+
return {
|
|
25481
|
+
byKey: (entityKey, id) => entityService.withEntity(entityKey).data().byKey(id),
|
|
25482
|
+
};
|
|
25483
|
+
},
|
|
25484
|
+
},
|
|
25298
25485
|
{ provide: AXP_WIDGET_DEFINITION_PROVIDER, useClass: AXPEntityWidgetsProvider, multi: true },
|
|
25299
25486
|
{
|
|
25300
25487
|
provide: ROUTES,
|
|
@@ -25311,6 +25498,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
25311
25498
|
useClass: AXPEntityCommandSearchDefinitionProvider,
|
|
25312
25499
|
multi: true,
|
|
25313
25500
|
},
|
|
25501
|
+
{
|
|
25502
|
+
provide: AXP_SEARCH_DEFINITION_LAZY_RESOLVER,
|
|
25503
|
+
useClass: AXPEntitySearchDefinitionLazyResolver,
|
|
25504
|
+
},
|
|
25314
25505
|
// Bind the middleware wrapper as the public storage service
|
|
25315
25506
|
{ provide: AXPEntityStorageService, useClass: AXPMiddlewareEntityStorageService },
|
|
25316
25507
|
{
|
|
@@ -25618,5 +25809,5 @@ var getEntityDetails_query = /*#__PURE__*/Object.freeze({
|
|
|
25618
25809
|
* Generated bundle index. Do not edit.
|
|
25619
25810
|
*/
|
|
25620
25811
|
|
|
25621
|
-
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,
|
|
25812
|
+
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, 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, 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, canPersistEntityListState, cloneLayoutArrays, 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, 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 };
|
|
25622
25813
|
//# sourceMappingURL=acorex-platform-layout-entity.mjs.map
|