@acorex/platform 20.7.6 → 20.7.8
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-core.mjs +5 -3
- package/fesm2022/acorex-platform-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-ZnTG7wlJ.mjs +121 -0
- package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-ZnTG7wlJ.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-components.mjs +232 -107
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +612 -330
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +11 -2
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- package/fesm2022/{acorex-platform-layout-widgets-repeater-widget-column.component-D4UOMW6k.mjs → acorex-platform-layout-widgets-repeater-widget-column.component-fcCirNxz.mjs} +2 -2
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-fcCirNxz.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets.mjs +582 -76
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-C31xDGGb.mjs → acorex-platform-themes-default-entity-master-list-view.component-DzWjSMSK.mjs} +5 -4
- package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-C31xDGGb.mjs.map → acorex-platform-themes-default-entity-master-list-view.component-DzWjSMSK.mjs.map} +1 -1
- package/fesm2022/acorex-platform-themes-default.mjs +2 -2
- package/layout/components/index.d.ts +49 -28
- package/layout/entity/index.d.ts +42 -41
- package/layout/widget-core/index.d.ts +11 -2
- package/layout/widgets/index.d.ts +130 -8
- package/package.json +1 -1
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-D4UOMW6k.mjs.map +0 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { AXToastService } from '@acorex/components/toast';
|
|
2
|
+
import { AXPlatform } from '@acorex/core/platform';
|
|
2
3
|
import * as i6 from '@acorex/core/translation';
|
|
3
4
|
import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
|
|
4
5
|
import * as i4$1 from '@acorex/platform/common';
|
|
5
6
|
import { AXPSettingsService, AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, getEntityInfo, AXPRefreshEvent, AXPReloadEvent, AXPCommonSettings, AXPEntityQueryType, AXPCleanNestedFilters, AXPWorkflowNavigateAction, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER } from '@acorex/platform/common';
|
|
6
|
-
import { AXPDeviceService, AXPBroadcastEventService, resolveActionLook, AXPExpressionEvaluatorService, AXPDistributedEventListenerService, AXPPlatformScope, AXPColumnWidthService, AXHighlightService, extractValue, setSmart, getChangedPaths, defaultColumnWidthProvider, AXP_COLUMN_WIDTH_PROVIDER, AXPSystemActionType } from '@acorex/platform/core';
|
|
7
|
+
import { AXPDeviceService, AXPBroadcastEventService, applyFilterArray, applySortArray, resolveActionLook, AXPExpressionEvaluatorService, AXPDistributedEventListenerService, AXPPlatformScope, AXPColumnWidthService, AXHighlightService, extractValue, setSmart, getChangedPaths, defaultColumnWidthProvider, AXP_COLUMN_WIDTH_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPSystemActionType } from '@acorex/platform/core';
|
|
7
8
|
import * as i0 from '@angular/core';
|
|
8
9
|
import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, input, viewChild, signal, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, computed, ChangeDetectorRef, effect, Input, afterNextRender, untracked, ViewEncapsulation, viewChildren, linkedSignal, HostBinding, output, NgModule } from '@angular/core';
|
|
9
10
|
import { Subject, takeUntil } from 'rxjs';
|
|
@@ -18,7 +19,7 @@ import { AXLoadingModule } from '@acorex/components/loading';
|
|
|
18
19
|
import * as i2 from '@acorex/components/popover';
|
|
19
20
|
import { AXPopoverModule } from '@acorex/components/popover';
|
|
20
21
|
import * as i3$1 from '@acorex/platform/layout/widget-core';
|
|
21
|
-
import { AXPWidgetsCatalog, AXPWidgetCoreModule, AXPPageStatus, AXPWidgetRegistryService, AXPColumnWidgetComponent, AXPValueWidgetComponent, AXPWidgetGroupEnum, AXPWidgetRendererDirective } from '@acorex/platform/layout/widget-core';
|
|
22
|
+
import { AXPWidgetsCatalog, AXPWidgetCoreModule, AXPPageStatus, AXPWidgetRegistryService, AXPColumnWidgetComponent, AXPValueWidgetComponent, AXPWidgetGroupEnum, AXPWidgetRendererDirective, AXP_WIDGETS_EDITOR_CATEGORY } from '@acorex/platform/layout/widget-core';
|
|
22
23
|
import { AXPCommandService, AXPQueryService, AXPQueryExecutor, provideCommandSetups, provideQuerySetups } from '@acorex/platform/runtime';
|
|
23
24
|
import * as i5 from '@angular/common';
|
|
24
25
|
import { CommonModule } from '@angular/common';
|
|
@@ -31,7 +32,6 @@ import { moveItemInArray } from '@angular/cdk/drag-drop';
|
|
|
31
32
|
import { AXDialogService } from '@acorex/components/dialog';
|
|
32
33
|
import { AXLoadingDialogService } from '@acorex/components/loading-dialog';
|
|
33
34
|
import { AXPopupService } from '@acorex/components/popup';
|
|
34
|
-
import { AXPlatform } from '@acorex/core/platform';
|
|
35
35
|
import * as i2$1 from '@acorex/components/badge';
|
|
36
36
|
import { AXBadgeModule } from '@acorex/components/badge';
|
|
37
37
|
import { AXCheckBoxModule } from '@acorex/components/check-box';
|
|
@@ -58,7 +58,6 @@ import * as i4$3 from '@acorex/components/dropdown';
|
|
|
58
58
|
import { AXDropdownModule } from '@acorex/components/dropdown';
|
|
59
59
|
import * as i4$4 from '@acorex/components/select-box';
|
|
60
60
|
import { AXSelectBoxModule } from '@acorex/components/select-box';
|
|
61
|
-
import { AXTextBoxModule } from '@acorex/components/text-box';
|
|
62
61
|
import * as i2$2 from '@acorex/components/tabs';
|
|
63
62
|
import { AXTabsModule } from '@acorex/components/tabs';
|
|
64
63
|
import { transform, isEqual as isEqual$1 } from 'lodash';
|
|
@@ -411,42 +410,43 @@ class AXPEntityResolver {
|
|
|
411
410
|
constructor() {
|
|
412
411
|
this.providers = inject(AXP_ENTITY_DEFINITION_LOADER);
|
|
413
412
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
const entity = await resolvedLoader.get(moduleName, entityName);
|
|
428
|
-
if (entity) {
|
|
429
|
-
return entity;
|
|
430
|
-
}
|
|
413
|
+
/** Aggregates list() from all entity loaders (including lazy). Populates fullName. */
|
|
414
|
+
async listAll() {
|
|
415
|
+
const loaders = await this.resolveLoaders();
|
|
416
|
+
const results = [];
|
|
417
|
+
for (const loader of loaders) {
|
|
418
|
+
const items = await loader.list();
|
|
419
|
+
for (const it of items) {
|
|
420
|
+
results.push({
|
|
421
|
+
name: it.name,
|
|
422
|
+
module: it.module,
|
|
423
|
+
fullName: `${it.module}.${it.name}`,
|
|
424
|
+
});
|
|
431
425
|
}
|
|
432
426
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
// If loader is a direct instance, use it directly
|
|
441
|
-
resolvedLoader = this.providers;
|
|
442
|
-
}
|
|
443
|
-
const entity = await resolvedLoader.get(moduleName, entityName);
|
|
444
|
-
if (entity) {
|
|
427
|
+
return results;
|
|
428
|
+
}
|
|
429
|
+
async get(moduleName, entityName) {
|
|
430
|
+
const loaders = await this.resolveLoaders();
|
|
431
|
+
for (const loader of loaders) {
|
|
432
|
+
const entity = await loader.get(moduleName, entityName);
|
|
433
|
+
if (entity)
|
|
445
434
|
return entity;
|
|
446
|
-
}
|
|
447
435
|
}
|
|
448
436
|
return null;
|
|
449
437
|
}
|
|
438
|
+
async resolveLoaders() {
|
|
439
|
+
const raw = this.providers;
|
|
440
|
+
if (!raw)
|
|
441
|
+
return [];
|
|
442
|
+
const arr = Array.isArray(raw) ? raw : [raw];
|
|
443
|
+
const loaders = [];
|
|
444
|
+
for (const p of arr) {
|
|
445
|
+
const loader = p instanceof Promise ? await p : p;
|
|
446
|
+
loaders.push(loader);
|
|
447
|
+
}
|
|
448
|
+
return loaders;
|
|
449
|
+
}
|
|
450
450
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPEntityResolver, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
451
451
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPEntityResolver, providedIn: 'root' }); }
|
|
452
452
|
}
|
|
@@ -784,28 +784,173 @@ class PropertyFilter {
|
|
|
784
784
|
const { moduleName, entityName } = parseEntityFullName(this.fullName);
|
|
785
785
|
const entity = await this.entityRegistry.resolve(moduleName, entityName);
|
|
786
786
|
// Select the appropriate interface based on kind
|
|
787
|
-
|
|
788
|
-
if (this.kind === 'create') {
|
|
789
|
-
iface = entity?.interfaces?.master?.create;
|
|
790
|
-
}
|
|
791
|
-
else if (this.kind === 'update') {
|
|
792
|
-
iface = entity?.interfaces?.master?.update;
|
|
793
|
-
}
|
|
794
|
-
else {
|
|
795
|
-
iface = entity?.interfaces?.master?.single;
|
|
796
|
-
}
|
|
787
|
+
const iface = getEntityInterface(entity, this.kind);
|
|
797
788
|
if (!iface) {
|
|
798
789
|
throw new Error(`Entity interface not found: ${entity.module}.${entity.name}.interfaces.master.${this.kind}`);
|
|
799
790
|
}
|
|
800
791
|
// Title and size
|
|
801
792
|
const title = this.overrideTitle || entity.formats?.individual || entity.title || `${entity.module}.${entity.name}`;
|
|
802
793
|
// Build content using LayoutBuilder
|
|
803
|
-
const
|
|
804
|
-
const
|
|
805
|
-
const
|
|
806
|
-
const allowedNames = this.computeAllowedNames(
|
|
807
|
-
//
|
|
808
|
-
const
|
|
794
|
+
const mainSections = (iface.sections ?? []).slice();
|
|
795
|
+
const mainProps = (entity.properties ?? []).slice();
|
|
796
|
+
const mainViewLayoutMap = buildViewLayoutMap(iface.properties ?? []);
|
|
797
|
+
const allowedNames = this.computeAllowedNames(mainProps.map((p) => p.name));
|
|
798
|
+
// Collect all groups for title lookup (main + merged)
|
|
799
|
+
const allGroups = [...(entity.groups ?? [])];
|
|
800
|
+
// Process merge-detail related entities
|
|
801
|
+
const mergeDetailEntities = (entity.relatedEntities ?? []).filter((re) => !re.hidden && re.layout?.type === 'merge-detail');
|
|
802
|
+
// Build merged properties map by section
|
|
803
|
+
const mergedPropsBySection = new Map();
|
|
804
|
+
// Initialize with main entity properties
|
|
805
|
+
for (const prop of mainProps) {
|
|
806
|
+
if (!allowedNames.has(prop.name) || !mainViewLayoutMap.has(prop.name))
|
|
807
|
+
continue;
|
|
808
|
+
const groupId = prop.groupId ?? 'default';
|
|
809
|
+
if (!mergedPropsBySection.has(groupId)) {
|
|
810
|
+
mergedPropsBySection.set(groupId, []);
|
|
811
|
+
}
|
|
812
|
+
const viewLayout = mainViewLayoutMap.get(prop.name);
|
|
813
|
+
mergedPropsBySection.get(groupId).push({
|
|
814
|
+
...prop,
|
|
815
|
+
__layout: viewLayout?.layout,
|
|
816
|
+
__order: viewLayout?.layout?.order,
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
// Track extra sections from related entities
|
|
820
|
+
const extraSections = [];
|
|
821
|
+
const mainSectionIds = new Set(mainSections.map((s) => s.id));
|
|
822
|
+
// Group related entities by position for ordered processing
|
|
823
|
+
const beforeEntities = mergeDetailEntities
|
|
824
|
+
.filter((re) => re.layout?.position === 'before')
|
|
825
|
+
.sort((a, b) => (a.layout?.order ?? Infinity) - (b.layout?.order ?? Infinity));
|
|
826
|
+
const middleEntities = mergeDetailEntities.filter((re) => !re.layout?.position || re.layout?.position === 'middle');
|
|
827
|
+
const afterEntities = mergeDetailEntities
|
|
828
|
+
.filter((re) => re.layout?.position === 'after')
|
|
829
|
+
.sort((a, b) => (a.layout?.order ?? Infinity) - (b.layout?.order ?? Infinity));
|
|
830
|
+
// Process related entities in order: before, middle, after
|
|
831
|
+
const processRelatedEntity = async (relatedEntity) => {
|
|
832
|
+
try {
|
|
833
|
+
const [relModuleName, relEntityName] = relatedEntity.entity.split('.');
|
|
834
|
+
const relEntityDef = await this.entityRegistry.resolve(relModuleName, relEntityName);
|
|
835
|
+
if (!relEntityDef)
|
|
836
|
+
return;
|
|
837
|
+
// Get the matching interface for the related entity
|
|
838
|
+
const relIface = getEntityInterface(relEntityDef, this.kind);
|
|
839
|
+
if (!relIface)
|
|
840
|
+
return;
|
|
841
|
+
// Merge related groups into allGroups (avoid duplicates)
|
|
842
|
+
for (const rg of relEntityDef.groups ?? []) {
|
|
843
|
+
if (!allGroups.some((g) => g.id === rg.id)) {
|
|
844
|
+
allGroups.push(rg);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
// Compute dataPath for field prefixing
|
|
848
|
+
const dataPath = relatedEntity.persistence?.dataPath || relEntityName;
|
|
849
|
+
const position = relatedEntity.layout?.position ?? 'middle';
|
|
850
|
+
const entityOrder = relatedEntity.layout?.order ?? Infinity;
|
|
851
|
+
// Build view layout map for related entity
|
|
852
|
+
const relViewLayoutMap = buildViewLayoutMap(relIface.properties ?? []);
|
|
853
|
+
// Process each section in related interface
|
|
854
|
+
for (const relSection of relIface.sections ?? []) {
|
|
855
|
+
const sectionId = relSection.id;
|
|
856
|
+
const sectionHasMainEquivalent = mainSectionIds.has(sectionId);
|
|
857
|
+
// Get properties for this section
|
|
858
|
+
const sectionProps = [];
|
|
859
|
+
for (const prop of relEntityDef.properties ?? []) {
|
|
860
|
+
if (prop.groupId !== sectionId)
|
|
861
|
+
continue;
|
|
862
|
+
if (!relViewLayoutMap.has(prop.name))
|
|
863
|
+
continue;
|
|
864
|
+
const viewLayout = relViewLayoutMap.get(prop.name);
|
|
865
|
+
// Clone property and add merge-detail metadata
|
|
866
|
+
const mergedProp = {
|
|
867
|
+
...prop,
|
|
868
|
+
__dataPath: dataPath,
|
|
869
|
+
__layout: viewLayout?.layout,
|
|
870
|
+
__order: viewLayout?.layout?.order,
|
|
871
|
+
};
|
|
872
|
+
// Prefix expressions in schema options
|
|
873
|
+
if (mergedProp.schema?.interface?.options) {
|
|
874
|
+
mergedProp.schema = {
|
|
875
|
+
...mergedProp.schema,
|
|
876
|
+
interface: {
|
|
877
|
+
...mergedProp.schema.interface,
|
|
878
|
+
options: prefixExpressions(mergedProp.schema.interface.options, dataPath),
|
|
879
|
+
},
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
// Prefix expressions in visible/readonly if they are strings
|
|
883
|
+
if (typeof mergedProp.schema?.visible === 'string') {
|
|
884
|
+
mergedProp.schema = {
|
|
885
|
+
...mergedProp.schema,
|
|
886
|
+
visible: prefixExpressions(mergedProp.schema.visible, dataPath),
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
if (typeof mergedProp.schema?.readonly === 'string') {
|
|
890
|
+
mergedProp.schema = {
|
|
891
|
+
...mergedProp.schema,
|
|
892
|
+
readonly: prefixExpressions(mergedProp.schema.readonly, dataPath),
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
sectionProps.push(mergedProp);
|
|
896
|
+
}
|
|
897
|
+
if (sectionProps.length === 0)
|
|
898
|
+
continue;
|
|
899
|
+
if (sectionHasMainEquivalent) {
|
|
900
|
+
// Merge into existing section
|
|
901
|
+
const existing = mergedPropsBySection.get(sectionId) ?? [];
|
|
902
|
+
if (position === 'before') {
|
|
903
|
+
mergedPropsBySection.set(sectionId, [...sectionProps, ...existing]);
|
|
904
|
+
}
|
|
905
|
+
else {
|
|
906
|
+
mergedPropsBySection.set(sectionId, [...existing, ...sectionProps]);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
else {
|
|
910
|
+
// Create new section entry
|
|
911
|
+
if (!mergedPropsBySection.has(sectionId)) {
|
|
912
|
+
mergedPropsBySection.set(sectionId, []);
|
|
913
|
+
}
|
|
914
|
+
const existing = mergedPropsBySection.get(sectionId) ?? [];
|
|
915
|
+
if (position === 'before') {
|
|
916
|
+
mergedPropsBySection.set(sectionId, [...sectionProps, ...existing]);
|
|
917
|
+
}
|
|
918
|
+
else {
|
|
919
|
+
mergedPropsBySection.set(sectionId, [...existing, ...sectionProps]);
|
|
920
|
+
}
|
|
921
|
+
// Track as extra section if not already tracked
|
|
922
|
+
if (!extraSections.some((s) => s.id === sectionId)) {
|
|
923
|
+
extraSections.push({
|
|
924
|
+
...relSection,
|
|
925
|
+
__entityOrder: entityOrder,
|
|
926
|
+
__position: position,
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
catch {
|
|
933
|
+
// Silently ignore failures to resolve or merge
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
// Process in order
|
|
937
|
+
for (const re of beforeEntities)
|
|
938
|
+
await processRelatedEntity(re);
|
|
939
|
+
for (const re of middleEntities)
|
|
940
|
+
await processRelatedEntity(re);
|
|
941
|
+
for (const re of afterEntities)
|
|
942
|
+
await processRelatedEntity(re);
|
|
943
|
+
// Build final sorted sections list
|
|
944
|
+
const finalSections = sortMergedSections(mainSections, extraSections, mainSectionIds);
|
|
945
|
+
// Calculate recommended dialog size based on form complexity (using merged data)
|
|
946
|
+
const allMergedProps = Array.from(mergedPropsBySection.values()).flat();
|
|
947
|
+
const mergedViewLayoutMap = new Map();
|
|
948
|
+
for (const prop of allMergedProps) {
|
|
949
|
+
if (prop.__layout) {
|
|
950
|
+
mergedViewLayoutMap.set(prop.name, { name: prop.name, layout: prop.__layout });
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
const calculatedSize = this.calculateRecommendedDialogSize(finalSections, allMergedProps, mergedViewLayoutMap, new Set(allMergedProps.map((p) => p.name)));
|
|
809
954
|
const dialog = this.layoutBuilder.create().dialog((d) => {
|
|
810
955
|
d.setTitle(title);
|
|
811
956
|
d.setSize(this.externalSize ?? calculatedSize);
|
|
@@ -819,24 +964,27 @@ class PropertyFilter {
|
|
|
819
964
|
// Configure grid with 12 columns (like Bootstrap)
|
|
820
965
|
grid.setColumns(12);
|
|
821
966
|
grid.setGap('1rem');
|
|
822
|
-
for (const section of
|
|
967
|
+
for (const section of finalSections) {
|
|
823
968
|
const groupId = section.id;
|
|
824
|
-
|
|
825
|
-
// This prevents cross-plugin leaks when multiple properties share the same group/section.
|
|
826
|
-
const groupProps = entityProps.filter((p) => p.groupId === groupId && allowedNames.has(p.name) && nameToViewLayout.has(p.name));
|
|
969
|
+
const sectionProps = mergedPropsBySection.get(groupId) ?? [];
|
|
827
970
|
const extraFields = this.extraFieldsByGroup.get(groupId) ?? [];
|
|
828
|
-
if (
|
|
971
|
+
if (sectionProps.length === 0 && extraFields.length === 0) {
|
|
829
972
|
continue;
|
|
830
973
|
}
|
|
831
974
|
grid.fieldset((fs) => {
|
|
832
975
|
fs.setLook('fieldset');
|
|
833
|
-
fs.setTitle((
|
|
976
|
+
fs.setTitle((getGroupTitleFromList(allGroups, groupId) || groupId));
|
|
834
977
|
fs.setCols(12); // Set fieldset to use 12-column grid layout
|
|
835
|
-
//
|
|
836
|
-
const orderedProps =
|
|
978
|
+
// Sort properties by order within section
|
|
979
|
+
const orderedProps = [...sectionProps].sort((a, b) => {
|
|
980
|
+
const aOrder = a.__order ?? Infinity;
|
|
981
|
+
const bOrder = b.__order ?? Infinity;
|
|
982
|
+
return aOrder - bOrder;
|
|
983
|
+
});
|
|
837
984
|
for (const prop of orderedProps) {
|
|
838
|
-
const
|
|
839
|
-
const
|
|
985
|
+
const mergedProp = prop;
|
|
986
|
+
const dataPath = mergedProp.__dataPath;
|
|
987
|
+
const fieldPath = dataPath ? `${dataPath}.${prop.name}` : prop.name;
|
|
840
988
|
fs.formField(prop.title, (field) => {
|
|
841
989
|
// Path & field-level visibility/readonly
|
|
842
990
|
field.path(fieldPath);
|
|
@@ -849,8 +997,8 @@ class PropertyFilter {
|
|
|
849
997
|
if (prop.schema?.defaultValue !== undefined) {
|
|
850
998
|
field.defaultValue(prop.schema.defaultValue);
|
|
851
999
|
}
|
|
852
|
-
// Layout mapping (per-field)
|
|
853
|
-
const fieldLayout = toFieldLayout(
|
|
1000
|
+
// Layout mapping (per-field)
|
|
1001
|
+
const fieldLayout = toFieldLayout(mergedProp.__layout);
|
|
854
1002
|
if (fieldLayout) {
|
|
855
1003
|
field.layout(fieldLayout);
|
|
856
1004
|
}
|
|
@@ -861,8 +1009,12 @@ class PropertyFilter {
|
|
|
861
1009
|
const widgetType = prop.schema?.interface?.type || '';
|
|
862
1010
|
const widgetOptions = buildWidgetOptions(prop);
|
|
863
1011
|
const extendedProperties = buildWidgetExtendedProperties(prop);
|
|
1012
|
+
// Prefix extended properties expressions if from related entity
|
|
1013
|
+
const finalExtendedProps = dataPath
|
|
1014
|
+
? prefixExpressions(extendedProperties, dataPath)
|
|
1015
|
+
: extendedProperties;
|
|
864
1016
|
// Merge extended properties into options (they will be extracted in addSingleWidget)
|
|
865
|
-
field.customWidget(widgetType, { ...widgetOptions, ...
|
|
1017
|
+
field.customWidget(widgetType, { ...widgetOptions, ...finalExtendedProps });
|
|
866
1018
|
});
|
|
867
1019
|
}
|
|
868
1020
|
// Append any extra fields requested by the caller for this group
|
|
@@ -1088,6 +1240,24 @@ function getGroupTitle(entity, groupId) {
|
|
|
1088
1240
|
const g = (entity.groups || []).find((x) => x.id === groupId);
|
|
1089
1241
|
return g?.title;
|
|
1090
1242
|
}
|
|
1243
|
+
function getGroupTitleFromList(groups, groupId) {
|
|
1244
|
+
const g = groups.find((x) => x.id === groupId);
|
|
1245
|
+
return g?.title;
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1248
|
+
* Gets the appropriate interface from an entity based on the kind
|
|
1249
|
+
*/
|
|
1250
|
+
function getEntityInterface(entity, kind) {
|
|
1251
|
+
if (kind === 'create') {
|
|
1252
|
+
return entity?.interfaces?.master?.create;
|
|
1253
|
+
}
|
|
1254
|
+
else if (kind === 'update') {
|
|
1255
|
+
return entity?.interfaces?.master?.update;
|
|
1256
|
+
}
|
|
1257
|
+
else {
|
|
1258
|
+
return entity?.interfaces?.master?.single;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1091
1261
|
function toCompatFormFieldBuilder(field) {
|
|
1092
1262
|
return {
|
|
1093
1263
|
...field,
|
|
@@ -1099,6 +1269,109 @@ function toCompatFormFieldBuilder(field) {
|
|
|
1099
1269
|
mode: (mode) => field.mode(mode),
|
|
1100
1270
|
};
|
|
1101
1271
|
}
|
|
1272
|
+
/**
|
|
1273
|
+
* Prefixes context.eval() expressions and expose targets with a dataPath.
|
|
1274
|
+
* - Transforms `context.eval("field")` to `context.eval("dataPath.field")`
|
|
1275
|
+
* - Transforms expose `target: "field"` to `target: "dataPath.field"`
|
|
1276
|
+
* Recursively processes objects and arrays.
|
|
1277
|
+
*/
|
|
1278
|
+
function prefixExpressions(value, dataPath, parentKey) {
|
|
1279
|
+
if (!dataPath)
|
|
1280
|
+
return value;
|
|
1281
|
+
if (typeof value === 'string') {
|
|
1282
|
+
// Special handling for 'target' key in expose arrays - prefix the path directly
|
|
1283
|
+
if (parentKey === 'target') {
|
|
1284
|
+
// Don't prefix if already prefixed or if it starts with $ (absolute path)
|
|
1285
|
+
if (value.startsWith(dataPath + '.') || value.startsWith('$')) {
|
|
1286
|
+
return value;
|
|
1287
|
+
}
|
|
1288
|
+
return `${dataPath}.${value}`;
|
|
1289
|
+
}
|
|
1290
|
+
// Match context.eval("...") or context.eval('...')
|
|
1291
|
+
return value.replace(/context\.eval\(["']([^"']+)["']\)/g, (match, path) => {
|
|
1292
|
+
// Don't prefix if already prefixed or if it's an absolute path
|
|
1293
|
+
if (path.startsWith(dataPath + '.') || path.startsWith('$')) {
|
|
1294
|
+
return match;
|
|
1295
|
+
}
|
|
1296
|
+
return `context.eval("${dataPath}.${path}")`;
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
if (Array.isArray(value)) {
|
|
1300
|
+
return value.map((item) => prefixExpressions(item, dataPath, parentKey));
|
|
1301
|
+
}
|
|
1302
|
+
if (value !== null && typeof value === 'object') {
|
|
1303
|
+
const result = {};
|
|
1304
|
+
for (const key of Object.keys(value)) {
|
|
1305
|
+
result[key] = prefixExpressions(value[key], dataPath, key);
|
|
1306
|
+
}
|
|
1307
|
+
return result;
|
|
1308
|
+
}
|
|
1309
|
+
return value;
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* Groups properties by their groupId (section)
|
|
1313
|
+
*/
|
|
1314
|
+
function groupPropertiesBySection(properties) {
|
|
1315
|
+
const map = new Map();
|
|
1316
|
+
for (const prop of properties) {
|
|
1317
|
+
const groupId = prop.groupId ?? 'default';
|
|
1318
|
+
if (!map.has(groupId)) {
|
|
1319
|
+
map.set(groupId, []);
|
|
1320
|
+
}
|
|
1321
|
+
map.get(groupId).push(prop);
|
|
1322
|
+
}
|
|
1323
|
+
return map;
|
|
1324
|
+
}
|
|
1325
|
+
/**
|
|
1326
|
+
* Sorts sections by position and order:
|
|
1327
|
+
* 1. Before sections (sorted by entityOrder, then section order)
|
|
1328
|
+
* 2. Middle sections (main + middle-only, sorted by effective order while preserving original index for stable sort)
|
|
1329
|
+
* 3. After sections (sorted by entityOrder, then section order)
|
|
1330
|
+
*/
|
|
1331
|
+
function sortMergedSections(mainSections, extraSections, mainSectionIds) {
|
|
1332
|
+
const beforeSections = extraSections
|
|
1333
|
+
.filter((s) => s.__position === 'before' && !mainSectionIds.has(s.id))
|
|
1334
|
+
.sort((a, b) => {
|
|
1335
|
+
const entityOrderDiff = (a.__entityOrder ?? Infinity) - (b.__entityOrder ?? Infinity);
|
|
1336
|
+
if (entityOrderDiff !== 0)
|
|
1337
|
+
return entityOrderDiff;
|
|
1338
|
+
return (a.order ?? 0) - (b.order ?? 0);
|
|
1339
|
+
});
|
|
1340
|
+
const middleSections = extraSections.filter((s) => s.__position === 'middle' && !mainSectionIds.has(s.id));
|
|
1341
|
+
const afterSections = extraSections
|
|
1342
|
+
.filter((s) => s.__position === 'after' && !mainSectionIds.has(s.id))
|
|
1343
|
+
.sort((a, b) => {
|
|
1344
|
+
const entityOrderDiff = (a.__entityOrder ?? Infinity) - (b.__entityOrder ?? Infinity);
|
|
1345
|
+
if (entityOrderDiff !== 0)
|
|
1346
|
+
return entityOrderDiff;
|
|
1347
|
+
return (a.order ?? 0) - (b.order ?? 0);
|
|
1348
|
+
});
|
|
1349
|
+
// Build index map for main sections to preserve original order when no explicit order is specified
|
|
1350
|
+
const mainSectionIndexMap = new Map();
|
|
1351
|
+
mainSections.forEach((s, idx) => mainSectionIndexMap.set(s.id, idx));
|
|
1352
|
+
// Middle block: main sections + middle-only sections
|
|
1353
|
+
// Sort by explicit order if present, otherwise use original array index for main sections
|
|
1354
|
+
// Extra middle sections without order go after main sections
|
|
1355
|
+
const middleBlock = [...mainSections, ...middleSections].sort((a, b) => {
|
|
1356
|
+
const aHasOrder = a.order !== undefined;
|
|
1357
|
+
const bHasOrder = b.order !== undefined;
|
|
1358
|
+
// If both have explicit order, sort by order
|
|
1359
|
+
if (aHasOrder && bHasOrder) {
|
|
1360
|
+
return a.order - b.order;
|
|
1361
|
+
}
|
|
1362
|
+
// If neither has order, preserve original array position for main sections
|
|
1363
|
+
if (!aHasOrder && !bHasOrder) {
|
|
1364
|
+
const aIdx = mainSectionIndexMap.get(a.id) ?? Infinity;
|
|
1365
|
+
const bIdx = mainSectionIndexMap.get(b.id) ?? Infinity;
|
|
1366
|
+
return aIdx - bIdx;
|
|
1367
|
+
}
|
|
1368
|
+
// If only one has order, the one with order comes first (explicit ordering takes precedence)
|
|
1369
|
+
if (aHasOrder)
|
|
1370
|
+
return -1;
|
|
1371
|
+
return 1;
|
|
1372
|
+
});
|
|
1373
|
+
return [...beforeSections, ...middleBlock, ...afterSections];
|
|
1374
|
+
}
|
|
1102
1375
|
|
|
1103
1376
|
class AXPCreateEntityCommand {
|
|
1104
1377
|
constructor() {
|
|
@@ -1108,6 +1381,7 @@ class AXPCreateEntityCommand {
|
|
|
1108
1381
|
this.toastService = inject(AXToastService);
|
|
1109
1382
|
this.translationService = inject(AXTranslationService);
|
|
1110
1383
|
this.eventService = inject(AXPBroadcastEventService);
|
|
1384
|
+
this.platform = inject(AXPlatform);
|
|
1111
1385
|
this.context = {};
|
|
1112
1386
|
}
|
|
1113
1387
|
async execute(input) {
|
|
@@ -1115,6 +1389,11 @@ class AXPCreateEntityCommand {
|
|
|
1115
1389
|
const { entity, entityInfo, data, options } = input.__context__;
|
|
1116
1390
|
const excludeProperties = options?.excludeProperties;
|
|
1117
1391
|
const includeProperties = options?.includeProperties;
|
|
1392
|
+
// Extract decoration and layout from options (similar to workflow)
|
|
1393
|
+
const decoration = options?.['decoration'];
|
|
1394
|
+
const layout = options?.['layout'];
|
|
1395
|
+
const headerTitle = decoration?.header?.title;
|
|
1396
|
+
const layoutSize = layout?.size;
|
|
1118
1397
|
const [moduleName, entityName] = (entity || '').split('.');
|
|
1119
1398
|
if (!moduleName || !entityName) {
|
|
1120
1399
|
return {
|
|
@@ -1138,13 +1417,25 @@ class AXPCreateEntityCommand {
|
|
|
1138
1417
|
if (includeProperties && includeProperties.length > 0) {
|
|
1139
1418
|
chain = chain.include(...includeProperties);
|
|
1140
1419
|
}
|
|
1141
|
-
if
|
|
1420
|
+
// Set dialog title: use decoration.header.title if available, otherwise use entityInfo.title
|
|
1421
|
+
if (headerTitle) {
|
|
1422
|
+
chain = chain.title(headerTitle);
|
|
1423
|
+
}
|
|
1424
|
+
else if (entityInfo?.title) {
|
|
1142
1425
|
const createText = await this.translationService.translateAsync('@general:actions.create.title');
|
|
1143
1426
|
const translatedTitle = await this.translationService.translateAsync(entityInfo.title);
|
|
1144
1427
|
chain = chain.title(`${createText} ${translatedTitle}`);
|
|
1145
1428
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1429
|
+
// Set dialog size: prioritize layout.size, then dialogSize from input, with platform-aware defaults
|
|
1430
|
+
const finalSize = layoutSize || dialogSize;
|
|
1431
|
+
if (this.platform.is('Mobile') || this.platform.is('SM')) {
|
|
1432
|
+
chain.size('full');
|
|
1433
|
+
}
|
|
1434
|
+
else if (finalSize) {
|
|
1435
|
+
chain.size(finalSize);
|
|
1436
|
+
}
|
|
1437
|
+
else {
|
|
1438
|
+
chain.size('md');
|
|
1148
1439
|
}
|
|
1149
1440
|
dialogRef = await chain.show();
|
|
1150
1441
|
if (dialogRef.action() == 'cancel') {
|
|
@@ -1780,7 +2071,7 @@ class AXPEntityDetailPopoverComponent {
|
|
|
1780
2071
|
return importantProperties;
|
|
1781
2072
|
}
|
|
1782
2073
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPEntityDetailPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1783
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AXPEntityDetailPopoverComponent, isStandalone: true, selector: "axp-entity-detail-popover", inputs: { entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: true, transformFunction: null }, entityId: { classPropertyName: "entityId", publicName: "entityId", isSignal: true, isRequired: true, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, breadcrumb: { classPropertyName: "breadcrumb", publicName: "breadcrumb", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "detailPopover", first: true, predicate: ["detailPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "<ax-popover [openOn]=\"'manual'\" #detailPopover (openChange)=\"onDetailPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface ax-border ax-rounded-lg ax-shadow-lg ax-p-4 ax-min-w-[400px]\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold ax-text-on-lightest-surface\">\n @if (entityDetails()?.entityData?.[textField()]) {\n {{ entityDetails()?.entityData[textField()] }}\n } @else {\n {{ item()?.[textField()] }}\n }\n </h3>\n @if (breadcrumb()) {\n <div class=\"ax-text-xs ax-text-neutral-500 ax-mt-1\">{{ breadcrumb() }}</div>\n }\n </div>\n @if (isLoadingDetails()) {\n <div class=\"ax-flex ax-items-center ax-justify-center ax-py-8\">\n <ax-loading>Loading details...</ax-loading>\n </div>\n } @else if (entityDetails()) {\n <div class=\"ax-space-y-3 ax-mb-4\">\n <!-- Important Entity Data -->\n @if (entityDetails()?.entityData) {\n <axp-widgets-container [context]=\"entityDetails()?.entityData\">\n <div class=\"ax-space-y-2\">\n @for (item of getEntityPropertiesWithWidgets(); track item.name) {\n <div class=\"ax-flex ax-justify-between ax-items-center\">\n <span class=\"ax-text-sm ax-font-medium\">{{ item.title | translate | async }}:</span>\n <div class=\"ax-flex-1 ax-ml-2 ax-max-w-48\">\n <ng-container axp-widget-renderer [node]=\"item.node\" [mode]=\"'view'\"></ng-container>\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n }\n </div>\n <div class=\"ax-flex ax-gap-2 ax-justify-end ax-sm\">\n <ax-button [color]=\"'primary'\" [look]=\"'solid'\" text=\"Open Details\" (click)=\"navigateToDetails()\"> </ax-button>\n </div>\n }\n </div>\n</ax-popover>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i3$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2074
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AXPEntityDetailPopoverComponent, isStandalone: true, selector: "axp-entity-detail-popover", inputs: { entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: true, transformFunction: null }, entityId: { classPropertyName: "entityId", publicName: "entityId", isSignal: true, isRequired: true, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, breadcrumb: { classPropertyName: "breadcrumb", publicName: "breadcrumb", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "detailPopover", first: true, predicate: ["detailPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "<ax-popover [openOn]=\"'manual'\" #detailPopover (openChange)=\"onDetailPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface ax-border ax-rounded-lg ax-shadow-lg ax-p-4 ax-min-w-[400px]\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold ax-text-on-lightest-surface\">\n @if (entityDetails()?.entityData?.[textField()]) {\n {{ entityDetails()?.entityData[textField()] }}\n } @else {\n {{ item()?.[textField()] }}\n }\n </h3>\n @if (breadcrumb()) {\n <div class=\"ax-text-xs ax-text-neutral-500 ax-mt-1\">{{ breadcrumb() }}</div>\n }\n </div>\n @if (isLoadingDetails()) {\n <div class=\"ax-flex ax-items-center ax-justify-center ax-py-8\">\n <ax-loading>Loading details...</ax-loading>\n </div>\n } @else if (entityDetails()) {\n <div class=\"ax-space-y-3 ax-mb-4\">\n <!-- Important Entity Data -->\n @if (entityDetails()?.entityData) {\n <axp-widgets-container [context]=\"entityDetails()?.entityData\">\n <div class=\"ax-space-y-2\">\n @for (item of getEntityPropertiesWithWidgets(); track item.name) {\n <div class=\"ax-flex ax-justify-between ax-items-center\">\n <span class=\"ax-text-sm ax-font-medium\">{{ item.title | translate | async }}:</span>\n <div class=\"ax-flex-1 ax-ml-2 ax-max-w-48\">\n <ng-container axp-widget-renderer [node]=\"item.node\" [mode]=\"'view'\"></ng-container>\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n }\n </div>\n <div class=\"ax-flex ax-gap-2 ax-justify-end ax-sm\">\n <ax-button [color]=\"'primary'\" [look]=\"'solid'\" text=\"Open Details\" (click)=\"navigateToDetails()\"> </ax-button>\n </div>\n }\n </div>\n</ax-popover>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "repositionOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i3$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1784
2075
|
}
|
|
1785
2076
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPEntityDetailPopoverComponent, decorators: [{
|
|
1786
2077
|
type: Component,
|
|
@@ -1884,6 +2175,95 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
1884
2175
|
args: [{ providedIn: 'root' }]
|
|
1885
2176
|
}] });
|
|
1886
2177
|
|
|
2178
|
+
/**
|
|
2179
|
+
* Data source definition provider that returns all entity names
|
|
2180
|
+
* from entity loaders' list() (const.ts in each module).
|
|
2181
|
+
*/
|
|
2182
|
+
class AXPEntitiesListDataSourceDefinition {
|
|
2183
|
+
constructor() {
|
|
2184
|
+
//#region ---- Services & Dependencies ----
|
|
2185
|
+
this.entityResolver = inject(AXPEntityResolver);
|
|
2186
|
+
//#endregion
|
|
2187
|
+
}
|
|
2188
|
+
//#endregion
|
|
2189
|
+
//#region ---- Public Methods ----
|
|
2190
|
+
items() {
|
|
2191
|
+
return Promise.resolve([
|
|
2192
|
+
{
|
|
2193
|
+
name: 'entities',
|
|
2194
|
+
title: 'Entities',
|
|
2195
|
+
columns: [
|
|
2196
|
+
{
|
|
2197
|
+
name: 'entity',
|
|
2198
|
+
title: 'Entity',
|
|
2199
|
+
datatype: 'string',
|
|
2200
|
+
type: AXPWidgetsCatalog.text,
|
|
2201
|
+
},
|
|
2202
|
+
{
|
|
2203
|
+
name: 'module',
|
|
2204
|
+
title: 'Module',
|
|
2205
|
+
datatype: 'string',
|
|
2206
|
+
type: AXPWidgetsCatalog.text,
|
|
2207
|
+
},
|
|
2208
|
+
{
|
|
2209
|
+
name: 'title',
|
|
2210
|
+
title: 'Title',
|
|
2211
|
+
datatype: 'string',
|
|
2212
|
+
type: AXPWidgetsCatalog.text,
|
|
2213
|
+
},
|
|
2214
|
+
],
|
|
2215
|
+
filters: [
|
|
2216
|
+
{
|
|
2217
|
+
field: 'entity',
|
|
2218
|
+
title: 'Entity',
|
|
2219
|
+
operator: { type: 'equal' },
|
|
2220
|
+
widget: { type: AXPWidgetsCatalog.text },
|
|
2221
|
+
filterType: { advance: true, inline: true },
|
|
2222
|
+
},
|
|
2223
|
+
{
|
|
2224
|
+
field: 'module',
|
|
2225
|
+
title: 'Module',
|
|
2226
|
+
operator: { type: 'equal' },
|
|
2227
|
+
widget: { type: AXPWidgetsCatalog.text },
|
|
2228
|
+
filterType: { advance: true, inline: true },
|
|
2229
|
+
},
|
|
2230
|
+
],
|
|
2231
|
+
textField: { name: 'title', title: 'Title' },
|
|
2232
|
+
valueField: { name: 'title', title: 'Title' },
|
|
2233
|
+
source: () => {
|
|
2234
|
+
return new AXDataSource({
|
|
2235
|
+
key: 'title',
|
|
2236
|
+
load: async (query) => {
|
|
2237
|
+
const entries = await this.entityResolver.listAll();
|
|
2238
|
+
let items = entries.map((e) => ({
|
|
2239
|
+
title: e.fullName,
|
|
2240
|
+
entity: e.name,
|
|
2241
|
+
module: e.module,
|
|
2242
|
+
}));
|
|
2243
|
+
if (query.filter) {
|
|
2244
|
+
items = applyFilterArray(items, [query.filter]);
|
|
2245
|
+
}
|
|
2246
|
+
const rawSort = Array.isArray(query.sort) ? query.sort : query.sort ? [query.sort] : [];
|
|
2247
|
+
const sortOpt = rawSort.length > 0 ? rawSort : [{ field: 'title', dir: 'asc' }];
|
|
2248
|
+
items = applySortArray(items, sortOpt);
|
|
2249
|
+
return { items, total: items.length };
|
|
2250
|
+
},
|
|
2251
|
+
byKey: async (key) => {
|
|
2252
|
+
const k = String(key);
|
|
2253
|
+
const entries = await this.entityResolver.listAll();
|
|
2254
|
+
const e = entries.find((x) => x.fullName === k);
|
|
2255
|
+
if (!e)
|
|
2256
|
+
throw new Error(`Entity not found: ${k}`);
|
|
2257
|
+
return { title: e.fullName, entity: e.name, module: e.module };
|
|
2258
|
+
},
|
|
2259
|
+
pageSize: 1000,
|
|
2260
|
+
});
|
|
2261
|
+
},
|
|
2262
|
+
},
|
|
2263
|
+
]);
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
|
|
1887
2267
|
class AXPEntityCommandTriggerViewModel {
|
|
1888
2268
|
constructor(entity, action) {
|
|
1889
2269
|
this.name = `${typeof action.command === 'string' ? action.command : action.command.name}&${action.name}`;
|
|
@@ -2909,6 +3289,8 @@ class AXPEntityMasterListViewModel {
|
|
|
2909
3289
|
if (sortKey === this.lastAppliedSortKey && filterKey === this.lastAppliedFilterKey) {
|
|
2910
3290
|
return; // No effective change; avoid redundant refresh
|
|
2911
3291
|
}
|
|
3292
|
+
// Determine if filters changed (for pagination reset)
|
|
3293
|
+
const filtersChanged = filterKey !== this.lastAppliedFilterKey;
|
|
2912
3294
|
this.lastAppliedSortKey = sortKey;
|
|
2913
3295
|
this.lastAppliedFilterKey = filterKey;
|
|
2914
3296
|
this.dataSource.clearFilter();
|
|
@@ -2919,7 +3301,7 @@ class AXPEntityMasterListViewModel {
|
|
|
2919
3301
|
operator: null,
|
|
2920
3302
|
filters: filters,
|
|
2921
3303
|
}));
|
|
2922
|
-
this.events$.next({ action: 'refresh' });
|
|
3304
|
+
this.events$.next({ action: 'refresh', meta: { resetPagination: filtersChanged } });
|
|
2923
3305
|
}
|
|
2924
3306
|
resetColumns() {
|
|
2925
3307
|
this.applyViewColumns();
|
|
@@ -4630,7 +5012,9 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4630
5012
|
};
|
|
4631
5013
|
return await context.expressionEvaluator.evaluate(actionData, scope);
|
|
4632
5014
|
};
|
|
4633
|
-
|
|
5015
|
+
// Don't evaluate actions here - keep expression strings for lazy evaluation at execution time
|
|
5016
|
+
// This ensures actions use the latest context data when executed
|
|
5017
|
+
const actions = relatedEntity?.actions ?? [];
|
|
4634
5018
|
const filters = await Promise.all(relatedEntity.conditions?.map(async (c) => {
|
|
4635
5019
|
const value = await evaluateExpressions(c.value);
|
|
4636
5020
|
return {
|
|
@@ -4645,7 +5029,7 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4645
5029
|
title: `${context.rootTitle}`,
|
|
4646
5030
|
label: relatedEntity.title,
|
|
4647
5031
|
icon: relatedEntity.icon || entityDef.icon,
|
|
4648
|
-
actions: this.mergeActions(entityDef,
|
|
5032
|
+
actions: this.mergeActions(entityDef, actions)
|
|
4649
5033
|
?.filter((a) => a.priority === 'primary')
|
|
4650
5034
|
?.map((a) => {
|
|
4651
5035
|
return {
|
|
@@ -4669,7 +5053,7 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4669
5053
|
execute: async (command, executeContext) => {
|
|
4670
5054
|
try {
|
|
4671
5055
|
const commandName = command.name.split('&')[0];
|
|
4672
|
-
const mergedActions = this.mergeActions(entityDef,
|
|
5056
|
+
const mergedActions = this.mergeActions(entityDef, actions);
|
|
4673
5057
|
const action = mergedActions.find((a) => {
|
|
4674
5058
|
return a.name === commandName || a.name.split('&')[0] === commandName;
|
|
4675
5059
|
});
|
|
@@ -4683,6 +5067,28 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4683
5067
|
},
|
|
4684
5068
|
};
|
|
4685
5069
|
}
|
|
5070
|
+
// Evaluate action options with current root context for lazy evaluation
|
|
5071
|
+
// This ensures actions use the latest context data when executed
|
|
5072
|
+
let evaluatedOptions = action.options;
|
|
5073
|
+
if (action.options && context.context && context.expressionEvaluator) {
|
|
5074
|
+
try {
|
|
5075
|
+
const scope = {
|
|
5076
|
+
context: {
|
|
5077
|
+
eval: (path) => {
|
|
5078
|
+
return get(context.context, path);
|
|
5079
|
+
},
|
|
5080
|
+
},
|
|
5081
|
+
};
|
|
5082
|
+
evaluatedOptions = await context.expressionEvaluator.evaluate(action.options, scope);
|
|
5083
|
+
}
|
|
5084
|
+
catch {
|
|
5085
|
+
// Keep original options if evaluation fails
|
|
5086
|
+
evaluatedOptions = action.options;
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
5089
|
+
const actionData = action.scope == AXPEntityCommandScope.Selected
|
|
5090
|
+
? executeContext
|
|
5091
|
+
: evaluatedOptions?.['process']?.data || null;
|
|
4686
5092
|
if (context.commandService.exists(commandName)) {
|
|
4687
5093
|
// check options for evaluation
|
|
4688
5094
|
await context.commandService.execute(commandName, {
|
|
@@ -4695,13 +5101,11 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4695
5101
|
parentKey: entityDef.parentKey,
|
|
4696
5102
|
source: `${entityDef.module}.${entityDef.name}`,
|
|
4697
5103
|
},
|
|
4698
|
-
data:
|
|
4699
|
-
|
|
4700
|
-
: action.options?.['process']?.data || null,
|
|
4701
|
-
options: action.options,
|
|
5104
|
+
data: actionData,
|
|
5105
|
+
options: evaluatedOptions,
|
|
4702
5106
|
metadata: action.metadata,
|
|
4703
5107
|
},
|
|
4704
|
-
options:
|
|
5108
|
+
options: evaluatedOptions,
|
|
4705
5109
|
metadata: action.metadata,
|
|
4706
5110
|
});
|
|
4707
5111
|
}
|
|
@@ -4715,10 +5119,8 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4715
5119
|
parentKey: entityDef.parentKey,
|
|
4716
5120
|
source: `${entityDef.module}.${entityDef.name}`,
|
|
4717
5121
|
},
|
|
4718
|
-
data:
|
|
4719
|
-
|
|
4720
|
-
: action.options?.['process']?.data || null,
|
|
4721
|
-
options: action.options,
|
|
5122
|
+
data: actionData,
|
|
5123
|
+
options: evaluatedOptions,
|
|
4722
5124
|
metadata: action.metadata,
|
|
4723
5125
|
});
|
|
4724
5126
|
}
|
|
@@ -4747,7 +5149,7 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4747
5149
|
options: {
|
|
4748
5150
|
entity: relatedEntity.entity,
|
|
4749
5151
|
showEntityActions: false,
|
|
4750
|
-
actions:
|
|
5152
|
+
actions: actions,
|
|
4751
5153
|
includeColumns: relatedEntity.columns,
|
|
4752
5154
|
},
|
|
4753
5155
|
},
|
|
@@ -4834,7 +5236,9 @@ class AXPTabListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4834
5236
|
hidden: true,
|
|
4835
5237
|
};
|
|
4836
5238
|
}) ?? []);
|
|
4837
|
-
|
|
5239
|
+
// Don't evaluate actions here - keep expression strings for lazy evaluation at execution time
|
|
5240
|
+
// This ensures actions use the latest context data when executed
|
|
5241
|
+
const actions = relatedEntity.actions;
|
|
4838
5242
|
return {
|
|
4839
5243
|
id: entityDef?.name ?? '',
|
|
4840
5244
|
title: relatedEntity.title ?? entityDef?.title ?? '',
|
|
@@ -4854,6 +5258,7 @@ class AXPTabListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4854
5258
|
showToolbar: false,
|
|
4855
5259
|
actions: actions,
|
|
4856
5260
|
maxHeight: '300px',
|
|
5261
|
+
includeColumns: relatedEntity.columns,
|
|
4857
5262
|
},
|
|
4858
5263
|
},
|
|
4859
5264
|
],
|
|
@@ -5989,6 +6394,7 @@ const AXPCrudModifier = {
|
|
|
5989
6394
|
if (!queries?.list) {
|
|
5990
6395
|
queries.list = {
|
|
5991
6396
|
execute: async (e) => {
|
|
6397
|
+
console.log({ e });
|
|
5992
6398
|
return await dataService.query(e);
|
|
5993
6399
|
},
|
|
5994
6400
|
type: AXPEntityQueryType.List,
|
|
@@ -10358,6 +10764,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
10358
10764
|
this.deviceService = inject(AXPDeviceService);
|
|
10359
10765
|
this.commandService = inject(AXPCommandService);
|
|
10360
10766
|
this.eventService = inject(AXPBroadcastEventService);
|
|
10767
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
10361
10768
|
this.isMounted = signal(false, ...(ngDevMode ? [{ debugName: "isMounted" }] : []));
|
|
10362
10769
|
this.entity = signal(null, ...(ngDevMode ? [{ debugName: "entity" }] : []));
|
|
10363
10770
|
this.listNode = signal(null, ...(ngDevMode ? [{ debugName: "listNode" }] : []));
|
|
@@ -10486,7 +10893,32 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
10486
10893
|
c.scope == AXPEntityCommandScope.TypeLevel));
|
|
10487
10894
|
});
|
|
10488
10895
|
const command = commandName.split('&')[0];
|
|
10489
|
-
//
|
|
10896
|
+
// Get current context from contextService for lazy evaluation
|
|
10897
|
+
const currentContext = this.contextService.initial();
|
|
10898
|
+
console.log('currentContext', currentContext);
|
|
10899
|
+
// Evaluate action options with current context if they contain expressions
|
|
10900
|
+
let evaluatedOptions = action?.options;
|
|
10901
|
+
if (action?.options && currentContext) {
|
|
10902
|
+
try {
|
|
10903
|
+
const scope = {
|
|
10904
|
+
context: {
|
|
10905
|
+
eval: (path) => {
|
|
10906
|
+
console.log({ path });
|
|
10907
|
+
return get(currentContext, path);
|
|
10908
|
+
},
|
|
10909
|
+
},
|
|
10910
|
+
};
|
|
10911
|
+
evaluatedOptions = await this.expressionEvaluator.evaluate(action.options, scope);
|
|
10912
|
+
}
|
|
10913
|
+
catch {
|
|
10914
|
+
// Keep original options if evaluation fails
|
|
10915
|
+
evaluatedOptions = action?.options;
|
|
10916
|
+
}
|
|
10917
|
+
}
|
|
10918
|
+
debugger;
|
|
10919
|
+
const actionData = action?.scope == AXPEntityCommandScope.Selected
|
|
10920
|
+
? this.selectedItems()
|
|
10921
|
+
: evaluatedOptions?.['process']?.data || null;
|
|
10490
10922
|
if (this.commandService.exists(command)) {
|
|
10491
10923
|
await this.commandService.execute(command, {
|
|
10492
10924
|
__context__: {
|
|
@@ -10498,10 +10930,8 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
10498
10930
|
parentKey: this.entity()?.parentKey,
|
|
10499
10931
|
source: `${this.entity()?.module}.${this.entity()?.name}`,
|
|
10500
10932
|
},
|
|
10501
|
-
data:
|
|
10502
|
-
|
|
10503
|
-
: action?.options?.['process']?.data || null,
|
|
10504
|
-
options: action?.options,
|
|
10933
|
+
data: actionData,
|
|
10934
|
+
options: evaluatedOptions,
|
|
10505
10935
|
metadata: action?.metadata,
|
|
10506
10936
|
},
|
|
10507
10937
|
});
|
|
@@ -10516,10 +10946,8 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
10516
10946
|
parentKey: this.entity()?.parentKey,
|
|
10517
10947
|
source: `${this.entity()?.module}.${this.entity()?.name}`,
|
|
10518
10948
|
},
|
|
10519
|
-
data:
|
|
10520
|
-
|
|
10521
|
-
: action?.options?.['process']?.data || null,
|
|
10522
|
-
options: action?.options,
|
|
10949
|
+
data: actionData,
|
|
10950
|
+
options: evaluatedOptions,
|
|
10523
10951
|
metadata: action?.metadata,
|
|
10524
10952
|
});
|
|
10525
10953
|
}
|
|
@@ -10957,189 +11385,6 @@ const AXPEntityListWidget = {
|
|
|
10957
11385
|
},
|
|
10958
11386
|
};
|
|
10959
11387
|
|
|
10960
|
-
class AXPLookupFilterWidgetEditComponent extends AXPValueWidgetComponent {
|
|
10961
|
-
constructor() {
|
|
10962
|
-
super(...arguments);
|
|
10963
|
-
//#region ---- Computed Properties ----
|
|
10964
|
-
this.editorPath = `__${this.path}EditorValue`;
|
|
10965
|
-
this.lookupWidgetRenderer = viewChild('widgetRenderer', ...(ngDevMode ? [{ debugName: "lookupWidgetRenderer" }] : []));
|
|
10966
|
-
this.entity = computed(() => this.options()['entity'], ...(ngDevMode ? [{ debugName: "entity" }] : []));
|
|
10967
|
-
this.textField = computed(() => this.options()['textField'] ?? 'title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
|
|
10968
|
-
this.valueField = computed(() => this.options()['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
|
|
10969
|
-
// protected expose = computed<string | undefined | any[]>(() => this.options()['expose'] as string);
|
|
10970
|
-
this.customFilter = computed(() => this.options()['filter'], ...(ngDevMode ? [{ debugName: "customFilter" }] : []));
|
|
10971
|
-
this.multiple = computed(() => (this.options()['multiple'] ?? false), ...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
10972
|
-
//#endregion
|
|
10973
|
-
//#region ---- Lookup Node ----
|
|
10974
|
-
this.lookupNode = signal({
|
|
10975
|
-
type: 'lookup-editor',
|
|
10976
|
-
path: this.path,
|
|
10977
|
-
options: {},
|
|
10978
|
-
}, ...(ngDevMode ? [{ debugName: "lookupNode" }] : []));
|
|
10979
|
-
//#endregion
|
|
10980
|
-
//#region ---- Effects ----
|
|
10981
|
-
this.#efUpdateLookupNode = effect(() => {
|
|
10982
|
-
// console.log('path:', this.path, this.expose());
|
|
10983
|
-
const node = {
|
|
10984
|
-
type: 'lookup-editor',
|
|
10985
|
-
defaultValue: this.getValue()?.value,
|
|
10986
|
-
path: this.editorPath,
|
|
10987
|
-
options: {
|
|
10988
|
-
entity: this.entity(),
|
|
10989
|
-
expose: [
|
|
10990
|
-
{
|
|
10991
|
-
source: this.textField(),
|
|
10992
|
-
target: this.multiple() ? `${this.path}EditorObj.{title}` : `${this.path}EditorObj.title`,
|
|
10993
|
-
},
|
|
10994
|
-
{
|
|
10995
|
-
source: this.valueField(),
|
|
10996
|
-
target: this.multiple() ? `${this.path}EditorObj.{id}` : `${this.path}EditorObj.id`,
|
|
10997
|
-
},
|
|
10998
|
-
],
|
|
10999
|
-
look: 'select',
|
|
11000
|
-
multiple: this.multiple(),
|
|
11001
|
-
textField: this.textField(),
|
|
11002
|
-
filter: this.customFilter(),
|
|
11003
|
-
allowClear: false,
|
|
11004
|
-
},
|
|
11005
|
-
};
|
|
11006
|
-
this.lookupNode.set(node);
|
|
11007
|
-
}, ...(ngDevMode ? [{ debugName: "#efUpdateLookupNode" }] : []));
|
|
11008
|
-
this.#efUpdateValue = effect(() => {
|
|
11009
|
-
const newValueObj = this.contextService.getValue(`${this.path}EditorObj`);
|
|
11010
|
-
const newValueId = untracked(() => this.contextService.getValue(this.editorPath));
|
|
11011
|
-
const prevValue = untracked(() => this.getValue()?.value);
|
|
11012
|
-
const newValue = this.multiple()
|
|
11013
|
-
? newValueObj?.map((v) => v[this.valueField()])
|
|
11014
|
-
: newValueObj?.[this.valueField()];
|
|
11015
|
-
const valueIsChanged = !isEqual(prevValue, newValue);
|
|
11016
|
-
if (!valueIsChanged) {
|
|
11017
|
-
return;
|
|
11018
|
-
}
|
|
11019
|
-
if (!newValueId || newValueId?.length == 0) {
|
|
11020
|
-
this.setValue({
|
|
11021
|
-
value: undefined,
|
|
11022
|
-
operation: {
|
|
11023
|
-
type: this.multiple() ? 'in' : 'equal',
|
|
11024
|
-
},
|
|
11025
|
-
});
|
|
11026
|
-
}
|
|
11027
|
-
const value = this.multiple()
|
|
11028
|
-
? newValueObj.map((v) => v[this.valueField()])
|
|
11029
|
-
: newValueObj?.[this.valueField()];
|
|
11030
|
-
const displayText = this.multiple()
|
|
11031
|
-
? newValueObj.map((v) => v[this.textField()]).join(',')
|
|
11032
|
-
: newValueObj?.[this.textField()];
|
|
11033
|
-
this.setValue({
|
|
11034
|
-
value: value,
|
|
11035
|
-
operation: {
|
|
11036
|
-
type: this.multiple() ? 'in' : 'equal',
|
|
11037
|
-
},
|
|
11038
|
-
displayText: displayText,
|
|
11039
|
-
});
|
|
11040
|
-
}, ...(ngDevMode ? [{ debugName: "#efUpdateValue" }] : []));
|
|
11041
|
-
//#endregion
|
|
11042
|
-
//#region ---- Focus Management ----
|
|
11043
|
-
this.shouldFocus = signal(false, ...(ngDevMode ? [{ debugName: "shouldFocus" }] : []));
|
|
11044
|
-
/**
|
|
11045
|
-
* Reactive effect to auto-focus the lookup editor when component is ready
|
|
11046
|
-
*/
|
|
11047
|
-
this.#focusEffect = effect(() => {
|
|
11048
|
-
const renderer = this.lookupWidgetRenderer();
|
|
11049
|
-
const shouldFocus = this.shouldFocus();
|
|
11050
|
-
// Early return if no renderer or shouldn't focus
|
|
11051
|
-
if (!renderer || !shouldFocus) {
|
|
11052
|
-
return;
|
|
11053
|
-
}
|
|
11054
|
-
// Listen to componentRefSignal reactively
|
|
11055
|
-
const componentRef = renderer.componentRefSignal();
|
|
11056
|
-
// When componentRef is set (not null), focus the widget
|
|
11057
|
-
if (componentRef) {
|
|
11058
|
-
const componentInstance = componentRef.instance;
|
|
11059
|
-
// Try to use the component's native focus method
|
|
11060
|
-
if (componentInstance && typeof componentInstance.focus === 'function') {
|
|
11061
|
-
try {
|
|
11062
|
-
componentInstance.focus();
|
|
11063
|
-
// Reset focus flag after successful focus
|
|
11064
|
-
this.shouldFocus.set(false);
|
|
11065
|
-
}
|
|
11066
|
-
catch (error) {
|
|
11067
|
-
// console.error('Error focusing lookup widget component:', error);
|
|
11068
|
-
}
|
|
11069
|
-
}
|
|
11070
|
-
}
|
|
11071
|
-
}, ...(ngDevMode ? [{ debugName: "#focusEffect" }] : []));
|
|
11072
|
-
}
|
|
11073
|
-
//#endregion
|
|
11074
|
-
//#region ---- Effects ----
|
|
11075
|
-
#efUpdateLookupNode;
|
|
11076
|
-
#efUpdateValue;
|
|
11077
|
-
/**
|
|
11078
|
-
* Reactive effect to auto-focus the lookup editor when component is ready
|
|
11079
|
-
*/
|
|
11080
|
-
#focusEffect;
|
|
11081
|
-
/**
|
|
11082
|
-
* Public focus method to trigger focusing
|
|
11083
|
-
*/
|
|
11084
|
-
focus() {
|
|
11085
|
-
this.shouldFocus.set(true);
|
|
11086
|
-
}
|
|
11087
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupFilterWidgetEditComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
11088
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.16", type: AXPLookupFilterWidgetEditComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "lookupWidgetRenderer", first: true, predicate: ["widgetRenderer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
11089
|
-
<ng-container
|
|
11090
|
-
axp-widget-renderer
|
|
11091
|
-
#widgetRenderer="widgetRenderer"
|
|
11092
|
-
[node]="lookupNode()"
|
|
11093
|
-
[mode]="'edit'"
|
|
11094
|
-
></ng-container>
|
|
11095
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
11096
|
-
}
|
|
11097
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupFilterWidgetEditComponent, decorators: [{
|
|
11098
|
-
type: Component,
|
|
11099
|
-
args: [{
|
|
11100
|
-
template: `
|
|
11101
|
-
<ng-container
|
|
11102
|
-
axp-widget-renderer
|
|
11103
|
-
#widgetRenderer="widgetRenderer"
|
|
11104
|
-
[node]="lookupNode()"
|
|
11105
|
-
[mode]="'edit'"
|
|
11106
|
-
></ng-container>
|
|
11107
|
-
`,
|
|
11108
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
11109
|
-
imports: [
|
|
11110
|
-
FormsModule,
|
|
11111
|
-
AXSelectBoxModule,
|
|
11112
|
-
AXTextBoxModule,
|
|
11113
|
-
AXButtonModule,
|
|
11114
|
-
AXDecoratorModule,
|
|
11115
|
-
AXLoadingModule,
|
|
11116
|
-
AXValidationModule,
|
|
11117
|
-
AXFormModule,
|
|
11118
|
-
AXPWidgetCoreModule,
|
|
11119
|
-
],
|
|
11120
|
-
}]
|
|
11121
|
-
}], propDecorators: { lookupWidgetRenderer: [{ type: i0.ViewChild, args: ['widgetRenderer', { isSignal: true }] }] } });
|
|
11122
|
-
|
|
11123
|
-
var lookupFilterWidgetEdit_component = /*#__PURE__*/Object.freeze({
|
|
11124
|
-
__proto__: null,
|
|
11125
|
-
AXPLookupFilterWidgetEditComponent: AXPLookupFilterWidgetEditComponent
|
|
11126
|
-
});
|
|
11127
|
-
|
|
11128
|
-
const AXPLookupFilterWidget = {
|
|
11129
|
-
name: 'lookup-filter',
|
|
11130
|
-
title: 'Lookup Filter',
|
|
11131
|
-
// categories: AXP_WIDGETS_FILTER_CATEGORY,
|
|
11132
|
-
type: 'filter',
|
|
11133
|
-
groups: [AXPWidgetGroupEnum.EntityWidget],
|
|
11134
|
-
icon: 'fa-light fa-square',
|
|
11135
|
-
properties: [AXP_NAME_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DISABLED_PROPERTY],
|
|
11136
|
-
components: {
|
|
11137
|
-
edit: {
|
|
11138
|
-
component: () => Promise.resolve().then(function () { return lookupFilterWidgetEdit_component; }).then((c) => c.AXPLookupFilterWidgetEditComponent),
|
|
11139
|
-
},
|
|
11140
|
-
},
|
|
11141
|
-
};
|
|
11142
|
-
|
|
11143
11388
|
class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
|
|
11144
11389
|
constructor() {
|
|
11145
11390
|
super(...arguments);
|
|
@@ -11853,7 +12098,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
11853
12098
|
this.multiple = input.required(...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
11854
12099
|
this.isLoading = input.required(...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
11855
12100
|
this.validationRules = input.required(...(ngDevMode ? [{ debugName: "validationRules" }] : []));
|
|
11856
|
-
this.
|
|
12101
|
+
this.hasClearButton = input(false, ...(ngDevMode ? [{ debugName: "hasClearButton" }] : []));
|
|
11857
12102
|
// Entity and configuration data (for showSelector and searchByValue)
|
|
11858
12103
|
this.entityDef = input.required(...(ngDevMode ? [{ debugName: "entityDef" }] : []));
|
|
11859
12104
|
this.customFilter = input.required(...(ngDevMode ? [{ debugName: "customFilter" }] : []));
|
|
@@ -11902,7 +12147,6 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
11902
12147
|
this.multipleValue = computed(() => this.multiple()(), ...(ngDevMode ? [{ debugName: "multipleValue" }] : []));
|
|
11903
12148
|
this.isLoadingValue = computed(() => this.isLoading()(), ...(ngDevMode ? [{ debugName: "isLoadingValue" }] : []));
|
|
11904
12149
|
this.validationRulesValue = computed(() => this.validationRules()(), ...(ngDevMode ? [{ debugName: "validationRulesValue" }] : []));
|
|
11905
|
-
this.allowClearValue = computed(() => this.allowClear()(), ...(ngDevMode ? [{ debugName: "allowClearValue" }] : []));
|
|
11906
12150
|
}
|
|
11907
12151
|
#focusEffect;
|
|
11908
12152
|
focus() {
|
|
@@ -12055,7 +12299,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
12055
12299
|
refresh() {
|
|
12056
12300
|
}
|
|
12057
12301
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupWidgetTagboxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
12058
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AXPLookupWidgetTagboxComponent, isStandalone: true, selector: "axp-lookup-widget-tagbox", inputs: { selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: true, transformFunction: null }, displayField: { classPropertyName: "displayField", publicName: "displayField", isSignal: true, isRequired: true, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: true, transformFunction: null }, displayFormat: { classPropertyName: "displayFormat", publicName: "displayFormat", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: true, transformFunction: null }, validationRules: { classPropertyName: "validationRules", publicName: "validationRules", isSignal: true, isRequired: true, transformFunction: null },
|
|
12302
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AXPLookupWidgetTagboxComponent, isStandalone: true, selector: "axp-lookup-widget-tagbox", inputs: { selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: true, transformFunction: null }, displayField: { classPropertyName: "displayField", publicName: "displayField", isSignal: true, isRequired: true, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: true, transformFunction: null }, displayFormat: { classPropertyName: "displayFormat", publicName: "displayFormat", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: true, transformFunction: null }, validationRules: { classPropertyName: "validationRules", publicName: "validationRules", isSignal: true, isRequired: true, transformFunction: null }, hasClearButton: { classPropertyName: "hasClearButton", publicName: "hasClearButton", isSignal: true, isRequired: false, transformFunction: null }, entityDef: { classPropertyName: "entityDef", publicName: "entityDef", isSignal: true, isRequired: true, transformFunction: null }, customFilter: { classPropertyName: "customFilter", publicName: "customFilter", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, parentFilters: { classPropertyName: "parentFilters", publicName: "parentFilters", isSignal: true, isRequired: false, transformFunction: null }, onSetLoading: { classPropertyName: "onSetLoading", publicName: "onSetLoading", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { valueChanged: "valueChanged" }, providers: [
|
|
12059
12303
|
{
|
|
12060
12304
|
provide: LookupWidgetLookBase,
|
|
12061
12305
|
useExisting: AXPLookupWidgetTagboxComponent,
|
|
@@ -12082,7 +12326,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
12082
12326
|
[options]="validation.options"
|
|
12083
12327
|
></ax-validation-rule>
|
|
12084
12328
|
}
|
|
12085
|
-
@if (selectedItemsValue().length > 1 ||
|
|
12329
|
+
@if (selectedItemsValue().length > 1 || hasClearButton()) {
|
|
12086
12330
|
<ax-clear-button ></ax-clear-button>
|
|
12087
12331
|
}
|
|
12088
12332
|
|
|
@@ -12137,7 +12381,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
12137
12381
|
[options]="validation.options"
|
|
12138
12382
|
></ax-validation-rule>
|
|
12139
12383
|
}
|
|
12140
|
-
@if (selectedItemsValue().length > 1 ||
|
|
12384
|
+
@if (selectedItemsValue().length > 1 || hasClearButton()) {
|
|
12141
12385
|
<ax-clear-button ></ax-clear-button>
|
|
12142
12386
|
}
|
|
12143
12387
|
|
|
@@ -12184,7 +12428,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
12184
12428
|
}
|
|
12185
12429
|
],
|
|
12186
12430
|
}]
|
|
12187
|
-
}], propDecorators: { selectedItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItems", required: true }] }], displayField: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayField", required: true }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: true }] }], displayFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayFormat", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: true }] }], validationRules: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationRules", required: true }] }],
|
|
12431
|
+
}], propDecorators: { selectedItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItems", required: true }] }], displayField: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayField", required: true }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: true }] }], displayFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayFormat", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: true }] }], validationRules: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationRules", required: true }] }], hasClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasClearButton", required: false }] }], entityDef: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityDef", required: true }] }], customFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "customFilter", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], parentFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentFilters", required: false }] }], onSetLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "onSetLoading", required: true }] }], valueChanged: [{ type: i0.Output, args: ["valueChanged"] }], tagBox: [{ type: i0.ViewChild, args: ['tagBoxComponent', { isSignal: true }] }] } });
|
|
12188
12432
|
|
|
12189
12433
|
class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
12190
12434
|
constructor() {
|
|
@@ -12201,21 +12445,16 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12201
12445
|
//#region ---- Computed Properties ----
|
|
12202
12446
|
this.expose = computed(() => this.options()['expose'], ...(ngDevMode ? [{ debugName: "expose" }] : []));
|
|
12203
12447
|
this.entity = computed(() => this.options()['entity'], ...(ngDevMode ? [{ debugName: "entity" }] : []));
|
|
12204
|
-
this.disabled = computed(() => this.options()['disabled'], ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
12448
|
+
this.disabled = computed(() => this.filterMode() ? false : this.options()['disabled'], ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
12205
12449
|
this.columns = computed(() => this.options()['columns'] ?? [], ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
12206
12450
|
this.textField = computed(() => this.options()['textField'] ?? '', ...(ngDevMode ? [{ debugName: "textField" }] : []));
|
|
12207
12451
|
this.hasClearButton = computed(() => this.options()['hasClearButton'] ?? false, ...(ngDevMode ? [{ debugName: "hasClearButton" }] : []));
|
|
12208
12452
|
this.customFilter = computed(() => this.options()['filter'], ...(ngDevMode ? [{ debugName: "customFilter" }] : []));
|
|
12453
|
+
this.filterMode = computed(() => this.options()['filterMode'], ...(ngDevMode ? [{ debugName: "filterMode" }] : []));
|
|
12209
12454
|
this.multiple = computed(() => (this.options()['multiple'] ?? false), ...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
12210
12455
|
this.look = computed(() => this.options()['look'] ?? 'lookup', ...(ngDevMode ? [{ debugName: "look" }] : []));
|
|
12211
|
-
this.allowClear = computed(() => (this.options()['allowClear'] ?? false), ...(ngDevMode ? [{ debugName: "allowClear" }] : []));
|
|
12212
12456
|
this.defaultTextField = computed(() => {
|
|
12213
|
-
const list = [
|
|
12214
|
-
'title',
|
|
12215
|
-
'name',
|
|
12216
|
-
'code',
|
|
12217
|
-
'description',
|
|
12218
|
-
];
|
|
12457
|
+
const list = ['title', 'name', 'code', 'description'];
|
|
12219
12458
|
const textField = list.find((c) => this.entityDef()?.properties.find((p) => p.name == c)) ?? 'title';
|
|
12220
12459
|
return textField;
|
|
12221
12460
|
}, ...(ngDevMode ? [{ debugName: "defaultTextField" }] : []));
|
|
@@ -12240,9 +12479,6 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12240
12479
|
const [module, entity] = this.entity().split('.');
|
|
12241
12480
|
this.entityDef.set(await this.entityResolver.resolve(module, entity));
|
|
12242
12481
|
}, ...(ngDevMode ? [{ debugName: "#efEntity" }] : []));
|
|
12243
|
-
this.#efFilter = effect(async () => {
|
|
12244
|
-
console.log('filter:', this.customFilter());
|
|
12245
|
-
}, ...(ngDevMode ? [{ debugName: "#efFilter" }] : []));
|
|
12246
12482
|
this.hasValue = (value) => (Array.isArray(value) && !isEmpty(value)) || !isNil(value);
|
|
12247
12483
|
this.#efValue = effect(() => {
|
|
12248
12484
|
const currentValue = this.getValue();
|
|
@@ -12277,7 +12513,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12277
12513
|
// Ensure items is always an array
|
|
12278
12514
|
items = castArray(items);
|
|
12279
12515
|
// Filter out null/undefined items
|
|
12280
|
-
items = items.filter(item => item != null);
|
|
12516
|
+
items = items.filter((item) => item != null);
|
|
12281
12517
|
this.selectedItems.set(items);
|
|
12282
12518
|
//
|
|
12283
12519
|
const keys = items.map((item) => get(item, this.valueField()));
|
|
@@ -12288,17 +12524,29 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12288
12524
|
this.expoesItems();
|
|
12289
12525
|
}
|
|
12290
12526
|
const newValue = this.singleOrMultiple(keys);
|
|
12291
|
-
this.
|
|
12527
|
+
if (this.filterMode()) {
|
|
12528
|
+
this.setValue({
|
|
12529
|
+
value: newValue,
|
|
12530
|
+
displayText: text,
|
|
12531
|
+
operation: {
|
|
12532
|
+
type: this.multiple() ? 'in' : 'equal',
|
|
12533
|
+
},
|
|
12534
|
+
});
|
|
12535
|
+
}
|
|
12536
|
+
else {
|
|
12537
|
+
this.setValue(newValue);
|
|
12538
|
+
}
|
|
12292
12539
|
};
|
|
12293
12540
|
}
|
|
12294
12541
|
#efEntity;
|
|
12295
|
-
#efFilter;
|
|
12296
12542
|
#efValue;
|
|
12297
12543
|
async findByValue() {
|
|
12298
12544
|
this.isLoading.set(true);
|
|
12299
12545
|
const rawValue = this.getValue();
|
|
12300
12546
|
// When multiple is true, ensure we always work with arrays
|
|
12301
|
-
const values = this.multiple()
|
|
12547
|
+
const values = this.multiple()
|
|
12548
|
+
? castArray(this.filterMode() ? rawValue.value : rawValue)
|
|
12549
|
+
: [rawValue].filter((v) => v != null);
|
|
12302
12550
|
if (!values.length) {
|
|
12303
12551
|
this.setItems([]);
|
|
12304
12552
|
this.isLoading.set(false);
|
|
@@ -12311,14 +12559,14 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12311
12559
|
if (this.multiple()) {
|
|
12312
12560
|
const items = await Promise.all(values
|
|
12313
12561
|
.map((value) => extractValue(value, this.valueField()))
|
|
12314
|
-
.filter(id => id != null)
|
|
12562
|
+
.filter((id) => id != null)
|
|
12315
12563
|
.map((id) => entityDataAccessor.byKey(id)));
|
|
12316
12564
|
// Filter out null/undefined results
|
|
12317
|
-
const validItems = items.filter(item => item != null);
|
|
12565
|
+
const validItems = items.filter((item) => item != null);
|
|
12318
12566
|
this.setItems(validItems);
|
|
12319
12567
|
}
|
|
12320
12568
|
else {
|
|
12321
|
-
const id = extractValue(values[0], this.valueField());
|
|
12569
|
+
const id = extractValue(this.filterMode() ? values[0].value : values[0], this.valueField());
|
|
12322
12570
|
if (id != null) {
|
|
12323
12571
|
const item = await entityDataAccessor.byKey(id);
|
|
12324
12572
|
this.setItems(item != null ? [item] : []);
|
|
@@ -12445,7 +12693,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12445
12693
|
[multiple]="multiple"
|
|
12446
12694
|
[isLoading]="isLoading"
|
|
12447
12695
|
[validationRules]="validationRules"
|
|
12448
|
-
[
|
|
12696
|
+
[hasClearButton]="hasClearButton()"
|
|
12449
12697
|
[entityDef]="entityDef"
|
|
12450
12698
|
[customFilter]="customFilter"
|
|
12451
12699
|
[columns]="columns"
|
|
@@ -12456,7 +12704,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12456
12704
|
}
|
|
12457
12705
|
}
|
|
12458
12706
|
}
|
|
12459
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXPLookupWidgetSelectComponent, selector: "axp-lookup-widget-select", inputs: ["entityDef", "customFilter", "selectedItems", "displayField", "valueField", "disabled", "multiple", "validationRules", "hasClearButton"], outputs: ["valueChanged"] }, { kind: "component", type: AXPLookupWidgetTagboxComponent, selector: "axp-lookup-widget-tagbox", inputs: ["selectedItems", "displayField", "valueField", "displayFormat", "disabled", "multiple", "isLoading", "validationRules", "
|
|
12707
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXPLookupWidgetSelectComponent, selector: "axp-lookup-widget-select", inputs: ["entityDef", "customFilter", "selectedItems", "displayField", "valueField", "disabled", "multiple", "validationRules", "hasClearButton"], outputs: ["valueChanged"] }, { kind: "component", type: AXPLookupWidgetTagboxComponent, selector: "axp-lookup-widget-tagbox", inputs: ["selectedItems", "displayField", "valueField", "displayFormat", "disabled", "multiple", "isLoading", "validationRules", "hasClearButton", "entityDef", "customFilter", "columns", "parentFilters", "onSetLoading"], outputs: ["valueChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
12460
12708
|
}
|
|
12461
12709
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupWidgetEditComponent, decorators: [{
|
|
12462
12710
|
type: Component,
|
|
@@ -12489,7 +12737,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
12489
12737
|
[multiple]="multiple"
|
|
12490
12738
|
[isLoading]="isLoading"
|
|
12491
12739
|
[validationRules]="validationRules"
|
|
12492
|
-
[
|
|
12740
|
+
[hasClearButton]="hasClearButton()"
|
|
12493
12741
|
[entityDef]="entityDef"
|
|
12494
12742
|
[customFilter]="customFilter"
|
|
12495
12743
|
[columns]="columns"
|
|
@@ -12502,11 +12750,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
12502
12750
|
}
|
|
12503
12751
|
`,
|
|
12504
12752
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
12505
|
-
imports: [
|
|
12506
|
-
CommonModule,
|
|
12507
|
-
AXPLookupWidgetSelectComponent,
|
|
12508
|
-
AXPLookupWidgetTagboxComponent,
|
|
12509
|
-
],
|
|
12753
|
+
imports: [CommonModule, AXPLookupWidgetSelectComponent, AXPLookupWidgetTagboxComponent],
|
|
12510
12754
|
}]
|
|
12511
12755
|
}], propDecorators: { componentLook: [{ type: i0.ViewChild, args: [i0.forwardRef(() => LookupWidgetLookBase), { isSignal: true }] }] } });
|
|
12512
12756
|
|
|
@@ -12632,7 +12876,7 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
12632
12876
|
return get(item, this.displayField()) ?? '';
|
|
12633
12877
|
}
|
|
12634
12878
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupWidgetColumnComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
12635
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AXPLookupWidgetColumnComponent, isStandalone: true, selector: "ng-component", inputs: { rawValue: "rawValue", rowData: "rowData" }, viewQueries: [{ propertyName: "moreButton", first: true, predicate: ["moreButton"], descendants: true, isSignal: true }, { propertyName: "morePopover", first: true, predicate: ["morePopover"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-flex ax-gap-1 ax-items-center\">\n @if (visibleItems().length > 0) {\n @for (item of visibleItems(); track $index) {\n <span class=\"ax-cursor-pointer hover:ax-text-primary hover:ax-underline\" (click)=\"handleItemClick($index)\">\n {{ getDisplayText(item) }}\n </span>\n @if ($index < visibleItems().length - 1) { <span class=\"ax-text-muted\">\u2022</span>\n }\n }\n } @else {\n <span class=\"ax-text-muted\">---</span>\n }\n\n @if (hasMoreItems()) {\n <span\n class=\"ax-absolute ax-flex ax-items-center ax-end-0 ax-px-1 ax-cursor-pointer ax-h-full hover:ax-primary-lighter\"\n (click)=\"showMoreItems()\" #moreButton>\n <i class=\"fa-light fa-ellipsis-vertical\"></i>\n </span>\n }\n</div>\n\n<!-- More Items Popover -->\n<ax-popover [openOn]=\"'manual'\" #morePopover (openChange)=\"onMorePopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface ax-border ax-rounded-lg ax-shadow-lg ax-p-4 ax-min-w-[280px]\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold\">All {{ allItems().length }} Items</h3>\n </div>\n <div class=\"ax-max-h-64 ax-flex ax-flex-col ax-gap-3\">\n @for (item of allItems(); track $index) {\n <span class=\"ax-cursor-pointer hover:ax-text-primary hover:ax-underline\" (click)=\"showItemDetail(item, $index)\">\n {{ getDisplayText(item) }}\n </span>\n }\n </div>\n </div>\n</ax-popover>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
12879
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AXPLookupWidgetColumnComponent, isStandalone: true, selector: "ng-component", inputs: { rawValue: "rawValue", rowData: "rowData" }, viewQueries: [{ propertyName: "moreButton", first: true, predicate: ["moreButton"], descendants: true, isSignal: true }, { propertyName: "morePopover", first: true, predicate: ["morePopover"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-flex ax-gap-1 ax-items-center\">\n @if (visibleItems().length > 0) {\n @for (item of visibleItems(); track $index) {\n <span class=\"ax-cursor-pointer hover:ax-text-primary hover:ax-underline\" (click)=\"handleItemClick($index)\">\n {{ getDisplayText(item) }}\n </span>\n @if ($index < visibleItems().length - 1) { <span class=\"ax-text-muted\">\u2022</span>\n }\n }\n } @else {\n <span class=\"ax-text-muted\">---</span>\n }\n\n @if (hasMoreItems()) {\n <span\n class=\"ax-absolute ax-flex ax-items-center ax-end-0 ax-px-1 ax-cursor-pointer ax-h-full hover:ax-primary-lighter\"\n (click)=\"showMoreItems()\" #moreButton>\n <i class=\"fa-light fa-ellipsis-vertical\"></i>\n </span>\n }\n</div>\n\n<!-- More Items Popover -->\n<ax-popover [openOn]=\"'manual'\" #morePopover (openChange)=\"onMorePopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface ax-border ax-rounded-lg ax-shadow-lg ax-p-4 ax-min-w-[280px]\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold\">All {{ allItems().length }} Items</h3>\n </div>\n <div class=\"ax-max-h-64 ax-flex ax-flex-col ax-gap-3\">\n @for (item of allItems(); track $index) {\n <span class=\"ax-cursor-pointer hover:ax-text-primary hover:ax-underline\" (click)=\"showItemDetail(item, $index)\">\n {{ getDisplayText(item) }}\n </span>\n }\n </div>\n </div>\n</ax-popover>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "repositionOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
12636
12880
|
}
|
|
12637
12881
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupWidgetColumnComponent, decorators: [{
|
|
12638
12882
|
type: Component,
|
|
@@ -14461,6 +14705,12 @@ class AXPEntityModule {
|
|
|
14461
14705
|
useValue: defaultColumnWidthProvider,
|
|
14462
14706
|
multi: true,
|
|
14463
14707
|
},
|
|
14708
|
+
// Entities list data source (all entity names from registry)
|
|
14709
|
+
{
|
|
14710
|
+
provide: AXP_DATASOURCE_DEFINITION_PROVIDER,
|
|
14711
|
+
useClass: AXPEntitiesListDataSourceDefinition,
|
|
14712
|
+
multi: true,
|
|
14713
|
+
},
|
|
14464
14714
|
// {
|
|
14465
14715
|
// provide: AXP_ENTITY_MODIFIER,
|
|
14466
14716
|
// useValue: layoutOrderingMiddlewareProvider,
|
|
@@ -14519,12 +14769,23 @@ class AXPEntityModule {
|
|
|
14519
14769
|
functions: {},
|
|
14520
14770
|
}),
|
|
14521
14771
|
AXPWidgetCoreModule.forChild({
|
|
14522
|
-
widgets: [
|
|
14523
|
-
|
|
14524
|
-
|
|
14525
|
-
|
|
14526
|
-
|
|
14527
|
-
|
|
14772
|
+
widgets: [AXPLookupWidget, AXPEntityListWidget, AXPEntityCategoryWidget, AXPMultiSourceSelectorWidget],
|
|
14773
|
+
extendedWidgets: [
|
|
14774
|
+
{
|
|
14775
|
+
parentName: AXPLookupWidget.name,
|
|
14776
|
+
widget: {
|
|
14777
|
+
name: 'lookup-filter',
|
|
14778
|
+
title: 'Lookup Filter',
|
|
14779
|
+
categories: AXP_WIDGETS_EDITOR_CATEGORY,
|
|
14780
|
+
groups: [AXPWidgetGroupEnum.EntityWidget],
|
|
14781
|
+
type: 'filter',
|
|
14782
|
+
components: {},
|
|
14783
|
+
options: {
|
|
14784
|
+
look: 'select',
|
|
14785
|
+
filterMode: true,
|
|
14786
|
+
},
|
|
14787
|
+
},
|
|
14788
|
+
},
|
|
14528
14789
|
],
|
|
14529
14790
|
})] }); }
|
|
14530
14791
|
}
|
|
@@ -14561,12 +14822,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
14561
14822
|
functions: {},
|
|
14562
14823
|
}),
|
|
14563
14824
|
AXPWidgetCoreModule.forChild({
|
|
14564
|
-
widgets: [
|
|
14565
|
-
|
|
14566
|
-
|
|
14567
|
-
|
|
14568
|
-
|
|
14569
|
-
|
|
14825
|
+
widgets: [AXPLookupWidget, AXPEntityListWidget, AXPEntityCategoryWidget, AXPMultiSourceSelectorWidget],
|
|
14826
|
+
extendedWidgets: [
|
|
14827
|
+
{
|
|
14828
|
+
parentName: AXPLookupWidget.name,
|
|
14829
|
+
widget: {
|
|
14830
|
+
name: 'lookup-filter',
|
|
14831
|
+
title: 'Lookup Filter',
|
|
14832
|
+
categories: AXP_WIDGETS_EDITOR_CATEGORY,
|
|
14833
|
+
groups: [AXPWidgetGroupEnum.EntityWidget],
|
|
14834
|
+
type: 'filter',
|
|
14835
|
+
components: {},
|
|
14836
|
+
options: {
|
|
14837
|
+
look: 'select',
|
|
14838
|
+
filterMode: true,
|
|
14839
|
+
},
|
|
14840
|
+
},
|
|
14841
|
+
},
|
|
14570
14842
|
],
|
|
14571
14843
|
}),
|
|
14572
14844
|
],
|
|
@@ -14606,6 +14878,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
14606
14878
|
useValue: defaultColumnWidthProvider,
|
|
14607
14879
|
multi: true,
|
|
14608
14880
|
},
|
|
14881
|
+
// Entities list data source (all entity names from registry)
|
|
14882
|
+
{
|
|
14883
|
+
provide: AXP_DATASOURCE_DEFINITION_PROVIDER,
|
|
14884
|
+
useClass: AXPEntitiesListDataSourceDefinition,
|
|
14885
|
+
multi: true,
|
|
14886
|
+
},
|
|
14609
14887
|
// {
|
|
14610
14888
|
// provide: AXP_ENTITY_MODIFIER,
|
|
14611
14889
|
// useValue: layoutOrderingMiddlewareProvider,
|
|
@@ -14723,18 +15001,22 @@ function entityMasterCreateAction() {
|
|
|
14723
15001
|
title: '@general:actions.create.title',
|
|
14724
15002
|
command: {
|
|
14725
15003
|
name: 'Entity:Create',
|
|
14726
|
-
// options: {
|
|
14727
|
-
// process: {
|
|
14728
|
-
// redirect: true,
|
|
14729
|
-
// canCreateNewOne: true,
|
|
14730
|
-
// },
|
|
14731
|
-
// },
|
|
14732
15004
|
},
|
|
14733
15005
|
priority: 'primary',
|
|
14734
15006
|
type: AXPSystemActionType.Create,
|
|
14735
15007
|
scope: AXPEntityCommandScope.TypeLevel,
|
|
14736
15008
|
};
|
|
14737
15009
|
}
|
|
15010
|
+
function entityMasterEditAction() {
|
|
15011
|
+
return {
|
|
15012
|
+
title: '@general:actions.edit.title',
|
|
15013
|
+
command: 'Entity:Update',
|
|
15014
|
+
priority: 'secondary',
|
|
15015
|
+
type: AXPSystemActionType.Update,
|
|
15016
|
+
scope: AXPEntityCommandScope.Individual,
|
|
15017
|
+
default: true,
|
|
15018
|
+
};
|
|
15019
|
+
}
|
|
14738
15020
|
function entityMasterBulkDeleteAction() {
|
|
14739
15021
|
return {
|
|
14740
15022
|
title: '@general:actions.delete-items.title',
|
|
@@ -14784,10 +15066,9 @@ function entityMasterCrudActions(options) {
|
|
|
14784
15066
|
if (opts.view) {
|
|
14785
15067
|
actions.push(entityMasterViewAction());
|
|
14786
15068
|
}
|
|
14787
|
-
|
|
14788
|
-
|
|
14789
|
-
|
|
14790
|
-
// }
|
|
15069
|
+
if (opts.edit) {
|
|
15070
|
+
actions.push(entityMasterEditAction());
|
|
15071
|
+
}
|
|
14791
15072
|
return actions;
|
|
14792
15073
|
}
|
|
14793
15074
|
function entityMasterRecordActions() {
|
|
@@ -14806,6 +15087,7 @@ function entityDetailsCreateActions(parentId) {
|
|
|
14806
15087
|
canCreateNewOne: true,
|
|
14807
15088
|
data: {
|
|
14808
15089
|
[parentId]: '{{context.eval("id")}}',
|
|
15090
|
+
notes: '{{context.eval("displayName")}}',
|
|
14809
15091
|
},
|
|
14810
15092
|
},
|
|
14811
15093
|
},
|
|
@@ -14953,5 +15235,5 @@ function detectEntityChanges(oldObj, newObj) {
|
|
|
14953
15235
|
* Generated bundle index. Do not edit.
|
|
14954
15236
|
*/
|
|
14955
15237
|
|
|
14956
|
-
export { AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityCommand, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorService, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityEventDispatcherService, AXPEntityEventsKeys, AXPEntityFormBuilderService, AXPEntityListTableService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPGetEntityDetailsQuery,
|
|
15238
|
+
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, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityEventDispatcherService, AXPEntityEventsKeys, AXPEntityFormBuilderService, AXPEntityListTableService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPGetEntityDetailsQuery, AXPLookupWidget, AXPLookupWidgetColumnComponent, AXPLookupWidgetEditComponent, AXPLookupWidgetViewComponent, AXPMiddlewareAbortError, AXPMiddlewareEntityStorageService, AXPModifyEntitySectionWorkflow, AXPMultiSourceDefinitionProviderContext, AXPMultiSourceDefinitionProviderService, AXPMultiSourceFederatedSearchService, AXPMultiSourceSelectorComponent, AXPMultiSourceSelectorService, AXPMultiSourceSelectorWidget, AXPMultiSourceSelectorWidgetColumnComponent, AXPMultiSourceSelectorWidgetEditComponent, AXPMultiSourceSelectorWidgetViewComponent, AXPMultiSourceType, AXPOpenEntityDetailsCommand, AXPQuickEntityModifyPopupAction, AXPQuickModifyEntityWorkflow, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPTruncatedBreadcrumbComponent, AXPUpdateEntityCommand, AXPViewEntityDetailsCommand, 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_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, EntityBuilder, EntityDataAccessor, actionExists, cloneLayoutArrays, columnWidthMiddleware, columnWidthMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, detectEntityChanges, ensureLayoutPropertyView, ensureLayoutSection, ensureListActions, entityDetailsCreateActions, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, isAXPMiddlewareAbortError, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider };
|
|
14957
15239
|
//# sourceMappingURL=acorex-platform-layout-entity.mjs.map
|