@acorex/platform 20.2.4-next.1 → 20.2.4-next.3
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/common/index.d.ts +9 -1
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +1 -0
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-components.mjs +26 -36
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +509 -230
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +106 -24
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-DXGLsVis.mjs → acorex-platform-themes-default-entity-master-list-view.component-e3Lxk5ZT.mjs} +3 -3
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-e3Lxk5ZT.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default.mjs +3 -3
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/fesm2022/{acorex-platform-widgets-file-list-popup.component-B601gPsW.mjs → acorex-platform-widgets-file-list-popup.component-BafU5Lfl.mjs} +4 -2
- package/fesm2022/acorex-platform-widgets-file-list-popup.component-BafU5Lfl.mjs.map +1 -0
- package/fesm2022/acorex-platform-widgets.mjs +84 -14
- package/fesm2022/acorex-platform-widgets.mjs.map +1 -1
- package/layout/builder/index.d.ts +1 -0
- package/layout/components/index.d.ts +1 -5
- package/layout/entity/index.d.ts +2 -2
- package/layout/views/index.d.ts +34 -0
- package/package.json +5 -5
- package/widgets/index.d.ts +8 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DXGLsVis.mjs.map +0 -1
- package/fesm2022/acorex-platform-widgets-file-list-popup.component-B601gPsW.mjs.map +0 -1
|
@@ -6,11 +6,11 @@ import { AXDataSource, AXCommonModule } from '@acorex/cdk/common';
|
|
|
6
6
|
import { AXFormatService } from '@acorex/core/format';
|
|
7
7
|
import { resolveActionLook, AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, getEntityInfo, AXPSettingService, AXPRefreshEvent, AXPReloadEvent, AXPCleanNestedFilters, AXPWorkflowNavigateAction, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER } from '@acorex/platform/common';
|
|
8
8
|
import * as i1$4 from '@acorex/platform/core';
|
|
9
|
-
import { AXPExpressionEvaluatorService, AXPPlatformScope, AXPDistributedEventListenerService,
|
|
9
|
+
import { AXPExpressionEvaluatorService, AXPPlatformScope, AXPDistributedEventListenerService, getChangedPaths, extractValue, setSmart } from '@acorex/platform/core';
|
|
10
10
|
import * as i2$2 from '@acorex/platform/workflow';
|
|
11
11
|
import { AXPWorkflowService, ofType, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowModule } from '@acorex/platform/workflow';
|
|
12
12
|
import * as i2 from '@acorex/platform/layout/builder';
|
|
13
|
-
import { AXPPageStatus, AXPWidgetRegistryService, AXPWidgetsCatalog, AXPValueWidgetComponent,
|
|
13
|
+
import { AXPPageStatus, AXPWidgetRegistryService, AXPWidgetsCatalog, AXPValueWidgetComponent, AXPWidgetRendererDirective, AXPLayoutBuilderModule, AXPWidgetGroupEnum, AXPLayoutWidgetComponent, AXPColumnWidgetComponent, AXP_WIDGETS_EDITOR_CATEGORY } from '@acorex/platform/layout/builder';
|
|
14
14
|
import { AXPLayoutThemeService } from '@acorex/platform/themes/shared';
|
|
15
15
|
import { Subject, takeUntil } from 'rxjs';
|
|
16
16
|
import { AXPSessionService, AXPAuthGuard } from '@acorex/platform/auth';
|
|
@@ -265,7 +265,6 @@ class AXPEntityDetailListViewModel {
|
|
|
265
265
|
}, ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
266
266
|
this.evaluateExpressions = async (actionData) => {
|
|
267
267
|
const parentData = this.parent.data;
|
|
268
|
-
console.log({ actionData, parentData });
|
|
269
268
|
const scope = {
|
|
270
269
|
context: {
|
|
271
270
|
eval: (path) => {
|
|
@@ -1157,10 +1156,28 @@ class AXPEntityMasterListViewModel {
|
|
|
1157
1156
|
const visibleProperties = properties.filter(({ schema }) => !schema?.hidden);
|
|
1158
1157
|
const visiblePropNames = new Set(visibleProperties.map(({ name }) => name));
|
|
1159
1158
|
return columns
|
|
1160
|
-
.filter(({ name }) => visiblePropNames.has(name))
|
|
1159
|
+
.filter(({ name, showAs }) => visiblePropNames.has(name) || showAs)
|
|
1161
1160
|
.map((column) => {
|
|
1162
|
-
|
|
1163
|
-
|
|
1161
|
+
if (column.showAs) {
|
|
1162
|
+
const widgetConfig = this.widgetResolver.resolve(column.showAs.type);
|
|
1163
|
+
const property = {
|
|
1164
|
+
...widgetConfig,
|
|
1165
|
+
name: column.name,
|
|
1166
|
+
title: column.title ?? '',
|
|
1167
|
+
schema: {
|
|
1168
|
+
dataType: 'string',
|
|
1169
|
+
interface: {
|
|
1170
|
+
type: column.showAs.type,
|
|
1171
|
+
options: column.showAs.options,
|
|
1172
|
+
},
|
|
1173
|
+
},
|
|
1174
|
+
};
|
|
1175
|
+
return new AXPEntityListViewColumnViewModel(property, column);
|
|
1176
|
+
}
|
|
1177
|
+
else {
|
|
1178
|
+
const property = visibleProperties.find(({ name }) => name === column.name);
|
|
1179
|
+
return new AXPEntityListViewColumnViewModel(property, column);
|
|
1180
|
+
}
|
|
1164
1181
|
});
|
|
1165
1182
|
};
|
|
1166
1183
|
this.visibleColumnCount = () => {
|
|
@@ -1459,8 +1476,7 @@ class AXPEntityMasterListViewModel {
|
|
|
1459
1476
|
const cols = this.view().columns;
|
|
1460
1477
|
const cloned = this.allAvailableColumns().map((c) => {
|
|
1461
1478
|
const column = this.entityDef.columns?.find((cc) => cc.name == c.name);
|
|
1462
|
-
const
|
|
1463
|
-
const col = new AXPEntityListViewColumnViewModel(prop, column);
|
|
1479
|
+
const col = new AXPEntityListViewColumnViewModel(c.property, column);
|
|
1464
1480
|
col.visible = !cols.some((c) => c == col.name) && col.visible != false;
|
|
1465
1481
|
return col;
|
|
1466
1482
|
});
|
|
@@ -2556,9 +2572,14 @@ class AXPLayoutAdapterBuilder {
|
|
|
2556
2572
|
this.adapter.pages = [...(this.adapter.pages || []), ...relatedPages];
|
|
2557
2573
|
return this;
|
|
2558
2574
|
}
|
|
2575
|
+
setPages(pages) {
|
|
2576
|
+
this.adapter.pages = pages;
|
|
2577
|
+
return this;
|
|
2578
|
+
}
|
|
2559
2579
|
build() {
|
|
2560
2580
|
return {
|
|
2561
|
-
title: this.entity?.
|
|
2581
|
+
title: `${this.entity?.interfaces?.master?.single?.title}`,
|
|
2582
|
+
label: this.entity?.formats.plural,
|
|
2562
2583
|
actions: [],
|
|
2563
2584
|
breadcrumbs: this.createBreadcrumbs(),
|
|
2564
2585
|
execute: this.createExecuteFunction(),
|
|
@@ -2585,7 +2606,7 @@ class AXPLayoutAdapterBuilder {
|
|
|
2585
2606
|
command: {
|
|
2586
2607
|
name: 'navigate',
|
|
2587
2608
|
options: {
|
|
2588
|
-
path: `/${session.application?.name}/m/${moduleName}/e/${entityName}/${this.rootContext.id}/
|
|
2609
|
+
path: `/${session.application?.name}/m/${moduleName}/e/${entityName}/${this.rootContext.id}/view`,
|
|
2589
2610
|
},
|
|
2590
2611
|
},
|
|
2591
2612
|
},
|
|
@@ -2655,40 +2676,29 @@ class AXPBaseRelatedEntityConverter {
|
|
|
2655
2676
|
groups,
|
|
2656
2677
|
};
|
|
2657
2678
|
}
|
|
2658
|
-
createGridLayoutStructure(singleInterface, helpers) {
|
|
2659
|
-
return
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
children: [
|
|
2679
|
-
{
|
|
2680
|
-
type: 'fieldset-layout',
|
|
2681
|
-
options: {
|
|
2682
|
-
title: helpers.getGroupById(s.id)?.title ?? '',
|
|
2683
|
-
collapsible: true,
|
|
2684
|
-
},
|
|
2685
|
-
children: [this.createPropertyGrid(s.id, helpers)],
|
|
2686
|
-
},
|
|
2687
|
-
],
|
|
2688
|
-
})),
|
|
2689
|
-
};
|
|
2679
|
+
async createGridLayoutStructure(singleInterface, helpers, evaluateExpressions) {
|
|
2680
|
+
return await this.createGridLayoutStructureInternal(singleInterface, helpers, evaluateExpressions);
|
|
2681
|
+
}
|
|
2682
|
+
//#region ---- Hidden Evaluation Helpers ----
|
|
2683
|
+
async getVisiblePropertiesByGroupId(sectionId, helpers, evaluateExpressions) {
|
|
2684
|
+
const properties = helpers.getPropertyByGroupId(sectionId) ?? [];
|
|
2685
|
+
const evaluated = await Promise.all(properties.map(async (property) => {
|
|
2686
|
+
let hidden = property?.schema?.hidden;
|
|
2687
|
+
if (typeof hidden === 'string' && evaluateExpressions) {
|
|
2688
|
+
try {
|
|
2689
|
+
const result = await evaluateExpressions({ hidden });
|
|
2690
|
+
hidden = result.hidden;
|
|
2691
|
+
}
|
|
2692
|
+
catch {
|
|
2693
|
+
hidden = false;
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
return { property, hidden: !!hidden };
|
|
2697
|
+
}));
|
|
2698
|
+
return evaluated.filter((x) => !x.hidden).map((x) => x.property);
|
|
2690
2699
|
}
|
|
2691
|
-
createPropertyGrid(sectionId, helpers) {
|
|
2700
|
+
async createPropertyGrid(sectionId, helpers, evaluateExpressions) {
|
|
2701
|
+
const visibleProperties = await this.getVisiblePropertiesByGroupId(sectionId, helpers, evaluateExpressions);
|
|
2692
2702
|
return {
|
|
2693
2703
|
type: 'grid-layout',
|
|
2694
2704
|
mode: 'edit',
|
|
@@ -2701,10 +2711,7 @@ class AXPBaseRelatedEntityConverter {
|
|
|
2701
2711
|
},
|
|
2702
2712
|
},
|
|
2703
2713
|
},
|
|
2704
|
-
children:
|
|
2705
|
-
.getPropertyByGroupId(sectionId)
|
|
2706
|
-
.filter((property) => !property.schema.hidden)
|
|
2707
|
-
.map((p) => {
|
|
2714
|
+
children: visibleProperties.map((p) => {
|
|
2708
2715
|
const layout = helpers.getPropertyLayout(p.name);
|
|
2709
2716
|
return {
|
|
2710
2717
|
type: 'grid-item-layout',
|
|
@@ -2719,6 +2726,7 @@ class AXPBaseRelatedEntityConverter {
|
|
|
2719
2726
|
type: 'form-field',
|
|
2720
2727
|
options: {
|
|
2721
2728
|
label: p.title,
|
|
2729
|
+
showLabel: layout?.label?.visible ?? true,
|
|
2722
2730
|
},
|
|
2723
2731
|
children: [
|
|
2724
2732
|
{
|
|
@@ -2738,23 +2746,74 @@ class AXPBaseRelatedEntityConverter {
|
|
|
2738
2746
|
}),
|
|
2739
2747
|
};
|
|
2740
2748
|
}
|
|
2749
|
+
async createGridLayoutStructureInternal(singleInterface, helpers, evaluateExpressions) {
|
|
2750
|
+
return {
|
|
2751
|
+
type: 'grid-layout',
|
|
2752
|
+
options: {
|
|
2753
|
+
grid: {
|
|
2754
|
+
default: {
|
|
2755
|
+
gridTemplateColumns: 'repeat(12, 1fr)',
|
|
2756
|
+
gridTemplateRows: 'repeat(1, 1fr)',
|
|
2757
|
+
gap: '20px',
|
|
2758
|
+
},
|
|
2759
|
+
},
|
|
2760
|
+
},
|
|
2761
|
+
children: await Promise.all(singleInterface?.sections.map(async (s) => ({
|
|
2762
|
+
type: 'grid-item-layout',
|
|
2763
|
+
name: s.id,
|
|
2764
|
+
options: {
|
|
2765
|
+
colSpan: s.layout?.positions?.lg?.colSpan ?? 12,
|
|
2766
|
+
colStart: s.layout?.positions?.lg?.colStart,
|
|
2767
|
+
colEnd: s.layout?.positions?.lg?.colEnd,
|
|
2768
|
+
},
|
|
2769
|
+
children: [
|
|
2770
|
+
{
|
|
2771
|
+
type: 'fieldset-layout',
|
|
2772
|
+
options: {
|
|
2773
|
+
title: helpers.getGroupById(s.id)?.title ?? '',
|
|
2774
|
+
collapsible: true,
|
|
2775
|
+
},
|
|
2776
|
+
children: [await this.createPropertyGrid(s.id, helpers, evaluateExpressions)],
|
|
2777
|
+
},
|
|
2778
|
+
],
|
|
2779
|
+
}))),
|
|
2780
|
+
};
|
|
2781
|
+
}
|
|
2741
2782
|
}
|
|
2742
2783
|
|
|
2743
2784
|
class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
|
|
2744
2785
|
async convert(relatedEntity, context) {
|
|
2745
2786
|
const { entityDef } = await this.getEntityDefinition(relatedEntity, context.entityResolver);
|
|
2746
2787
|
const helpers = this.createEntityHelpers(entityDef);
|
|
2788
|
+
const evaluateExpressions = async (actionData) => {
|
|
2789
|
+
const scope = {
|
|
2790
|
+
context: {
|
|
2791
|
+
eval: (path) => {
|
|
2792
|
+
return get(context.context, path);
|
|
2793
|
+
},
|
|
2794
|
+
},
|
|
2795
|
+
};
|
|
2796
|
+
return await context.expressionEvaluator.evaluate(actionData, scope);
|
|
2797
|
+
};
|
|
2798
|
+
// Build related tabs for the related entity page (mirrors main-entity tab building)
|
|
2799
|
+
const tabDetailEntities = entityDef?.relatedEntities?.filter((re) => !re.hidden && re.layout?.type === 'tab-detail');
|
|
2800
|
+
const tabListEntities = entityDef?.relatedEntities?.filter((re) => !re.hidden && (!re.layout?.type || re.layout?.type === 'tab-list'));
|
|
2801
|
+
const factory = new AXPRelatedEntityConverterFactory();
|
|
2802
|
+
const tabDetailTabs = await this.buildTabDetails(factory, tabDetailEntities ?? [], context);
|
|
2803
|
+
const tabListTabs = await this.buildTabLists(factory, tabListEntities ?? [], context);
|
|
2747
2804
|
return {
|
|
2748
2805
|
id: entityDef?.name ?? '',
|
|
2749
|
-
title:
|
|
2806
|
+
title: `${context.rootTitle}`,
|
|
2750
2807
|
label: relatedEntity.title ?? entityDef?.formats.displayName ?? '',
|
|
2751
2808
|
icon: relatedEntity.icon || entityDef.icon,
|
|
2752
2809
|
settings: this.createPageSettings(),
|
|
2753
|
-
load: this.createLoadFunction(entityDef, relatedEntity),
|
|
2810
|
+
load: this.createLoadFunction(entityDef, relatedEntity, evaluateExpressions),
|
|
2754
2811
|
execute: this.createExecuteFunction(entityDef),
|
|
2755
|
-
|
|
2812
|
+
// tabs: [...tabDetailTabs, ...tabListTabs],
|
|
2813
|
+
content: [await this.createGridLayoutStructure(helpers.singleInterface, helpers, evaluateExpressions)],
|
|
2756
2814
|
};
|
|
2757
2815
|
}
|
|
2816
|
+
//#region ---- Utility Methods ----
|
|
2758
2817
|
createPageSettings() {
|
|
2759
2818
|
return {
|
|
2760
2819
|
commands: {
|
|
@@ -2773,11 +2832,12 @@ class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
|
|
|
2773
2832
|
},
|
|
2774
2833
|
};
|
|
2775
2834
|
}
|
|
2776
|
-
createLoadFunction(entityDef, relatedEntity) {
|
|
2835
|
+
createLoadFunction(entityDef, relatedEntity, evaluateExpressions) {
|
|
2777
2836
|
return async (context) => {
|
|
2778
2837
|
const fn = entityDef?.queries.byKey?.execute;
|
|
2779
|
-
const
|
|
2780
|
-
const
|
|
2838
|
+
const conditionValues = relatedEntity.conditions?.map((c) => c.value) ?? [];
|
|
2839
|
+
const evaluatedConditionValues = await Promise.all(conditionValues.map((c) => evaluateExpressions(c)));
|
|
2840
|
+
const id = evaluatedConditionValues[0];
|
|
2781
2841
|
const result = await fn(id);
|
|
2782
2842
|
return { success: true, result };
|
|
2783
2843
|
};
|
|
@@ -2797,6 +2857,42 @@ class AXPPageDetailsConverter extends AXPBaseRelatedEntityConverter {
|
|
|
2797
2857
|
}
|
|
2798
2858
|
};
|
|
2799
2859
|
}
|
|
2860
|
+
//#endregion
|
|
2861
|
+
//#region ---- Tab Builders ----
|
|
2862
|
+
/**
|
|
2863
|
+
* Builds tab-detail items for a related entity page using the shared converters.
|
|
2864
|
+
*/
|
|
2865
|
+
async buildTabDetails(factory, tabDetailEntities, ctx) {
|
|
2866
|
+
if (!ctx?.entityResolver || !tabDetailEntities?.length) {
|
|
2867
|
+
return [];
|
|
2868
|
+
}
|
|
2869
|
+
const tabs = [];
|
|
2870
|
+
for (const re of tabDetailEntities) {
|
|
2871
|
+
const converter = factory.createTabDetailsConverter();
|
|
2872
|
+
tabs.push(await converter.convert(re, {
|
|
2873
|
+
entityResolver: ctx.entityResolver,
|
|
2874
|
+
}));
|
|
2875
|
+
}
|
|
2876
|
+
return tabs;
|
|
2877
|
+
}
|
|
2878
|
+
/**
|
|
2879
|
+
* Builds tab-list items for a related entity page using the shared converters with context-aware filters/actions.
|
|
2880
|
+
*/
|
|
2881
|
+
async buildTabLists(factory, tabListEntities, ctx) {
|
|
2882
|
+
if (!ctx?.entityResolver || !tabListEntities?.length) {
|
|
2883
|
+
return [];
|
|
2884
|
+
}
|
|
2885
|
+
const tabs = [];
|
|
2886
|
+
for (const re of tabListEntities) {
|
|
2887
|
+
const converter = factory.createTabListConverter();
|
|
2888
|
+
tabs.push(await converter.convert(re, {
|
|
2889
|
+
entityResolver: ctx.entityResolver,
|
|
2890
|
+
expressionEvaluator: ctx.expressionEvaluator,
|
|
2891
|
+
context: ctx.context,
|
|
2892
|
+
}));
|
|
2893
|
+
}
|
|
2894
|
+
return tabs;
|
|
2895
|
+
}
|
|
2800
2896
|
}
|
|
2801
2897
|
|
|
2802
2898
|
class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
@@ -2812,6 +2908,7 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
2812
2908
|
};
|
|
2813
2909
|
return await context.expressionEvaluator.evaluate(actionData, scope);
|
|
2814
2910
|
};
|
|
2911
|
+
const evaluatedActions = await evaluateExpressions(relatedEntity?.actions);
|
|
2815
2912
|
const filters = relatedEntity.conditions?.map(async (c) => {
|
|
2816
2913
|
const value = await evaluateExpressions(c.value);
|
|
2817
2914
|
return {
|
|
@@ -2826,17 +2923,13 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
2826
2923
|
title: `${context.rootTitle}`,
|
|
2827
2924
|
label: relatedEntity.title,
|
|
2828
2925
|
icon: relatedEntity.icon || entityDef.icon,
|
|
2829
|
-
actions: this.mergeActions(entityDef,
|
|
2926
|
+
actions: this.mergeActions(entityDef, evaluatedActions)
|
|
2830
2927
|
?.filter((a) => a.priority === 'primary')
|
|
2831
2928
|
?.map((a) => {
|
|
2832
2929
|
return {
|
|
2833
2930
|
...a,
|
|
2834
2931
|
zone: 'header',
|
|
2835
|
-
|
|
2836
|
-
// a.scope === AXPEntityCommandScope.Selected
|
|
2837
|
-
// ? "{{widget.find('table').outputs().selectedItem().length > 0}}"
|
|
2838
|
-
// : true,
|
|
2839
|
-
visible: '{{context.eval("table")}}',
|
|
2932
|
+
visible: !a.hidden,
|
|
2840
2933
|
priority: 'primary',
|
|
2841
2934
|
name: a.name,
|
|
2842
2935
|
title: a.title,
|
|
@@ -2854,7 +2947,7 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
2854
2947
|
execute: async (command, executeContext) => {
|
|
2855
2948
|
try {
|
|
2856
2949
|
const commandName = command.name.split('&')[0];
|
|
2857
|
-
const mergedActions = this.mergeActions(entityDef,
|
|
2950
|
+
const mergedActions = this.mergeActions(entityDef, evaluatedActions);
|
|
2858
2951
|
const action = mergedActions.find((a) => {
|
|
2859
2952
|
return a.name === commandName || a.name.split('&')[0] === commandName;
|
|
2860
2953
|
});
|
|
@@ -2869,10 +2962,6 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
2869
2962
|
},
|
|
2870
2963
|
};
|
|
2871
2964
|
}
|
|
2872
|
-
let evaluatedOptions = command.options;
|
|
2873
|
-
if (action.options) {
|
|
2874
|
-
evaluatedOptions = await evaluateExpressions(action.options);
|
|
2875
|
-
}
|
|
2876
2965
|
await context.workflowService.execute(commandName, {
|
|
2877
2966
|
entity: getEntityInfo(entityDef).source,
|
|
2878
2967
|
entityInfo: {
|
|
@@ -2884,8 +2973,8 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
2884
2973
|
},
|
|
2885
2974
|
data: action.scope == AXPEntityCommandScope.Selected
|
|
2886
2975
|
? executeContext
|
|
2887
|
-
:
|
|
2888
|
-
options:
|
|
2976
|
+
: action.options?.['process']?.data || null,
|
|
2977
|
+
options: action.options,
|
|
2889
2978
|
metadata: action.metadata,
|
|
2890
2979
|
});
|
|
2891
2980
|
return { success: true };
|
|
@@ -2914,14 +3003,15 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
2914
3003
|
options: {
|
|
2915
3004
|
entity: relatedEntity.entity,
|
|
2916
3005
|
showEntityActions: false,
|
|
3006
|
+
actions: evaluatedActions,
|
|
2917
3007
|
},
|
|
2918
3008
|
},
|
|
2919
3009
|
],
|
|
2920
3010
|
};
|
|
2921
3011
|
}
|
|
2922
|
-
mergeActions(entityDef,
|
|
3012
|
+
mergeActions(entityDef, relatedEntityActions) {
|
|
2923
3013
|
const originalList = entityDef?.interfaces?.master?.list?.actions ?? [];
|
|
2924
|
-
const relatedEntityActionList =
|
|
3014
|
+
const relatedEntityActionList = relatedEntityActions ?? [];
|
|
2925
3015
|
// Create a map to track which actions from relatedEntityActionList have been used
|
|
2926
3016
|
const usedOverrideActions = new Set();
|
|
2927
3017
|
// Start with original actions, applying overrides where they exist
|
|
@@ -2958,7 +3048,7 @@ class AXPTabDetailsConverter extends AXPBaseRelatedEntityConverter {
|
|
|
2958
3048
|
id: entityDef?.name ?? '',
|
|
2959
3049
|
title: relatedEntity.title ?? entityDef?.title ?? '',
|
|
2960
3050
|
icon: relatedEntity.icon || entityDef.icon,
|
|
2961
|
-
content: [this.createGridLayoutStructure(helpers.singleInterface, helpers)],
|
|
3051
|
+
content: [await this.createGridLayoutStructure(helpers.singleInterface, helpers)],
|
|
2962
3052
|
};
|
|
2963
3053
|
}
|
|
2964
3054
|
}
|
|
@@ -2986,6 +3076,7 @@ class AXPTabListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
2986
3076
|
hidden: true,
|
|
2987
3077
|
};
|
|
2988
3078
|
}) ?? [];
|
|
3079
|
+
const actions = await evaluateExpressions(relatedEntity.actions);
|
|
2989
3080
|
return {
|
|
2990
3081
|
id: entityDef?.name ?? '',
|
|
2991
3082
|
title: relatedEntity.title ?? entityDef?.title ?? '',
|
|
@@ -2993,7 +3084,7 @@ class AXPTabListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
2993
3084
|
content: [
|
|
2994
3085
|
{
|
|
2995
3086
|
type: AXPWidgetsCatalog.entityList,
|
|
2996
|
-
name:
|
|
3087
|
+
name: `${relatedEntity.entity}-tab-list`,
|
|
2997
3088
|
defaultValue: {
|
|
2998
3089
|
toolbar: {
|
|
2999
3090
|
filters: await Promise.all(filters),
|
|
@@ -3002,7 +3093,8 @@ class AXPTabListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
3002
3093
|
options: {
|
|
3003
3094
|
entity: relatedEntity.entity,
|
|
3004
3095
|
showEntityActions: true,
|
|
3005
|
-
showToolbar:
|
|
3096
|
+
showToolbar: false,
|
|
3097
|
+
actions: actions,
|
|
3006
3098
|
},
|
|
3007
3099
|
},
|
|
3008
3100
|
],
|
|
@@ -3064,30 +3156,46 @@ class AXPMainEntityContentBuilder {
|
|
|
3064
3156
|
return groups.some((group) => group.id === section.id);
|
|
3065
3157
|
}) ?? []);
|
|
3066
3158
|
};
|
|
3067
|
-
|
|
3068
|
-
|
|
3159
|
+
// Create expression evaluator for actions
|
|
3160
|
+
const evaluateExpressions = dependencies?.expressionEvaluator
|
|
3161
|
+
? this.createExpressionEvaluator(rootContext, dependencies.expressionEvaluator)
|
|
3162
|
+
: null;
|
|
3163
|
+
const getVisiblePropertyByGroupId = async (groupId) => {
|
|
3164
|
+
const properties = entity?.properties.filter((p) => p.groupId === groupId) ?? [];
|
|
3165
|
+
const evaluated = await Promise.all(properties.map(async (p) => {
|
|
3166
|
+
// If you later need expression-based hidden logic, evaluate it here
|
|
3167
|
+
let hidden = p?.schema?.hidden;
|
|
3168
|
+
if (typeof hidden === 'string' && evaluateExpressions) {
|
|
3169
|
+
try {
|
|
3170
|
+
const res = await evaluateExpressions({ hidden });
|
|
3171
|
+
hidden = res.hidden;
|
|
3172
|
+
}
|
|
3173
|
+
catch {
|
|
3174
|
+
hidden = false;
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3177
|
+
return { prop: p, hidden: !!hidden };
|
|
3178
|
+
}));
|
|
3179
|
+
return evaluated.filter((x) => !x.hidden).map((x) => x.prop);
|
|
3069
3180
|
};
|
|
3070
3181
|
const getPropertyLayout = (name) => {
|
|
3071
3182
|
return singleInterface?.properties?.find((p) => p.name === name)?.layout;
|
|
3072
3183
|
};
|
|
3073
3184
|
// Get related entities for tabs
|
|
3074
|
-
const tabDetailEntities = entity?.relatedEntities?.filter((re) => !re.hidden && re.
|
|
3075
|
-
const tabListEntities = entity?.relatedEntities?.filter((re) => !re.hidden && (!re.
|
|
3185
|
+
const tabDetailEntities = entity?.relatedEntities?.filter((re) => !re.hidden && re.layout?.type === 'tab-detail');
|
|
3186
|
+
const tabListEntities = entity?.relatedEntities?.filter((re) => !re.hidden && (!re.layout?.type || re.layout?.type === 'tab-list'));
|
|
3076
3187
|
// Build related tabs if dependencies are provided
|
|
3077
3188
|
const tabDetailTabs = await this.buildTabDetails(tabDetailEntities ?? [], dependencies);
|
|
3078
3189
|
const tabListTabs = await this.buildTabLists(tabListEntities ?? [], rootContext, dependencies);
|
|
3079
3190
|
// Build actions from single interface
|
|
3080
3191
|
const actions = this.buildActions(entity, singleInterface);
|
|
3081
|
-
// Create expression evaluator for actions
|
|
3082
|
-
const evaluateExpressions = dependencies?.expressionEvaluator
|
|
3083
|
-
? this.createExpressionEvaluator(rootContext, dependencies.expressionEvaluator)
|
|
3084
|
-
: null;
|
|
3085
3192
|
return {
|
|
3086
3193
|
id: entity?.name ?? '',
|
|
3087
3194
|
title: singleInterface?.title ?? entity?.formats.individual ?? '',
|
|
3088
3195
|
label: entity?.formats.displayName ?? singleInterface?.title ?? '',
|
|
3089
3196
|
icon: entity?.icon,
|
|
3090
3197
|
actions: await this.buildEvaluatedActions(actions, evaluateExpressions),
|
|
3198
|
+
isPrimary: true,
|
|
3091
3199
|
settings: {
|
|
3092
3200
|
commands: {
|
|
3093
3201
|
reject: {
|
|
@@ -3184,7 +3292,7 @@ class AXPMainEntityContentBuilder {
|
|
|
3184
3292
|
},
|
|
3185
3293
|
},
|
|
3186
3294
|
},
|
|
3187
|
-
children: filterValidSections(singleInterface?.sections ?? []).map((s) => ({
|
|
3295
|
+
children: await Promise.all(filterValidSections(singleInterface?.sections ?? []).map(async (s) => ({
|
|
3188
3296
|
type: 'grid-item-layout',
|
|
3189
3297
|
name: s.id,
|
|
3190
3298
|
options: {
|
|
@@ -3212,9 +3320,7 @@ class AXPMainEntityContentBuilder {
|
|
|
3212
3320
|
},
|
|
3213
3321
|
},
|
|
3214
3322
|
},
|
|
3215
|
-
children:
|
|
3216
|
-
.filter((property) => !property.schema.hidden)
|
|
3217
|
-
.map((p) => {
|
|
3323
|
+
children: (await getVisiblePropertyByGroupId(s.id)).map((p) => {
|
|
3218
3324
|
const layout = getPropertyLayout(p.name);
|
|
3219
3325
|
return {
|
|
3220
3326
|
type: 'grid-item-layout',
|
|
@@ -3229,6 +3335,7 @@ class AXPMainEntityContentBuilder {
|
|
|
3229
3335
|
type: 'form-field',
|
|
3230
3336
|
options: {
|
|
3231
3337
|
label: p.title,
|
|
3338
|
+
showLabel: layout?.label?.visible ?? true,
|
|
3232
3339
|
},
|
|
3233
3340
|
children: [
|
|
3234
3341
|
{
|
|
@@ -3256,7 +3363,7 @@ class AXPMainEntityContentBuilder {
|
|
|
3256
3363
|
],
|
|
3257
3364
|
},
|
|
3258
3365
|
],
|
|
3259
|
-
})),
|
|
3366
|
+
}))),
|
|
3260
3367
|
},
|
|
3261
3368
|
],
|
|
3262
3369
|
};
|
|
@@ -3270,7 +3377,8 @@ class AXPMainEntityContentBuilder {
|
|
|
3270
3377
|
const scope = {
|
|
3271
3378
|
context: {
|
|
3272
3379
|
eval: (path) => {
|
|
3273
|
-
|
|
3380
|
+
const value = get(context, path);
|
|
3381
|
+
return value;
|
|
3274
3382
|
},
|
|
3275
3383
|
},
|
|
3276
3384
|
};
|
|
@@ -3382,11 +3490,15 @@ class AXPLayoutAdapterFactory {
|
|
|
3382
3490
|
throw new Error(`Entity ${moduleName}.${entityName} not found`);
|
|
3383
3491
|
}
|
|
3384
3492
|
const rootContext = await this.loadRootContext(entity, id);
|
|
3493
|
+
// Build main and related pages
|
|
3494
|
+
const mainPage = await this.buildMainPage(entity, rootContext, dependencies);
|
|
3495
|
+
const relatedPages = await this.buildRelatedPages(entity, rootContext, dependencies);
|
|
3496
|
+
// Compose ordered pages around the primary page
|
|
3497
|
+
const orderedPages = this.composePagesWithPositions(mainPage, relatedPages, entity);
|
|
3385
3498
|
return this.layoutAdapterBuilder
|
|
3386
3499
|
.setEntity(entity, rootContext)
|
|
3387
3500
|
.setDependencies(dependencies)
|
|
3388
|
-
.
|
|
3389
|
-
.setRelatedPages(await this.buildRelatedPages(entity, rootContext, dependencies))
|
|
3501
|
+
.setPages(orderedPages)
|
|
3390
3502
|
.build();
|
|
3391
3503
|
}
|
|
3392
3504
|
async loadRootContext(entity, id) {
|
|
@@ -3399,13 +3511,17 @@ class AXPLayoutAdapterFactory {
|
|
|
3399
3511
|
async buildRelatedPages(entity, rootContext, dependencies) {
|
|
3400
3512
|
const pages = [];
|
|
3401
3513
|
// Page Details
|
|
3402
|
-
const pageDetailEntities = entity?.relatedEntities?.filter((re) => !re.hidden && re.
|
|
3514
|
+
const pageDetailEntities = entity?.relatedEntities?.filter((re) => !re.hidden && re.layout?.type === 'page-detail');
|
|
3403
3515
|
for (const relatedEntity of pageDetailEntities || []) {
|
|
3404
3516
|
const converter = this.relatedEntityConverterFactory.createPageDetailsConverter();
|
|
3405
|
-
pages.push(await converter.convert(relatedEntity, {
|
|
3517
|
+
pages.push(await converter.convert(relatedEntity, {
|
|
3518
|
+
...dependencies,
|
|
3519
|
+
context: rootContext,
|
|
3520
|
+
rootTitle: await this.getRootTitle(entity, rootContext, dependencies),
|
|
3521
|
+
}));
|
|
3406
3522
|
}
|
|
3407
3523
|
// Page Lists
|
|
3408
|
-
const pageListEntities = entity?.relatedEntities?.filter((re) => !re.hidden && re.
|
|
3524
|
+
const pageListEntities = entity?.relatedEntities?.filter((re) => !re.hidden && re.layout?.type === 'page-list');
|
|
3409
3525
|
for (const relatedEntity of pageListEntities || []) {
|
|
3410
3526
|
const converter = this.relatedEntityConverterFactory.createPageListConverter();
|
|
3411
3527
|
pages.push(await converter.convert(relatedEntity, {
|
|
@@ -3416,9 +3532,46 @@ class AXPLayoutAdapterFactory {
|
|
|
3416
3532
|
}
|
|
3417
3533
|
return pages;
|
|
3418
3534
|
}
|
|
3535
|
+
composePagesWithPositions(mainPage, relatedPages, entity) {
|
|
3536
|
+
// Only consider related entities with layout types page-detail or page-list
|
|
3537
|
+
const pageEntities = (entity?.relatedEntities || []).filter((re) => !re.hidden && (re.layout?.type === 'page-detail' || re.layout?.type === 'page-list'));
|
|
3538
|
+
// Build a map from entity name to its layout config (order/position)
|
|
3539
|
+
const layoutConfigByEntity = {};
|
|
3540
|
+
for (const re of pageEntities) {
|
|
3541
|
+
const [, entityName] = (re.entity || '').split('.');
|
|
3542
|
+
const key = entityName || re.entity;
|
|
3543
|
+
layoutConfigByEntity[key] = { order: re.layout?.order, position: re.layout?.position };
|
|
3544
|
+
}
|
|
3545
|
+
// Split related pages into before/after buckets based on their relatedEntity layout
|
|
3546
|
+
const before = [];
|
|
3547
|
+
const after = [];
|
|
3548
|
+
for (const page of relatedPages) {
|
|
3549
|
+
const conf = layoutConfigByEntity[page.id];
|
|
3550
|
+
const position = conf?.position ?? 'after';
|
|
3551
|
+
if (position === 'before') {
|
|
3552
|
+
before.push(page);
|
|
3553
|
+
}
|
|
3554
|
+
else {
|
|
3555
|
+
after.push(page);
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3558
|
+
// Sort by order within each bucket (undefined orders go last)
|
|
3559
|
+
const sortByOrder = (a, b) => {
|
|
3560
|
+
const ao = layoutConfigByEntity[a.id]?.order ?? Number.POSITIVE_INFINITY;
|
|
3561
|
+
const bo = layoutConfigByEntity[b.id]?.order ?? Number.POSITIVE_INFINITY;
|
|
3562
|
+
return ao - bo;
|
|
3563
|
+
};
|
|
3564
|
+
before.sort(sortByOrder);
|
|
3565
|
+
after.sort(sortByOrder);
|
|
3566
|
+
// Ensure the main page is primary
|
|
3567
|
+
mainPage.isPrimary = true;
|
|
3568
|
+
// Compose final pages: before -> main -> after
|
|
3569
|
+
return [...before, mainPage, ...after];
|
|
3570
|
+
}
|
|
3419
3571
|
async getRootTitle(entity, rootContext, dependencies) {
|
|
3420
3572
|
// Logic for getting root title
|
|
3421
|
-
|
|
3573
|
+
const title = await dependencies.expressionEvaluator.evaluate(entity.interfaces?.master?.single?.title, rootContext);
|
|
3574
|
+
return title;
|
|
3422
3575
|
}
|
|
3423
3576
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutAdapterFactory, deps: [{ token: AXPRelatedEntityConverterFactory }, { token: AXPMainEntityContentBuilder }, { token: AXPLayoutAdapterBuilder }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3424
3577
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPLayoutAdapterFactory, providedIn: 'root' }); }
|
|
@@ -3486,6 +3639,81 @@ class AXPEntitySearchDefinitionProvider {
|
|
|
3486
3639
|
}
|
|
3487
3640
|
}
|
|
3488
3641
|
|
|
3642
|
+
//#region ---- Column Mapping Helpers ----
|
|
3643
|
+
/**
|
|
3644
|
+
* Maps an entity property to a list widget column configuration.
|
|
3645
|
+
* Preserves readonly behavior and leverages the property's interface options when available.
|
|
3646
|
+
*/
|
|
3647
|
+
function mapPropertyToWidgetColumn(property) {
|
|
3648
|
+
return {
|
|
3649
|
+
name: property.name,
|
|
3650
|
+
title: property.title,
|
|
3651
|
+
visible: true,
|
|
3652
|
+
widget: property.schema?.interface
|
|
3653
|
+
? {
|
|
3654
|
+
type: property.schema.interface.type || 'text-editor',
|
|
3655
|
+
path: property.name,
|
|
3656
|
+
options: {
|
|
3657
|
+
readonly: true,
|
|
3658
|
+
...property.schema.interface.options,
|
|
3659
|
+
},
|
|
3660
|
+
}
|
|
3661
|
+
: {
|
|
3662
|
+
type: 'text-editor',
|
|
3663
|
+
path: property.name,
|
|
3664
|
+
options: { readonly: true },
|
|
3665
|
+
},
|
|
3666
|
+
};
|
|
3667
|
+
}
|
|
3668
|
+
/**
|
|
3669
|
+
* Maps an entity column metadata (and its related property) to a list widget column configuration.
|
|
3670
|
+
*/
|
|
3671
|
+
function mapEntityColumnToWidgetColumn(entity, column) {
|
|
3672
|
+
const property = entity.properties.find((p) => p.name === column.name);
|
|
3673
|
+
return {
|
|
3674
|
+
name: column.name,
|
|
3675
|
+
title: column.title || property?.title || column.name,
|
|
3676
|
+
width: column.options?.width,
|
|
3677
|
+
visible: column.options?.visible !== false,
|
|
3678
|
+
widget: property?.schema?.interface
|
|
3679
|
+
? {
|
|
3680
|
+
type: property.schema.interface.type || 'text-editor',
|
|
3681
|
+
path: column.options?.dataPath || column.name,
|
|
3682
|
+
options: {
|
|
3683
|
+
readonly: true,
|
|
3684
|
+
...property.schema.interface.options,
|
|
3685
|
+
},
|
|
3686
|
+
}
|
|
3687
|
+
: {
|
|
3688
|
+
type: 'text-editor',
|
|
3689
|
+
path: column.options?.dataPath || column.name,
|
|
3690
|
+
options: { readonly: true },
|
|
3691
|
+
},
|
|
3692
|
+
};
|
|
3693
|
+
}
|
|
3694
|
+
//#endregion
|
|
3695
|
+
//#region ---- Include/Exclude Utilities ----
|
|
3696
|
+
/**
|
|
3697
|
+
* Applies include and exclude filters to a named collection while preserving order.
|
|
3698
|
+
*/
|
|
3699
|
+
function applyIncludeExclude(items, include = [], exclude = []) {
|
|
3700
|
+
let result = items;
|
|
3701
|
+
if (include.length > 0) {
|
|
3702
|
+
result = result.filter((i) => include.includes(i.name));
|
|
3703
|
+
}
|
|
3704
|
+
if (exclude.length > 0) {
|
|
3705
|
+
result = result.filter((i) => !exclude.includes(i.name));
|
|
3706
|
+
}
|
|
3707
|
+
return result;
|
|
3708
|
+
}
|
|
3709
|
+
/**
|
|
3710
|
+
* Returns only visible (non-hidden) properties of an entity.
|
|
3711
|
+
*/
|
|
3712
|
+
function getVisibleProperties(entity) {
|
|
3713
|
+
return entity.properties.filter((prop) => !prop.schema?.hidden);
|
|
3714
|
+
}
|
|
3715
|
+
//#endregion
|
|
3716
|
+
|
|
3489
3717
|
class AXPEntityListTableService {
|
|
3490
3718
|
constructor() {
|
|
3491
3719
|
//#region ---- Services & Dependencies ----
|
|
@@ -3493,6 +3721,9 @@ class AXPEntityListTableService {
|
|
|
3493
3721
|
this.workflow = inject(AXPWorkflowService);
|
|
3494
3722
|
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
3495
3723
|
this.evaluateExpressions = async (options, data) => {
|
|
3724
|
+
if (!options) {
|
|
3725
|
+
return {};
|
|
3726
|
+
}
|
|
3496
3727
|
const scope = {
|
|
3497
3728
|
context: {
|
|
3498
3729
|
eval: (path) => {
|
|
@@ -3508,8 +3739,7 @@ class AXPEntityListTableService {
|
|
|
3508
3739
|
/**
|
|
3509
3740
|
* Convert Entity to List Widget Options
|
|
3510
3741
|
*/
|
|
3511
|
-
async convertEntityToListOptions(entity, options) {
|
|
3512
|
-
const allActions = entity.interfaces?.master?.list?.actions?.map((tr) => new AXPEntityCommandTriggerViewModel(entity, tr)) ?? [];
|
|
3742
|
+
async convertEntityToListOptions(entity, options, allActions) {
|
|
3513
3743
|
const listOptions = {
|
|
3514
3744
|
// 📊 Data Source
|
|
3515
3745
|
dataSource: this.createDataSource(entity),
|
|
@@ -3561,72 +3791,17 @@ class AXPEntityListTableService {
|
|
|
3561
3791
|
createColumnsFromProperties(entity, options) {
|
|
3562
3792
|
const excludeColumns = options?.excludeColumns || [];
|
|
3563
3793
|
const includeColumns = options?.includeColumns || [];
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
else {
|
|
3570
|
-
// Otherwise use properties
|
|
3571
|
-
columns = entity.properties
|
|
3572
|
-
.filter((prop) => !prop.schema.hidden) // Only visible properties
|
|
3573
|
-
.map((prop) => ({
|
|
3574
|
-
name: prop.name,
|
|
3575
|
-
title: prop.title,
|
|
3576
|
-
visible: true,
|
|
3577
|
-
widget: prop.schema.interface
|
|
3578
|
-
? {
|
|
3579
|
-
type: prop.schema.interface.type || 'text-editor',
|
|
3580
|
-
path: prop.name,
|
|
3581
|
-
options: {
|
|
3582
|
-
readonly: true,
|
|
3583
|
-
...prop.schema.interface.options,
|
|
3584
|
-
},
|
|
3585
|
-
}
|
|
3586
|
-
: {
|
|
3587
|
-
type: 'text-editor',
|
|
3588
|
-
path: prop.name,
|
|
3589
|
-
options: { readonly: true },
|
|
3590
|
-
},
|
|
3591
|
-
}));
|
|
3592
|
-
}
|
|
3593
|
-
// Apply include/exclude filters
|
|
3594
|
-
if (includeColumns.length > 0) {
|
|
3595
|
-
// If includeColumns is specified, only include those columns
|
|
3596
|
-
columns = columns.filter((col) => includeColumns.includes(col.name));
|
|
3597
|
-
}
|
|
3598
|
-
if (excludeColumns.length > 0) {
|
|
3599
|
-
// If excludeColumns is specified, exclude those columns
|
|
3600
|
-
columns = columns.filter((col) => !excludeColumns.includes(col.name));
|
|
3601
|
-
}
|
|
3602
|
-
return columns;
|
|
3794
|
+
// If columns are defined, use them; otherwise use visible properties
|
|
3795
|
+
const baseColumns = entity.columns && entity.columns.length > 0
|
|
3796
|
+
? entity.columns.map((col) => this.mapEntityColumnToWidgetColumn(entity, col))
|
|
3797
|
+
: getVisibleProperties(entity).map((prop) => mapPropertyToWidgetColumn(prop));
|
|
3798
|
+
return applyIncludeExclude(baseColumns, includeColumns, excludeColumns);
|
|
3603
3799
|
}
|
|
3604
3800
|
/**
|
|
3605
3801
|
* Map EntityTableColumn to ListWidgetColumn
|
|
3606
3802
|
*/
|
|
3607
3803
|
mapEntityColumnToWidgetColumn(entity, column) {
|
|
3608
|
-
|
|
3609
|
-
const property = entity.properties.find((p) => p.name === column.name);
|
|
3610
|
-
return {
|
|
3611
|
-
name: column.name,
|
|
3612
|
-
title: column.title || property?.title || column.name,
|
|
3613
|
-
width: column.options?.width,
|
|
3614
|
-
visible: column.options?.visible !== false,
|
|
3615
|
-
widget: property?.schema.interface
|
|
3616
|
-
? {
|
|
3617
|
-
type: property.schema.interface.type || 'text-editor',
|
|
3618
|
-
path: column.options?.dataPath || column.name,
|
|
3619
|
-
options: {
|
|
3620
|
-
readonly: true,
|
|
3621
|
-
...property.schema.interface.options,
|
|
3622
|
-
},
|
|
3623
|
-
}
|
|
3624
|
-
: {
|
|
3625
|
-
type: 'text-editor',
|
|
3626
|
-
path: column.options?.dataPath || column.name,
|
|
3627
|
-
options: { readonly: true },
|
|
3628
|
-
},
|
|
3629
|
-
};
|
|
3804
|
+
return mapEntityColumnToWidgetColumn(entity, column);
|
|
3630
3805
|
}
|
|
3631
3806
|
/**
|
|
3632
3807
|
* Convert Entity Actions to Row Commands
|
|
@@ -3642,7 +3817,7 @@ class AXPEntityListTableService {
|
|
|
3642
3817
|
icon: action.icon,
|
|
3643
3818
|
color: action.color,
|
|
3644
3819
|
look: 'outline',
|
|
3645
|
-
visible: action.hidden,
|
|
3820
|
+
visible: !action.hidden,
|
|
3646
3821
|
disabled: action.disabled,
|
|
3647
3822
|
}));
|
|
3648
3823
|
}
|
|
@@ -3653,6 +3828,36 @@ class AXPEntityListTableService {
|
|
|
3653
3828
|
const actions = entity.interfaces?.master?.list?.actions || [];
|
|
3654
3829
|
return actions.some((action) => action.scope === AXPEntityCommandScope.Selected);
|
|
3655
3830
|
}
|
|
3831
|
+
/**
|
|
3832
|
+
* Handle execution of a row command (shared by double-click and command handlers)
|
|
3833
|
+
*/
|
|
3834
|
+
async handleRowCommand(e, selectedRows, entity, allActions) {
|
|
3835
|
+
const data = e.data;
|
|
3836
|
+
const commandName = e.name;
|
|
3837
|
+
const action = allActions.find((c) => {
|
|
3838
|
+
return (c.name == e.name &&
|
|
3839
|
+
((selectedRows?.length
|
|
3840
|
+
? c.scope == AXPEntityCommandScope.Selected
|
|
3841
|
+
: c.scope == AXPEntityCommandScope.Individual) ||
|
|
3842
|
+
c.scope == AXPEntityCommandScope.TypeLevel));
|
|
3843
|
+
});
|
|
3844
|
+
const command = commandName.split('&')[0];
|
|
3845
|
+
const options = await this.evaluateExpressions(action?.options, data);
|
|
3846
|
+
await this.workflow.execute(command, {
|
|
3847
|
+
entity: getEntityInfo(entity).source,
|
|
3848
|
+
entityInfo: {
|
|
3849
|
+
name: entity.name,
|
|
3850
|
+
module: entity.module,
|
|
3851
|
+
title: entity.title,
|
|
3852
|
+
parentKey: entity.parentKey,
|
|
3853
|
+
source: entity.source,
|
|
3854
|
+
},
|
|
3855
|
+
data: action?.scope == AXPEntityCommandScope.Selected ? selectedRows : data,
|
|
3856
|
+
options: options,
|
|
3857
|
+
metadata: action?.metadata,
|
|
3858
|
+
});
|
|
3859
|
+
console.log('Entity List - Row command:', e.name, e.data);
|
|
3860
|
+
}
|
|
3656
3861
|
/**
|
|
3657
3862
|
* Create default events
|
|
3658
3863
|
*/
|
|
@@ -3661,38 +3866,27 @@ class AXPEntityListTableService {
|
|
|
3661
3866
|
onRowClick: (row) => {
|
|
3662
3867
|
console.log('Entity List - Row clicked:', row);
|
|
3663
3868
|
},
|
|
3664
|
-
onRowDoubleClick: (
|
|
3665
|
-
console.log('Entity List - Row double clicked:',
|
|
3869
|
+
onRowDoubleClick: (e) => {
|
|
3870
|
+
console.log('Entity List - Row double clicked:', e);
|
|
3871
|
+
const defaultAction = allActions.find((c) => {
|
|
3872
|
+
const commandName = c.name.split('&')[0];
|
|
3873
|
+
return (c.default || commandName === 'open-entity') && !c.hidden;
|
|
3874
|
+
});
|
|
3875
|
+
if (!defaultAction) {
|
|
3876
|
+
return;
|
|
3877
|
+
}
|
|
3878
|
+
const d = {
|
|
3879
|
+
component: e.component,
|
|
3880
|
+
name: defaultAction.name,
|
|
3881
|
+
data: e.data,
|
|
3882
|
+
};
|
|
3883
|
+
this.handleRowCommand(d, undefined, entity, allActions);
|
|
3666
3884
|
},
|
|
3667
3885
|
onSelectionChange: (selectedRows) => {
|
|
3668
3886
|
console.log('Entity List - Selection changed:', selectedRows);
|
|
3669
3887
|
},
|
|
3670
3888
|
onRowCommand: async (e, selectedRows) => {
|
|
3671
|
-
|
|
3672
|
-
const commandName = e.name;
|
|
3673
|
-
const action = allActions.find((c) => {
|
|
3674
|
-
return (c.name == e.name &&
|
|
3675
|
-
((selectedRows?.length
|
|
3676
|
-
? c.scope == AXPEntityCommandScope.Selected
|
|
3677
|
-
: c.scope == AXPEntityCommandScope.Individual) ||
|
|
3678
|
-
c.scope == AXPEntityCommandScope.TypeLevel));
|
|
3679
|
-
});
|
|
3680
|
-
const command = commandName.split('&')[0];
|
|
3681
|
-
const options = await this.evaluateExpressions(action?.options, data);
|
|
3682
|
-
await this.workflow.execute(command, {
|
|
3683
|
-
entity: getEntityInfo(entity).source,
|
|
3684
|
-
entityInfo: {
|
|
3685
|
-
name: entity.name,
|
|
3686
|
-
module: entity.module,
|
|
3687
|
-
title: entity.title,
|
|
3688
|
-
parentKey: entity.parentKey,
|
|
3689
|
-
source: entity.source,
|
|
3690
|
-
},
|
|
3691
|
-
data: action?.scope == AXPEntityCommandScope.Selected ? selectedRows : data,
|
|
3692
|
-
options: options,
|
|
3693
|
-
metadata: action?.metadata,
|
|
3694
|
-
});
|
|
3695
|
-
console.log('Entity List - Row command:', e.name, e.data);
|
|
3889
|
+
await this.handleRowCommand(e, selectedRows, entity, allActions);
|
|
3696
3890
|
},
|
|
3697
3891
|
};
|
|
3698
3892
|
}
|
|
@@ -3754,29 +3948,29 @@ class AXPEntityListToolbarService {
|
|
|
3754
3948
|
* Create Column Definitions for Toolbar
|
|
3755
3949
|
*/
|
|
3756
3950
|
createColumnDefinitions(entity, options) {
|
|
3757
|
-
const { columns = []
|
|
3951
|
+
const { columns = [] } = entity;
|
|
3758
3952
|
const excludeColumns = options?.excludeColumns || [];
|
|
3759
3953
|
const includeColumns = options?.includeColumns || [];
|
|
3760
|
-
const visibleProperties =
|
|
3954
|
+
const visibleProperties = getVisibleProperties(entity);
|
|
3761
3955
|
const visiblePropNames = new Set(visibleProperties.map(({ name }) => name));
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
name:
|
|
3776
|
-
title: property
|
|
3777
|
-
visible:
|
|
3778
|
-
};
|
|
3779
|
-
|
|
3956
|
+
// Prefer explicit entity.columns if present; fallback to visible properties
|
|
3957
|
+
const baseColumns = columns.length > 0
|
|
3958
|
+
? columns
|
|
3959
|
+
.filter(({ name }) => visiblePropNames.has(name))
|
|
3960
|
+
.map((column) => {
|
|
3961
|
+
const property = visibleProperties.find(({ name }) => name === column.name);
|
|
3962
|
+
return {
|
|
3963
|
+
name: column.name,
|
|
3964
|
+
title: property?.title,
|
|
3965
|
+
visible: column?.options?.visible ?? true,
|
|
3966
|
+
};
|
|
3967
|
+
})
|
|
3968
|
+
: visibleProperties.map((property) => ({
|
|
3969
|
+
name: property.name,
|
|
3970
|
+
title: property.title,
|
|
3971
|
+
visible: true,
|
|
3972
|
+
}));
|
|
3973
|
+
return applyIncludeExclude(baseColumns, includeColumns, excludeColumns);
|
|
3780
3974
|
}
|
|
3781
3975
|
/**
|
|
3782
3976
|
* Create Sort Definitions for Toolbar
|
|
@@ -3805,7 +3999,6 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
3805
3999
|
this.entityListTableService = inject(AXPEntityListTableService);
|
|
3806
4000
|
this.entityListToolbarService = inject(AXPEntityListToolbarService);
|
|
3807
4001
|
this.layoutThemeService = inject(AXPLayoutThemeService);
|
|
3808
|
-
this.container = viewChild(AXPWidgetContainerComponent, ...(ngDevMode ? [{ debugName: "container" }] : []));
|
|
3809
4002
|
this.isMounted = signal(false, ...(ngDevMode ? [{ debugName: "isMounted" }] : []));
|
|
3810
4003
|
this.entity = signal(null, ...(ngDevMode ? [{ debugName: "entity" }] : []));
|
|
3811
4004
|
this.listNode = signal(null, ...(ngDevMode ? [{ debugName: "listNode" }] : []));
|
|
@@ -3813,19 +4006,41 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
3813
4006
|
this.allWidgets = viewChildren(AXPWidgetRendererDirective, ...(ngDevMode ? [{ debugName: "allWidgets" }] : []));
|
|
3814
4007
|
this.listWidget = linkedSignal(() => this.allWidgets().find((widget) => widget.node()?.type === AXPWidgetsCatalog.list));
|
|
3815
4008
|
this.toolbarWidget = computed(() => this.allWidgets().find((widget) => widget.node()?.type === AXPWidgetsCatalog.listToolbar), ...(ngDevMode ? [{ debugName: "toolbarWidget" }] : []));
|
|
3816
|
-
this.selectedItems =
|
|
4009
|
+
this.selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
|
|
3817
4010
|
this.toolbarNode = signal(null, ...(ngDevMode ? [{ debugName: "toolbarNode" }] : []));
|
|
3818
4011
|
this.destroyed = new Subject();
|
|
3819
4012
|
//options
|
|
3820
4013
|
this.entitySource = computed(() => this.options()['entity'], ...(ngDevMode ? [{ debugName: "entitySource" }] : []));
|
|
3821
4014
|
this.excludeColumns = computed(() => this.options()['excludeColumns'], ...(ngDevMode ? [{ debugName: "excludeColumns" }] : []));
|
|
3822
4015
|
this.includeColumns = computed(() => this.options()['includeColumns'], ...(ngDevMode ? [{ debugName: "includeColumns" }] : []));
|
|
4016
|
+
this.externalActions = computed(() => this.options()['actions'], ...(ngDevMode ? [{ debugName: "externalActions" }] : []));
|
|
3823
4017
|
this.showEntityActions = computed(() => this.options()['showEntityActions'] ?? true, ...(ngDevMode ? [{ debugName: "showEntityActions" }] : []));
|
|
3824
4018
|
this.showToolbar = computed(() => this.options()['showToolbar'] ?? true, ...(ngDevMode ? [{ debugName: "showToolbar" }] : []));
|
|
3825
4019
|
//actions
|
|
3826
4020
|
this.allActions = computed(() => {
|
|
3827
|
-
const
|
|
3828
|
-
|
|
4021
|
+
const originalList = this.entity()?.interfaces?.master?.list?.actions ?? [];
|
|
4022
|
+
const externalActionList = this.externalActions() ?? [];
|
|
4023
|
+
const usedOverrideActions = new Set();
|
|
4024
|
+
const mergedActions = originalList.map((originalAction) => {
|
|
4025
|
+
const originalCommandName = typeof originalAction.command === 'string' ? originalAction.command : originalAction.command?.name;
|
|
4026
|
+
const overrideAction = externalActionList.find((action) => {
|
|
4027
|
+
const actionCommandName = typeof action?.command === 'string' ? action.command : action?.command?.name;
|
|
4028
|
+
return actionCommandName === originalCommandName;
|
|
4029
|
+
});
|
|
4030
|
+
if (overrideAction) {
|
|
4031
|
+
const overrideKey = `${typeof overrideAction.command === 'string' ? overrideAction.command : overrideAction.command?.name}`;
|
|
4032
|
+
usedOverrideActions.add(overrideKey);
|
|
4033
|
+
return new AXPEntityCommandTriggerViewModel(this.entity(), overrideAction);
|
|
4034
|
+
}
|
|
4035
|
+
return new AXPEntityCommandTriggerViewModel(this.entity(), originalAction);
|
|
4036
|
+
});
|
|
4037
|
+
const additionalActions = externalActionList
|
|
4038
|
+
.filter((action) => {
|
|
4039
|
+
const actionKey = `${typeof action?.command === 'string' ? action.command : action?.command?.name}`;
|
|
4040
|
+
return !usedOverrideActions.has(actionKey);
|
|
4041
|
+
})
|
|
4042
|
+
.map((action) => new AXPEntityCommandTriggerViewModel(this.entity(), action));
|
|
4043
|
+
return [...additionalActions, ...mergedActions];
|
|
3829
4044
|
}, ...(ngDevMode ? [{ debugName: "allActions" }] : []));
|
|
3830
4045
|
this.primaryActions = computed(() => {
|
|
3831
4046
|
const actions = this.allActions()
|
|
@@ -3913,7 +4128,9 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
3913
4128
|
parentKey: this.entity()?.parentKey,
|
|
3914
4129
|
source: this.entity()?.source,
|
|
3915
4130
|
},
|
|
3916
|
-
data: action?.scope == AXPEntityCommandScope.Selected
|
|
4131
|
+
data: action?.scope == AXPEntityCommandScope.Selected
|
|
4132
|
+
? this.selectedItems()
|
|
4133
|
+
: action?.options?.['process']?.data || null,
|
|
3917
4134
|
options: action?.options,
|
|
3918
4135
|
metadata: action?.metadata,
|
|
3919
4136
|
});
|
|
@@ -3979,10 +4196,30 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
3979
4196
|
* TODO: Implement column change logic
|
|
3980
4197
|
*/
|
|
3981
4198
|
handleColumnChanges(changeTracker) {
|
|
3982
|
-
if (changeTracker.isColumnsChanged) {
|
|
3983
|
-
|
|
3984
|
-
|
|
4199
|
+
if (!changeTracker.isColumnsChanged) {
|
|
4200
|
+
return;
|
|
4201
|
+
}
|
|
4202
|
+
const listInstance = this.listWidget()?.instance;
|
|
4203
|
+
const toolbarState = this.getValue()?.toolbar;
|
|
4204
|
+
if (!listInstance || !toolbarState?.columns) {
|
|
4205
|
+
return;
|
|
3985
4206
|
}
|
|
4207
|
+
// Current columns from list options
|
|
4208
|
+
const currentColumns = (listInstance.options()['columns'] || []);
|
|
4209
|
+
const columnByName = new Map(currentColumns.map((c) => [c.name, c]));
|
|
4210
|
+
// Build new ordered columns array based on toolbar order/visibility
|
|
4211
|
+
const updatedColumns = toolbarState.columns
|
|
4212
|
+
.map((q) => {
|
|
4213
|
+
const base = columnByName.get(q.name);
|
|
4214
|
+
if (!base) {
|
|
4215
|
+
return null;
|
|
4216
|
+
}
|
|
4217
|
+
// Preserve all existing column config but update visibility
|
|
4218
|
+
return { ...base, visible: q.visible };
|
|
4219
|
+
})
|
|
4220
|
+
.filter((c) => c != null);
|
|
4221
|
+
// Apply updated columns to the list widget and refresh
|
|
4222
|
+
listInstance.setOptions({ columns: updatedColumns });
|
|
3986
4223
|
}
|
|
3987
4224
|
async ngOnInit() {
|
|
3988
4225
|
super.ngOnInit();
|
|
@@ -4000,7 +4237,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
4000
4237
|
excludeColumns: this.excludeColumns(),
|
|
4001
4238
|
includeColumns: this.includeColumns(),
|
|
4002
4239
|
};
|
|
4003
|
-
const listOptions = await this.entityListTableService.convertEntityToListOptions(resolvedEntity, options);
|
|
4240
|
+
const listOptions = await this.entityListTableService.convertEntityToListOptions(resolvedEntity, options, this.allActions());
|
|
4004
4241
|
const toolbarOptions = await this.entityListToolbarService.convertEntityToolbarOptions(resolvedEntity, options);
|
|
4005
4242
|
this.listNode.set({
|
|
4006
4243
|
type: AXPWidgetsCatalog.list,
|
|
@@ -4022,7 +4259,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
4022
4259
|
},
|
|
4023
4260
|
});
|
|
4024
4261
|
}
|
|
4025
|
-
ngAfterViewInit() {
|
|
4262
|
+
async ngAfterViewInit() {
|
|
4026
4263
|
this.workflow.events$
|
|
4027
4264
|
.pipe(ofType(AXPRefreshEvent))
|
|
4028
4265
|
.pipe(takeUntil(this.destroyed))
|
|
@@ -4031,6 +4268,15 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
4031
4268
|
this.listWidget()?.instance.call('refresh');
|
|
4032
4269
|
}
|
|
4033
4270
|
});
|
|
4271
|
+
const listWidget = (await this.layoutService.waitForWidget(`${this.entitySource()}-tab-list_table`, 500));
|
|
4272
|
+
if (listWidget?.api && typeof listWidget.api === 'function') {
|
|
4273
|
+
const onSelectionChange = listWidget.api()['onSelectionChange'];
|
|
4274
|
+
if (onSelectionChange) {
|
|
4275
|
+
onSelectionChange.pipe(takeUntil(this.destroyed)).subscribe((e) => {
|
|
4276
|
+
this.selectedItems.set(e);
|
|
4277
|
+
});
|
|
4278
|
+
}
|
|
4279
|
+
}
|
|
4034
4280
|
}
|
|
4035
4281
|
ngOnDestroy() {
|
|
4036
4282
|
this.listWidget.set(undefined);
|
|
@@ -4038,7 +4284,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
4038
4284
|
this.destroyed.complete();
|
|
4039
4285
|
}
|
|
4040
4286
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: AXPEntityListWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
4041
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: AXPEntityListWidgetViewComponent, isStandalone: true, selector: "ng-component", host: { properties: { "class": "\"ax-h-full\"" } }, providers: [AXPEntityListTableService, AXPEntityListToolbarService], viewQueries: [{ propertyName: "
|
|
4287
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: AXPEntityListWidgetViewComponent, isStandalone: true, selector: "ng-component", host: { properties: { "class": "\"ax-h-full\"" } }, providers: [AXPEntityListTableService, AXPEntityListToolbarService], viewQueries: [{ propertyName: "list", first: true, predicate: ["list"], descendants: true, isSignal: true }, { propertyName: "allWidgets", predicate: AXPWidgetRendererDirective, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
4042
4288
|
@if (showEntityActions()) {
|
|
4043
4289
|
<div class="ax-flex ax-gap-2 ax-justify-end ax-mb-4">
|
|
4044
4290
|
@for (action of primaryActions(); track $index) {
|
|
@@ -4769,6 +5015,7 @@ class AXPLookupWidgetSelectorViewModel {
|
|
|
4769
5015
|
this.options = options;
|
|
4770
5016
|
this.workflow = this.injector.get(AXPWorkflowService);
|
|
4771
5017
|
this.filterOperatorMiddleware = this.injector.get(AXPFilterOperatorMiddlewareService);
|
|
5018
|
+
this.widgetResolver = this.injector.get(AXPWidgetRegistryService);
|
|
4772
5019
|
this.dataSource = new AXDataSource({
|
|
4773
5020
|
byKey: (key) => {
|
|
4774
5021
|
const func = this.entityDef.queries.byKey.execute;
|
|
@@ -4798,15 +5045,33 @@ class AXPLookupWidgetSelectorViewModel {
|
|
|
4798
5045
|
return this.inlineFiltersPlaceholders().length > 0;
|
|
4799
5046
|
}, ...(ngDevMode ? [{ debugName: "hasInlineFilters" }] : []));
|
|
4800
5047
|
this.columns = () => {
|
|
4801
|
-
const
|
|
4802
|
-
const
|
|
4803
|
-
const
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
5048
|
+
const { columns = [], properties } = this.entityDef;
|
|
5049
|
+
const visibleProperties = properties.filter(({ schema }) => !schema?.hidden);
|
|
5050
|
+
const visiblePropNames = new Set(visibleProperties.map(({ name }) => name));
|
|
5051
|
+
return columns
|
|
5052
|
+
.filter(({ name, showAs }) => visiblePropNames.has(name) || showAs)
|
|
5053
|
+
.filter(({ name }) => ((this.options.columns?.length ?? 0) == 0) || this.options.columns?.includes(name))
|
|
5054
|
+
.map((column) => {
|
|
5055
|
+
if (column.showAs) {
|
|
5056
|
+
const widgetConfig = this.widgetResolver.resolve(column.showAs.type);
|
|
5057
|
+
const property = {
|
|
5058
|
+
...widgetConfig,
|
|
5059
|
+
name: column.name,
|
|
5060
|
+
title: column.title ?? '',
|
|
5061
|
+
schema: {
|
|
5062
|
+
dataType: 'string',
|
|
5063
|
+
interface: {
|
|
5064
|
+
type: column.showAs.type,
|
|
5065
|
+
options: column.showAs.options,
|
|
5066
|
+
},
|
|
5067
|
+
},
|
|
5068
|
+
};
|
|
5069
|
+
return new AXPEntityListViewColumnViewModel(property, column);
|
|
5070
|
+
}
|
|
5071
|
+
else {
|
|
5072
|
+
const property = visibleProperties.find(({ name }) => name === column.name);
|
|
5073
|
+
return new AXPEntityListViewColumnViewModel(property, column);
|
|
5074
|
+
}
|
|
4810
5075
|
});
|
|
4811
5076
|
};
|
|
4812
5077
|
this.inlineFilters = {
|
|
@@ -4915,13 +5180,24 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
4915
5180
|
this.entity = computed(() => this.options()['entity'], ...(ngDevMode ? [{ debugName: "entity" }] : []));
|
|
4916
5181
|
this.disabled = computed(() => this.options()['disabled'], ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
4917
5182
|
this.columns = computed(() => this.options()['columns'] ?? [], ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
5183
|
+
this.textField = computed(() => this.options()['textField'] ?? '', ...(ngDevMode ? [{ debugName: "textField" }] : []));
|
|
4918
5184
|
this.customFilter = computed(() => this.options()['filter'], ...(ngDevMode ? [{ debugName: "customFilter" }] : []));
|
|
4919
5185
|
this.multiple = computed(() => (this.options()['multiple'] ?? false), ...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
4920
5186
|
this.look = computed(() => this.options()['look'] ?? 'lookup', ...(ngDevMode ? [{ debugName: "look" }] : []));
|
|
4921
5187
|
this.allowClear = computed(() => (this.options()['allowClear'] ?? false), ...(ngDevMode ? [{ debugName: "allowClear" }] : []));
|
|
4922
|
-
this.
|
|
4923
|
-
|
|
4924
|
-
|
|
5188
|
+
this.defaultTextField = computed(() => {
|
|
5189
|
+
const textField = this.entityDef()?.formats.lookup ?? this.entityDef()?.properties.find((c) => c.name != 'id')?.name ?? 'title';
|
|
5190
|
+
return textField;
|
|
5191
|
+
}, ...(ngDevMode ? [{ debugName: "defaultTextField" }] : []));
|
|
5192
|
+
this.displayField = computed(() => {
|
|
5193
|
+
if (this.textField()) {
|
|
5194
|
+
return this.textField();
|
|
5195
|
+
}
|
|
5196
|
+
return this.defaultTextField();
|
|
5197
|
+
}, ...(ngDevMode ? [{ debugName: "displayField" }] : []));
|
|
5198
|
+
this.selectedItemsText = computed(() => {
|
|
5199
|
+
return this.selectedItems().map((item) => get(item, this.displayField())).join(', ');
|
|
5200
|
+
}, ...(ngDevMode ? [{ debugName: "selectedItemsText" }] : []));
|
|
4925
5201
|
this.valueField = computed(() => this.entityDef()?.properties.find((c) => c.name == 'id')?.name ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
|
|
4926
5202
|
this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : []));
|
|
4927
5203
|
this.searchTerm = signal(null, ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
@@ -5061,6 +5337,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
5061
5337
|
this.selectedItems.set(items);
|
|
5062
5338
|
//
|
|
5063
5339
|
const keys = items.map((item) => get(item, this.valueField()));
|
|
5340
|
+
const text = items.map((item) => get(item, this.displayField()));
|
|
5064
5341
|
//
|
|
5065
5342
|
// extract data from valueField and set context by expose path
|
|
5066
5343
|
if (this.expose()) {
|
|
@@ -5116,7 +5393,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
5116
5393
|
<ax-select-box
|
|
5117
5394
|
[dataSource]="vm()?.dataSource!"
|
|
5118
5395
|
[ngModel]="selectedItems()"
|
|
5119
|
-
[textField]="
|
|
5396
|
+
[textField]="displayField()"
|
|
5120
5397
|
[valueField]="valueField()"
|
|
5121
5398
|
[disabled]="disabled()"
|
|
5122
5399
|
[multiple]="multiple()"
|
|
@@ -5130,9 +5407,10 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
5130
5407
|
}
|
|
5131
5408
|
</ax-select-box>
|
|
5132
5409
|
} @else {
|
|
5410
|
+
{{selectedItemsText()}}
|
|
5133
5411
|
<ax-tag-box
|
|
5134
5412
|
[ngModel]="selectedItems()"
|
|
5135
|
-
[textField]="
|
|
5413
|
+
[textField]="displayField()"
|
|
5136
5414
|
[valueField]="valueField()"
|
|
5137
5415
|
(onValueChanged)="handleValueChange($event)"
|
|
5138
5416
|
[placeholder]="placeholder() | translate | async"
|
|
@@ -5182,7 +5460,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
|
|
|
5182
5460
|
<ax-select-box
|
|
5183
5461
|
[dataSource]="vm()?.dataSource!"
|
|
5184
5462
|
[ngModel]="selectedItems()"
|
|
5185
|
-
[textField]="
|
|
5463
|
+
[textField]="displayField()"
|
|
5186
5464
|
[valueField]="valueField()"
|
|
5187
5465
|
[disabled]="disabled()"
|
|
5188
5466
|
[multiple]="multiple()"
|
|
@@ -5196,9 +5474,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
|
|
|
5196
5474
|
}
|
|
5197
5475
|
</ax-select-box>
|
|
5198
5476
|
} @else {
|
|
5477
|
+
{{selectedItemsText()}}
|
|
5199
5478
|
<ax-tag-box
|
|
5200
5479
|
[ngModel]="selectedItems()"
|
|
5201
|
-
[textField]="
|
|
5480
|
+
[textField]="displayField()"
|
|
5202
5481
|
[valueField]="valueField()"
|
|
5203
5482
|
(onValueChanged)="handleValueChange($event)"
|
|
5204
5483
|
[placeholder]="placeholder() | translate | async"
|
|
@@ -6120,7 +6399,7 @@ class AXPShowDetailViewAction extends AXPWorkflowAction {
|
|
|
6120
6399
|
const [module, entity] = context.getVariable('entity').split('.');
|
|
6121
6400
|
const { id } = context.getVariable('data');
|
|
6122
6401
|
const newPayload = {
|
|
6123
|
-
commands: `/${this.sessionService.application?.name}/m/${module}/e/${entity}/${id}/
|
|
6402
|
+
commands: `/${this.sessionService.application?.name}/m/${module}/e/${entity}/${id}/view`,
|
|
6124
6403
|
};
|
|
6125
6404
|
context.setVariable('payload', newPayload);
|
|
6126
6405
|
this.navigation.execute(context);
|