@acorex/platform 20.7.5 → 20.7.7
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 +576 -317
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +2 -2
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +10 -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 +680 -149
- 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 +40 -40
- package/layout/widget-core/index.d.ts +11 -2
- package/layout/widgets/index.d.ts +135 -8
- package/package.json +5 -5
- 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();
|
|
@@ -4854,6 +5236,7 @@ class AXPTabListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4854
5236
|
showToolbar: false,
|
|
4855
5237
|
actions: actions,
|
|
4856
5238
|
maxHeight: '300px',
|
|
5239
|
+
includeColumns: relatedEntity.columns,
|
|
4857
5240
|
},
|
|
4858
5241
|
},
|
|
4859
5242
|
],
|
|
@@ -5989,6 +6372,7 @@ const AXPCrudModifier = {
|
|
|
5989
6372
|
if (!queries?.list) {
|
|
5990
6373
|
queries.list = {
|
|
5991
6374
|
execute: async (e) => {
|
|
6375
|
+
console.log({ e });
|
|
5992
6376
|
return await dataService.query(e);
|
|
5993
6377
|
},
|
|
5994
6378
|
type: AXPEntityQueryType.List,
|
|
@@ -6501,24 +6885,46 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6501
6885
|
if (this.treeData.categoryEntityDef?.parentKey) {
|
|
6502
6886
|
this.treeConfig.parentKey = this.treeData.categoryEntityDef.parentKey;
|
|
6503
6887
|
}
|
|
6504
|
-
//
|
|
6505
|
-
//
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6888
|
+
// CRITICAL FIX: Parse initial selected values and set selectedNodeIds BEFORE tree renders.
|
|
6889
|
+
// This allows the datasource callback to mark nodes as selected when they load.
|
|
6890
|
+
// Previously, we tried to sync selection while loading was true, but the tree
|
|
6891
|
+
// component doesn't exist until loading is false, causing sync methods to fail silently.
|
|
6892
|
+
const initialSelectedIds = this.selectedValues().filter((id) => id && id !== 'all');
|
|
6893
|
+
if (initialSelectedIds.length > 0) {
|
|
6894
|
+
// Load missing node data into cache first (needed for path calculation and node display)
|
|
6895
|
+
await this.loadMissingNodeData(initialSelectedIds);
|
|
6896
|
+
// Set selectedNodeIds so datasource callback can use it to mark nodes as selected
|
|
6897
|
+
this.selectedNodeIds.set(initialSelectedIds);
|
|
6513
6898
|
}
|
|
6514
6899
|
}
|
|
6515
6900
|
catch (error) {
|
|
6516
6901
|
console.error('Error loading entity definition:', error);
|
|
6517
6902
|
}
|
|
6518
6903
|
finally {
|
|
6904
|
+
// Now let tree render by setting loading to false
|
|
6519
6905
|
this.loading.set(false);
|
|
6520
|
-
this.isInitializing = false; // Mark initialization as complete
|
|
6521
6906
|
}
|
|
6907
|
+
// AFTER tree renders, perform selection sync operations.
|
|
6908
|
+
// This must happen after loading.set(false) so the tree component exists in DOM.
|
|
6909
|
+
const selectedIds = this.selectedNodeIds();
|
|
6910
|
+
if (selectedIds.length > 0) {
|
|
6911
|
+
try {
|
|
6912
|
+
// Wait for tree to render and stabilize
|
|
6913
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
6914
|
+
// Build ancestor chains for path expansion (so selected nodes become visible)
|
|
6915
|
+
const ancestorChains = await this.buildAncestorChains(selectedIds);
|
|
6916
|
+
// Expand ancestor nodes to make selected nodes visible in tree
|
|
6917
|
+
await this.expandAncestorNodesInOrder(ancestorChains);
|
|
6918
|
+
// Wait for tree to process expansions
|
|
6919
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
6920
|
+
// Final sync to ensure all nodes are properly selected in tree component
|
|
6921
|
+
await this.syncSelectionWithTree(selectedIds);
|
|
6922
|
+
}
|
|
6923
|
+
catch (error) {
|
|
6924
|
+
console.error('Error syncing selection after tree render:', error);
|
|
6925
|
+
}
|
|
6926
|
+
}
|
|
6927
|
+
this.isInitializing = false; // Mark initialization as complete
|
|
6522
6928
|
}
|
|
6523
6929
|
//#endregion
|
|
6524
6930
|
//#region ---- Public Methods ----
|
|
@@ -9318,7 +9724,7 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
9318
9724
|
textField: signal(this.textField()),
|
|
9319
9725
|
valueField: signal(this.valueField()),
|
|
9320
9726
|
allowMultiple: signal(this.multiple()),
|
|
9321
|
-
|
|
9727
|
+
selectedValues: signal(selectedIds),
|
|
9322
9728
|
searchPlaceholder: signal(this.searchPlaceholderText()),
|
|
9323
9729
|
excludedNodeId: signal(excludedNodeId),
|
|
9324
9730
|
},
|
|
@@ -10935,189 +11341,6 @@ const AXPEntityListWidget = {
|
|
|
10935
11341
|
},
|
|
10936
11342
|
};
|
|
10937
11343
|
|
|
10938
|
-
class AXPLookupFilterWidgetEditComponent extends AXPValueWidgetComponent {
|
|
10939
|
-
constructor() {
|
|
10940
|
-
super(...arguments);
|
|
10941
|
-
//#region ---- Computed Properties ----
|
|
10942
|
-
this.editorPath = `__${this.path}EditorValue`;
|
|
10943
|
-
this.lookupWidgetRenderer = viewChild('widgetRenderer', ...(ngDevMode ? [{ debugName: "lookupWidgetRenderer" }] : []));
|
|
10944
|
-
this.entity = computed(() => this.options()['entity'], ...(ngDevMode ? [{ debugName: "entity" }] : []));
|
|
10945
|
-
this.textField = computed(() => this.options()['textField'] ?? 'title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
|
|
10946
|
-
this.valueField = computed(() => this.options()['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
|
|
10947
|
-
// protected expose = computed<string | undefined | any[]>(() => this.options()['expose'] as string);
|
|
10948
|
-
this.customFilter = computed(() => this.options()['filter'], ...(ngDevMode ? [{ debugName: "customFilter" }] : []));
|
|
10949
|
-
this.multiple = computed(() => (this.options()['multiple'] ?? false), ...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
10950
|
-
//#endregion
|
|
10951
|
-
//#region ---- Lookup Node ----
|
|
10952
|
-
this.lookupNode = signal({
|
|
10953
|
-
type: 'lookup-editor',
|
|
10954
|
-
path: this.path,
|
|
10955
|
-
options: {},
|
|
10956
|
-
}, ...(ngDevMode ? [{ debugName: "lookupNode" }] : []));
|
|
10957
|
-
//#endregion
|
|
10958
|
-
//#region ---- Effects ----
|
|
10959
|
-
this.#efUpdateLookupNode = effect(() => {
|
|
10960
|
-
// console.log('path:', this.path, this.expose());
|
|
10961
|
-
const node = {
|
|
10962
|
-
type: 'lookup-editor',
|
|
10963
|
-
defaultValue: this.getValue()?.value,
|
|
10964
|
-
path: this.editorPath,
|
|
10965
|
-
options: {
|
|
10966
|
-
entity: this.entity(),
|
|
10967
|
-
expose: [
|
|
10968
|
-
{
|
|
10969
|
-
source: this.textField(),
|
|
10970
|
-
target: this.multiple() ? `${this.path}EditorObj.{title}` : `${this.path}EditorObj.title`,
|
|
10971
|
-
},
|
|
10972
|
-
{
|
|
10973
|
-
source: this.valueField(),
|
|
10974
|
-
target: this.multiple() ? `${this.path}EditorObj.{id}` : `${this.path}EditorObj.id`,
|
|
10975
|
-
},
|
|
10976
|
-
],
|
|
10977
|
-
look: 'select',
|
|
10978
|
-
multiple: this.multiple(),
|
|
10979
|
-
textField: this.textField(),
|
|
10980
|
-
filter: this.customFilter(),
|
|
10981
|
-
allowClear: false,
|
|
10982
|
-
},
|
|
10983
|
-
};
|
|
10984
|
-
this.lookupNode.set(node);
|
|
10985
|
-
}, ...(ngDevMode ? [{ debugName: "#efUpdateLookupNode" }] : []));
|
|
10986
|
-
this.#efUpdateValue = effect(() => {
|
|
10987
|
-
const newValueObj = this.contextService.getValue(`${this.path}EditorObj`);
|
|
10988
|
-
const newValueId = untracked(() => this.contextService.getValue(this.editorPath));
|
|
10989
|
-
const prevValue = untracked(() => this.getValue()?.value);
|
|
10990
|
-
const newValue = this.multiple()
|
|
10991
|
-
? newValueObj?.map((v) => v[this.valueField()])
|
|
10992
|
-
: newValueObj?.[this.valueField()];
|
|
10993
|
-
const valueIsChanged = !isEqual(prevValue, newValue);
|
|
10994
|
-
if (!valueIsChanged) {
|
|
10995
|
-
return;
|
|
10996
|
-
}
|
|
10997
|
-
if (!newValueId || newValueId?.length == 0) {
|
|
10998
|
-
this.setValue({
|
|
10999
|
-
value: undefined,
|
|
11000
|
-
operation: {
|
|
11001
|
-
type: this.multiple() ? 'in' : 'equal',
|
|
11002
|
-
},
|
|
11003
|
-
});
|
|
11004
|
-
}
|
|
11005
|
-
const value = this.multiple()
|
|
11006
|
-
? newValueObj.map((v) => v[this.valueField()])
|
|
11007
|
-
: newValueObj?.[this.valueField()];
|
|
11008
|
-
const displayText = this.multiple()
|
|
11009
|
-
? newValueObj.map((v) => v[this.textField()]).join(',')
|
|
11010
|
-
: newValueObj?.[this.textField()];
|
|
11011
|
-
this.setValue({
|
|
11012
|
-
value: value,
|
|
11013
|
-
operation: {
|
|
11014
|
-
type: this.multiple() ? 'in' : 'equal',
|
|
11015
|
-
},
|
|
11016
|
-
displayText: displayText,
|
|
11017
|
-
});
|
|
11018
|
-
}, ...(ngDevMode ? [{ debugName: "#efUpdateValue" }] : []));
|
|
11019
|
-
//#endregion
|
|
11020
|
-
//#region ---- Focus Management ----
|
|
11021
|
-
this.shouldFocus = signal(false, ...(ngDevMode ? [{ debugName: "shouldFocus" }] : []));
|
|
11022
|
-
/**
|
|
11023
|
-
* Reactive effect to auto-focus the lookup editor when component is ready
|
|
11024
|
-
*/
|
|
11025
|
-
this.#focusEffect = effect(() => {
|
|
11026
|
-
const renderer = this.lookupWidgetRenderer();
|
|
11027
|
-
const shouldFocus = this.shouldFocus();
|
|
11028
|
-
// Early return if no renderer or shouldn't focus
|
|
11029
|
-
if (!renderer || !shouldFocus) {
|
|
11030
|
-
return;
|
|
11031
|
-
}
|
|
11032
|
-
// Listen to componentRefSignal reactively
|
|
11033
|
-
const componentRef = renderer.componentRefSignal();
|
|
11034
|
-
// When componentRef is set (not null), focus the widget
|
|
11035
|
-
if (componentRef) {
|
|
11036
|
-
const componentInstance = componentRef.instance;
|
|
11037
|
-
// Try to use the component's native focus method
|
|
11038
|
-
if (componentInstance && typeof componentInstance.focus === 'function') {
|
|
11039
|
-
try {
|
|
11040
|
-
componentInstance.focus();
|
|
11041
|
-
// Reset focus flag after successful focus
|
|
11042
|
-
this.shouldFocus.set(false);
|
|
11043
|
-
}
|
|
11044
|
-
catch (error) {
|
|
11045
|
-
// console.error('Error focusing lookup widget component:', error);
|
|
11046
|
-
}
|
|
11047
|
-
}
|
|
11048
|
-
}
|
|
11049
|
-
}, ...(ngDevMode ? [{ debugName: "#focusEffect" }] : []));
|
|
11050
|
-
}
|
|
11051
|
-
//#endregion
|
|
11052
|
-
//#region ---- Effects ----
|
|
11053
|
-
#efUpdateLookupNode;
|
|
11054
|
-
#efUpdateValue;
|
|
11055
|
-
/**
|
|
11056
|
-
* Reactive effect to auto-focus the lookup editor when component is ready
|
|
11057
|
-
*/
|
|
11058
|
-
#focusEffect;
|
|
11059
|
-
/**
|
|
11060
|
-
* Public focus method to trigger focusing
|
|
11061
|
-
*/
|
|
11062
|
-
focus() {
|
|
11063
|
-
this.shouldFocus.set(true);
|
|
11064
|
-
}
|
|
11065
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupFilterWidgetEditComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
11066
|
-
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: `
|
|
11067
|
-
<ng-container
|
|
11068
|
-
axp-widget-renderer
|
|
11069
|
-
#widgetRenderer="widgetRenderer"
|
|
11070
|
-
[node]="lookupNode()"
|
|
11071
|
-
[mode]="'edit'"
|
|
11072
|
-
></ng-container>
|
|
11073
|
-
`, 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 }); }
|
|
11074
|
-
}
|
|
11075
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupFilterWidgetEditComponent, decorators: [{
|
|
11076
|
-
type: Component,
|
|
11077
|
-
args: [{
|
|
11078
|
-
template: `
|
|
11079
|
-
<ng-container
|
|
11080
|
-
axp-widget-renderer
|
|
11081
|
-
#widgetRenderer="widgetRenderer"
|
|
11082
|
-
[node]="lookupNode()"
|
|
11083
|
-
[mode]="'edit'"
|
|
11084
|
-
></ng-container>
|
|
11085
|
-
`,
|
|
11086
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
11087
|
-
imports: [
|
|
11088
|
-
FormsModule,
|
|
11089
|
-
AXSelectBoxModule,
|
|
11090
|
-
AXTextBoxModule,
|
|
11091
|
-
AXButtonModule,
|
|
11092
|
-
AXDecoratorModule,
|
|
11093
|
-
AXLoadingModule,
|
|
11094
|
-
AXValidationModule,
|
|
11095
|
-
AXFormModule,
|
|
11096
|
-
AXPWidgetCoreModule,
|
|
11097
|
-
],
|
|
11098
|
-
}]
|
|
11099
|
-
}], propDecorators: { lookupWidgetRenderer: [{ type: i0.ViewChild, args: ['widgetRenderer', { isSignal: true }] }] } });
|
|
11100
|
-
|
|
11101
|
-
var lookupFilterWidgetEdit_component = /*#__PURE__*/Object.freeze({
|
|
11102
|
-
__proto__: null,
|
|
11103
|
-
AXPLookupFilterWidgetEditComponent: AXPLookupFilterWidgetEditComponent
|
|
11104
|
-
});
|
|
11105
|
-
|
|
11106
|
-
const AXPLookupFilterWidget = {
|
|
11107
|
-
name: 'lookup-filter',
|
|
11108
|
-
title: 'Lookup Filter',
|
|
11109
|
-
// categories: AXP_WIDGETS_FILTER_CATEGORY,
|
|
11110
|
-
type: 'filter',
|
|
11111
|
-
groups: [AXPWidgetGroupEnum.EntityWidget],
|
|
11112
|
-
icon: 'fa-light fa-square',
|
|
11113
|
-
properties: [AXP_NAME_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DISABLED_PROPERTY],
|
|
11114
|
-
components: {
|
|
11115
|
-
edit: {
|
|
11116
|
-
component: () => Promise.resolve().then(function () { return lookupFilterWidgetEdit_component; }).then((c) => c.AXPLookupFilterWidgetEditComponent),
|
|
11117
|
-
},
|
|
11118
|
-
},
|
|
11119
|
-
};
|
|
11120
|
-
|
|
11121
11344
|
class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
|
|
11122
11345
|
constructor() {
|
|
11123
11346
|
super(...arguments);
|
|
@@ -11831,7 +12054,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
11831
12054
|
this.multiple = input.required(...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
11832
12055
|
this.isLoading = input.required(...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
11833
12056
|
this.validationRules = input.required(...(ngDevMode ? [{ debugName: "validationRules" }] : []));
|
|
11834
|
-
this.
|
|
12057
|
+
this.hasClearButton = input(false, ...(ngDevMode ? [{ debugName: "hasClearButton" }] : []));
|
|
11835
12058
|
// Entity and configuration data (for showSelector and searchByValue)
|
|
11836
12059
|
this.entityDef = input.required(...(ngDevMode ? [{ debugName: "entityDef" }] : []));
|
|
11837
12060
|
this.customFilter = input.required(...(ngDevMode ? [{ debugName: "customFilter" }] : []));
|
|
@@ -11880,7 +12103,6 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
11880
12103
|
this.multipleValue = computed(() => this.multiple()(), ...(ngDevMode ? [{ debugName: "multipleValue" }] : []));
|
|
11881
12104
|
this.isLoadingValue = computed(() => this.isLoading()(), ...(ngDevMode ? [{ debugName: "isLoadingValue" }] : []));
|
|
11882
12105
|
this.validationRulesValue = computed(() => this.validationRules()(), ...(ngDevMode ? [{ debugName: "validationRulesValue" }] : []));
|
|
11883
|
-
this.allowClearValue = computed(() => this.allowClear()(), ...(ngDevMode ? [{ debugName: "allowClearValue" }] : []));
|
|
11884
12106
|
}
|
|
11885
12107
|
#focusEffect;
|
|
11886
12108
|
focus() {
|
|
@@ -12033,7 +12255,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
12033
12255
|
refresh() {
|
|
12034
12256
|
}
|
|
12035
12257
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupWidgetTagboxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
12036
|
-
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 },
|
|
12258
|
+
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: [
|
|
12037
12259
|
{
|
|
12038
12260
|
provide: LookupWidgetLookBase,
|
|
12039
12261
|
useExisting: AXPLookupWidgetTagboxComponent,
|
|
@@ -12060,7 +12282,7 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
|
|
|
12060
12282
|
[options]="validation.options"
|
|
12061
12283
|
></ax-validation-rule>
|
|
12062
12284
|
}
|
|
12063
|
-
@if (selectedItemsValue().length > 1 ||
|
|
12285
|
+
@if (selectedItemsValue().length > 1 || hasClearButton()) {
|
|
12064
12286
|
<ax-clear-button ></ax-clear-button>
|
|
12065
12287
|
}
|
|
12066
12288
|
|
|
@@ -12115,7 +12337,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
12115
12337
|
[options]="validation.options"
|
|
12116
12338
|
></ax-validation-rule>
|
|
12117
12339
|
}
|
|
12118
|
-
@if (selectedItemsValue().length > 1 ||
|
|
12340
|
+
@if (selectedItemsValue().length > 1 || hasClearButton()) {
|
|
12119
12341
|
<ax-clear-button ></ax-clear-button>
|
|
12120
12342
|
}
|
|
12121
12343
|
|
|
@@ -12162,7 +12384,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
12162
12384
|
}
|
|
12163
12385
|
],
|
|
12164
12386
|
}]
|
|
12165
|
-
}], 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 }] }],
|
|
12387
|
+
}], 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 }] }] } });
|
|
12166
12388
|
|
|
12167
12389
|
class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
12168
12390
|
constructor() {
|
|
@@ -12184,16 +12406,11 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12184
12406
|
this.textField = computed(() => this.options()['textField'] ?? '', ...(ngDevMode ? [{ debugName: "textField" }] : []));
|
|
12185
12407
|
this.hasClearButton = computed(() => this.options()['hasClearButton'] ?? false, ...(ngDevMode ? [{ debugName: "hasClearButton" }] : []));
|
|
12186
12408
|
this.customFilter = computed(() => this.options()['filter'], ...(ngDevMode ? [{ debugName: "customFilter" }] : []));
|
|
12409
|
+
this.filterMode = computed(() => this.options()['filterMode'], ...(ngDevMode ? [{ debugName: "filterMode" }] : []));
|
|
12187
12410
|
this.multiple = computed(() => (this.options()['multiple'] ?? false), ...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
12188
12411
|
this.look = computed(() => this.options()['look'] ?? 'lookup', ...(ngDevMode ? [{ debugName: "look" }] : []));
|
|
12189
|
-
this.allowClear = computed(() => (this.options()['allowClear'] ?? false), ...(ngDevMode ? [{ debugName: "allowClear" }] : []));
|
|
12190
12412
|
this.defaultTextField = computed(() => {
|
|
12191
|
-
const list = [
|
|
12192
|
-
'title',
|
|
12193
|
-
'name',
|
|
12194
|
-
'code',
|
|
12195
|
-
'description',
|
|
12196
|
-
];
|
|
12413
|
+
const list = ['title', 'name', 'code', 'description'];
|
|
12197
12414
|
const textField = list.find((c) => this.entityDef()?.properties.find((p) => p.name == c)) ?? 'title';
|
|
12198
12415
|
return textField;
|
|
12199
12416
|
}, ...(ngDevMode ? [{ debugName: "defaultTextField" }] : []));
|
|
@@ -12218,9 +12435,6 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12218
12435
|
const [module, entity] = this.entity().split('.');
|
|
12219
12436
|
this.entityDef.set(await this.entityResolver.resolve(module, entity));
|
|
12220
12437
|
}, ...(ngDevMode ? [{ debugName: "#efEntity" }] : []));
|
|
12221
|
-
this.#efFilter = effect(async () => {
|
|
12222
|
-
console.log('filter:', this.customFilter());
|
|
12223
|
-
}, ...(ngDevMode ? [{ debugName: "#efFilter" }] : []));
|
|
12224
12438
|
this.hasValue = (value) => (Array.isArray(value) && !isEmpty(value)) || !isNil(value);
|
|
12225
12439
|
this.#efValue = effect(() => {
|
|
12226
12440
|
const currentValue = this.getValue();
|
|
@@ -12255,7 +12469,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12255
12469
|
// Ensure items is always an array
|
|
12256
12470
|
items = castArray(items);
|
|
12257
12471
|
// Filter out null/undefined items
|
|
12258
|
-
items = items.filter(item => item != null);
|
|
12472
|
+
items = items.filter((item) => item != null);
|
|
12259
12473
|
this.selectedItems.set(items);
|
|
12260
12474
|
//
|
|
12261
12475
|
const keys = items.map((item) => get(item, this.valueField()));
|
|
@@ -12266,17 +12480,29 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12266
12480
|
this.expoesItems();
|
|
12267
12481
|
}
|
|
12268
12482
|
const newValue = this.singleOrMultiple(keys);
|
|
12269
|
-
this.
|
|
12483
|
+
if (this.filterMode()) {
|
|
12484
|
+
this.setValue({
|
|
12485
|
+
value: newValue,
|
|
12486
|
+
displayText: text,
|
|
12487
|
+
operation: {
|
|
12488
|
+
type: this.multiple() ? 'in' : 'contains',
|
|
12489
|
+
},
|
|
12490
|
+
});
|
|
12491
|
+
}
|
|
12492
|
+
else {
|
|
12493
|
+
this.setValue(newValue);
|
|
12494
|
+
}
|
|
12270
12495
|
};
|
|
12271
12496
|
}
|
|
12272
12497
|
#efEntity;
|
|
12273
|
-
#efFilter;
|
|
12274
12498
|
#efValue;
|
|
12275
12499
|
async findByValue() {
|
|
12276
12500
|
this.isLoading.set(true);
|
|
12277
12501
|
const rawValue = this.getValue();
|
|
12278
12502
|
// When multiple is true, ensure we always work with arrays
|
|
12279
|
-
const values = this.multiple()
|
|
12503
|
+
const values = this.multiple()
|
|
12504
|
+
? castArray(this.filterMode() ? rawValue.value : rawValue)
|
|
12505
|
+
: [rawValue].filter((v) => v != null);
|
|
12280
12506
|
if (!values.length) {
|
|
12281
12507
|
this.setItems([]);
|
|
12282
12508
|
this.isLoading.set(false);
|
|
@@ -12289,14 +12515,14 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12289
12515
|
if (this.multiple()) {
|
|
12290
12516
|
const items = await Promise.all(values
|
|
12291
12517
|
.map((value) => extractValue(value, this.valueField()))
|
|
12292
|
-
.filter(id => id != null)
|
|
12518
|
+
.filter((id) => id != null)
|
|
12293
12519
|
.map((id) => entityDataAccessor.byKey(id)));
|
|
12294
12520
|
// Filter out null/undefined results
|
|
12295
|
-
const validItems = items.filter(item => item != null);
|
|
12521
|
+
const validItems = items.filter((item) => item != null);
|
|
12296
12522
|
this.setItems(validItems);
|
|
12297
12523
|
}
|
|
12298
12524
|
else {
|
|
12299
|
-
const id = extractValue(values[0], this.valueField());
|
|
12525
|
+
const id = extractValue(this.filterMode() ? values[0].value : values[0], this.valueField());
|
|
12300
12526
|
if (id != null) {
|
|
12301
12527
|
const item = await entityDataAccessor.byKey(id);
|
|
12302
12528
|
this.setItems(item != null ? [item] : []);
|
|
@@ -12423,7 +12649,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12423
12649
|
[multiple]="multiple"
|
|
12424
12650
|
[isLoading]="isLoading"
|
|
12425
12651
|
[validationRules]="validationRules"
|
|
12426
|
-
[
|
|
12652
|
+
[hasClearButton]="hasClearButton()"
|
|
12427
12653
|
[entityDef]="entityDef"
|
|
12428
12654
|
[customFilter]="customFilter"
|
|
12429
12655
|
[columns]="columns"
|
|
@@ -12434,7 +12660,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
12434
12660
|
}
|
|
12435
12661
|
}
|
|
12436
12662
|
}
|
|
12437
|
-
`, 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", "
|
|
12663
|
+
`, 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 }); }
|
|
12438
12664
|
}
|
|
12439
12665
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupWidgetEditComponent, decorators: [{
|
|
12440
12666
|
type: Component,
|
|
@@ -12467,7 +12693,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
12467
12693
|
[multiple]="multiple"
|
|
12468
12694
|
[isLoading]="isLoading"
|
|
12469
12695
|
[validationRules]="validationRules"
|
|
12470
|
-
[
|
|
12696
|
+
[hasClearButton]="hasClearButton()"
|
|
12471
12697
|
[entityDef]="entityDef"
|
|
12472
12698
|
[customFilter]="customFilter"
|
|
12473
12699
|
[columns]="columns"
|
|
@@ -12480,11 +12706,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
12480
12706
|
}
|
|
12481
12707
|
`,
|
|
12482
12708
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
12483
|
-
imports: [
|
|
12484
|
-
CommonModule,
|
|
12485
|
-
AXPLookupWidgetSelectComponent,
|
|
12486
|
-
AXPLookupWidgetTagboxComponent,
|
|
12487
|
-
],
|
|
12709
|
+
imports: [CommonModule, AXPLookupWidgetSelectComponent, AXPLookupWidgetTagboxComponent],
|
|
12488
12710
|
}]
|
|
12489
12711
|
}], propDecorators: { componentLook: [{ type: i0.ViewChild, args: [i0.forwardRef(() => LookupWidgetLookBase), { isSignal: true }] }] } });
|
|
12490
12712
|
|
|
@@ -12610,7 +12832,7 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
12610
12832
|
return get(item, this.displayField()) ?? '';
|
|
12611
12833
|
}
|
|
12612
12834
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupWidgetColumnComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
12613
|
-
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 }); }
|
|
12835
|
+
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 }); }
|
|
12614
12836
|
}
|
|
12615
12837
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPLookupWidgetColumnComponent, decorators: [{
|
|
12616
12838
|
type: Component,
|
|
@@ -14439,6 +14661,12 @@ class AXPEntityModule {
|
|
|
14439
14661
|
useValue: defaultColumnWidthProvider,
|
|
14440
14662
|
multi: true,
|
|
14441
14663
|
},
|
|
14664
|
+
// Entities list data source (all entity names from registry)
|
|
14665
|
+
{
|
|
14666
|
+
provide: AXP_DATASOURCE_DEFINITION_PROVIDER,
|
|
14667
|
+
useClass: AXPEntitiesListDataSourceDefinition,
|
|
14668
|
+
multi: true,
|
|
14669
|
+
},
|
|
14442
14670
|
// {
|
|
14443
14671
|
// provide: AXP_ENTITY_MODIFIER,
|
|
14444
14672
|
// useValue: layoutOrderingMiddlewareProvider,
|
|
@@ -14497,12 +14725,23 @@ class AXPEntityModule {
|
|
|
14497
14725
|
functions: {},
|
|
14498
14726
|
}),
|
|
14499
14727
|
AXPWidgetCoreModule.forChild({
|
|
14500
|
-
widgets: [
|
|
14501
|
-
|
|
14502
|
-
|
|
14503
|
-
|
|
14504
|
-
|
|
14505
|
-
|
|
14728
|
+
widgets: [AXPLookupWidget, AXPEntityListWidget, AXPEntityCategoryWidget, AXPMultiSourceSelectorWidget],
|
|
14729
|
+
extendedWidgets: [
|
|
14730
|
+
{
|
|
14731
|
+
parentName: AXPLookupWidget.name,
|
|
14732
|
+
widget: {
|
|
14733
|
+
name: 'lookup-filter',
|
|
14734
|
+
title: 'Lookup Filter',
|
|
14735
|
+
categories: AXP_WIDGETS_EDITOR_CATEGORY,
|
|
14736
|
+
groups: [AXPWidgetGroupEnum.EntityWidget],
|
|
14737
|
+
type: 'filter',
|
|
14738
|
+
components: {},
|
|
14739
|
+
options: {
|
|
14740
|
+
look: 'select',
|
|
14741
|
+
filterMode: true,
|
|
14742
|
+
},
|
|
14743
|
+
},
|
|
14744
|
+
},
|
|
14506
14745
|
],
|
|
14507
14746
|
})] }); }
|
|
14508
14747
|
}
|
|
@@ -14539,12 +14778,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
14539
14778
|
functions: {},
|
|
14540
14779
|
}),
|
|
14541
14780
|
AXPWidgetCoreModule.forChild({
|
|
14542
|
-
widgets: [
|
|
14543
|
-
|
|
14544
|
-
|
|
14545
|
-
|
|
14546
|
-
|
|
14547
|
-
|
|
14781
|
+
widgets: [AXPLookupWidget, AXPEntityListWidget, AXPEntityCategoryWidget, AXPMultiSourceSelectorWidget],
|
|
14782
|
+
extendedWidgets: [
|
|
14783
|
+
{
|
|
14784
|
+
parentName: AXPLookupWidget.name,
|
|
14785
|
+
widget: {
|
|
14786
|
+
name: 'lookup-filter',
|
|
14787
|
+
title: 'Lookup Filter',
|
|
14788
|
+
categories: AXP_WIDGETS_EDITOR_CATEGORY,
|
|
14789
|
+
groups: [AXPWidgetGroupEnum.EntityWidget],
|
|
14790
|
+
type: 'filter',
|
|
14791
|
+
components: {},
|
|
14792
|
+
options: {
|
|
14793
|
+
look: 'select',
|
|
14794
|
+
filterMode: true,
|
|
14795
|
+
},
|
|
14796
|
+
},
|
|
14797
|
+
},
|
|
14548
14798
|
],
|
|
14549
14799
|
}),
|
|
14550
14800
|
],
|
|
@@ -14584,6 +14834,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
14584
14834
|
useValue: defaultColumnWidthProvider,
|
|
14585
14835
|
multi: true,
|
|
14586
14836
|
},
|
|
14837
|
+
// Entities list data source (all entity names from registry)
|
|
14838
|
+
{
|
|
14839
|
+
provide: AXP_DATASOURCE_DEFINITION_PROVIDER,
|
|
14840
|
+
useClass: AXPEntitiesListDataSourceDefinition,
|
|
14841
|
+
multi: true,
|
|
14842
|
+
},
|
|
14587
14843
|
// {
|
|
14588
14844
|
// provide: AXP_ENTITY_MODIFIER,
|
|
14589
14845
|
// useValue: layoutOrderingMiddlewareProvider,
|
|
@@ -14701,18 +14957,22 @@ function entityMasterCreateAction() {
|
|
|
14701
14957
|
title: '@general:actions.create.title',
|
|
14702
14958
|
command: {
|
|
14703
14959
|
name: 'Entity:Create',
|
|
14704
|
-
// options: {
|
|
14705
|
-
// process: {
|
|
14706
|
-
// redirect: true,
|
|
14707
|
-
// canCreateNewOne: true,
|
|
14708
|
-
// },
|
|
14709
|
-
// },
|
|
14710
14960
|
},
|
|
14711
14961
|
priority: 'primary',
|
|
14712
14962
|
type: AXPSystemActionType.Create,
|
|
14713
14963
|
scope: AXPEntityCommandScope.TypeLevel,
|
|
14714
14964
|
};
|
|
14715
14965
|
}
|
|
14966
|
+
function entityMasterEditAction() {
|
|
14967
|
+
return {
|
|
14968
|
+
title: '@general:actions.edit.title',
|
|
14969
|
+
command: 'Entity:Update',
|
|
14970
|
+
priority: 'secondary',
|
|
14971
|
+
type: AXPSystemActionType.Update,
|
|
14972
|
+
scope: AXPEntityCommandScope.Individual,
|
|
14973
|
+
default: true,
|
|
14974
|
+
};
|
|
14975
|
+
}
|
|
14716
14976
|
function entityMasterBulkDeleteAction() {
|
|
14717
14977
|
return {
|
|
14718
14978
|
title: '@general:actions.delete-items.title',
|
|
@@ -14762,10 +15022,9 @@ function entityMasterCrudActions(options) {
|
|
|
14762
15022
|
if (opts.view) {
|
|
14763
15023
|
actions.push(entityMasterViewAction());
|
|
14764
15024
|
}
|
|
14765
|
-
|
|
14766
|
-
|
|
14767
|
-
|
|
14768
|
-
// }
|
|
15025
|
+
if (opts.edit) {
|
|
15026
|
+
actions.push(entityMasterEditAction());
|
|
15027
|
+
}
|
|
14769
15028
|
return actions;
|
|
14770
15029
|
}
|
|
14771
15030
|
function entityMasterRecordActions() {
|
|
@@ -14931,5 +15190,5 @@ function detectEntityChanges(oldObj, newObj) {
|
|
|
14931
15190
|
* Generated bundle index. Do not edit.
|
|
14932
15191
|
*/
|
|
14933
15192
|
|
|
14934
|
-
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,
|
|
15193
|
+
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 };
|
|
14935
15194
|
//# sourceMappingURL=acorex-platform-layout-entity.mjs.map
|