@acorex/platform 20.6.0-next.20 → 20.6.0-next.22
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-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +414 -177
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +4 -2
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widgets.mjs +13 -12
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-CenhnHXi.mjs → acorex-platform-themes-default-entity-master-list-view.component-DBysy2Ky.mjs} +26 -5
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DBysy2Ky.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default.mjs +2 -2
- package/layout/entity/index.d.ts +35 -23
- package/layout/widgets/index.d.ts +2 -1
- package/package.json +13 -13
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-CenhnHXi.mjs.map +0 -1
|
@@ -4,9 +4,9 @@ import { AXTranslationService, AXTranslationModule } from '@acorex/core/translat
|
|
|
4
4
|
import * as i4 from '@acorex/platform/common';
|
|
5
5
|
import { AXPSettingService, AXPFilterOperatorMiddlewareService, AXPEntityCommandScope, getEntityInfo, AXPRefreshEvent, AXPReloadEvent, AXPCommonSettings, AXPCleanNestedFilters, AXPWorkflowNavigateAction, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER } from '@acorex/platform/common';
|
|
6
6
|
import * as i1$2 from '@acorex/platform/core';
|
|
7
|
-
import { AXPDeviceService, AXPBroadcastEventService, resolveActionLook, AXPExpressionEvaluatorService, AXPDistributedEventListenerService, AXPPlatformScope, extractValue, setSmart, getChangedPaths, AXPSystemActionType } from '@acorex/platform/core';
|
|
7
|
+
import { AXPDeviceService, AXPBroadcastEventService, resolveActionLook, AXPExpressionEvaluatorService, AXPDistributedEventListenerService, AXPPlatformScope, AXHighlightService, extractValue, setSmart, getChangedPaths, AXPSystemActionType } from '@acorex/platform/core';
|
|
8
8
|
import * as i0 from '@angular/core';
|
|
9
|
-
import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, input, viewChild, signal, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, computed, afterNextRender, ViewEncapsulation, ChangeDetectorRef,
|
|
9
|
+
import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, input, viewChild, signal, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, computed, effect, Input, afterNextRender, ViewEncapsulation, ChangeDetectorRef, viewChildren, linkedSignal, untracked, HostBinding, ViewChild, NgModule } from '@angular/core';
|
|
10
10
|
import { Subject, takeUntil } from 'rxjs';
|
|
11
11
|
import { AXPLayoutBuilderService } from '@acorex/platform/layout/builder';
|
|
12
12
|
import { merge, castArray, get, cloneDeep, set, orderBy, isNil, isEqual, isEmpty, sortBy } from 'lodash-es';
|
|
@@ -33,6 +33,7 @@ import { AXDialogService } from '@acorex/components/dialog';
|
|
|
33
33
|
import { AXLoadingDialogService } from '@acorex/components/loading-dialog';
|
|
34
34
|
import { AXPopupService } from '@acorex/components/popup';
|
|
35
35
|
import { AXPlatform } from '@acorex/core/platform';
|
|
36
|
+
import { AXCheckBoxModule } from '@acorex/components/check-box';
|
|
36
37
|
import * as i2$1 from '@acorex/components/decorators';
|
|
37
38
|
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
38
39
|
import { AXBasePageComponent } from '@acorex/components/page';
|
|
@@ -41,6 +42,9 @@ import { AXSearchBoxModule, AXSearchBoxComponent } from '@acorex/components/sear
|
|
|
41
42
|
import * as i4$1 from '@acorex/components/skeleton';
|
|
42
43
|
import { AXSkeletonModule } from '@acorex/components/skeleton';
|
|
43
44
|
import { AXTreeViewComponent } from '@acorex/components/tree-view';
|
|
45
|
+
import { AXPStateMessageComponent, AXPDataSelectorService, AXPWidgetPropertyViewerComponent } from '@acorex/platform/layout/components';
|
|
46
|
+
import * as i1$1 from '@angular/forms';
|
|
47
|
+
import { FormsModule } from '@angular/forms';
|
|
44
48
|
import * as i2$2 from '@acorex/components/badge';
|
|
45
49
|
import { AXBadgeModule } from '@acorex/components/badge';
|
|
46
50
|
import * as i5$1 from '@acorex/components/form';
|
|
@@ -49,15 +53,12 @@ import { AXValidationModule } from '@acorex/core/validation';
|
|
|
49
53
|
import { AXP_DISABLED_PROPERTY, AXP_ALLOW_CLEAR_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DATA_PROPERTY_GROUP, AXP_ALLOW_MULTIPLE_PROPERTY, AXP_NAME_PROPERTY, AXPFileUploaderWidgetService } from '@acorex/platform/layout/widgets';
|
|
50
54
|
import * as i4$2 from '@acorex/components/dropdown';
|
|
51
55
|
import { AXDropdownModule } from '@acorex/components/dropdown';
|
|
52
|
-
import * as i1$1 from '@angular/forms';
|
|
53
|
-
import { FormsModule } from '@angular/forms';
|
|
54
56
|
import * as i7 from '@acorex/components/select-box';
|
|
55
57
|
import { AXSelectBoxModule } from '@acorex/components/select-box';
|
|
56
58
|
import * as i2$3 from '@acorex/components/text-box';
|
|
57
59
|
import { AXTextBoxModule, AXTextBoxComponent } from '@acorex/components/text-box';
|
|
58
60
|
import * as i6$1 from '@acorex/components/tag-box';
|
|
59
61
|
import { AXTagBoxComponent, AXTagBoxModule } from '@acorex/components/tag-box';
|
|
60
|
-
import { AXPDataSelectorService, AXPWidgetPropertyViewerComponent } from '@acorex/platform/layout/components';
|
|
61
62
|
import { transform, isEqual as isEqual$1 } from 'lodash';
|
|
62
63
|
|
|
63
64
|
function ensureListActions(ctx) {
|
|
@@ -725,9 +726,11 @@ class PropertyFilter {
|
|
|
725
726
|
const entityProps = (entity.properties ?? []).slice();
|
|
726
727
|
const nameToViewLayout = buildViewLayoutMap(iface.properties ?? []);
|
|
727
728
|
const allowedNames = this.computeAllowedNames(entityProps.map((p) => p.name));
|
|
729
|
+
// Calculate recommended dialog size based on form complexity
|
|
730
|
+
const calculatedSize = this.calculateRecommendedDialogSize(sections, entityProps, nameToViewLayout, allowedNames);
|
|
728
731
|
const dialog = this.layoutBuilder.create().dialog((d) => {
|
|
729
732
|
d.setTitle(title);
|
|
730
|
-
d.setSize(this.externalSize ??
|
|
733
|
+
d.setSize(this.externalSize ?? calculatedSize);
|
|
731
734
|
d.setCloseButton(true);
|
|
732
735
|
d.content((layout) => {
|
|
733
736
|
// Default mode: 'view' for single, 'edit' for create/update
|
|
@@ -759,7 +762,7 @@ class PropertyFilter {
|
|
|
759
762
|
fs.formField(prop.title, (field) => {
|
|
760
763
|
// Path & field-level visibility/readonly
|
|
761
764
|
field.path(fieldPath);
|
|
762
|
-
if (prop.schema?.visible) {
|
|
765
|
+
if (prop.schema?.visible !== undefined) {
|
|
763
766
|
field.visible(prop.schema?.visible);
|
|
764
767
|
}
|
|
765
768
|
if (prop.schema?.readonly !== undefined) {
|
|
@@ -840,6 +843,78 @@ class PropertyFilter {
|
|
|
840
843
|
}
|
|
841
844
|
return new Set(allNames);
|
|
842
845
|
}
|
|
846
|
+
/**
|
|
847
|
+
* Calculates the recommended dialog size based on form complexity.
|
|
848
|
+
* Considers number of sections, properties, and average field width.
|
|
849
|
+
*
|
|
850
|
+
* @param sections - Interface sections to display
|
|
851
|
+
* @param entityProps - All entity properties
|
|
852
|
+
* @param nameToViewLayout - Map of property names to their view layout configurations
|
|
853
|
+
* @param allowedNames - Set of property names that should be displayed (after filtering)
|
|
854
|
+
* @returns Recommended dialog size ('full' | 'lg' | 'md')
|
|
855
|
+
*/
|
|
856
|
+
calculateRecommendedDialogSize(sections, entityProps, nameToViewLayout, allowedNames) {
|
|
857
|
+
// Mobile devices always use full screen
|
|
858
|
+
if (this.deviceService.isMobileDevice()) {
|
|
859
|
+
return 'full';
|
|
860
|
+
}
|
|
861
|
+
// Calculate number of visible properties
|
|
862
|
+
const visibleProperties = entityProps.filter((p) => allowedNames.has(p.name) && nameToViewLayout.has(p.name));
|
|
863
|
+
const visiblePropertyCount = visibleProperties.length;
|
|
864
|
+
// Calculate average colSpan to determine field width
|
|
865
|
+
// colSpan determines how many columns a field occupies in a 12-column grid
|
|
866
|
+
// Examples:
|
|
867
|
+
// - colSpan = 12 → 1 field per row (full width)
|
|
868
|
+
// - colSpan = 6 → 2 fields per row (half width each)
|
|
869
|
+
// - colSpan = 4 → 3 fields per row (one-third width each)
|
|
870
|
+
// - colSpan = 3 → 4 fields per row (one-quarter width each)
|
|
871
|
+
let totalColSpan = 0;
|
|
872
|
+
let propertiesWithLayout = 0;
|
|
873
|
+
let hasColSpan3 = false; // Track if any field has colSpan = 3
|
|
874
|
+
for (const prop of visibleProperties) {
|
|
875
|
+
const viewLayout = nameToViewLayout.get(prop.name);
|
|
876
|
+
const positions = viewLayout?.layout?.positions;
|
|
877
|
+
if (positions) {
|
|
878
|
+
// Get colSpan from the largest available breakpoint
|
|
879
|
+
const colSpan = positions.lg?.colSpan ?? positions.xl?.colSpan ?? positions.md?.colSpan ?? positions.sm?.colSpan ?? 12; // default: full width
|
|
880
|
+
totalColSpan += colSpan;
|
|
881
|
+
propertiesWithLayout++;
|
|
882
|
+
// Check if this field has colSpan = 3
|
|
883
|
+
if (colSpan <= 3) {
|
|
884
|
+
hasColSpan3 = true;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
else {
|
|
888
|
+
// If no layout defined, assume full width (12 columns)
|
|
889
|
+
totalColSpan += 12;
|
|
890
|
+
propertiesWithLayout++;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
// Average colSpan: lower value = more fields per row, higher value = fewer fields per row
|
|
894
|
+
const avgColSpan = propertiesWithLayout > 0 ? totalColSpan / propertiesWithLayout : 12;
|
|
895
|
+
// Decision logic:
|
|
896
|
+
// - 10+ properties → complex form → needs 'lg'
|
|
897
|
+
// - avgColSpan <= 4 → 3+ fields per row → needs 'lg' (more horizontal space needed)
|
|
898
|
+
// - hasColSpan3 && avgColSpan <= 6 → row can sum to 12 with colSpan=3 (e.g., 9+3, 5+4+3, etc.) → needs 'lg'
|
|
899
|
+
// - Otherwise → 'md' is sufficient
|
|
900
|
+
if (visiblePropertyCount >= 10) {
|
|
901
|
+
return 'lg';
|
|
902
|
+
}
|
|
903
|
+
// If average colSpan <= 4, it means we can fit 3+ fields per row (12/4 = 3)
|
|
904
|
+
// This requires more horizontal space, so use 'lg'
|
|
905
|
+
if (avgColSpan <= 4) {
|
|
906
|
+
return 'lg';
|
|
907
|
+
}
|
|
908
|
+
// If there's a field with colSpan = 3 and avgColSpan <= 6,
|
|
909
|
+
// it means rows can sum to 12 with multiple fields including the colSpan=3 field
|
|
910
|
+
// (e.g., 9+3=12, 5+4+3=12, 4+3+3+2=12, etc.)
|
|
911
|
+
// This needs 'lg' for better horizontal space to accommodate the layout
|
|
912
|
+
if (hasColSpan3 && avgColSpan <= 6) {
|
|
913
|
+
return 'lg';
|
|
914
|
+
}
|
|
915
|
+
// For other cases (including full-width fields), 'md' is sufficient
|
|
916
|
+
return 'md';
|
|
917
|
+
}
|
|
843
918
|
}
|
|
844
919
|
//#endregion
|
|
845
920
|
//#region ---- Helpers ----
|
|
@@ -946,6 +1021,7 @@ class AXPCreateEntityCommand {
|
|
|
946
1021
|
}
|
|
947
1022
|
async execute(input) {
|
|
948
1023
|
const excludeProperties = input['excludeProperties'];
|
|
1024
|
+
const dialogSize = input['dialogSize'];
|
|
949
1025
|
const { entity, entityInfo, data } = input.__context__;
|
|
950
1026
|
const [moduleName, entityName] = (entity || '').split('.');
|
|
951
1027
|
if (!moduleName || !entityName) {
|
|
@@ -972,6 +1048,9 @@ class AXPCreateEntityCommand {
|
|
|
972
1048
|
const translatedTitle = await this.translationService.translateAsync(entityInfo.title);
|
|
973
1049
|
chain = chain.title(`${createText} ${translatedTitle}`);
|
|
974
1050
|
}
|
|
1051
|
+
if (dialogSize) {
|
|
1052
|
+
chain.size(dialogSize);
|
|
1053
|
+
}
|
|
975
1054
|
dialogRef = await chain.show();
|
|
976
1055
|
if (dialogRef.action() == 'cancel') {
|
|
977
1056
|
dialogRef.close();
|
|
@@ -1063,6 +1142,7 @@ class AXPUpdateEntityCommand {
|
|
|
1063
1142
|
//#region ---- Command Execution ----
|
|
1064
1143
|
async execute(input) {
|
|
1065
1144
|
const excludeProperties = input['excludeProperties'];
|
|
1145
|
+
const dialogSize = input['dialogSize'];
|
|
1066
1146
|
const { entity, entityInfo, data } = input.__context__;
|
|
1067
1147
|
const [moduleName, entityName] = (entity || '').split('.');
|
|
1068
1148
|
if (!moduleName || !entityName) {
|
|
@@ -1099,6 +1179,9 @@ class AXPUpdateEntityCommand {
|
|
|
1099
1179
|
const translatedTitle = await this.translationService.translateAsync(entityInfo.title);
|
|
1100
1180
|
chain = chain.title(`${editText} ${translatedTitle}`);
|
|
1101
1181
|
}
|
|
1182
|
+
if (dialogSize) {
|
|
1183
|
+
chain.size(dialogSize);
|
|
1184
|
+
}
|
|
1102
1185
|
dialogRef = await chain.show();
|
|
1103
1186
|
if (dialogRef.action() === 'cancel') {
|
|
1104
1187
|
dialogRef.close();
|
|
@@ -5815,13 +5898,14 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
5815
5898
|
//#region ---- Services & Dependencies ----
|
|
5816
5899
|
this.categoryTreeService = inject(AXPCategoryTreeService);
|
|
5817
5900
|
this.translationService = inject(AXTranslationService);
|
|
5901
|
+
this.highlightService = inject(AXHighlightService);
|
|
5818
5902
|
//#endregion
|
|
5819
5903
|
//#region ---- Properties (Set by popup service) ----
|
|
5820
5904
|
this.entityKey = signal('', ...(ngDevMode ? [{ debugName: "entityKey" }] : []));
|
|
5821
5905
|
this.textField = signal('title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
|
|
5822
5906
|
this.valueField = signal('id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
|
|
5823
5907
|
this.allowMultiple = signal(false, ...(ngDevMode ? [{ debugName: "allowMultiple" }] : []));
|
|
5824
|
-
this.selectionBehavior = signal('
|
|
5908
|
+
this.selectionBehavior = signal('all', ...(ngDevMode ? [{ debugName: "selectionBehavior" }] : []));
|
|
5825
5909
|
this.selectedValues = signal([], ...(ngDevMode ? [{ debugName: "selectedValues" }] : []));
|
|
5826
5910
|
this.searchPlaceholder = signal('@general:terms.interface.category.search.placeholder', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
|
|
5827
5911
|
this.excludedNodeId = signal(undefined, ...(ngDevMode ? [{ debugName: "excludedNodeId" }] : [])); // Node ID to disable
|
|
@@ -5987,11 +6071,11 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
5987
6071
|
return;
|
|
5988
6072
|
}
|
|
5989
6073
|
// Prevent concurrent searches
|
|
5990
|
-
if (this.isSearching() && this.currentSearchTerm !== null) {
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
}
|
|
6074
|
+
// if (this.isSearching() && this.currentSearchTerm !== null) {
|
|
6075
|
+
// if (this.currentSearchTerm === searchTerm) {
|
|
6076
|
+
// return;
|
|
6077
|
+
// }
|
|
6078
|
+
// }
|
|
5995
6079
|
this.searchValue.set(event.value ?? '');
|
|
5996
6080
|
this.currentSearchTerm = searchTerm;
|
|
5997
6081
|
const treeComponent = this.tree();
|
|
@@ -6031,8 +6115,12 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6031
6115
|
}
|
|
6032
6116
|
if (!searchResults || searchResults.length === 0) {
|
|
6033
6117
|
this.matchingNodeIds.clear();
|
|
6118
|
+
this.relevantNodeIds.clear();
|
|
6034
6119
|
this.searchResultCount.set(0);
|
|
6035
6120
|
await this.updateTranslatedMessages(0, searchTerm);
|
|
6121
|
+
// Clear highlighting and reload tree to show all nodes
|
|
6122
|
+
this.highlightService.clear();
|
|
6123
|
+
await treeComponent.reloadData();
|
|
6036
6124
|
return;
|
|
6037
6125
|
}
|
|
6038
6126
|
// Store matching node IDs from search results
|
|
@@ -6085,11 +6173,25 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6085
6173
|
}
|
|
6086
6174
|
}
|
|
6087
6175
|
}
|
|
6176
|
+
// Step 5: Apply highlighting after tree is rendered
|
|
6177
|
+
// Use setTimeout to ensure DOM is updated after tree reload
|
|
6178
|
+
setTimeout(() => {
|
|
6179
|
+
if (this.searchValue().trim()) {
|
|
6180
|
+
this.highlightService.highlight('ax-tree-view .ax-truncate', this.searchValue().trim());
|
|
6181
|
+
}
|
|
6182
|
+
}, 100);
|
|
6088
6183
|
}
|
|
6089
6184
|
catch (error) {
|
|
6090
6185
|
console.error('Error searching categories:', error);
|
|
6091
6186
|
this.matchingNodeIds.clear();
|
|
6187
|
+
this.relevantNodeIds.clear();
|
|
6092
6188
|
this.searchResultCount.set(0);
|
|
6189
|
+
this.highlightService.clear();
|
|
6190
|
+
// Reload tree to clear any filters
|
|
6191
|
+
const treeComponent = this.tree();
|
|
6192
|
+
if (treeComponent) {
|
|
6193
|
+
await treeComponent.reloadData();
|
|
6194
|
+
}
|
|
6093
6195
|
}
|
|
6094
6196
|
finally {
|
|
6095
6197
|
if (this.currentSearchTerm === searchTerm) {
|
|
@@ -6356,6 +6458,8 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6356
6458
|
this.isSearching.set(false);
|
|
6357
6459
|
this.matchingNodeIds.clear();
|
|
6358
6460
|
this.relevantNodeIds.clear();
|
|
6461
|
+
// Clear highlighting
|
|
6462
|
+
this.highlightService.clear();
|
|
6359
6463
|
const treeComponent = this.tree();
|
|
6360
6464
|
if (!treeComponent) {
|
|
6361
6465
|
this.expandedNodesBeforeSearch = [];
|
|
@@ -6452,6 +6556,36 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6452
6556
|
isMatchingNode(nodeId) {
|
|
6453
6557
|
return this.matchingNodeIds.has(nodeId);
|
|
6454
6558
|
}
|
|
6559
|
+
/**
|
|
6560
|
+
* Checks if a node is currently selected
|
|
6561
|
+
*/
|
|
6562
|
+
isNodeSelected(nodeId) {
|
|
6563
|
+
if (!nodeId || nodeId === 'all') {
|
|
6564
|
+
return false;
|
|
6565
|
+
}
|
|
6566
|
+
const id = String(nodeId);
|
|
6567
|
+
return this.selectedNodeIds().includes(id);
|
|
6568
|
+
}
|
|
6569
|
+
/**
|
|
6570
|
+
* Handles checkbox change event to toggle node selection
|
|
6571
|
+
*/
|
|
6572
|
+
// protected handleCheckboxChange(nodeId: string | number | undefined, checked: boolean): void {
|
|
6573
|
+
// if (!nodeId || nodeId === 'all') {
|
|
6574
|
+
// return;
|
|
6575
|
+
// }
|
|
6576
|
+
// const id = String(nodeId);
|
|
6577
|
+
// const treeComponent = this.tree();
|
|
6578
|
+
// if (!treeComponent) {
|
|
6579
|
+
// return;
|
|
6580
|
+
// }
|
|
6581
|
+
// if (checked) {
|
|
6582
|
+
// // Select the node
|
|
6583
|
+
// treeComponent.selectNode(id);
|
|
6584
|
+
// } else {
|
|
6585
|
+
// // Deselect the node
|
|
6586
|
+
// treeComponent.deselectNode(id);
|
|
6587
|
+
// }
|
|
6588
|
+
// }
|
|
6455
6589
|
//#endregion
|
|
6456
6590
|
async updateSelectedNodes(selectedIds) {
|
|
6457
6591
|
if (!selectedIds || selectedIds.length === 0) {
|
|
@@ -6823,23 +6957,18 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6823
6957
|
<div class="ax-text-xs ax-text-muted ax-flex ax-items-center ax-gap-1">
|
|
6824
6958
|
@if (searchResultCount() > 0) {
|
|
6825
6959
|
<span>{{ resultsFoundText() }}</span>
|
|
6826
|
-
} @else {
|
|
6827
|
-
<span>{{ '@general:terms.interface.category.search.no-results' | translate | async }}</span>
|
|
6828
6960
|
}
|
|
6829
6961
|
</div>
|
|
6830
6962
|
}
|
|
6831
6963
|
</div>
|
|
6832
6964
|
@if (showNoSearchResults()) {
|
|
6833
|
-
<div class="ax-flex-1 ax-flex ax-items-center ax-justify-center
|
|
6834
|
-
<
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
{{ '@general:terms.interface.category.search.no-results-found.description' | translate | async }}
|
|
6841
|
-
</p>
|
|
6842
|
-
</div>
|
|
6965
|
+
<div class="ax-flex-1 ax-flex ax-items-center ax-justify-center">
|
|
6966
|
+
<axp-state-message
|
|
6967
|
+
icon="fa-light fa-search"
|
|
6968
|
+
[title]="'@general:terms.interface.category.search.no-results-found.title'"
|
|
6969
|
+
[description]="'@general:terms.interface.category.search.no-results-found.description'"
|
|
6970
|
+
>
|
|
6971
|
+
</axp-state-message>
|
|
6843
6972
|
</div>
|
|
6844
6973
|
} @else {
|
|
6845
6974
|
<div class="ax-flex-1 ax-overflow-auto ax-p-4">
|
|
@@ -6862,18 +6991,18 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6862
6991
|
<ng-template #itemTemplate let-node="node" let-level="level">
|
|
6863
6992
|
@if (node) {
|
|
6864
6993
|
@let item = node.data || node;
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6994
|
+
<div class="ax-flex ax-items-center ax-gap-2 ax-w-full ax-overflow-hidden ax-p-2 ax-pe-0">
|
|
6995
|
+
<!-- <ax-check-box
|
|
6996
|
+
[ngModel]="isNodeSelected(node.id)"
|
|
6997
|
+
(onValueChanged)="handleCheckboxChange(node.id, $event.value)"
|
|
6998
|
+
(click)="$event.stopPropagation()"
|
|
6999
|
+
[disabled]="node.disabled || node.id === 'all'"
|
|
7000
|
+
></ax-check-box> -->
|
|
6872
7001
|
<ax-icon
|
|
6873
7002
|
class="fas fa-folder"
|
|
6874
7003
|
[style.color]="item.color ?? 'rgba(var(--ax-sys-color-warning-500), 1)'"
|
|
6875
7004
|
></ax-icon>
|
|
6876
|
-
<span class="ax-truncate"
|
|
7005
|
+
<span class="ax-truncate">{{ node.title }}</span>
|
|
6877
7006
|
</div>
|
|
6878
7007
|
}
|
|
6879
7008
|
</ng-template>
|
|
@@ -6881,8 +7010,13 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6881
7010
|
}
|
|
6882
7011
|
</div>
|
|
6883
7012
|
} @else {
|
|
6884
|
-
<div class="ax-
|
|
6885
|
-
<
|
|
7013
|
+
<div class="ax-flex-1 ax-flex ax-items-center ax-justify-center">
|
|
7014
|
+
<axp-state-message
|
|
7015
|
+
icon="fa-light fa-folder-open"
|
|
7016
|
+
[title]="'@general:terms.interface.category.search.no-records.title'"
|
|
7017
|
+
[description]="'@general:terms.interface.category.search.no-records.description'"
|
|
7018
|
+
>
|
|
7019
|
+
</axp-state-message>
|
|
6886
7020
|
</div>
|
|
6887
7021
|
}
|
|
6888
7022
|
</div>
|
|
@@ -6897,11 +7031,12 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6897
7031
|
look="solid"
|
|
6898
7032
|
color="primary"
|
|
6899
7033
|
[text]="'@general:actions.ok.title' | translate | async"
|
|
7034
|
+
[disabled]="selectedNodeIds().length === 0"
|
|
6900
7035
|
(onClick)="onConfirm()"
|
|
6901
7036
|
></ax-button>
|
|
6902
7037
|
</ax-suffix>
|
|
6903
7038
|
</ax-footer>
|
|
6904
|
-
`, isInline: true, 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: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i3$2.AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i4$1.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "component", type: AXTreeViewComponent, selector: "ax-tree-view", inputs: ["datasource", "selectMode", "selectionBehavior", "dragArea", "dragBehavior", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "look", "nodeTemplate", "idField", "titleField", "tooltipField", "iconField", "expandedField", "selectedField", "indeterminateField", "disabledField", "hiddenField", "childrenField", "childrenCountField", "dataField", "inheritDisabled", "expandOnDoubleClick"], outputs: ["datasourceChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onNodeDoubleClick", "onNodeClick", "onSelectionChange", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7039
|
+
`, isInline: true, 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: AXCheckBoxModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i3$2.AXSearchBoxComponent, selector: "ax-search-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "class", "delayTime", "type", "autoSearch"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i4$1.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "component", type: AXTreeViewComponent, selector: "ax-tree-view", inputs: ["datasource", "selectMode", "selectionBehavior", "dragArea", "dragBehavior", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "look", "nodeTemplate", "idField", "titleField", "tooltipField", "iconField", "expandedField", "selectedField", "indeterminateField", "disabledField", "hiddenField", "childrenField", "childrenCountField", "dataField", "inheritDisabled", "expandOnDoubleClick"], outputs: ["datasourceChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onNodeDoubleClick", "onNodeClick", "onSelectionChange", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "variant"] }, { kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6905
7040
|
}
|
|
6906
7041
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryTreeSelectorComponent, decorators: [{
|
|
6907
7042
|
type: Component,
|
|
@@ -6932,23 +7067,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
6932
7067
|
<div class="ax-text-xs ax-text-muted ax-flex ax-items-center ax-gap-1">
|
|
6933
7068
|
@if (searchResultCount() > 0) {
|
|
6934
7069
|
<span>{{ resultsFoundText() }}</span>
|
|
6935
|
-
} @else {
|
|
6936
|
-
<span>{{ '@general:terms.interface.category.search.no-results' | translate | async }}</span>
|
|
6937
7070
|
}
|
|
6938
7071
|
</div>
|
|
6939
7072
|
}
|
|
6940
7073
|
</div>
|
|
6941
7074
|
@if (showNoSearchResults()) {
|
|
6942
|
-
<div class="ax-flex-1 ax-flex ax-items-center ax-justify-center
|
|
6943
|
-
<
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
{{ '@general:terms.interface.category.search.no-results-found.description' | translate | async }}
|
|
6950
|
-
</p>
|
|
6951
|
-
</div>
|
|
7075
|
+
<div class="ax-flex-1 ax-flex ax-items-center ax-justify-center">
|
|
7076
|
+
<axp-state-message
|
|
7077
|
+
icon="fa-light fa-search"
|
|
7078
|
+
[title]="'@general:terms.interface.category.search.no-results-found.title'"
|
|
7079
|
+
[description]="'@general:terms.interface.category.search.no-results-found.description'"
|
|
7080
|
+
>
|
|
7081
|
+
</axp-state-message>
|
|
6952
7082
|
</div>
|
|
6953
7083
|
} @else {
|
|
6954
7084
|
<div class="ax-flex-1 ax-overflow-auto ax-p-4">
|
|
@@ -6971,18 +7101,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
6971
7101
|
<ng-template #itemTemplate let-node="node" let-level="level">
|
|
6972
7102
|
@if (node) {
|
|
6973
7103
|
@let item = node.data || node;
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
7104
|
+
<div class="ax-flex ax-items-center ax-gap-2 ax-w-full ax-overflow-hidden ax-p-2 ax-pe-0">
|
|
7105
|
+
<!-- <ax-check-box
|
|
7106
|
+
[ngModel]="isNodeSelected(node.id)"
|
|
7107
|
+
(onValueChanged)="handleCheckboxChange(node.id, $event.value)"
|
|
7108
|
+
(click)="$event.stopPropagation()"
|
|
7109
|
+
[disabled]="node.disabled || node.id === 'all'"
|
|
7110
|
+
></ax-check-box> -->
|
|
6981
7111
|
<ax-icon
|
|
6982
7112
|
class="fas fa-folder"
|
|
6983
7113
|
[style.color]="item.color ?? 'rgba(var(--ax-sys-color-warning-500), 1)'"
|
|
6984
7114
|
></ax-icon>
|
|
6985
|
-
<span class="ax-truncate"
|
|
7115
|
+
<span class="ax-truncate">{{ node.title }}</span>
|
|
6986
7116
|
</div>
|
|
6987
7117
|
}
|
|
6988
7118
|
</ng-template>
|
|
@@ -6990,8 +7120,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
6990
7120
|
}
|
|
6991
7121
|
</div>
|
|
6992
7122
|
} @else {
|
|
6993
|
-
<div class="ax-
|
|
6994
|
-
<
|
|
7123
|
+
<div class="ax-flex-1 ax-flex ax-items-center ax-justify-center">
|
|
7124
|
+
<axp-state-message
|
|
7125
|
+
icon="fa-light fa-folder-open"
|
|
7126
|
+
[title]="'@general:terms.interface.category.search.no-records.title'"
|
|
7127
|
+
[description]="'@general:terms.interface.category.search.no-records.description'"
|
|
7128
|
+
>
|
|
7129
|
+
</axp-state-message>
|
|
6995
7130
|
</div>
|
|
6996
7131
|
}
|
|
6997
7132
|
</div>
|
|
@@ -7006,6 +7141,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
7006
7141
|
look="solid"
|
|
7007
7142
|
color="primary"
|
|
7008
7143
|
[text]="'@general:actions.ok.title' | translate | async"
|
|
7144
|
+
[disabled]="selectedNodeIds().length === 0"
|
|
7009
7145
|
(onClick)="onConfirm()"
|
|
7010
7146
|
></ax-button>
|
|
7011
7147
|
</ax-suffix>
|
|
@@ -7015,11 +7151,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
7015
7151
|
imports: [
|
|
7016
7152
|
CommonModule,
|
|
7017
7153
|
AXButtonModule,
|
|
7154
|
+
AXCheckBoxModule,
|
|
7018
7155
|
AXDecoratorModule,
|
|
7019
7156
|
AXSearchBoxModule,
|
|
7020
7157
|
AXSkeletonModule,
|
|
7021
7158
|
AXTreeViewComponent,
|
|
7022
7159
|
AXTranslationModule,
|
|
7160
|
+
AXPStateMessageComponent,
|
|
7161
|
+
FormsModule,
|
|
7023
7162
|
],
|
|
7024
7163
|
}]
|
|
7025
7164
|
}], propDecorators: { tree: [{ type: i0.ViewChild, args: ['tree', { isSignal: true }] }] } });
|
|
@@ -7027,177 +7166,275 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
7027
7166
|
class AXPEntityCategoryWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
7028
7167
|
constructor() {
|
|
7029
7168
|
super(...arguments);
|
|
7030
|
-
//#region ---- Dependencies ----
|
|
7169
|
+
//#region ---- Services & Dependencies ----
|
|
7031
7170
|
this.entityDetailPopoverService = inject(AXPEntityDetailPopoverService);
|
|
7032
7171
|
this.formatService = inject(AXFormatService);
|
|
7172
|
+
this.entityResolver = inject(AXPEntityResolver);
|
|
7033
7173
|
//#endregion
|
|
7034
|
-
//#region ----
|
|
7035
|
-
this.
|
|
7036
|
-
this.morePopover = viewChild('morePopover', ...(ngDevMode ? [{ debugName: "morePopover" }] : []));
|
|
7174
|
+
//#region ---- Inputs ----
|
|
7175
|
+
this.rawValueSignal = signal(null, ...(ngDevMode ? [{ debugName: "rawValueSignal" }] : []));
|
|
7037
7176
|
//#endregion
|
|
7038
|
-
//#region ---- Properties ----
|
|
7039
|
-
this.
|
|
7040
|
-
this.valueField = this.options['valueField'] ?? 'id';
|
|
7041
|
-
this.textField = this.options['textField'] ?? 'title';
|
|
7042
|
-
this.
|
|
7043
|
-
this.
|
|
7044
|
-
|
|
7177
|
+
//#region ---- Computed Properties ----
|
|
7178
|
+
this.entity = computed(() => this.options['entity'] ?? '', ...(ngDevMode ? [{ debugName: "entity" }] : []));
|
|
7179
|
+
this.valueField = computed(() => this.options['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
|
|
7180
|
+
this.textField = computed(() => this.options['textField'] ?? 'title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
|
|
7181
|
+
this.columnName = computed(() => this.options['columnName'] ?? '', ...(ngDevMode ? [{ debugName: "columnName" }] : []));
|
|
7182
|
+
this.defaultTextField = computed(() => {
|
|
7183
|
+
const textField = this.entityDef()?.formats.lookup ?? this.entityDef()?.properties.find((c) => c.name != 'id')?.name ?? 'title';
|
|
7184
|
+
return textField;
|
|
7185
|
+
}, ...(ngDevMode ? [{ debugName: "defaultTextField" }] : []));
|
|
7186
|
+
this.displayField = computed(() => {
|
|
7187
|
+
if (this.textField()) {
|
|
7188
|
+
return this.textField();
|
|
7189
|
+
}
|
|
7190
|
+
return this.defaultTextField();
|
|
7191
|
+
}, ...(ngDevMode ? [{ debugName: "displayField" }] : []));
|
|
7045
7192
|
//#endregion
|
|
7046
|
-
//#region ----
|
|
7047
|
-
this.
|
|
7193
|
+
//#region ---- Component State ----
|
|
7194
|
+
this.host = inject(ElementRef);
|
|
7195
|
+
this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : []));
|
|
7196
|
+
this.displayItems = signal([], ...(ngDevMode ? [{ debugName: "displayItems" }] : []));
|
|
7048
7197
|
this.selectedItemIndex = signal(-1, ...(ngDevMode ? [{ debugName: "selectedItemIndex" }] : []));
|
|
7049
7198
|
//#endregion
|
|
7050
|
-
//#region ----
|
|
7051
|
-
this.
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7199
|
+
//#region ---- Effects ----
|
|
7200
|
+
this.efEntity = effect(async () => {
|
|
7201
|
+
const entityKey = this.entity();
|
|
7202
|
+
if (!entityKey) {
|
|
7203
|
+
return;
|
|
7204
|
+
}
|
|
7205
|
+
const [module, entity] = entityKey.split('.');
|
|
7206
|
+
if (!module || !entity) {
|
|
7207
|
+
return;
|
|
7208
|
+
}
|
|
7209
|
+
this.entityDef.set(await this.entityResolver.get(module, entity));
|
|
7210
|
+
}, ...(ngDevMode ? [{ debugName: "efEntity" }] : []));
|
|
7211
|
+
this.efDisplay = effect(async () => {
|
|
7212
|
+
const value = this.rawValueSignal();
|
|
7213
|
+
const entity = this.entityDef();
|
|
7214
|
+
// Wait for entity definition to be loaded before processing value
|
|
7215
|
+
if (!entity) {
|
|
7216
|
+
this.displayItems.set([]);
|
|
7217
|
+
return;
|
|
7218
|
+
}
|
|
7219
|
+
if (isNil(value)) {
|
|
7220
|
+
this.displayItems.set([]);
|
|
7221
|
+
}
|
|
7222
|
+
else {
|
|
7223
|
+
const items = castArray(value);
|
|
7224
|
+
const itemsWithPaths = await Promise.all(items.map((item) => this.extractItemWithPath(item)));
|
|
7225
|
+
this.displayItems.set(itemsWithPaths.filter((c) => c != null));
|
|
7226
|
+
}
|
|
7227
|
+
}, ...(ngDevMode ? [{ debugName: "efDisplay" }] : []));
|
|
7228
|
+
//#endregion
|
|
7229
|
+
//#region ---- Computed Properties (Derived) ----
|
|
7230
|
+
this.visibleItems = computed(() => this.displayItems(), ...(ngDevMode ? [{ debugName: "visibleItems" }] : []));
|
|
7231
|
+
}
|
|
7232
|
+
set rawValueInput(value) {
|
|
7233
|
+
this.rawValueSignal.set(value);
|
|
7071
7234
|
}
|
|
7072
7235
|
//#endregion
|
|
7073
7236
|
//#region ---- Public Methods ----
|
|
7074
|
-
showMoreItems() {
|
|
7075
|
-
this.entityDetailPopoverService.hide();
|
|
7076
|
-
this.openMorePopover();
|
|
7077
|
-
}
|
|
7078
|
-
onMorePopoverOpenChange(event) {
|
|
7079
|
-
this.isMorePopoverOpen.set(event);
|
|
7080
|
-
}
|
|
7081
7237
|
async showItemDetail(item, index) {
|
|
7082
|
-
const columnData = this.rowData[this.columnName];
|
|
7238
|
+
const columnData = this.rowData[this.columnName()];
|
|
7083
7239
|
const id = Array.isArray(columnData) ? columnData[index] : columnData;
|
|
7084
7240
|
this.selectedItemIndex.set(index);
|
|
7085
|
-
this.
|
|
7086
|
-
if (
|
|
7241
|
+
const entityKey = this.entity();
|
|
7242
|
+
if (entityKey && id) {
|
|
7087
7243
|
await this.entityDetailPopoverService.show(this.host, {
|
|
7088
|
-
entity:
|
|
7244
|
+
entity: entityKey,
|
|
7089
7245
|
id: id,
|
|
7090
|
-
textField: this.textField,
|
|
7091
|
-
valueField: this.valueField,
|
|
7246
|
+
textField: this.textField(),
|
|
7247
|
+
valueField: this.valueField(),
|
|
7092
7248
|
item,
|
|
7093
7249
|
});
|
|
7094
7250
|
}
|
|
7095
7251
|
}
|
|
7096
7252
|
handleItemClick(index) {
|
|
7097
|
-
const items = this.
|
|
7253
|
+
const items = this.visibleItems();
|
|
7098
7254
|
if (index < items.length) {
|
|
7099
7255
|
const item = items[index];
|
|
7100
7256
|
this.showItemDetail(item, index);
|
|
7101
7257
|
}
|
|
7102
7258
|
}
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
|
|
7106
|
-
if (this.morePopover() && this.moreButton()) {
|
|
7107
|
-
this.morePopover().target = this.moreButton().nativeElement;
|
|
7108
|
-
this.morePopover().open();
|
|
7109
|
-
this.isMorePopoverOpen.set(true);
|
|
7259
|
+
getItemPath(item) {
|
|
7260
|
+
if (!item) {
|
|
7261
|
+
return [];
|
|
7110
7262
|
}
|
|
7263
|
+
// If path is available as array, return it
|
|
7264
|
+
if (item.path && Array.isArray(item.path) && item.path.length > 0) {
|
|
7265
|
+
return item.path;
|
|
7266
|
+
}
|
|
7267
|
+
// Fall back to display field if no path
|
|
7268
|
+
const displayValue = get(item, this.displayField());
|
|
7269
|
+
return displayValue ? [String(displayValue)] : [];
|
|
7111
7270
|
}
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7271
|
+
hasParent(item) {
|
|
7272
|
+
const path = this.getItemPath(item);
|
|
7273
|
+
return path.length > 1;
|
|
7274
|
+
}
|
|
7275
|
+
getItemText(item) {
|
|
7276
|
+
const path = this.getItemPath(item);
|
|
7277
|
+
if (path.length === 0) {
|
|
7278
|
+
return '';
|
|
7116
7279
|
}
|
|
7280
|
+
// Return the last item in the path (the actual node)
|
|
7281
|
+
return path[path.length - 1];
|
|
7117
7282
|
}
|
|
7118
|
-
|
|
7283
|
+
getItemId(item) {
|
|
7284
|
+
if (!item) {
|
|
7285
|
+
return '';
|
|
7286
|
+
}
|
|
7287
|
+
return String(get(item, this.valueField()) ?? '');
|
|
7288
|
+
}
|
|
7289
|
+
//#endregion
|
|
7290
|
+
//#region ---- Private Methods ----
|
|
7291
|
+
async extractItemWithPath(item) {
|
|
7119
7292
|
if (isNil(item)) {
|
|
7120
7293
|
return null;
|
|
7121
7294
|
}
|
|
7295
|
+
let itemObj;
|
|
7122
7296
|
if (typeof item === 'object') {
|
|
7123
|
-
|
|
7297
|
+
itemObj = item;
|
|
7124
7298
|
}
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7299
|
+
else {
|
|
7300
|
+
// If item is just an ID, fetch the full item
|
|
7301
|
+
const byKey = this.entityDef()?.queries.byKey?.execute;
|
|
7302
|
+
if (byKey) {
|
|
7303
|
+
try {
|
|
7304
|
+
itemObj = await byKey(item);
|
|
7305
|
+
}
|
|
7306
|
+
catch (error) {
|
|
7307
|
+
console.error('Error fetching item:', error);
|
|
7308
|
+
return null;
|
|
7309
|
+
}
|
|
7310
|
+
}
|
|
7311
|
+
else {
|
|
7312
|
+
itemObj = {
|
|
7313
|
+
[this.valueField()]: item,
|
|
7314
|
+
[this.textField()]: item,
|
|
7315
|
+
};
|
|
7316
|
+
}
|
|
7317
|
+
}
|
|
7318
|
+
// If item already has a path array, return it as is
|
|
7319
|
+
if (itemObj.path && Array.isArray(itemObj.path) && itemObj.path.length > 0) {
|
|
7320
|
+
return itemObj;
|
|
7321
|
+
}
|
|
7322
|
+
// Calculate path for the item
|
|
7323
|
+
return await this.calculateItemPath(itemObj);
|
|
7129
7324
|
}
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7325
|
+
/**
|
|
7326
|
+
* Calculate the full path from root to the item.
|
|
7327
|
+
* Returns an array of strings like ["C", "B"] for item B under parent C.
|
|
7328
|
+
*/
|
|
7329
|
+
async calculateItemPath(item) {
|
|
7330
|
+
if (!item || !this.entityDef()) {
|
|
7331
|
+
return item;
|
|
7332
|
+
}
|
|
7333
|
+
// If item already has a path array, return it as is
|
|
7334
|
+
if (item.path && Array.isArray(item.path) && item.path.length > 0) {
|
|
7335
|
+
return item;
|
|
7336
|
+
}
|
|
7337
|
+
const parentKey = this.entityDef()?.parentKey;
|
|
7338
|
+
if (!parentKey) {
|
|
7339
|
+
// No parent key means flat structure, return item with just its title as path array
|
|
7340
|
+
const title = get(item, this.displayField()) ?? '';
|
|
7341
|
+
return { ...item, path: title ? [title] : [] };
|
|
7133
7342
|
}
|
|
7134
|
-
|
|
7343
|
+
const valueField = this.valueField();
|
|
7344
|
+
const textField = this.displayField();
|
|
7345
|
+
const byKey = this.entityDef()?.queries.byKey?.execute;
|
|
7346
|
+
if (!byKey) {
|
|
7347
|
+
return item;
|
|
7348
|
+
}
|
|
7349
|
+
const path = [];
|
|
7350
|
+
let currentItem = item;
|
|
7351
|
+
const visitedIds = new Set(); // Prevent infinite loops
|
|
7352
|
+
// Build path by traversing up the parent chain
|
|
7353
|
+
while (currentItem) {
|
|
7354
|
+
const currentId = String(get(currentItem, valueField) ?? '');
|
|
7355
|
+
if (!currentId || visitedIds.has(currentId)) {
|
|
7356
|
+
break; // Prevent infinite loops
|
|
7357
|
+
}
|
|
7358
|
+
visitedIds.add(currentId);
|
|
7359
|
+
const title = String(get(currentItem, textField) ?? '');
|
|
7360
|
+
if (title) {
|
|
7361
|
+
path.unshift(title); // Add to beginning to maintain hierarchy order
|
|
7362
|
+
}
|
|
7363
|
+
// Get parent ID from current item
|
|
7364
|
+
const parentId = get(currentItem, parentKey);
|
|
7365
|
+
if (!parentId || parentId === 'all' || parentId === currentId) {
|
|
7366
|
+
break; // Reached root or invalid parent
|
|
7367
|
+
}
|
|
7368
|
+
try {
|
|
7369
|
+
// Fetch parent item
|
|
7370
|
+
const parentItem = await byKey(parentId);
|
|
7371
|
+
if (!parentItem) {
|
|
7372
|
+
break; // Parent not found, stop traversal
|
|
7373
|
+
}
|
|
7374
|
+
currentItem = parentItem;
|
|
7375
|
+
}
|
|
7376
|
+
catch (error) {
|
|
7377
|
+
console.error('Error fetching parent item:', error);
|
|
7378
|
+
break;
|
|
7379
|
+
}
|
|
7380
|
+
}
|
|
7381
|
+
// Return item with path array, or just the item title if no path
|
|
7382
|
+
const pathArray = path.length > 0 ? path : get(item, textField) ? [String(get(item, textField))] : [];
|
|
7383
|
+
return { ...item, path: pathArray };
|
|
7135
7384
|
}
|
|
7136
7385
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetColumnComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
7137
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityCategoryWidgetColumnComponent, isStandalone: true, selector: "axp-entity-category-widget-column", inputs: { rawValue: "rawValue", rowData: "rowData"
|
|
7138
|
-
<div class="ax-flex ax-
|
|
7139
|
-
@for (item of visibleItems(); track
|
|
7140
|
-
<ax-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
@for (item of remainingItems(); track $index) {
|
|
7153
|
-
<ax-badge
|
|
7154
|
-
class="ax-p-0.5 ax-cursor-pointer"
|
|
7155
|
-
[text]="getDisplayText(item)"
|
|
7156
|
-
(click)="handleItemClick(visibleItems().length + $index)"
|
|
7157
|
-
></ax-badge>
|
|
7158
|
-
}
|
|
7159
|
-
</div>
|
|
7160
|
-
</ax-popover>
|
|
7386
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityCategoryWidgetColumnComponent, isStandalone: true, selector: "axp-entity-category-widget-column", inputs: { rawValue: "rawValue", rowData: "rowData", rawValueInput: ["rawValue", "rawValueInput"] }, host: { classAttribute: "ax-w-full" }, usesInheritance: true, ngImport: i0, template: `
|
|
7387
|
+
<div class="ax-flex ax-flex-col ax-gap-1.5">
|
|
7388
|
+
@for (item of visibleItems(); track getItemId(item)) {
|
|
7389
|
+
<div class=" ax-cursor-pointer" (click)="handleItemClick($index)">
|
|
7390
|
+
@if (hasParent(item)) {
|
|
7391
|
+
<ax-badge [color]="'primary'" [look]="'twotone'" class="ax-p-0.5" [text]="getItemText(item)">
|
|
7392
|
+
<ax-prefix>
|
|
7393
|
+
<i class="fas fa-ellipsis-h ax-text-neutral-400 ax-text-xs ax-ps-1"></i>
|
|
7394
|
+
<i class="fas fa-chevron-right ax-text-neutral-400 ax-text-xs ax-px-1"></i>
|
|
7395
|
+
</ax-prefix>
|
|
7396
|
+
</ax-badge>
|
|
7397
|
+
} @else {
|
|
7398
|
+
<ax-badge [color]="'primary'" [look]="'twotone'" class="ax-p-0.5" [text]="getItemText(item)"> </ax-badge>
|
|
7399
|
+
}
|
|
7400
|
+
</div>
|
|
7161
7401
|
}
|
|
7162
7402
|
</div>
|
|
7163
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type:
|
|
7403
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7164
7404
|
}
|
|
7165
7405
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetColumnComponent, decorators: [{
|
|
7166
7406
|
type: Component,
|
|
7167
7407
|
args: [{
|
|
7168
7408
|
selector: 'axp-entity-category-widget-column',
|
|
7409
|
+
host: {
|
|
7410
|
+
class: 'ax-w-full',
|
|
7411
|
+
},
|
|
7169
7412
|
template: `
|
|
7170
|
-
<div class="ax-flex ax-
|
|
7171
|
-
@for (item of visibleItems(); track
|
|
7172
|
-
<ax-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
@for (item of remainingItems(); track $index) {
|
|
7185
|
-
<ax-badge
|
|
7186
|
-
class="ax-p-0.5 ax-cursor-pointer"
|
|
7187
|
-
[text]="getDisplayText(item)"
|
|
7188
|
-
(click)="handleItemClick(visibleItems().length + $index)"
|
|
7189
|
-
></ax-badge>
|
|
7190
|
-
}
|
|
7191
|
-
</div>
|
|
7192
|
-
</ax-popover>
|
|
7413
|
+
<div class="ax-flex ax-flex-col ax-gap-1.5">
|
|
7414
|
+
@for (item of visibleItems(); track getItemId(item)) {
|
|
7415
|
+
<div class=" ax-cursor-pointer" (click)="handleItemClick($index)">
|
|
7416
|
+
@if (hasParent(item)) {
|
|
7417
|
+
<ax-badge [color]="'primary'" [look]="'twotone'" class="ax-p-0.5" [text]="getItemText(item)">
|
|
7418
|
+
<ax-prefix>
|
|
7419
|
+
<i class="fas fa-ellipsis-h ax-text-neutral-400 ax-text-xs ax-ps-1"></i>
|
|
7420
|
+
<i class="fas fa-chevron-right ax-text-neutral-400 ax-text-xs ax-px-1"></i>
|
|
7421
|
+
</ax-prefix>
|
|
7422
|
+
</ax-badge>
|
|
7423
|
+
} @else {
|
|
7424
|
+
<ax-badge [color]="'primary'" [look]="'twotone'" class="ax-p-0.5" [text]="getItemText(item)"> </ax-badge>
|
|
7425
|
+
}
|
|
7426
|
+
</div>
|
|
7193
7427
|
}
|
|
7194
7428
|
</div>
|
|
7195
7429
|
`,
|
|
7196
7430
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
7197
|
-
imports: [CommonModule, AXBadgeModule,
|
|
7431
|
+
imports: [CommonModule, AXBadgeModule, AXDecoratorModule],
|
|
7198
7432
|
inputs: ['rawValue', 'rowData'],
|
|
7199
7433
|
}]
|
|
7200
|
-
}], propDecorators: {
|
|
7434
|
+
}], propDecorators: { rawValueInput: [{
|
|
7435
|
+
type: Input,
|
|
7436
|
+
args: ['rawValue']
|
|
7437
|
+
}] } });
|
|
7201
7438
|
|
|
7202
7439
|
var entityCategoryWidgetColumn_component = /*#__PURE__*/Object.freeze({
|
|
7203
7440
|
__proto__: null,
|