@acorex/platform 21.0.0-next.40 → 21.0.0-next.41
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-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +115 -29
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs +59 -4
- package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +995 -545
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- package/fesm2022/{acorex-platform-layout-widgets-repeater-widget-column.component-BGQqY5Mw.mjs → acorex-platform-layout-widgets-repeater-widget-column.component-BGO75IMz.mjs} +9 -4
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGO75IMz.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets.mjs +418 -106
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/acorex-platform-workflow.mjs +2 -1
- package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
- package/package.json +1 -1
- package/types/acorex-platform-common.d.ts +14 -10
- package/types/acorex-platform-layout-builder.d.ts +20 -2
- package/types/acorex-platform-layout-designer.d.ts +35 -3
- package/types/acorex-platform-layout-entity.d.ts +46 -5
- package/types/acorex-platform-layout-widget-core.d.ts +2 -5
- package/types/acorex-platform-layout-widgets.d.ts +108 -51
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGQqY5Mw.mjs.map +0 -1
|
@@ -2,13 +2,16 @@ import { AXToastService } from '@acorex/components/toast';
|
|
|
2
2
|
import * as i6 from '@acorex/core/translation';
|
|
3
3
|
import { AXTranslationService, AXTranslationModule, resolveMultiLanguageString } from '@acorex/core/translation';
|
|
4
4
|
import * as i4$4 from '@acorex/platform/common';
|
|
5
|
-
import { AXPSettingsService, AXPCommonSettings, AXPFilterOperatorMiddlewareService,
|
|
5
|
+
import { AXPEntityCommandScope, AXPSettingsService, AXPCommonSettings, AXPFilterOperatorMiddlewareService, getEntityInfo, AXPRefreshEvent, AXPReloadEvent, AXPCleanNestedFilters, AXPDefaultMultiLanguageConfigService, withDefaultMultiLanguageOnWidgetNodeTree, AXPEntityQueryType, AXPWorkflowNavigateAction, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER, AXPMenuItemsDataSourceDefinition } from '@acorex/platform/common';
|
|
6
6
|
import * as i0 from '@angular/core';
|
|
7
7
|
import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, input, viewChild, signal, computed, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, ChangeDetectorRef, effect, Input, afterNextRender, untracked, ViewEncapsulation, viewChildren, linkedSignal, HostBinding, output, NgModule, makeEnvironmentProviders } from '@angular/core';
|
|
8
8
|
import { Subject, takeUntil } from 'rxjs';
|
|
9
9
|
import { AXPLayoutBuilderService, LayoutBuilderModule } from '@acorex/platform/layout/builder';
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
10
|
+
import * as i3 from '@acorex/platform/layout/widget-core';
|
|
11
|
+
import { AXPWidgetsCatalog, AXPWidgetCoreModule, AXPPageStatus, AXPWidgetRegistryService, AXPColumnWidgetComponent, AXPValueWidgetComponent, AXPWidgetGroupEnum, createBooleanProperty, AXPWidgetRendererDirective, createSelectProperty, createStringProperty, AXP_WIDGETS_EDITOR_CATEGORY, AXP_WIDGET_DEFINITION_PROVIDER } from '@acorex/platform/layout/widget-core';
|
|
12
|
+
import { AXPSystemActionType, AXPDeviceService, AXPExpressionEvaluatorService, AXPBroadcastEventService, applyFilterArray, applySortArray, resolveActionLook, AXPDistributedEventListenerService, AXPPlatformScope, AXHighlightService, extractValue, setSmart, getChangedPaths, objectKeyValueTransforms, 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 } from 'lodash-es';
|
|
14
|
+
import { transform, isEqual } from 'lodash';
|
|
12
15
|
import { AXPSessionService, AXPAuthGuard, AXPPermissionDefinitionsDataSourceDefinition } from '@acorex/platform/auth';
|
|
13
16
|
import { Router, ActivatedRoute, RouterModule, ROUTES } from '@angular/router';
|
|
14
17
|
import { defineCommand, AXP_COMMAND_DEFINITION_CATEGORY_ENTITY, AXPCommandService, AXPQueryService, AXPQueryExecutor, provideCommandSetups, provideQuerySetups, AXPCommandRegistry, AXPQueryRegistry } from '@acorex/platform/runtime';
|
|
@@ -18,8 +21,6 @@ import * as i4 from '@acorex/components/loading';
|
|
|
18
21
|
import { AXLoadingModule } from '@acorex/components/loading';
|
|
19
22
|
import * as i2 from '@acorex/components/popover';
|
|
20
23
|
import { AXPopoverModule } from '@acorex/components/popover';
|
|
21
|
-
import * as i3 from '@acorex/platform/layout/widget-core';
|
|
22
|
-
import { AXPWidgetsCatalog, AXPWidgetCoreModule, AXPPageStatus, AXPWidgetRegistryService, AXPColumnWidgetComponent, AXPValueWidgetComponent, AXPWidgetGroupEnum, createBooleanProperty, AXPWidgetRendererDirective, createSelectProperty, createStringProperty, AXP_WIDGETS_EDITOR_CATEGORY, AXP_WIDGET_DEFINITION_PROVIDER } from '@acorex/platform/layout/widget-core';
|
|
23
24
|
import * as i5 from '@angular/common';
|
|
24
25
|
import { CommonModule, AsyncPipe } from '@angular/common';
|
|
25
26
|
import { AXPThemeLayoutBlockComponent, AXPPreloadFiltersComponent, AXPStateMessageComponent, AXPColumnItemListComponent, AXPDataSelectorService, AXPPageComponentRegistryService } from '@acorex/platform/layout/components';
|
|
@@ -69,7 +70,6 @@ import * as i5$3 from '@acorex/components/label';
|
|
|
69
70
|
import { AXLabelModule } from '@acorex/components/label';
|
|
70
71
|
import * as i7 from '@acorex/components/text-box';
|
|
71
72
|
import { AXTextBoxModule } from '@acorex/components/text-box';
|
|
72
|
-
import { transform, isEqual as isEqual$1 } from 'lodash';
|
|
73
73
|
|
|
74
74
|
function ensureListActions(ctx) {
|
|
75
75
|
ctx.interfaces.update((i) => {
|
|
@@ -803,6 +803,308 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
803
803
|
}]
|
|
804
804
|
}] });
|
|
805
805
|
|
|
806
|
+
// #region Master
|
|
807
|
+
function entityMasterCreateAction() {
|
|
808
|
+
return {
|
|
809
|
+
title: '@general:actions.create.title',
|
|
810
|
+
command: {
|
|
811
|
+
name: 'Entity:Create',
|
|
812
|
+
},
|
|
813
|
+
priority: 'primary',
|
|
814
|
+
type: AXPSystemActionType.Create,
|
|
815
|
+
scope: AXPEntityCommandScope.TypeLevel,
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
function entityMasterEditAction() {
|
|
819
|
+
return {
|
|
820
|
+
title: '@general:actions.edit.title',
|
|
821
|
+
command: 'Entity:Update',
|
|
822
|
+
priority: 'secondary',
|
|
823
|
+
type: AXPSystemActionType.Update,
|
|
824
|
+
scope: AXPEntityCommandScope.Individual,
|
|
825
|
+
default: true,
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
function entityMasterBulkDeleteAction() {
|
|
829
|
+
return {
|
|
830
|
+
title: '@general:actions.delete-items.title',
|
|
831
|
+
command: 'delete-entity',
|
|
832
|
+
priority: 'primary',
|
|
833
|
+
type: AXPSystemActionType.Delete,
|
|
834
|
+
scope: AXPEntityCommandScope.Selected,
|
|
835
|
+
order: 100,
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
function entityMasterViewAction() {
|
|
839
|
+
return {
|
|
840
|
+
title: '@general:actions.view.title',
|
|
841
|
+
command: 'open-entity',
|
|
842
|
+
priority: 'secondary',
|
|
843
|
+
type: AXPSystemActionType.View,
|
|
844
|
+
scope: AXPEntityCommandScope.Individual,
|
|
845
|
+
default: true,
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
function entityMasterDeleteAction() {
|
|
849
|
+
return {
|
|
850
|
+
title: '@general:actions.delete.title',
|
|
851
|
+
command: 'delete-entity',
|
|
852
|
+
priority: 'secondary',
|
|
853
|
+
type: AXPSystemActionType.Delete,
|
|
854
|
+
scope: AXPEntityCommandScope.Individual,
|
|
855
|
+
order: 100,
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
function entityMasterCrudActions(options) {
|
|
859
|
+
const opts = {
|
|
860
|
+
create: true,
|
|
861
|
+
delete: true,
|
|
862
|
+
view: true,
|
|
863
|
+
edit: false,
|
|
864
|
+
...options,
|
|
865
|
+
};
|
|
866
|
+
const actions = [];
|
|
867
|
+
if (opts.create) {
|
|
868
|
+
actions.push(entityMasterCreateAction());
|
|
869
|
+
}
|
|
870
|
+
if (opts.delete) {
|
|
871
|
+
actions.push(entityMasterBulkDeleteAction());
|
|
872
|
+
actions.push(entityMasterDeleteAction());
|
|
873
|
+
}
|
|
874
|
+
if (opts.view) {
|
|
875
|
+
actions.push(entityMasterViewAction());
|
|
876
|
+
}
|
|
877
|
+
if (opts.edit) {
|
|
878
|
+
actions.push(entityMasterEditAction());
|
|
879
|
+
}
|
|
880
|
+
return actions;
|
|
881
|
+
}
|
|
882
|
+
function entityMasterRecordActions() {
|
|
883
|
+
return [entityMasterDeleteAction()];
|
|
884
|
+
}
|
|
885
|
+
// #endregion
|
|
886
|
+
// #region Details
|
|
887
|
+
function entityDetailsCreateActions(parentId) {
|
|
888
|
+
return {
|
|
889
|
+
title: '@general:actions.create.title',
|
|
890
|
+
command: {
|
|
891
|
+
name: 'Entity:Create',
|
|
892
|
+
options: {
|
|
893
|
+
process: {
|
|
894
|
+
redirect: false,
|
|
895
|
+
canCreateNewOne: true,
|
|
896
|
+
data: {
|
|
897
|
+
[parentId]: '{{context.eval("id")}}',
|
|
898
|
+
},
|
|
899
|
+
},
|
|
900
|
+
},
|
|
901
|
+
},
|
|
902
|
+
priority: 'primary',
|
|
903
|
+
type: AXPSystemActionType.Create,
|
|
904
|
+
scope: AXPEntityCommandScope.TypeLevel,
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Type-level Create with empty `process.data`; the FK is supplied from `relatedEntity.persistence.foreignKeyField`
|
|
909
|
+
* when the related list is built (see `mergeForeignKeyFieldIntoCreateActions`).
|
|
910
|
+
*/
|
|
911
|
+
function entityDetailsCreateActionsDeferredParent() {
|
|
912
|
+
return {
|
|
913
|
+
title: '@general:actions.create.title',
|
|
914
|
+
command: {
|
|
915
|
+
name: 'Entity:Create',
|
|
916
|
+
options: {
|
|
917
|
+
process: {
|
|
918
|
+
redirect: false,
|
|
919
|
+
canCreateNewOne: true,
|
|
920
|
+
data: {},
|
|
921
|
+
},
|
|
922
|
+
},
|
|
923
|
+
},
|
|
924
|
+
priority: 'primary',
|
|
925
|
+
type: AXPSystemActionType.Create,
|
|
926
|
+
scope: AXPEntityCommandScope.TypeLevel,
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Ensures each type-level `Entity:Create` action includes `process.data[foreignKeyField]` bound to the parent row id.
|
|
931
|
+
*/
|
|
932
|
+
function mergeForeignKeyFieldIntoCreateActions(foreignKeyField, actions) {
|
|
933
|
+
if (!foreignKeyField || !actions?.length) {
|
|
934
|
+
return actions ?? [];
|
|
935
|
+
}
|
|
936
|
+
return actions.map((a) => {
|
|
937
|
+
const cmd = a.command;
|
|
938
|
+
if (typeof cmd !== 'object' ||
|
|
939
|
+
!cmd ||
|
|
940
|
+
cmd.name !== 'Entity:Create' ||
|
|
941
|
+
a.scope !== AXPEntityCommandScope.TypeLevel) {
|
|
942
|
+
return a;
|
|
943
|
+
}
|
|
944
|
+
const opts = (cmd.options ?? {});
|
|
945
|
+
const proc = (opts['process'] ?? {});
|
|
946
|
+
const data = { ...(proc['data'] ?? {}) };
|
|
947
|
+
if (data[foreignKeyField] === undefined || data[foreignKeyField] === null || data[foreignKeyField] === '') {
|
|
948
|
+
data[foreignKeyField] = '{{ context.eval("id") }}';
|
|
949
|
+
}
|
|
950
|
+
return {
|
|
951
|
+
...a,
|
|
952
|
+
command: {
|
|
953
|
+
...cmd,
|
|
954
|
+
options: { ...opts, process: { ...proc, data } },
|
|
955
|
+
},
|
|
956
|
+
};
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
/** Property names hidden on nested Create from a related list (`excludeProperties` plus `foreignKeyField` when set). */
|
|
960
|
+
function collectNestedCreateHiddenProperties(relatedEntity) {
|
|
961
|
+
const fk = relatedEntity.persistence?.foreignKeyField;
|
|
962
|
+
const merged = [...(relatedEntity.excludeProperties ?? [])];
|
|
963
|
+
if (fk) {
|
|
964
|
+
merged.push(fk);
|
|
965
|
+
}
|
|
966
|
+
const unique = [...new Set(merged)];
|
|
967
|
+
return unique.length ? unique : undefined;
|
|
968
|
+
}
|
|
969
|
+
function entityDetailsSimpleCondition(fk) {
|
|
970
|
+
return {
|
|
971
|
+
name: fk,
|
|
972
|
+
operator: { type: 'equal' },
|
|
973
|
+
value: '{{context.eval("id")}}',
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
function entityDetailsReferenceCondition(type) {
|
|
977
|
+
return [
|
|
978
|
+
{
|
|
979
|
+
name: 'reference.id',
|
|
980
|
+
operator: { type: 'equal' },
|
|
981
|
+
value: '{{context.eval("id")}}',
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
name: 'reference.type',
|
|
985
|
+
operator: { type: 'equal' },
|
|
986
|
+
value: type,
|
|
987
|
+
},
|
|
988
|
+
];
|
|
989
|
+
}
|
|
990
|
+
function entityDetailsEditAction() {
|
|
991
|
+
return {
|
|
992
|
+
title: '@general:actions.edit.title',
|
|
993
|
+
// command: 'quick-modify-entity',
|
|
994
|
+
command: 'Entity:Update',
|
|
995
|
+
priority: 'secondary',
|
|
996
|
+
type: AXPSystemActionType.Update,
|
|
997
|
+
default: true,
|
|
998
|
+
scope: AXPEntityCommandScope.Individual,
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
function entityDetailsNewEditAction() {
|
|
1002
|
+
return {
|
|
1003
|
+
title: 'New Edit',
|
|
1004
|
+
command: {
|
|
1005
|
+
name: 'Entity:Update',
|
|
1006
|
+
},
|
|
1007
|
+
priority: 'secondary',
|
|
1008
|
+
type: AXPSystemActionType.Update,
|
|
1009
|
+
default: true,
|
|
1010
|
+
scope: AXPEntityCommandScope.Individual,
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
function entityOverrideDetailsViewAction() {
|
|
1014
|
+
return {
|
|
1015
|
+
title: '@general:actions.view.title',
|
|
1016
|
+
command: 'open-entity',
|
|
1017
|
+
priority: 'secondary',
|
|
1018
|
+
hidden: true,
|
|
1019
|
+
type: AXPSystemActionType.View,
|
|
1020
|
+
scope: AXPEntityCommandScope.Individual,
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
function entityDetailsCrudActions(parentId, options) {
|
|
1024
|
+
const opts = {
|
|
1025
|
+
create: true,
|
|
1026
|
+
delete: true,
|
|
1027
|
+
view: true,
|
|
1028
|
+
edit: true,
|
|
1029
|
+
...options,
|
|
1030
|
+
};
|
|
1031
|
+
const actions = [];
|
|
1032
|
+
if (opts.create) {
|
|
1033
|
+
if (parentId) {
|
|
1034
|
+
actions.push(entityDetailsCreateActions(parentId));
|
|
1035
|
+
}
|
|
1036
|
+
else {
|
|
1037
|
+
actions.push(entityDetailsCreateActionsDeferredParent());
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
if (opts.edit) {
|
|
1041
|
+
actions.push(entityDetailsEditAction());
|
|
1042
|
+
}
|
|
1043
|
+
if (opts.view) {
|
|
1044
|
+
actions.push(entityOverrideDetailsViewAction());
|
|
1045
|
+
}
|
|
1046
|
+
return actions;
|
|
1047
|
+
}
|
|
1048
|
+
function entityDetailsReferenceCreateActions(type) {
|
|
1049
|
+
return [
|
|
1050
|
+
{
|
|
1051
|
+
title: '@general:actions.create.title',
|
|
1052
|
+
command: {
|
|
1053
|
+
name: 'Entity:Create',
|
|
1054
|
+
options: {
|
|
1055
|
+
process: {
|
|
1056
|
+
redirect: false,
|
|
1057
|
+
canCreateNewOne: true,
|
|
1058
|
+
data: {
|
|
1059
|
+
reference: {
|
|
1060
|
+
id: '{{context.eval("id")}}',
|
|
1061
|
+
type: type,
|
|
1062
|
+
},
|
|
1063
|
+
},
|
|
1064
|
+
},
|
|
1065
|
+
},
|
|
1066
|
+
},
|
|
1067
|
+
priority: 'primary',
|
|
1068
|
+
type: AXPSystemActionType.Create,
|
|
1069
|
+
scope: AXPEntityCommandScope.TypeLevel,
|
|
1070
|
+
},
|
|
1071
|
+
entityDetailsEditAction(),
|
|
1072
|
+
entityOverrideDetailsViewAction(),
|
|
1073
|
+
];
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Computes a diff between two plain objects with array-aware semantics.
|
|
1077
|
+
* - For arrays of objects with an id field, computes added/removed by id.
|
|
1078
|
+
* - For arrays of primitives or objects without id, uses deep equality.
|
|
1079
|
+
* - For scalars/objects, reports oldValue/newValue when changed.
|
|
1080
|
+
*/
|
|
1081
|
+
function detectEntityChanges(oldObj, newObj) {
|
|
1082
|
+
return transform(newObj, (result, value, key) => {
|
|
1083
|
+
if (!isEqual(value, oldObj[key])) {
|
|
1084
|
+
const oldValue = oldObj[key];
|
|
1085
|
+
if (Array.isArray(value) || Array.isArray(oldValue)) {
|
|
1086
|
+
const oldArray = Array.isArray(oldValue) ? oldValue : [];
|
|
1087
|
+
const newArray = Array.isArray(value) ? value : [];
|
|
1088
|
+
const hasId = newArray.length > 0 && typeof newArray[0] === 'object' && newArray[0] !== null && 'id' in newArray[0];
|
|
1089
|
+
if (hasId) {
|
|
1090
|
+
const added = newArray.filter((item) => !oldArray.some((oldItem) => oldItem.id === item.id));
|
|
1091
|
+
const removed = oldArray.filter((item) => !newArray.some((newItem) => newItem.id === item.id));
|
|
1092
|
+
result[key] = { oldValue, newValue: value, added, removed };
|
|
1093
|
+
}
|
|
1094
|
+
else {
|
|
1095
|
+
const added = newArray.filter((item) => !oldArray.some((oldItem) => isEqual(item, oldItem)));
|
|
1096
|
+
const removed = oldArray.filter((item) => !newArray.some((newItem) => isEqual(item, newItem)));
|
|
1097
|
+
result[key] = { oldValue, newValue: value, added, removed };
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
else {
|
|
1101
|
+
result[key] = { oldValue, newValue: value };
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
}, {});
|
|
1105
|
+
}
|
|
1106
|
+
//#endregion
|
|
1107
|
+
|
|
806
1108
|
/**
|
|
807
1109
|
* Maps entity property `description` (or any i18n key / multi-language payload) to `form-field`
|
|
808
1110
|
* widget options. Returns `undefined` when there is nothing to show.
|
|
@@ -818,6 +1120,88 @@ function hintFormFieldOptionsFromDescription(description) {
|
|
|
818
1120
|
}
|
|
819
1121
|
//#endregion
|
|
820
1122
|
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region ---- Helpers ----
|
|
1125
|
+
function isRelatedEntityStringColumns(columns) {
|
|
1126
|
+
return columns.length === 0 || typeof columns[0] === 'string';
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Property names from `AXPRelatedEntity.columns` (no expression evaluation).
|
|
1130
|
+
* Empty array means caller can treat as “no name filter” (show all allowed by entity).
|
|
1131
|
+
*/
|
|
1132
|
+
function getRelatedEntityColumnNames(columns) {
|
|
1133
|
+
if (!columns?.length) {
|
|
1134
|
+
return [];
|
|
1135
|
+
}
|
|
1136
|
+
if (isRelatedEntityStringColumns(columns)) {
|
|
1137
|
+
return [...columns];
|
|
1138
|
+
}
|
|
1139
|
+
return columns.map((c) => c.name);
|
|
1140
|
+
}
|
|
1141
|
+
function isTruthyVisible(value) {
|
|
1142
|
+
if (value === true) {
|
|
1143
|
+
return true;
|
|
1144
|
+
}
|
|
1145
|
+
if (value === false || value === null || value === undefined) {
|
|
1146
|
+
return false;
|
|
1147
|
+
}
|
|
1148
|
+
if (typeof value === 'string') {
|
|
1149
|
+
const t = value.trim().toLowerCase();
|
|
1150
|
+
return t !== '' && t !== 'false' && t !== '0';
|
|
1151
|
+
}
|
|
1152
|
+
if (typeof value === 'number') {
|
|
1153
|
+
return value !== 0 && !Number.isNaN(value);
|
|
1154
|
+
}
|
|
1155
|
+
return Boolean(value);
|
|
1156
|
+
}
|
|
1157
|
+
//#endregion
|
|
1158
|
+
//#region ---- Public API ----
|
|
1159
|
+
/**
|
|
1160
|
+
* Resolves `AXPRelatedEntity.columns` for `entity-list`:
|
|
1161
|
+
* - `string[]` → `includeColumns` only (legacy).
|
|
1162
|
+
* - `AXPEntityTableColumn[]` → evaluates `options.visible` when it is a string (parent detail context),
|
|
1163
|
+
* drops hidden / invisible columns, and returns `relatedTableColumns` + matching `includeColumns`.
|
|
1164
|
+
*/
|
|
1165
|
+
async function resolveRelatedEntityColumns(columns, expressionEvaluator, scope) {
|
|
1166
|
+
if (!columns?.length) {
|
|
1167
|
+
return {};
|
|
1168
|
+
}
|
|
1169
|
+
if (isRelatedEntityStringColumns(columns)) {
|
|
1170
|
+
return { includeColumns: getRelatedEntityColumnNames(columns) };
|
|
1171
|
+
}
|
|
1172
|
+
const relatedTableColumns = [];
|
|
1173
|
+
for (const raw of columns) {
|
|
1174
|
+
const col = cloneDeep(raw);
|
|
1175
|
+
if (col.hidden === true) {
|
|
1176
|
+
continue;
|
|
1177
|
+
}
|
|
1178
|
+
let visible = col.options?.visible;
|
|
1179
|
+
if (visible === undefined) {
|
|
1180
|
+
visible = true;
|
|
1181
|
+
}
|
|
1182
|
+
else if (typeof visible === 'string') {
|
|
1183
|
+
const evaluated = await expressionEvaluator.evaluate(visible, scope);
|
|
1184
|
+
visible = isTruthyVisible(evaluated);
|
|
1185
|
+
}
|
|
1186
|
+
if (visible === false) {
|
|
1187
|
+
continue;
|
|
1188
|
+
}
|
|
1189
|
+
col.options = { ...col.options, visible: true };
|
|
1190
|
+
relatedTableColumns.push(col);
|
|
1191
|
+
}
|
|
1192
|
+
return {
|
|
1193
|
+
relatedTableColumns,
|
|
1194
|
+
includeColumns: relatedTableColumns.map((c) => c.name),
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
//#endregion
|
|
1198
|
+
|
|
1199
|
+
/** Registered widget name for entity create/update step wizard (dialog footer uses `widget:${name}.next`). */
|
|
1200
|
+
const ENTITY_FORM_STEP_WIZARD_NAME = 'entityFormStepWizard';
|
|
1201
|
+
/** Footer command: validate, persist main entity, merge context, advance wizard. */
|
|
1202
|
+
const ENTITY_FORM_ACTION_FIRST_STEP_CONTINUE = 'entity-form-first-step-continue';
|
|
1203
|
+
/** Footer command: close dialog (data already saved per step). */
|
|
1204
|
+
const ENTITY_FORM_ACTION_DONE = 'entity-form-done';
|
|
821
1205
|
//#endregion
|
|
822
1206
|
class AXPEntityFormBuilderService {
|
|
823
1207
|
constructor() {
|
|
@@ -825,11 +1209,12 @@ class AXPEntityFormBuilderService {
|
|
|
825
1209
|
this.entityRegistry = inject(AXPEntityDefinitionRegistryService);
|
|
826
1210
|
this.layoutBuilder = inject(AXPLayoutBuilderService);
|
|
827
1211
|
this.deviceService = inject(AXPDeviceService);
|
|
1212
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
828
1213
|
}
|
|
829
1214
|
//#endregion
|
|
830
1215
|
//#region ---- Public API ----
|
|
831
1216
|
entity(fullName) {
|
|
832
|
-
return new InterfaceSelector(this.entityRegistry, this.layoutBuilder, this.deviceService, fullName, this);
|
|
1217
|
+
return new InterfaceSelector(this.entityRegistry, this.layoutBuilder, this.deviceService, this.expressionEvaluator, fullName, this);
|
|
833
1218
|
}
|
|
834
1219
|
/**
|
|
835
1220
|
* Fetches a record by ID for the specified entity.
|
|
@@ -863,15 +1248,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
863
1248
|
}] });
|
|
864
1249
|
//#region ---- Builders ----
|
|
865
1250
|
class InterfaceSelector {
|
|
866
|
-
constructor(entityRegistry, layoutBuilder, deviceService, fullName, formBuilderService) {
|
|
1251
|
+
constructor(entityRegistry, layoutBuilder, deviceService, expressionEvaluator, fullName, formBuilderService) {
|
|
867
1252
|
this.entityRegistry = entityRegistry;
|
|
868
1253
|
this.layoutBuilder = layoutBuilder;
|
|
869
1254
|
this.deviceService = deviceService;
|
|
1255
|
+
this.expressionEvaluator = expressionEvaluator;
|
|
870
1256
|
this.fullName = fullName;
|
|
871
1257
|
this.formBuilderService = formBuilderService;
|
|
872
1258
|
}
|
|
873
1259
|
create(initialData) {
|
|
874
|
-
const filter = new PropertyFilter(this.entityRegistry, this.layoutBuilder, this.deviceService, this.fullName, 'create', undefined, this.formBuilderService);
|
|
1260
|
+
const filter = new PropertyFilter(this.entityRegistry, this.layoutBuilder, this.deviceService, this.expressionEvaluator, this.fullName, 'create', undefined, this.formBuilderService);
|
|
875
1261
|
if (initialData) {
|
|
876
1262
|
filter.context(initialData);
|
|
877
1263
|
}
|
|
@@ -887,7 +1273,7 @@ class InterfaceSelector {
|
|
|
887
1273
|
initialData = data;
|
|
888
1274
|
recordId = data['id'] || data['_id'];
|
|
889
1275
|
}
|
|
890
|
-
const filter = new PropertyFilter(this.entityRegistry, this.layoutBuilder, this.deviceService, this.fullName, 'update', recordId, this.formBuilderService);
|
|
1276
|
+
const filter = new PropertyFilter(this.entityRegistry, this.layoutBuilder, this.deviceService, this.expressionEvaluator, this.fullName, 'update', recordId, this.formBuilderService);
|
|
891
1277
|
if (Object.keys(initialData).length > 0) {
|
|
892
1278
|
filter.context(initialData);
|
|
893
1279
|
}
|
|
@@ -903,7 +1289,7 @@ class InterfaceSelector {
|
|
|
903
1289
|
initialData = data;
|
|
904
1290
|
recordId = data['id'] || data['_id'];
|
|
905
1291
|
}
|
|
906
|
-
const filter = new PropertyFilter(this.entityRegistry, this.layoutBuilder, this.deviceService, this.fullName, 'single', recordId, this.formBuilderService);
|
|
1292
|
+
const filter = new PropertyFilter(this.entityRegistry, this.layoutBuilder, this.deviceService, this.expressionEvaluator, this.fullName, 'single', recordId, this.formBuilderService);
|
|
907
1293
|
if (Object.keys(initialData).length > 0) {
|
|
908
1294
|
filter.context(initialData);
|
|
909
1295
|
}
|
|
@@ -911,10 +1297,11 @@ class InterfaceSelector {
|
|
|
911
1297
|
}
|
|
912
1298
|
}
|
|
913
1299
|
class PropertyFilter {
|
|
914
|
-
constructor(entityRegistry, layoutBuilder, deviceService, fullName, kind, recordId, formBuilderService) {
|
|
1300
|
+
constructor(entityRegistry, layoutBuilder, deviceService, expressionEvaluator, fullName, kind, recordId, formBuilderService) {
|
|
915
1301
|
this.entityRegistry = entityRegistry;
|
|
916
1302
|
this.layoutBuilder = layoutBuilder;
|
|
917
1303
|
this.deviceService = deviceService;
|
|
1304
|
+
this.expressionEvaluator = expressionEvaluator;
|
|
918
1305
|
this.fullName = fullName;
|
|
919
1306
|
this.kind = kind;
|
|
920
1307
|
this.formBuilderService = formBuilderService;
|
|
@@ -971,11 +1358,10 @@ class PropertyFilter {
|
|
|
971
1358
|
return this;
|
|
972
1359
|
}
|
|
973
1360
|
async build() {
|
|
974
|
-
const dialog = await this.buildDialog();
|
|
1361
|
+
const dialog = await this.buildDialog({});
|
|
975
1362
|
return dialog.build();
|
|
976
1363
|
}
|
|
977
1364
|
async show() {
|
|
978
|
-
const dialog = await this.buildDialog();
|
|
979
1365
|
// Context: always load by key when we have a record id (authoritative full row), then merge any
|
|
980
1366
|
// caller/list row context. Skipping fetch when initialContext was non-empty left dialogs without
|
|
981
1367
|
// fields not present on the passed row (e.g. Entity:View single() with partial list payload).
|
|
@@ -1000,14 +1386,17 @@ class PropertyFilter {
|
|
|
1000
1386
|
}
|
|
1001
1387
|
}
|
|
1002
1388
|
const effectiveContext = merge({}, this.initialContext, baseContext);
|
|
1389
|
+
const dialog = await this.buildDialog(effectiveContext);
|
|
1003
1390
|
dialog.setContext(effectiveContext);
|
|
1004
1391
|
return await dialog.show();
|
|
1005
1392
|
}
|
|
1006
1393
|
/**
|
|
1007
1394
|
* Builds the dialog node structure without showing it.
|
|
1008
1395
|
* This method is shared by both build() and show() methods.
|
|
1396
|
+
*
|
|
1397
|
+
* @param modelForRelatedEval Merged root model used to evaluate related list filters (show() passes full row).
|
|
1009
1398
|
*/
|
|
1010
|
-
async buildDialog() {
|
|
1399
|
+
async buildDialog(modelForRelatedEval) {
|
|
1011
1400
|
const { moduleName, entityName } = parseEntityFullName(this.fullName);
|
|
1012
1401
|
const entity = await this.entityRegistry.resolve(moduleName, entityName);
|
|
1013
1402
|
// Select the appropriate interface based on kind
|
|
@@ -1025,7 +1414,9 @@ class PropertyFilter {
|
|
|
1025
1414
|
// Collect all groups for title lookup (main + merged)
|
|
1026
1415
|
const allGroups = [...(entity.groups ?? [])];
|
|
1027
1416
|
// Process merge-detail related entities
|
|
1028
|
-
const mergeDetailEntities = (entity.relatedEntities ?? []).filter((re) => !re.hidden &&
|
|
1417
|
+
const mergeDetailEntities = (entity.relatedEntities ?? []).filter((re) => !re.hidden &&
|
|
1418
|
+
re.layout?.type === 'merge-detail' &&
|
|
1419
|
+
isRelatedEntityIncludedOnMasterForm(re, this.kind, 'merge-detail'));
|
|
1029
1420
|
// Build merged properties map by section
|
|
1030
1421
|
const mergedPropsBySection = new Map();
|
|
1031
1422
|
// Initialize with main entity properties
|
|
@@ -1198,118 +1589,270 @@ class PropertyFilter {
|
|
|
1198
1589
|
return sectionProps.length > 0 || extraFields.length > 0;
|
|
1199
1590
|
});
|
|
1200
1591
|
const sectionScaleFactors = normalizeLayoutFillRowGaps(renderedSections, (s) => s.layout, (s) => s.id);
|
|
1592
|
+
const filterEvalRoot = merge({}, this.initialContext, modelForRelatedEval);
|
|
1593
|
+
const listRelatedEntities = collectListRelatedEntitiesForFormWizard(entity, this.kind);
|
|
1594
|
+
const useListWizard = listRelatedEntities.length > 0 && (this.kind === 'create' || this.kind === 'update');
|
|
1595
|
+
const listWizardSteps = [];
|
|
1596
|
+
for (const re of listRelatedEntities) {
|
|
1597
|
+
const [rm, en] = re.entity.split('.');
|
|
1598
|
+
const relDef = await this.entityRegistry.resolve(rm, en);
|
|
1599
|
+
listWizardSteps.push({
|
|
1600
|
+
stepId: buildEntityFormRelatedStepId(re),
|
|
1601
|
+
title: (re.title ?? relDef?.title ?? re.entity),
|
|
1602
|
+
rel: re,
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
const prebuiltRelatedListConfigs = useListWizard
|
|
1606
|
+
? await Promise.all(listWizardSteps.map((s) => this.buildRelatedEntityListWidgetOptions(s.rel, filterEvalRoot)))
|
|
1607
|
+
: [];
|
|
1608
|
+
const mainFormGridArgs = {
|
|
1609
|
+
entity,
|
|
1610
|
+
finalSections,
|
|
1611
|
+
mergedPropsBySection,
|
|
1612
|
+
allGroups,
|
|
1613
|
+
extraFieldsByGroup: this.extraFieldsByGroup,
|
|
1614
|
+
sectionScaleFactors,
|
|
1615
|
+
};
|
|
1201
1616
|
const dialog = this.layoutBuilder.create().dialog((d) => {
|
|
1202
1617
|
d.setTitle(title);
|
|
1203
|
-
d.setSize(this.externalSize ?? calculatedSize);
|
|
1618
|
+
d.setSize(this.externalSize ?? (useListWizard ? 'lg' : calculatedSize));
|
|
1204
1619
|
d.setCloseButton(true);
|
|
1205
1620
|
d.content((layout) => {
|
|
1206
|
-
// Default mode: 'view' for single, 'edit' for create/update
|
|
1207
1621
|
const defaultMode = this.kind === 'single' ? 'view' : 'edit';
|
|
1208
1622
|
layout.mode(this.externalMode ?? defaultMode);
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
}
|
|
1221
|
-
const sectionLayout = section.layout ?? undefined;
|
|
1222
|
-
grid.item(sectionLayout, (fs) => {
|
|
1223
|
-
const sectionVisible = section.layout?.visible;
|
|
1224
|
-
if (sectionVisible !== undefined && sectionVisible !== null) {
|
|
1225
|
-
fs.visible(sectionVisible);
|
|
1226
|
-
}
|
|
1227
|
-
fs.setLook('fieldset');
|
|
1228
|
-
fs.setTitle((getGroupTitleFromList(allGroups, groupId) || groupId));
|
|
1229
|
-
fs.setCols(12);
|
|
1230
|
-
// Section label visibility (fieldset title/legend)
|
|
1231
|
-
// Prefer current interface (create/update/single) section layout, fallback to master.single section layout.
|
|
1232
|
-
const sectionLabelVisible = section?.layout?.label?.visible ??
|
|
1233
|
-
entity?.interfaces?.master?.single?.sections?.find((s) => s?.id === groupId)?.layout?.label
|
|
1234
|
-
?.visible;
|
|
1235
|
-
if (sectionLabelVisible === false) {
|
|
1236
|
-
// Different parts of the system refer to this concept with different keys.
|
|
1237
|
-
// - Fieldset view renderer currently uses `showTitle`
|
|
1238
|
-
// - Fieldset designer/property system uses `showHeader`
|
|
1239
|
-
fs.setOptions({ showTitle: false, showHeader: false });
|
|
1240
|
-
}
|
|
1241
|
-
// Sort properties by order within section
|
|
1242
|
-
const orderedProps = [...sectionProps].sort((a, b) => {
|
|
1243
|
-
const aOrder = a.__order ?? Infinity;
|
|
1244
|
-
const bOrder = b.__order ?? Infinity;
|
|
1245
|
-
return aOrder - bOrder;
|
|
1623
|
+
if (useListWizard) {
|
|
1624
|
+
layout.stepWizard((w) => {
|
|
1625
|
+
w.name(ENTITY_FORM_STEP_WIZARD_NAME);
|
|
1626
|
+
w.setLook('circular');
|
|
1627
|
+
w.setShowActions(false);
|
|
1628
|
+
const mainStepTitle = (entity.formats?.individual ||
|
|
1629
|
+
entity.title ||
|
|
1630
|
+
`${entity.module}.${entity.name}`);
|
|
1631
|
+
w.step('main', mainStepTitle, (step) => {
|
|
1632
|
+
step.content((inner) => {
|
|
1633
|
+
inner.grid((grid) => this.fillMainEntityFormGrid(grid, mainFormGridArgs));
|
|
1246
1634
|
});
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
field.defaultValue(prop.schema.defaultValue);
|
|
1263
|
-
}
|
|
1264
|
-
const fieldLayout = toFieldLayout(mergedProp.__layout);
|
|
1265
|
-
if (fieldLayout) {
|
|
1266
|
-
field.layout(fieldLayout);
|
|
1267
|
-
}
|
|
1268
|
-
if (fieldLayout?.label?.visible === false) {
|
|
1269
|
-
field.setShowLabel(false);
|
|
1270
|
-
}
|
|
1271
|
-
const hintOpts = hintFormFieldOptionsFromDescription(prop.description);
|
|
1272
|
-
if (hintOpts) {
|
|
1273
|
-
field.setOptions(hintOpts);
|
|
1274
|
-
}
|
|
1275
|
-
const widgetType = prop.schema?.interface?.type || '';
|
|
1276
|
-
const widgetOptions = buildWidgetOptions(prop);
|
|
1277
|
-
const extendedProperties = buildWidgetExtendedProperties(prop);
|
|
1278
|
-
const finalExtendedProps = dataPath
|
|
1279
|
-
? prefixExpressions(extendedProperties, dataPath)
|
|
1280
|
-
: extendedProperties;
|
|
1281
|
-
field.customWidget(widgetType, { ...widgetOptions, ...finalExtendedProps });
|
|
1282
|
-
});
|
|
1283
|
-
}
|
|
1284
|
-
for (const extra of extraFields) {
|
|
1285
|
-
const label = extra.path?.split('.').slice(-1)[0] || extra.path;
|
|
1286
|
-
fs.formField(label, (f) => {
|
|
1287
|
-
const legacy = toCompatFormFieldBuilder(f);
|
|
1288
|
-
legacy.path(extra.path);
|
|
1289
|
-
extra.delegate?.(legacy);
|
|
1635
|
+
});
|
|
1636
|
+
listWizardSteps.forEach((step, idx) => {
|
|
1637
|
+
const built = prebuiltRelatedListConfigs[idx];
|
|
1638
|
+
w.step(step.stepId, step.title, (st) => {
|
|
1639
|
+
st.content((inner) => {
|
|
1640
|
+
// Step content uses root LayoutBuilder (no customWidget); wrap in flex like other roots.
|
|
1641
|
+
inner.flex((flex) => {
|
|
1642
|
+
flex.customWidget(AXPWidgetsCatalog.entityList, (iw) => {
|
|
1643
|
+
iw.name(built.name);
|
|
1644
|
+
if (built.defaultValue) {
|
|
1645
|
+
iw.defaultValue(built.defaultValue);
|
|
1646
|
+
}
|
|
1647
|
+
iw.options(built.options);
|
|
1648
|
+
});
|
|
1649
|
+
});
|
|
1290
1650
|
});
|
|
1291
|
-
}
|
|
1651
|
+
});
|
|
1292
1652
|
});
|
|
1293
|
-
}
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
else {
|
|
1656
|
+
layout.grid((grid) => this.fillMainEntityFormGrid(grid, mainFormGridArgs));
|
|
1657
|
+
}
|
|
1658
|
+
});
|
|
1659
|
+
if (this.externalActionsDelegate && !useListWizard) {
|
|
1660
|
+
d.setActions(this.externalActionsDelegate);
|
|
1661
|
+
}
|
|
1662
|
+
else if (useListWizard) {
|
|
1663
|
+
d.setActions((ab) => configureEntityFormWizardFooterActions(ab, ENTITY_FORM_STEP_WIZARD_NAME, this.kind === 'create'
|
|
1664
|
+
? '{{ ((typeof context.id === "string" && context.id.length > 0) || (typeof context.id === "number" && !isNaN(context.id)) || (typeof context._id === "string" && context._id.length > 0) || (typeof context._id === "number" && !isNaN(context._id))) ? "@general:entity-form.update-and-continue.title" : "@general:entity-form.create-and-continue.title" }}'
|
|
1665
|
+
: '@general:entity-form.save-and-continue.title'));
|
|
1666
|
+
}
|
|
1667
|
+
else if (this.kind === 'single') {
|
|
1668
|
+
d.setActions((a) => a.submit('@general:actions.close.title'));
|
|
1669
|
+
}
|
|
1670
|
+
else {
|
|
1671
|
+
d.setActions((a) => a.submit(this.kind === 'create' ? '@general:actions.create.title' : '@general:actions.apply.title'));
|
|
1672
|
+
}
|
|
1673
|
+
if (useListWizard && this.onActionHandler) {
|
|
1674
|
+
d.onAction(this.createWizardOnActionWrapper(this.onActionHandler));
|
|
1675
|
+
}
|
|
1676
|
+
else if (this.onActionHandler) {
|
|
1677
|
+
d.onAction(this.onActionHandler);
|
|
1678
|
+
}
|
|
1679
|
+
else if (this.kind === 'single') {
|
|
1680
|
+
d.onAction(async () => ({ success: true, skipValidate: true }));
|
|
1681
|
+
}
|
|
1682
|
+
});
|
|
1683
|
+
return dialog;
|
|
1684
|
+
}
|
|
1685
|
+
/**
|
|
1686
|
+
* Renders main entity fieldsets and fields into a grid container (step 1 or non-wizard form).
|
|
1687
|
+
*/
|
|
1688
|
+
fillMainEntityFormGrid(grid, args) {
|
|
1689
|
+
grid.setColumns(12);
|
|
1690
|
+
grid.setGap('1rem');
|
|
1691
|
+
for (const section of args.finalSections) {
|
|
1692
|
+
const groupId = section.id;
|
|
1693
|
+
const sectionProps = args.mergedPropsBySection.get(groupId) ?? [];
|
|
1694
|
+
const extraFields = args.extraFieldsByGroup.get(groupId) ?? [];
|
|
1695
|
+
if (sectionProps.length === 0 && extraFields.length === 0) {
|
|
1696
|
+
continue;
|
|
1697
|
+
}
|
|
1698
|
+
const sectionLayout = section.layout ?? undefined;
|
|
1699
|
+
grid.item(sectionLayout, (fs) => {
|
|
1700
|
+
const sectionVisible = section.layout?.visible;
|
|
1701
|
+
if (sectionVisible !== undefined && sectionVisible !== null) {
|
|
1702
|
+
fs.visible(sectionVisible);
|
|
1703
|
+
}
|
|
1704
|
+
fs.setLook('fieldset');
|
|
1705
|
+
fs.setTitle((getGroupTitleFromList(args.allGroups, groupId) || groupId));
|
|
1706
|
+
fs.setCols(12);
|
|
1707
|
+
const sectionLabelVisible = section.layout?.label?.visible ??
|
|
1708
|
+
args.entity.interfaces?.master?.single?.sections?.find((s) => s?.id === groupId)?.layout?.label?.visible;
|
|
1709
|
+
if (sectionLabelVisible === false) {
|
|
1710
|
+
const legendHidden = { showTitle: false, showHeader: false };
|
|
1711
|
+
fs.setOptions(legendHidden);
|
|
1712
|
+
}
|
|
1713
|
+
const orderedProps = [...sectionProps].sort((a, b) => {
|
|
1714
|
+
const aOrder = a.__order ?? Infinity;
|
|
1715
|
+
const bOrder = b.__order ?? Infinity;
|
|
1716
|
+
return aOrder - bOrder;
|
|
1294
1717
|
});
|
|
1718
|
+
applySectionScaleToProperties(orderedProps, args.sectionScaleFactors.get(groupId));
|
|
1719
|
+
normalizeLayoutFillRowGaps(orderedProps, (p) => p.__layout);
|
|
1720
|
+
for (const prop of orderedProps) {
|
|
1721
|
+
const mergedProp = prop;
|
|
1722
|
+
const dataPath = mergedProp.__dataPath;
|
|
1723
|
+
const fieldPath = dataPath ? `${dataPath}.${prop.name}` : prop.name;
|
|
1724
|
+
fs.formField(prop.title, (field) => {
|
|
1725
|
+
field.path(fieldPath);
|
|
1726
|
+
if (prop.schema?.visible !== undefined) {
|
|
1727
|
+
field.visible(prop.schema?.visible);
|
|
1728
|
+
}
|
|
1729
|
+
if (prop.schema?.readonly !== undefined) {
|
|
1730
|
+
field.readonly(prop.schema.readonly);
|
|
1731
|
+
}
|
|
1732
|
+
if (prop.schema?.defaultValue !== undefined) {
|
|
1733
|
+
field.defaultValue(prop.schema.defaultValue);
|
|
1734
|
+
}
|
|
1735
|
+
const fieldLayout = toFieldLayout(mergedProp.__layout);
|
|
1736
|
+
if (fieldLayout) {
|
|
1737
|
+
field.layout(fieldLayout);
|
|
1738
|
+
}
|
|
1739
|
+
if (fieldLayout?.label?.visible === false) {
|
|
1740
|
+
field.setShowLabel(false);
|
|
1741
|
+
}
|
|
1742
|
+
const hintOpts = hintFormFieldOptionsFromDescription(prop.description);
|
|
1743
|
+
if (hintOpts) {
|
|
1744
|
+
field.setOptions(hintOpts);
|
|
1745
|
+
}
|
|
1746
|
+
const widgetType = prop.schema?.interface?.type || '';
|
|
1747
|
+
const widgetOptions = buildWidgetOptions(prop);
|
|
1748
|
+
const extendedProperties = buildWidgetExtendedProperties(prop);
|
|
1749
|
+
const finalExtendedProps = dataPath ? prefixExpressions(extendedProperties, dataPath) : extendedProperties;
|
|
1750
|
+
field.customWidget(widgetType, { ...widgetOptions, ...finalExtendedProps });
|
|
1751
|
+
});
|
|
1752
|
+
}
|
|
1753
|
+
for (const extra of extraFields) {
|
|
1754
|
+
const label = extra.path?.split('.').slice(-1)[0] || extra.path;
|
|
1755
|
+
fs.formField(label, (f) => {
|
|
1756
|
+
const legacy = toCompatFormFieldBuilder(f);
|
|
1757
|
+
legacy.path(extra.path);
|
|
1758
|
+
extra.delegate?.(legacy);
|
|
1759
|
+
});
|
|
1760
|
+
}
|
|
1295
1761
|
});
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
async buildRelatedEntityListWidgetOptions(relatedEntity, filterEvalRoot) {
|
|
1765
|
+
const evaluateExpressions = async (actionData) => {
|
|
1766
|
+
const scope = {
|
|
1767
|
+
context: {
|
|
1768
|
+
eval: (path) => get(filterEvalRoot, path),
|
|
1769
|
+
},
|
|
1770
|
+
};
|
|
1771
|
+
return await this.expressionEvaluator.evaluate(actionData, scope);
|
|
1772
|
+
};
|
|
1773
|
+
const syncRelatedFromRoot = this.kind === 'create';
|
|
1774
|
+
const foreignKeyField = relatedEntity.persistence?.foreignKeyField;
|
|
1775
|
+
const filters = syncRelatedFromRoot
|
|
1776
|
+
? []
|
|
1777
|
+
: await Promise.all(relatedEntity.conditions?.map(async (c) => {
|
|
1778
|
+
const value = await evaluateExpressions(c.value);
|
|
1779
|
+
return {
|
|
1780
|
+
field: c.name,
|
|
1781
|
+
operator: c.operator,
|
|
1782
|
+
value,
|
|
1783
|
+
hidden: true,
|
|
1784
|
+
};
|
|
1785
|
+
}) ?? []);
|
|
1786
|
+
const rawOrEvaluatedActions = syncRelatedFromRoot
|
|
1787
|
+
? (relatedEntity.actions ?? [])
|
|
1788
|
+
: await this.evaluateRelatedEntityActionsForFormWizard(relatedEntity.actions, filterEvalRoot);
|
|
1789
|
+
const evaluatedActions = mergeForeignKeyFieldIntoCreateActions(foreignKeyField, rawOrEvaluatedActions);
|
|
1790
|
+
const columnScope = {
|
|
1791
|
+
context: {
|
|
1792
|
+
eval: (path) => get(filterEvalRoot, path),
|
|
1793
|
+
},
|
|
1794
|
+
};
|
|
1795
|
+
const { includeColumns, relatedTableColumns } = await resolveRelatedEntityColumns(relatedEntity.columns, this.expressionEvaluator, columnScope);
|
|
1796
|
+
const nestedCreateHiddenProperties = collectNestedCreateHiddenProperties(relatedEntity);
|
|
1797
|
+
return {
|
|
1798
|
+
name: `${relatedEntity.entity}-entity-form-step`,
|
|
1799
|
+
defaultValue: {
|
|
1800
|
+
toolbar: {
|
|
1801
|
+
filters,
|
|
1802
|
+
},
|
|
1803
|
+
},
|
|
1804
|
+
options: {
|
|
1805
|
+
entity: relatedEntity.entity,
|
|
1806
|
+
showEntityActions: true,
|
|
1807
|
+
showToolbar: false,
|
|
1808
|
+
actions: evaluatedActions,
|
|
1809
|
+
maxHeight: '400px',
|
|
1810
|
+
includeColumns,
|
|
1811
|
+
relatedTableColumns,
|
|
1812
|
+
customFilterDefinitions: relatedEntity.customFilterDefinitions,
|
|
1813
|
+
...(foreignKeyField ? { foreignKeyField } : {}),
|
|
1814
|
+
...(nestedCreateHiddenProperties?.length ? { nestedCreateHiddenProperties } : {}),
|
|
1815
|
+
...(syncRelatedFromRoot && relatedEntity.conditions?.length
|
|
1816
|
+
? {
|
|
1817
|
+
relatedFilterConditionSpecs: cloneDeep(relatedEntity.conditions),
|
|
1818
|
+
syncRelatedListFiltersFromDialogContext: true,
|
|
1819
|
+
}
|
|
1820
|
+
: {}),
|
|
1821
|
+
},
|
|
1822
|
+
};
|
|
1823
|
+
}
|
|
1824
|
+
async evaluateRelatedEntityActionsForFormWizard(actions, filterEvalRoot) {
|
|
1825
|
+
const list = actions ?? [];
|
|
1826
|
+
const scope = {
|
|
1827
|
+
context: {
|
|
1828
|
+
eval: (path) => get(filterEvalRoot, path),
|
|
1829
|
+
},
|
|
1830
|
+
};
|
|
1831
|
+
return Promise.all(list.map(async (action) => {
|
|
1832
|
+
if (action.scope === AXPEntityCommandScope.Individual) {
|
|
1833
|
+
return action;
|
|
1303
1834
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1835
|
+
return (await this.expressionEvaluator.evaluate(action, scope));
|
|
1836
|
+
}));
|
|
1837
|
+
}
|
|
1838
|
+
createWizardOnActionWrapper(userHandler) {
|
|
1839
|
+
return async (ref) => {
|
|
1840
|
+
const action = ref.action();
|
|
1841
|
+
if (action === ENTITY_FORM_ACTION_DONE) {
|
|
1842
|
+
return { success: true, data: ref.context(), skipValidate: true };
|
|
1307
1843
|
}
|
|
1308
|
-
if (
|
|
1309
|
-
|
|
1844
|
+
if (action === ENTITY_FORM_ACTION_FIRST_STEP_CONTINUE) {
|
|
1845
|
+
const out = (await userHandler(ref));
|
|
1846
|
+
if (out?.success === false) {
|
|
1847
|
+
return out;
|
|
1848
|
+
}
|
|
1849
|
+
const item = out?.data?.item ?? out?.data ?? {};
|
|
1850
|
+
ref.patchContext?.(merge({}, ref.context(), item));
|
|
1851
|
+
await ref.invokeWidget?.(ENTITY_FORM_STEP_WIZARD_NAME, 'next', { setLoading: ref.setLoading });
|
|
1852
|
+
return merge({}, out, { keepDialogOpen: true });
|
|
1310
1853
|
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1854
|
+
return await userHandler(ref);
|
|
1855
|
+
};
|
|
1313
1856
|
}
|
|
1314
1857
|
computeAllowedNames(allNames) {
|
|
1315
1858
|
if (this.includeList && this.includeList.size > 0) {
|
|
@@ -1591,6 +2134,62 @@ function buildWidgetExtendedProperties(prop) {
|
|
|
1591
2134
|
}
|
|
1592
2135
|
return extended;
|
|
1593
2136
|
}
|
|
2137
|
+
function isRelatedEntityIncludedOnMasterForm(related, kind, placementKind) {
|
|
2138
|
+
if (kind !== 'create' && kind !== 'update') {
|
|
2139
|
+
return true;
|
|
2140
|
+
}
|
|
2141
|
+
const defaultInclusive = placementKind === 'merge-detail';
|
|
2142
|
+
if (kind === 'create') {
|
|
2143
|
+
const flag = related.appearOn?.create;
|
|
2144
|
+
return defaultInclusive ? flag !== false : flag === true;
|
|
2145
|
+
}
|
|
2146
|
+
const flag = related.appearOn?.update;
|
|
2147
|
+
return defaultInclusive ? flag !== false : flag === true;
|
|
2148
|
+
}
|
|
2149
|
+
function collectListRelatedEntitiesForFormWizard(entity, kind) {
|
|
2150
|
+
return (entity.relatedEntities ?? [])
|
|
2151
|
+
.filter((re) => !re.hidden &&
|
|
2152
|
+
(re.layout?.type === 'tab-list' || re.layout?.type === 'page-list') &&
|
|
2153
|
+
isRelatedEntityIncludedOnMasterForm(re, kind, 'list'))
|
|
2154
|
+
.sort((a, b) => (a.layout?.order ?? 0) - (b.layout?.order ?? 0));
|
|
2155
|
+
}
|
|
2156
|
+
function buildEntityFormRelatedStepId(re) {
|
|
2157
|
+
const safe = re.entity.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
2158
|
+
return `related-${safe}-${re.layout?.order ?? 0}`;
|
|
2159
|
+
}
|
|
2160
|
+
function configureEntityFormWizardFooterActions(ab, wizardName, firstStepContinueTitleKey) {
|
|
2161
|
+
ab.custom({
|
|
2162
|
+
title: '@general:actions.previous.title',
|
|
2163
|
+
command: `widget:${wizardName}.previous`,
|
|
2164
|
+
icon: 'fa-regular fa-arrow-left',
|
|
2165
|
+
color: 'primary',
|
|
2166
|
+
position: 'suffix',
|
|
2167
|
+
disabled: '{{api.getStatus().isFirst}}',
|
|
2168
|
+
});
|
|
2169
|
+
ab.custom({
|
|
2170
|
+
title: firstStepContinueTitleKey,
|
|
2171
|
+
command: { name: ENTITY_FORM_ACTION_FIRST_STEP_CONTINUE },
|
|
2172
|
+
color: 'primary',
|
|
2173
|
+
position: 'suffix',
|
|
2174
|
+
hidden: '{{!api.getStatus().isFirst}}',
|
|
2175
|
+
predicateApiWidgetName: wizardName,
|
|
2176
|
+
});
|
|
2177
|
+
ab.custom({
|
|
2178
|
+
title: '@general:actions.next.title',
|
|
2179
|
+
command: `widget:${wizardName}.next`,
|
|
2180
|
+
color: 'primary',
|
|
2181
|
+
position: 'suffix',
|
|
2182
|
+
hidden: '{{api.getStatus().isFirst || api.getStatus().isLast}}',
|
|
2183
|
+
});
|
|
2184
|
+
ab.custom({
|
|
2185
|
+
title: '@general:entity-form.done.title',
|
|
2186
|
+
command: { name: ENTITY_FORM_ACTION_DONE },
|
|
2187
|
+
color: 'primary',
|
|
2188
|
+
position: 'suffix',
|
|
2189
|
+
hidden: '{{!api.getStatus().isLast}}',
|
|
2190
|
+
predicateApiWidgetName: wizardName,
|
|
2191
|
+
});
|
|
2192
|
+
}
|
|
1594
2193
|
function getGroupTitle(entity, groupId) {
|
|
1595
2194
|
const g = (entity.groups || []).find((x) => x.id === groupId);
|
|
1596
2195
|
return g?.title;
|
|
@@ -1779,6 +2378,11 @@ var openEntityDetails_command = /*#__PURE__*/Object.freeze({
|
|
|
1779
2378
|
AXPOpenEntityDetailsCommand: AXPOpenEntityDetailsCommand
|
|
1780
2379
|
});
|
|
1781
2380
|
|
|
2381
|
+
/** Matches persisted PK checks used for choose update vs create (strict types only). */
|
|
2382
|
+
function hasPersistedRootId(context) {
|
|
2383
|
+
const raw = context?.id ?? context?._id;
|
|
2384
|
+
return (typeof raw === 'string' && raw.length > 0) || (typeof raw === 'number' && !Number.isNaN(raw));
|
|
2385
|
+
}
|
|
1782
2386
|
class AXPCreateEntityCommand {
|
|
1783
2387
|
constructor() {
|
|
1784
2388
|
this.entityForm = inject(AXPEntityFormBuilderService);
|
|
@@ -1812,7 +2416,6 @@ class AXPCreateEntityCommand {
|
|
|
1812
2416
|
const entityRef = await this.entityService.resolve(moduleName, entityName);
|
|
1813
2417
|
let chain = this.entityForm.entity(`${moduleName}.${entityName}`).create(data);
|
|
1814
2418
|
chain.actions((actions) => {
|
|
1815
|
-
actions.cancel('@general:actions.cancel.title');
|
|
1816
2419
|
actions.submit('@general:actions.create.title');
|
|
1817
2420
|
});
|
|
1818
2421
|
if (excludeProperties && excludeProperties.length > 0) {
|
|
@@ -1837,25 +2440,31 @@ class AXPCreateEntityCommand {
|
|
|
1837
2440
|
}
|
|
1838
2441
|
const result = await chain
|
|
1839
2442
|
.onAction(async (dialogRef) => {
|
|
1840
|
-
if (dialogRef.action() === 'cancel') {
|
|
1841
|
-
return { success: false };
|
|
1842
|
-
}
|
|
1843
2443
|
const createFn = entityRef.commands?.create?.execute;
|
|
1844
|
-
|
|
1845
|
-
|
|
2444
|
+
const updateFn = entityRef.commands?.update?.execute;
|
|
2445
|
+
const context = dialogRef.context();
|
|
2446
|
+
console.log('context', context);
|
|
2447
|
+
const hasPersistedId = hasPersistedRootId(context);
|
|
2448
|
+
const persistFn = hasPersistedId ? updateFn : createFn;
|
|
2449
|
+
const missingPersistHandlerMsg = hasPersistedId
|
|
2450
|
+
? await this.translationService.translateAsync('@general:messages.entity.update-command-unavailable')
|
|
2451
|
+
: await this.translationService.translateAsync('@general:messages.entity.create-command-unavailable');
|
|
2452
|
+
const failedMsgKey = hasPersistedId
|
|
2453
|
+
? '@general:messages.entity.update-failed'
|
|
2454
|
+
: '@general:messages.entity.create-failed';
|
|
2455
|
+
if (!persistFn) {
|
|
1846
2456
|
if (enableOperationToasts) {
|
|
1847
2457
|
this.toastService.show({
|
|
1848
2458
|
color: 'danger',
|
|
1849
2459
|
title: await this.translationService.translateAsync('@general:messages.generic.error.title'),
|
|
1850
|
-
content:
|
|
2460
|
+
content: missingPersistHandlerMsg,
|
|
1851
2461
|
});
|
|
1852
2462
|
}
|
|
1853
|
-
throw new Error(
|
|
2463
|
+
throw new Error(missingPersistHandlerMsg);
|
|
1854
2464
|
}
|
|
1855
2465
|
dialogRef.setLoading(true);
|
|
1856
2466
|
try {
|
|
1857
|
-
const
|
|
1858
|
-
const result = await createFn(context);
|
|
2467
|
+
const result = await persistFn(context);
|
|
1859
2468
|
if (result) {
|
|
1860
2469
|
return {
|
|
1861
2470
|
success: true,
|
|
@@ -1869,13 +2478,13 @@ class AXPCreateEntityCommand {
|
|
|
1869
2478
|
return {
|
|
1870
2479
|
success: false,
|
|
1871
2480
|
message: {
|
|
1872
|
-
text: await this.translationService.translateAsync(
|
|
2481
|
+
text: await this.translationService.translateAsync(failedMsgKey),
|
|
1873
2482
|
},
|
|
1874
2483
|
};
|
|
1875
2484
|
}
|
|
1876
2485
|
}
|
|
1877
2486
|
catch (e) {
|
|
1878
|
-
const errorMsg = e.message ?? (await this.translationService.translateAsync(
|
|
2487
|
+
const errorMsg = e.message ?? (await this.translationService.translateAsync(failedMsgKey));
|
|
1879
2488
|
if (enableOperationToasts) {
|
|
1880
2489
|
this.toastService.show({
|
|
1881
2490
|
color: 'danger',
|
|
@@ -2013,9 +2622,7 @@ class AXPUpdateEntityCommand {
|
|
|
2013
2622
|
};
|
|
2014
2623
|
}
|
|
2015
2624
|
const entityRef = await this.entityService.resolve(moduleName, entityName);
|
|
2016
|
-
let dialogRef;
|
|
2017
2625
|
try {
|
|
2018
|
-
// Validate data type
|
|
2019
2626
|
if (!data || (typeof data !== 'string' && typeof data !== 'object')) {
|
|
2020
2627
|
return {
|
|
2021
2628
|
success: false,
|
|
@@ -2024,10 +2631,8 @@ class AXPUpdateEntityCommand {
|
|
|
2024
2631
|
},
|
|
2025
2632
|
};
|
|
2026
2633
|
}
|
|
2027
|
-
// Pass data directly to update() - it handles string | object internally
|
|
2028
2634
|
let chain = this.entityForm.entity(`${moduleName}.${entityName}`).update(data);
|
|
2029
2635
|
chain.actions((actions) => {
|
|
2030
|
-
actions.cancel('@general:actions.cancel.title');
|
|
2031
2636
|
actions.submit('@general:actions.apply.title');
|
|
2032
2637
|
});
|
|
2033
2638
|
if (excludeProperties && excludeProperties.length > 0) {
|
|
@@ -2048,19 +2653,8 @@ class AXPUpdateEntityCommand {
|
|
|
2048
2653
|
if (finalSize) {
|
|
2049
2654
|
chain.size(finalSize);
|
|
2050
2655
|
}
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
dialogRef.close();
|
|
2054
|
-
return {
|
|
2055
|
-
success: false,
|
|
2056
|
-
// message: {
|
|
2057
|
-
// text: await this.translationService.translateAsync('@general:messages.generic.cancel.description'),
|
|
2058
|
-
// },
|
|
2059
|
-
};
|
|
2060
|
-
}
|
|
2061
|
-
else if (dialogRef.action() === 'submit') {
|
|
2062
|
-
dialogRef.setLoading(true);
|
|
2063
|
-
const context = dialogRef.context();
|
|
2656
|
+
return (await chain
|
|
2657
|
+
.onAction(async (dialogRef) => {
|
|
2064
2658
|
const updateFn = entityRef.commands?.update?.execute;
|
|
2065
2659
|
if (!updateFn) {
|
|
2066
2660
|
const msg = await this.translationService.translateAsync('@general:messages.entity.update-command-unavailable');
|
|
@@ -2071,35 +2665,44 @@ class AXPUpdateEntityCommand {
|
|
|
2071
2665
|
content: msg,
|
|
2072
2666
|
});
|
|
2073
2667
|
}
|
|
2074
|
-
|
|
2075
|
-
success: false,
|
|
2076
|
-
message: { text: msg },
|
|
2077
|
-
};
|
|
2668
|
+
throw new Error(msg);
|
|
2078
2669
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
dialogRef.
|
|
2670
|
+
dialogRef.setLoading(true);
|
|
2671
|
+
try {
|
|
2672
|
+
const context = dialogRef.context();
|
|
2673
|
+
const result = await updateFn(context);
|
|
2674
|
+
if (result) {
|
|
2675
|
+
return {
|
|
2676
|
+
success: true,
|
|
2677
|
+
data: result.data ?? result,
|
|
2678
|
+
message: {
|
|
2679
|
+
text: await this.translationService.translateAsync('@general:messages.generic.success.description'),
|
|
2680
|
+
},
|
|
2681
|
+
};
|
|
2682
|
+
}
|
|
2082
2683
|
return {
|
|
2083
|
-
success:
|
|
2084
|
-
data: result,
|
|
2684
|
+
success: false,
|
|
2085
2685
|
message: {
|
|
2086
|
-
text: await this.translationService.translateAsync('@general:messages.
|
|
2686
|
+
text: await this.translationService.translateAsync('@general:messages.entity.command-no-result'),
|
|
2087
2687
|
},
|
|
2088
2688
|
};
|
|
2089
2689
|
}
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2690
|
+
catch (e) {
|
|
2691
|
+
const errorMsg = e.message ?? (await this.translationService.translateAsync('@general:messages.entity.update-failed'));
|
|
2692
|
+
if (enableOperationToasts) {
|
|
2693
|
+
this.toastService.show({
|
|
2694
|
+
color: 'danger',
|
|
2695
|
+
title: await this.translationService.translateAsync('@general:messages.generic.error.title'),
|
|
2696
|
+
content: errorMsg,
|
|
2697
|
+
});
|
|
2698
|
+
}
|
|
2699
|
+
throw e;
|
|
2700
|
+
}
|
|
2701
|
+
finally {
|
|
2702
|
+
dialogRef.setLoading(false);
|
|
2703
|
+
}
|
|
2704
|
+
})
|
|
2705
|
+
.show());
|
|
2103
2706
|
}
|
|
2104
2707
|
catch (error) {
|
|
2105
2708
|
const text = error instanceof Error
|
|
@@ -2117,11 +2720,6 @@ class AXPUpdateEntityCommand {
|
|
|
2117
2720
|
message: { text },
|
|
2118
2721
|
};
|
|
2119
2722
|
}
|
|
2120
|
-
finally {
|
|
2121
|
-
if (dialogRef) {
|
|
2122
|
-
dialogRef.setLoading(false);
|
|
2123
|
-
}
|
|
2124
|
-
}
|
|
2125
2723
|
}
|
|
2126
2724
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPUpdateEntityCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2127
2725
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPUpdateEntityCommand, providedIn: 'root' }); }
|
|
@@ -3326,82 +3924,6 @@ class AXPEntityListViewColumnViewModel {
|
|
|
3326
3924
|
}
|
|
3327
3925
|
}
|
|
3328
3926
|
|
|
3329
|
-
//#endregion
|
|
3330
|
-
//#region ---- Helpers ----
|
|
3331
|
-
function isRelatedEntityStringColumns(columns) {
|
|
3332
|
-
return columns.length === 0 || typeof columns[0] === 'string';
|
|
3333
|
-
}
|
|
3334
|
-
/**
|
|
3335
|
-
* Property names from `AXPRelatedEntity.columns` (no expression evaluation).
|
|
3336
|
-
* Empty array means caller can treat as “no name filter” (show all allowed by entity).
|
|
3337
|
-
*/
|
|
3338
|
-
function getRelatedEntityColumnNames(columns) {
|
|
3339
|
-
if (!columns?.length) {
|
|
3340
|
-
return [];
|
|
3341
|
-
}
|
|
3342
|
-
if (isRelatedEntityStringColumns(columns)) {
|
|
3343
|
-
return [...columns];
|
|
3344
|
-
}
|
|
3345
|
-
return columns.map((c) => c.name);
|
|
3346
|
-
}
|
|
3347
|
-
function isTruthyVisible(value) {
|
|
3348
|
-
if (value === true) {
|
|
3349
|
-
return true;
|
|
3350
|
-
}
|
|
3351
|
-
if (value === false || value === null || value === undefined) {
|
|
3352
|
-
return false;
|
|
3353
|
-
}
|
|
3354
|
-
if (typeof value === 'string') {
|
|
3355
|
-
const t = value.trim().toLowerCase();
|
|
3356
|
-
return t !== '' && t !== 'false' && t !== '0';
|
|
3357
|
-
}
|
|
3358
|
-
if (typeof value === 'number') {
|
|
3359
|
-
return value !== 0 && !Number.isNaN(value);
|
|
3360
|
-
}
|
|
3361
|
-
return Boolean(value);
|
|
3362
|
-
}
|
|
3363
|
-
//#endregion
|
|
3364
|
-
//#region ---- Public API ----
|
|
3365
|
-
/**
|
|
3366
|
-
* Resolves `AXPRelatedEntity.columns` for `entity-list`:
|
|
3367
|
-
* - `string[]` → `includeColumns` only (legacy).
|
|
3368
|
-
* - `AXPEntityTableColumn[]` → evaluates `options.visible` when it is a string (parent detail context),
|
|
3369
|
-
* drops hidden / invisible columns, and returns `relatedTableColumns` + matching `includeColumns`.
|
|
3370
|
-
*/
|
|
3371
|
-
async function resolveRelatedEntityColumns(columns, expressionEvaluator, scope) {
|
|
3372
|
-
if (!columns?.length) {
|
|
3373
|
-
return {};
|
|
3374
|
-
}
|
|
3375
|
-
if (isRelatedEntityStringColumns(columns)) {
|
|
3376
|
-
return { includeColumns: getRelatedEntityColumnNames(columns) };
|
|
3377
|
-
}
|
|
3378
|
-
const relatedTableColumns = [];
|
|
3379
|
-
for (const raw of columns) {
|
|
3380
|
-
const col = cloneDeep(raw);
|
|
3381
|
-
if (col.hidden === true) {
|
|
3382
|
-
continue;
|
|
3383
|
-
}
|
|
3384
|
-
let visible = col.options?.visible;
|
|
3385
|
-
if (visible === undefined) {
|
|
3386
|
-
visible = true;
|
|
3387
|
-
}
|
|
3388
|
-
else if (typeof visible === 'string') {
|
|
3389
|
-
const evaluated = await expressionEvaluator.evaluate(visible, scope);
|
|
3390
|
-
visible = isTruthyVisible(evaluated);
|
|
3391
|
-
}
|
|
3392
|
-
if (visible === false) {
|
|
3393
|
-
continue;
|
|
3394
|
-
}
|
|
3395
|
-
col.options = { ...col.options, visible: true };
|
|
3396
|
-
relatedTableColumns.push(col);
|
|
3397
|
-
}
|
|
3398
|
-
return {
|
|
3399
|
-
relatedTableColumns,
|
|
3400
|
-
includeColumns: relatedTableColumns.map((c) => c.name),
|
|
3401
|
-
};
|
|
3402
|
-
}
|
|
3403
|
-
//#endregion
|
|
3404
|
-
|
|
3405
3927
|
class AXPEntityDetailListViewModel {
|
|
3406
3928
|
constructor(injector, detailEntityConfig, parent) {
|
|
3407
3929
|
this.injector = injector;
|
|
@@ -4302,7 +4824,6 @@ class AXPEntityMasterListViewModel {
|
|
|
4302
4824
|
width: c.width,
|
|
4303
4825
|
}));
|
|
4304
4826
|
set(newSettings, `list.views.${this.view().name}.columns`, updatedColumns);
|
|
4305
|
-
console.log(newSettings, `list.views.${this.view().name}.columns`);
|
|
4306
4827
|
return newSettings;
|
|
4307
4828
|
});
|
|
4308
4829
|
break;
|
|
@@ -10441,6 +10962,42 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
10441
10962
|
}));
|
|
10442
10963
|
return actions;
|
|
10443
10964
|
}, ...(ngDevMode ? [{ debugName: "secondaryActions" }] : /* istanbul ignore next */ []));
|
|
10965
|
+
/** Keeps related-list filters in sync with dialog context for create wizards (main id appears after first-step save). */
|
|
10966
|
+
this.#relatedFilterSyncEffect = effect(() => {
|
|
10967
|
+
const opts = this.options();
|
|
10968
|
+
if (!opts['syncRelatedListFiltersFromDialogContext']) {
|
|
10969
|
+
return;
|
|
10970
|
+
}
|
|
10971
|
+
const specs = opts['relatedFilterConditionSpecs'];
|
|
10972
|
+
if (!specs?.length) {
|
|
10973
|
+
return;
|
|
10974
|
+
}
|
|
10975
|
+
this.contextService.data();
|
|
10976
|
+
if (!this.fullPath()) {
|
|
10977
|
+
return;
|
|
10978
|
+
}
|
|
10979
|
+
untracked(() => void this.applyRelatedFiltersFromContextAndDatasource(specs));
|
|
10980
|
+
}, ...(ngDevMode ? [{ debugName: "#relatedFilterSyncEffect" }] : /* istanbul ignore next */ []));
|
|
10981
|
+
/** Patches data-list `refresh` so the grid footer / toolbar refresh keeps parent-scoped filters on the data source. */
|
|
10982
|
+
this.#patchDataListRefreshEffect = effect(() => {
|
|
10983
|
+
const inst = this.listWidget()?.instance;
|
|
10984
|
+
const opts = this.options();
|
|
10985
|
+
if (!inst?.refresh || inst.__axpEntityListRefreshPatched || !opts['syncRelatedListFiltersFromDialogContext']) {
|
|
10986
|
+
return;
|
|
10987
|
+
}
|
|
10988
|
+
inst.__axpEntityListRefreshPatched = true;
|
|
10989
|
+
const originalRefresh = inst.refresh.bind(inst);
|
|
10990
|
+
inst.refresh = () => {
|
|
10991
|
+
void (async () => {
|
|
10992
|
+
const o = this.options();
|
|
10993
|
+
const specs = o['relatedFilterConditionSpecs'];
|
|
10994
|
+
if (o['syncRelatedListFiltersFromDialogContext'] && specs?.length) {
|
|
10995
|
+
await this.applyRelatedFiltersFromContextAndDatasource(specs);
|
|
10996
|
+
}
|
|
10997
|
+
originalRefresh();
|
|
10998
|
+
})();
|
|
10999
|
+
};
|
|
11000
|
+
}, ...(ngDevMode ? [{ debugName: "#patchDataListRefreshEffect" }] : /* istanbul ignore next */ []));
|
|
10444
11001
|
//#region ---- Query Change Handler ----
|
|
10445
11002
|
this.queries = undefined;
|
|
10446
11003
|
this.#effect = effect(() => {
|
|
@@ -10491,12 +11048,32 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
10491
11048
|
const commandData = action?.scope == AXPEntityCommandScope.Selected
|
|
10492
11049
|
? this.selectedItems()
|
|
10493
11050
|
: action?.options?.['process']?.data || null;
|
|
10494
|
-
|
|
10495
|
-
const
|
|
10496
|
-
const
|
|
10497
|
-
const
|
|
10498
|
-
|
|
10499
|
-
|
|
11051
|
+
let options = await this.evaluateToolbarExpressions(action?.options, commandData);
|
|
11052
|
+
const listOpts = this.options();
|
|
11053
|
+
const foreignKeyFieldName = listOpts['foreignKeyField'];
|
|
11054
|
+
const createExcludes = listOpts['nestedCreateHiddenProperties'] ?? [];
|
|
11055
|
+
if (command === 'Entity:Create' && foreignKeyFieldName) {
|
|
11056
|
+
const root = this.contextService.snapshot();
|
|
11057
|
+
const idVal = get(root, 'id');
|
|
11058
|
+
options = merge({}, options);
|
|
11059
|
+
options['process'] = merge({}, options['process'], {
|
|
11060
|
+
data: merge({}, options['process']?.data ?? {}, {
|
|
11061
|
+
...(idVal !== undefined && idVal !== null && idVal !== '' ? { [foreignKeyFieldName]: idVal } : {}),
|
|
11062
|
+
}),
|
|
11063
|
+
});
|
|
11064
|
+
}
|
|
11065
|
+
if (command === 'Entity:Create' && createExcludes.length) {
|
|
11066
|
+
const existing = (options['excludeProperties'] ?? []).slice();
|
|
11067
|
+
options = merge({}, options);
|
|
11068
|
+
options['excludeProperties'] = [...new Set([...createExcludes, ...existing])];
|
|
11069
|
+
}
|
|
11070
|
+
const relatedExcludes = listOpts['excludeProperties'];
|
|
11071
|
+
const exclusionsFromList = relatedExcludes?.filter(Boolean) ?? [];
|
|
11072
|
+
if (exclusionsFromList.length && (command === 'Entity:Create' || command === 'Entity:Update')) {
|
|
11073
|
+
const existing = (options['excludeProperties'] ?? []).slice();
|
|
11074
|
+
options = merge({}, options);
|
|
11075
|
+
options['excludeProperties'] = [...new Set([...existing, ...exclusionsFromList])];
|
|
11076
|
+
}
|
|
10500
11077
|
if (this.commandService.exists(command)) {
|
|
10501
11078
|
await this.commandService.execute(command, {
|
|
10502
11079
|
__context__: {
|
|
@@ -10536,13 +11113,88 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
10536
11113
|
if (!opts) {
|
|
10537
11114
|
return {};
|
|
10538
11115
|
}
|
|
11116
|
+
const root = this.contextService.snapshot();
|
|
10539
11117
|
const scope = {
|
|
10540
11118
|
context: {
|
|
10541
|
-
eval: (path) => get(expressionData, path),
|
|
11119
|
+
eval: (path) => get(root, path) ?? get(expressionData, path),
|
|
10542
11120
|
},
|
|
10543
11121
|
};
|
|
10544
11122
|
return (await this.expressionEvaluator.evaluate(opts, scope));
|
|
10545
11123
|
}
|
|
11124
|
+
/**
|
|
11125
|
+
* Re-evaluates related-entity list filters from the live dialog form context (e.g. after create saves the main row id).
|
|
11126
|
+
*/
|
|
11127
|
+
async applyRelatedFiltersFromContext(specs) {
|
|
11128
|
+
const root = this.contextService.snapshot();
|
|
11129
|
+
const scope = {
|
|
11130
|
+
context: {
|
|
11131
|
+
eval: (path) => get(root, path),
|
|
11132
|
+
},
|
|
11133
|
+
};
|
|
11134
|
+
const filters = await Promise.all(specs.map(async (c) => ({
|
|
11135
|
+
field: c.name,
|
|
11136
|
+
operator: c.operator,
|
|
11137
|
+
value: await this.expressionEvaluator.evaluate(c.value, scope),
|
|
11138
|
+
hidden: true,
|
|
11139
|
+
})));
|
|
11140
|
+
if (!this.fullPath()) {
|
|
11141
|
+
return;
|
|
11142
|
+
}
|
|
11143
|
+
const current = this.getValue();
|
|
11144
|
+
if (isEqual$1(current?.toolbar?.filters, filters)) {
|
|
11145
|
+
return;
|
|
11146
|
+
}
|
|
11147
|
+
this.setValue({
|
|
11148
|
+
...current,
|
|
11149
|
+
toolbar: { ...(current?.toolbar ?? {}), filters },
|
|
11150
|
+
});
|
|
11151
|
+
}
|
|
11152
|
+
/** Keeps related-list filters in sync with dialog context for create wizards (main id appears after first-step save). */
|
|
11153
|
+
#relatedFilterSyncEffect;
|
|
11154
|
+
/**
|
|
11155
|
+
* Pushes current toolbar filters to the embedded list data source when both exist.
|
|
11156
|
+
* Returns false while data-list is still mounting (see deferred listNode.set in ngOnInit).
|
|
11157
|
+
*/
|
|
11158
|
+
pushToolbarFiltersToDataSource() {
|
|
11159
|
+
const listInstance = this.listWidget()?.instance;
|
|
11160
|
+
const dataSource = listInstance?.options?.()?.['dataSource'];
|
|
11161
|
+
const toolbar = this.getValue()?.toolbar;
|
|
11162
|
+
if (!dataSource?.filter || !toolbar?.filters?.length) {
|
|
11163
|
+
return false;
|
|
11164
|
+
}
|
|
11165
|
+
dataSource.filter({ filters: toolbar.filters });
|
|
11166
|
+
return true;
|
|
11167
|
+
}
|
|
11168
|
+
/**
|
|
11169
|
+
* Writes toolbar filters from specs and pushes them onto the data source so refresh/reload keeps the parent scope.
|
|
11170
|
+
*/
|
|
11171
|
+
async applyRelatedFiltersFromContextAndDatasource(specs) {
|
|
11172
|
+
await this.applyRelatedFiltersFromContext(specs);
|
|
11173
|
+
if (this.pushToolbarFiltersToDataSource()) {
|
|
11174
|
+
return;
|
|
11175
|
+
}
|
|
11176
|
+
const opts = this.options();
|
|
11177
|
+
if (!opts['syncRelatedListFiltersFromDialogContext']) {
|
|
11178
|
+
return;
|
|
11179
|
+
}
|
|
11180
|
+
/** Data-list is created in ngOnInit via deferred listNode.set; retry briefly until instance exposes dataSource. */
|
|
11181
|
+
const maxAttempts = 40;
|
|
11182
|
+
const delayMs = 50;
|
|
11183
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
11184
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
11185
|
+
if (this.pushToolbarFiltersToDataSource()) {
|
|
11186
|
+
return;
|
|
11187
|
+
}
|
|
11188
|
+
}
|
|
11189
|
+
}
|
|
11190
|
+
/**
|
|
11191
|
+
* Refreshes the embedded data list (toolbar / workflow). In wizard mode, `refresh` is patched to re-apply scoped filters first.
|
|
11192
|
+
*/
|
|
11193
|
+
refreshGridWithParentScopedFilters() {
|
|
11194
|
+
this.listWidget()?.instance?.call('refresh');
|
|
11195
|
+
}
|
|
11196
|
+
/** Patches data-list `refresh` so the grid footer / toolbar refresh keeps parent-scoped filters on the data source. */
|
|
11197
|
+
#patchDataListRefreshEffect;
|
|
10546
11198
|
#effect;
|
|
10547
11199
|
/**
|
|
10548
11200
|
* Validates that all required dependencies are available
|
|
@@ -10669,6 +11321,9 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
10669
11321
|
columns: this.getValue()?.toolbar?.columns,
|
|
10670
11322
|
},
|
|
10671
11323
|
});
|
|
11324
|
+
queueMicrotask(() => {
|
|
11325
|
+
void this.pushToolbarFiltersToDataSource();
|
|
11326
|
+
});
|
|
10672
11327
|
}, 100);
|
|
10673
11328
|
}
|
|
10674
11329
|
async ngAfterViewInit() {
|
|
@@ -10677,7 +11332,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
10677
11332
|
.pipe(takeUntil(this.destroyed))
|
|
10678
11333
|
.subscribe((event) => {
|
|
10679
11334
|
if (event.payload.entity == this.entitySource()) {
|
|
10680
|
-
this.
|
|
11335
|
+
this.refreshGridWithParentScopedFilters();
|
|
10681
11336
|
}
|
|
10682
11337
|
});
|
|
10683
11338
|
this.eventService
|
|
@@ -10685,7 +11340,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
10685
11340
|
.pipe(takeUntil(this.destroyed))
|
|
10686
11341
|
.subscribe((e) => {
|
|
10687
11342
|
if (e.data.name == `${this.entity()?.module}.${this.entity()?.name}`) {
|
|
10688
|
-
this.
|
|
11343
|
+
this.refreshGridWithParentScopedFilters();
|
|
10689
11344
|
}
|
|
10690
11345
|
});
|
|
10691
11346
|
const listWidget = (await this.layoutService.waitForWidget(`${this.entitySource()}-tab-list_table`, 500));
|
|
@@ -12262,7 +12917,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12262
12917
|
const prevValue = this.previousValue();
|
|
12263
12918
|
const isInitialized = this.initialized();
|
|
12264
12919
|
// Check if value has actually changed
|
|
12265
|
-
const valueChanged = !isEqual(currentValue, prevValue);
|
|
12920
|
+
const valueChanged = !isEqual$1(currentValue, prevValue);
|
|
12266
12921
|
// Determine if we should update:
|
|
12267
12922
|
// 1. First initialization with a value
|
|
12268
12923
|
// 2. Value becomes empty after initialization
|
|
@@ -12413,67 +13068,53 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12413
13068
|
}
|
|
12414
13069
|
}
|
|
12415
13070
|
/**
|
|
12416
|
-
*
|
|
13071
|
+
* Writes expose targets into context using per-path updates.
|
|
13072
|
+
* Avoids `contextService.patch()` with nested objects: patch shallow-merges top-level keys only,
|
|
13073
|
+
* so e.g. `{ person: { educationLevel: { id, title } } }` would replace the entire `person`
|
|
13074
|
+
* object and drop sibling fields like `person.educationLevelId`, causing a value/effect loop.
|
|
12417
13075
|
*/
|
|
12418
13076
|
expoesItems() {
|
|
12419
13077
|
const exposeValue = castArray(this.expose());
|
|
12420
|
-
const itemToExpose = {};
|
|
12421
13078
|
const items = this.selectedItems();
|
|
12422
13079
|
const isEmpty = !items || items.length === 0;
|
|
12423
|
-
// If items are empty, group expose configs by parent path and set parent to null
|
|
12424
13080
|
if (isEmpty) {
|
|
12425
13081
|
const parentPaths = new Set();
|
|
12426
13082
|
exposeValue.forEach((i) => {
|
|
12427
13083
|
if (typeof i === 'string') {
|
|
12428
|
-
// For string expose, the path itself is the target
|
|
12429
13084
|
const pathParts = i.split('.');
|
|
12430
13085
|
if (pathParts.length > 1) {
|
|
12431
|
-
|
|
12432
|
-
const parentPath = pathParts.slice(0, -1).join('.');
|
|
12433
|
-
parentPaths.add(parentPath);
|
|
13086
|
+
parentPaths.add(pathParts.slice(0, -1).join('.'));
|
|
12434
13087
|
}
|
|
12435
13088
|
else {
|
|
12436
|
-
|
|
12437
|
-
setSmart(itemToExpose, i, null);
|
|
13089
|
+
this.contextService.update(i, null);
|
|
12438
13090
|
}
|
|
12439
13091
|
}
|
|
12440
13092
|
else {
|
|
12441
|
-
// For object expose, extract parent path from target
|
|
12442
13093
|
const pathParts = i.target.split('.');
|
|
12443
|
-
if (pathParts.length > 1) {
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12449
|
-
// Single level path, set directly to null
|
|
12450
|
-
setSmart(itemToExpose, i.target, null);
|
|
12451
|
-
}
|
|
12452
|
-
}
|
|
12453
|
-
});
|
|
12454
|
-
// Set all parent paths to null
|
|
12455
|
-
parentPaths.forEach((parentPath) => {
|
|
12456
|
-
setSmart(itemToExpose, parentPath, null);
|
|
12457
|
-
});
|
|
12458
|
-
}
|
|
12459
|
-
else {
|
|
12460
|
-
// Normal processing when items exist
|
|
12461
|
-
exposeValue.forEach((i) => {
|
|
12462
|
-
if (typeof i == 'string') {
|
|
12463
|
-
const values = items.map((item) => set({}, i, get(item, i)));
|
|
12464
|
-
setSmart(itemToExpose, i, this.singleOrMultiple(values));
|
|
12465
|
-
}
|
|
12466
|
-
else {
|
|
12467
|
-
// extract data from item by source path and set context by target path
|
|
12468
|
-
const values = this.multiple()
|
|
12469
|
-
? items.map((item) => set({}, i.source, get(item, i.source)))
|
|
12470
|
-
: items.map((item) => get(item, i.source));
|
|
12471
|
-
setSmart(itemToExpose, i.target, this.singleOrMultiple(values));
|
|
13094
|
+
if (pathParts.length > 1) {
|
|
13095
|
+
parentPaths.add(pathParts.slice(0, -1).join('.'));
|
|
13096
|
+
}
|
|
13097
|
+
else {
|
|
13098
|
+
this.contextService.update(i.target, null);
|
|
13099
|
+
}
|
|
12472
13100
|
}
|
|
12473
13101
|
});
|
|
13102
|
+
parentPaths.forEach((parentPath) => {
|
|
13103
|
+
this.contextService.update(parentPath, null);
|
|
13104
|
+
});
|
|
13105
|
+
return;
|
|
12474
13106
|
}
|
|
12475
|
-
|
|
12476
|
-
|
|
13107
|
+
exposeValue.forEach((i) => {
|
|
13108
|
+
if (typeof i === 'string') {
|
|
13109
|
+
const values = items.map((item) => set({}, i, get(item, i)));
|
|
13110
|
+
this.contextService.update(i, this.singleOrMultiple(values));
|
|
13111
|
+
}
|
|
13112
|
+
else {
|
|
13113
|
+
const values = this.multiple()
|
|
13114
|
+
? items.map((item) => set({}, i.source, get(item, i.source)))
|
|
13115
|
+
: items.map((item) => get(item, i.source));
|
|
13116
|
+
this.contextService.update(i.target, this.singleOrMultiple(values));
|
|
13117
|
+
}
|
|
12477
13118
|
});
|
|
12478
13119
|
}
|
|
12479
13120
|
singleOrMultiple(values) {
|
|
@@ -16676,16 +17317,34 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
16676
17317
|
evaluatedOptions = action.options;
|
|
16677
17318
|
}
|
|
16678
17319
|
}
|
|
16679
|
-
|
|
17320
|
+
let actionData = action.scope == AXPEntityCommandScope.Selected
|
|
16680
17321
|
? executeContext
|
|
16681
17322
|
: evaluatedOptions?.['process']?.data || null;
|
|
16682
|
-
|
|
16683
|
-
|
|
16684
|
-
|
|
16685
|
-
|
|
16686
|
-
|
|
16687
|
-
|
|
16688
|
-
|
|
17323
|
+
const foreignKeyField = relatedEntity.persistence?.foreignKeyField;
|
|
17324
|
+
if (commandName === 'Entity:Create' && foreignKeyField && context.context) {
|
|
17325
|
+
const parentId = get(context.context, 'id');
|
|
17326
|
+
actionData = {
|
|
17327
|
+
...(typeof actionData === 'object' && actionData !== null ? actionData : {}),
|
|
17328
|
+
...(parentId !== undefined && parentId !== null && parentId !== ''
|
|
17329
|
+
? { [foreignKeyField]: parentId }
|
|
17330
|
+
: {}),
|
|
17331
|
+
};
|
|
17332
|
+
}
|
|
17333
|
+
const createExcludes = [
|
|
17334
|
+
...new Set([
|
|
17335
|
+
...(relatedEntity.excludeProperties ?? []),
|
|
17336
|
+
...(commandName === 'Entity:Create' && foreignKeyField ? [foreignKeyField] : []),
|
|
17337
|
+
]),
|
|
17338
|
+
];
|
|
17339
|
+
const excludeForCreate = commandName === 'Entity:Create' && createExcludes.length > 0;
|
|
17340
|
+
const excludeForUpdate = commandName === 'Entity:Update' &&
|
|
17341
|
+
relatedEntity.excludeProperties &&
|
|
17342
|
+
relatedEntity.excludeProperties.length > 0;
|
|
17343
|
+
const mergedOptions = excludeForCreate
|
|
17344
|
+
? { ...evaluatedOptions, excludeProperties: createExcludes }
|
|
17345
|
+
: excludeForUpdate
|
|
17346
|
+
? { ...evaluatedOptions, excludeProperties: relatedEntity.excludeProperties }
|
|
17347
|
+
: evaluatedOptions;
|
|
16689
17348
|
if (context.commandService.exists(commandName)) {
|
|
16690
17349
|
// check options for evaluation
|
|
16691
17350
|
await context.commandService.execute(commandName, {
|
|
@@ -18443,6 +19102,7 @@ const AXPCrudModifier = {
|
|
|
18443
19102
|
if (!command?.create) {
|
|
18444
19103
|
command.create = {
|
|
18445
19104
|
execute: async (data) => {
|
|
19105
|
+
console.log('create', ctx.module.get() + '.' + ctx.name.get(), data);
|
|
18446
19106
|
const res = await dataService.insertOne(data);
|
|
18447
19107
|
return { id: res };
|
|
18448
19108
|
},
|
|
@@ -18458,6 +19118,7 @@ const AXPCrudModifier = {
|
|
|
18458
19118
|
if (!command?.update) {
|
|
18459
19119
|
command.update = {
|
|
18460
19120
|
execute: async (data) => {
|
|
19121
|
+
console.log('update', ctx.module.get() + '.' + ctx.name.get(), data);
|
|
18461
19122
|
return await dataService.updateOne(data.id, data);
|
|
18462
19123
|
},
|
|
18463
19124
|
};
|
|
@@ -18472,7 +19133,6 @@ const AXPCrudModifier = {
|
|
|
18472
19133
|
queries.byKey = {
|
|
18473
19134
|
execute: async (id) => {
|
|
18474
19135
|
const data = await dataService.getOne(id);
|
|
18475
|
-
// debugger;
|
|
18476
19136
|
return data;
|
|
18477
19137
|
},
|
|
18478
19138
|
type: AXPEntityQueryType.Single,
|
|
@@ -18481,6 +19141,7 @@ const AXPCrudModifier = {
|
|
|
18481
19141
|
if (!queries?.list) {
|
|
18482
19142
|
queries.list = {
|
|
18483
19143
|
execute: async (e) => {
|
|
19144
|
+
console.log('query', ctx.module.get() + '.' + ctx.name.get(), e);
|
|
18484
19145
|
return await dataService.query(e);
|
|
18485
19146
|
},
|
|
18486
19147
|
type: AXPEntityQueryType.List,
|
|
@@ -19076,10 +19737,34 @@ class AXPShowListViewAction extends AXPWorkflowAction {
|
|
|
19076
19737
|
this.sessionService = inject(AXPSessionService);
|
|
19077
19738
|
}
|
|
19078
19739
|
async execute(context) {
|
|
19079
|
-
const
|
|
19740
|
+
const entity = context.getVariable('entity');
|
|
19741
|
+
const [moduleName, entityName] = entity.split('.');
|
|
19080
19742
|
const newPayload = {
|
|
19081
19743
|
commands: `/${this.sessionService.application?.name}/m/${moduleName}/e/${entityName}/list`,
|
|
19082
19744
|
};
|
|
19745
|
+
const conditions = context.getVariable('conditions');
|
|
19746
|
+
if (Array.isArray(conditions) && conditions.length > 0) {
|
|
19747
|
+
const filterQueries = conditions
|
|
19748
|
+
.map((c) => {
|
|
19749
|
+
const field = c.name ?? c.field;
|
|
19750
|
+
if (!field || c.value === undefined || c.value === null || c.value === '') {
|
|
19751
|
+
return null;
|
|
19752
|
+
}
|
|
19753
|
+
return {
|
|
19754
|
+
field,
|
|
19755
|
+
operator: c.operator ?? { type: 'equal' },
|
|
19756
|
+
value: c.value,
|
|
19757
|
+
};
|
|
19758
|
+
})
|
|
19759
|
+
.filter((entry) => entry !== null);
|
|
19760
|
+
if (filterQueries.length > 0) {
|
|
19761
|
+
newPayload.extras = {
|
|
19762
|
+
queryParams: {
|
|
19763
|
+
filters: JSON.stringify(filterQueries),
|
|
19764
|
+
},
|
|
19765
|
+
};
|
|
19766
|
+
}
|
|
19767
|
+
}
|
|
19083
19768
|
context.setVariable('payload', newPayload);
|
|
19084
19769
|
this.navigation.execute(context);
|
|
19085
19770
|
}
|
|
@@ -19646,244 +20331,9 @@ var getEntityDetails_query = /*#__PURE__*/Object.freeze({
|
|
|
19646
20331
|
AXPGetEntityDetailsQuery: AXPGetEntityDetailsQuery
|
|
19647
20332
|
});
|
|
19648
20333
|
|
|
19649
|
-
// #region Master
|
|
19650
|
-
function entityMasterCreateAction() {
|
|
19651
|
-
return {
|
|
19652
|
-
title: '@general:actions.create.title',
|
|
19653
|
-
command: {
|
|
19654
|
-
name: 'Entity:Create',
|
|
19655
|
-
},
|
|
19656
|
-
priority: 'primary',
|
|
19657
|
-
type: AXPSystemActionType.Create,
|
|
19658
|
-
scope: AXPEntityCommandScope.TypeLevel,
|
|
19659
|
-
};
|
|
19660
|
-
}
|
|
19661
|
-
function entityMasterEditAction() {
|
|
19662
|
-
return {
|
|
19663
|
-
title: '@general:actions.edit.title',
|
|
19664
|
-
command: 'Entity:Update',
|
|
19665
|
-
priority: 'secondary',
|
|
19666
|
-
type: AXPSystemActionType.Update,
|
|
19667
|
-
scope: AXPEntityCommandScope.Individual,
|
|
19668
|
-
default: true,
|
|
19669
|
-
};
|
|
19670
|
-
}
|
|
19671
|
-
function entityMasterBulkDeleteAction() {
|
|
19672
|
-
return {
|
|
19673
|
-
title: '@general:actions.delete-items.title',
|
|
19674
|
-
command: 'delete-entity',
|
|
19675
|
-
priority: 'primary',
|
|
19676
|
-
type: AXPSystemActionType.Delete,
|
|
19677
|
-
scope: AXPEntityCommandScope.Selected,
|
|
19678
|
-
order: 100,
|
|
19679
|
-
};
|
|
19680
|
-
}
|
|
19681
|
-
function entityMasterViewAction() {
|
|
19682
|
-
return {
|
|
19683
|
-
title: '@general:actions.view.title',
|
|
19684
|
-
command: 'open-entity',
|
|
19685
|
-
priority: 'secondary',
|
|
19686
|
-
type: AXPSystemActionType.View,
|
|
19687
|
-
scope: AXPEntityCommandScope.Individual,
|
|
19688
|
-
default: true,
|
|
19689
|
-
};
|
|
19690
|
-
}
|
|
19691
|
-
function entityMasterDeleteAction() {
|
|
19692
|
-
return {
|
|
19693
|
-
title: '@general:actions.delete.title',
|
|
19694
|
-
command: 'delete-entity',
|
|
19695
|
-
priority: 'secondary',
|
|
19696
|
-
type: AXPSystemActionType.Delete,
|
|
19697
|
-
scope: AXPEntityCommandScope.Individual,
|
|
19698
|
-
order: 100,
|
|
19699
|
-
};
|
|
19700
|
-
}
|
|
19701
|
-
function entityMasterCrudActions(options) {
|
|
19702
|
-
const opts = {
|
|
19703
|
-
create: true,
|
|
19704
|
-
delete: true,
|
|
19705
|
-
view: true,
|
|
19706
|
-
edit: false,
|
|
19707
|
-
...options,
|
|
19708
|
-
};
|
|
19709
|
-
const actions = [];
|
|
19710
|
-
if (opts.create) {
|
|
19711
|
-
actions.push(entityMasterCreateAction());
|
|
19712
|
-
}
|
|
19713
|
-
if (opts.delete) {
|
|
19714
|
-
actions.push(entityMasterBulkDeleteAction());
|
|
19715
|
-
actions.push(entityMasterDeleteAction());
|
|
19716
|
-
}
|
|
19717
|
-
if (opts.view) {
|
|
19718
|
-
actions.push(entityMasterViewAction());
|
|
19719
|
-
}
|
|
19720
|
-
if (opts.edit) {
|
|
19721
|
-
actions.push(entityMasterEditAction());
|
|
19722
|
-
}
|
|
19723
|
-
return actions;
|
|
19724
|
-
}
|
|
19725
|
-
function entityMasterRecordActions() {
|
|
19726
|
-
return [entityMasterDeleteAction()];
|
|
19727
|
-
}
|
|
19728
|
-
// #endregion
|
|
19729
|
-
// #region Details
|
|
19730
|
-
function entityDetailsCreateActions(parentId) {
|
|
19731
|
-
return {
|
|
19732
|
-
title: '@general:actions.create.title',
|
|
19733
|
-
command: {
|
|
19734
|
-
name: 'Entity:Create',
|
|
19735
|
-
options: {
|
|
19736
|
-
process: {
|
|
19737
|
-
redirect: false,
|
|
19738
|
-
canCreateNewOne: true,
|
|
19739
|
-
data: {
|
|
19740
|
-
[parentId]: '{{context.eval("id")}}',
|
|
19741
|
-
},
|
|
19742
|
-
},
|
|
19743
|
-
},
|
|
19744
|
-
},
|
|
19745
|
-
priority: 'primary',
|
|
19746
|
-
type: AXPSystemActionType.Create,
|
|
19747
|
-
scope: AXPEntityCommandScope.TypeLevel,
|
|
19748
|
-
};
|
|
19749
|
-
}
|
|
19750
|
-
function entityDetailsSimpleCondition(fk) {
|
|
19751
|
-
return {
|
|
19752
|
-
name: fk,
|
|
19753
|
-
operator: { type: 'equal' },
|
|
19754
|
-
value: '{{context.eval("id")}}',
|
|
19755
|
-
};
|
|
19756
|
-
}
|
|
19757
|
-
function entityDetailsReferenceCondition(type) {
|
|
19758
|
-
return [
|
|
19759
|
-
{
|
|
19760
|
-
name: 'reference.id',
|
|
19761
|
-
operator: { type: 'equal' },
|
|
19762
|
-
value: '{{context.eval("id")}}',
|
|
19763
|
-
},
|
|
19764
|
-
{
|
|
19765
|
-
name: 'reference.type',
|
|
19766
|
-
operator: { type: 'equal' },
|
|
19767
|
-
value: type,
|
|
19768
|
-
},
|
|
19769
|
-
];
|
|
19770
|
-
}
|
|
19771
|
-
function entityDetailsEditAction() {
|
|
19772
|
-
return {
|
|
19773
|
-
title: '@general:actions.edit.title',
|
|
19774
|
-
// command: 'quick-modify-entity',
|
|
19775
|
-
command: 'Entity:Update',
|
|
19776
|
-
priority: 'secondary',
|
|
19777
|
-
type: AXPSystemActionType.Update,
|
|
19778
|
-
default: true,
|
|
19779
|
-
scope: AXPEntityCommandScope.Individual,
|
|
19780
|
-
};
|
|
19781
|
-
}
|
|
19782
|
-
function entityDetailsNewEditAction() {
|
|
19783
|
-
return {
|
|
19784
|
-
title: 'New Edit',
|
|
19785
|
-
command: {
|
|
19786
|
-
name: 'Entity:Update',
|
|
19787
|
-
},
|
|
19788
|
-
priority: 'secondary',
|
|
19789
|
-
type: AXPSystemActionType.Update,
|
|
19790
|
-
default: true,
|
|
19791
|
-
scope: AXPEntityCommandScope.Individual,
|
|
19792
|
-
};
|
|
19793
|
-
}
|
|
19794
|
-
function entityOverrideDetailsViewAction() {
|
|
19795
|
-
return {
|
|
19796
|
-
title: '@general:actions.view.title',
|
|
19797
|
-
command: 'open-entity',
|
|
19798
|
-
priority: 'secondary',
|
|
19799
|
-
hidden: true,
|
|
19800
|
-
type: AXPSystemActionType.View,
|
|
19801
|
-
scope: AXPEntityCommandScope.Individual,
|
|
19802
|
-
};
|
|
19803
|
-
}
|
|
19804
|
-
function entityDetailsCrudActions(parentId, options) {
|
|
19805
|
-
const opts = {
|
|
19806
|
-
create: true,
|
|
19807
|
-
delete: true,
|
|
19808
|
-
view: true,
|
|
19809
|
-
edit: true,
|
|
19810
|
-
...options,
|
|
19811
|
-
};
|
|
19812
|
-
const actions = [];
|
|
19813
|
-
if (opts.create) {
|
|
19814
|
-
actions.push(entityDetailsCreateActions(parentId));
|
|
19815
|
-
}
|
|
19816
|
-
if (opts.edit) {
|
|
19817
|
-
actions.push(entityDetailsEditAction());
|
|
19818
|
-
}
|
|
19819
|
-
if (opts.view) {
|
|
19820
|
-
actions.push(entityOverrideDetailsViewAction());
|
|
19821
|
-
}
|
|
19822
|
-
return actions;
|
|
19823
|
-
}
|
|
19824
|
-
function entityDetailsReferenceCreateActions(type) {
|
|
19825
|
-
return [
|
|
19826
|
-
{
|
|
19827
|
-
title: '@general:actions.create.title',
|
|
19828
|
-
command: {
|
|
19829
|
-
name: 'Entity:Create',
|
|
19830
|
-
options: {
|
|
19831
|
-
process: {
|
|
19832
|
-
redirect: false,
|
|
19833
|
-
canCreateNewOne: true,
|
|
19834
|
-
data: {
|
|
19835
|
-
reference: {
|
|
19836
|
-
id: '{{context.eval("id")}}',
|
|
19837
|
-
type: type,
|
|
19838
|
-
},
|
|
19839
|
-
},
|
|
19840
|
-
},
|
|
19841
|
-
},
|
|
19842
|
-
},
|
|
19843
|
-
priority: 'primary',
|
|
19844
|
-
type: AXPSystemActionType.Create,
|
|
19845
|
-
scope: AXPEntityCommandScope.TypeLevel,
|
|
19846
|
-
},
|
|
19847
|
-
entityDetailsEditAction(),
|
|
19848
|
-
entityOverrideDetailsViewAction(),
|
|
19849
|
-
];
|
|
19850
|
-
}
|
|
19851
|
-
/**
|
|
19852
|
-
* Computes a diff between two plain objects with array-aware semantics.
|
|
19853
|
-
* - For arrays of objects with an id field, computes added/removed by id.
|
|
19854
|
-
* - For arrays of primitives or objects without id, uses deep equality.
|
|
19855
|
-
* - For scalars/objects, reports oldValue/newValue when changed.
|
|
19856
|
-
*/
|
|
19857
|
-
function detectEntityChanges(oldObj, newObj) {
|
|
19858
|
-
return transform(newObj, (result, value, key) => {
|
|
19859
|
-
if (!isEqual$1(value, oldObj[key])) {
|
|
19860
|
-
const oldValue = oldObj[key];
|
|
19861
|
-
if (Array.isArray(value) || Array.isArray(oldValue)) {
|
|
19862
|
-
const oldArray = Array.isArray(oldValue) ? oldValue : [];
|
|
19863
|
-
const newArray = Array.isArray(value) ? value : [];
|
|
19864
|
-
const hasId = newArray.length > 0 && typeof newArray[0] === 'object' && newArray[0] !== null && 'id' in newArray[0];
|
|
19865
|
-
if (hasId) {
|
|
19866
|
-
const added = newArray.filter((item) => !oldArray.some((oldItem) => oldItem.id === item.id));
|
|
19867
|
-
const removed = oldArray.filter((item) => !newArray.some((newItem) => newItem.id === item.id));
|
|
19868
|
-
result[key] = { oldValue, newValue: value, added, removed };
|
|
19869
|
-
}
|
|
19870
|
-
else {
|
|
19871
|
-
const added = newArray.filter((item) => !oldArray.some((oldItem) => isEqual$1(item, oldItem)));
|
|
19872
|
-
const removed = oldArray.filter((item) => !newArray.some((newItem) => isEqual$1(item, newItem)));
|
|
19873
|
-
result[key] = { oldValue, newValue: value, added, removed };
|
|
19874
|
-
}
|
|
19875
|
-
}
|
|
19876
|
-
else {
|
|
19877
|
-
result[key] = { oldValue, newValue: value };
|
|
19878
|
-
}
|
|
19879
|
-
}
|
|
19880
|
-
}, {});
|
|
19881
|
-
}
|
|
19882
|
-
//#endregion
|
|
19883
|
-
|
|
19884
20334
|
/**
|
|
19885
20335
|
* Generated bundle index. Do not edit.
|
|
19886
20336
|
*/
|
|
19887
20337
|
|
|
19888
|
-
export { AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityCommand, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEntitiesListDataSourceDefinition, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorService, AXPEntityDefinitionProviderWidget, AXPEntityDefinitionProviderWidgetEditComponent, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityEventDispatcherService, AXPEntityEventsKeys, AXPEntityFormBuilderService, AXPEntityListTableService, AXPEntityListToolbarService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityPreloadFiltersContainerComponent, AXPEntityPreloadFiltersViewModel, AXPEntityPreloadFiltersViewModelResolver, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, 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, EntityBuilder, EntityDataAccessor, actionExists, axpCreateEntityAiToolInputDefaults, axpCreateEntityCommandDefinition, cloneLayoutArrays, columnOrderingMiddleware, columnOrderingMiddlewareProvider, columnWidthMiddleware, columnWidthMiddlewareProvider, createColumnOrderingMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, defaultMultiLanguageMiddleware, defaultMultiLanguageMiddlewareProvider, detectEntityChanges, ensureLayoutPropertyView, ensureLayoutSection, ensureListActions, entityDetailsCreateActions, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, getMasterInterfacePropertySortKey, isAXPMiddlewareAbortError, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider, provideEntity, resolveEntityPluginDetailPageOrder, searchResultDescriptionMiddleware, searchResultDescriptionMiddlewareProvider };
|
|
20338
|
+
export { AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityCommand, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEntitiesListDataSourceDefinition, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorService, AXPEntityDefinitionProviderWidget, AXPEntityDefinitionProviderWidgetEditComponent, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityEventDispatcherService, AXPEntityEventsKeys, AXPEntityFormBuilderService, AXPEntityListTableService, AXPEntityListToolbarService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityPreloadFiltersContainerComponent, AXPEntityPreloadFiltersViewModel, AXPEntityPreloadFiltersViewModelResolver, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, 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, EntityBuilder, EntityDataAccessor, actionExists, axpCreateEntityAiToolInputDefaults, axpCreateEntityCommandDefinition, cloneLayoutArrays, collectNestedCreateHiddenProperties, columnOrderingMiddleware, columnOrderingMiddlewareProvider, columnWidthMiddleware, columnWidthMiddlewareProvider, createColumnOrderingMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, defaultMultiLanguageMiddleware, defaultMultiLanguageMiddlewareProvider, detectEntityChanges, ensureLayoutPropertyView, ensureLayoutSection, ensureListActions, entityDetailsCreateActions, entityDetailsCreateActionsDeferredParent, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, getMasterInterfacePropertySortKey, isAXPMiddlewareAbortError, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider, mergeForeignKeyFieldIntoCreateActions, provideEntity, resolveEntityPluginDetailPageOrder, searchResultDescriptionMiddleware, searchResultDescriptionMiddlewareProvider };
|
|
19889
20339
|
//# sourceMappingURL=acorex-platform-layout-entity.mjs.map
|