@acorex/platform 20.6.0-next.22 → 20.6.0-next.24
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-components.mjs +2 -2
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +1302 -353
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widgets.mjs +1 -1
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-DBysy2Ky.mjs → acorex-platform-themes-default-entity-master-list-view.component-Cym8pq0v.mjs} +3 -3
- package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-DBysy2Ky.mjs.map → acorex-platform-themes-default-entity-master-list-view.component-Cym8pq0v.mjs.map} +1 -1
- package/fesm2022/acorex-platform-themes-default.mjs +2 -2
- package/layout/entity/index.d.ts +73 -7
- package/package.json +11 -11
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { AXToastService } from '@acorex/components/toast';
|
|
2
2
|
import * as i6 from '@acorex/core/translation';
|
|
3
3
|
import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
|
|
4
|
-
import * as i4 from '@acorex/platform/common';
|
|
4
|
+
import * as i4$1 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
|
-
import * as i1$
|
|
6
|
+
import * as i1$1 from '@acorex/platform/core';
|
|
7
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
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
|
-
import { merge, castArray, get, cloneDeep, set, orderBy, isNil,
|
|
12
|
+
import { merge, castArray, get, cloneDeep, set, orderBy, isNil, isEmpty, isEqual, sortBy } from 'lodash-es';
|
|
13
13
|
import { AXPSessionService, AXPAuthGuard } from '@acorex/platform/auth';
|
|
14
14
|
import { Router, RouterModule, ROUTES } from '@angular/router';
|
|
15
15
|
import * as i3 from '@acorex/components/button';
|
|
16
16
|
import { AXButtonModule } from '@acorex/components/button';
|
|
17
|
-
import * as
|
|
17
|
+
import * as i4 from '@acorex/components/loading';
|
|
18
18
|
import { AXLoadingModule } from '@acorex/components/loading';
|
|
19
19
|
import * as i2 from '@acorex/components/popover';
|
|
20
20
|
import { AXPopoverModule } from '@acorex/components/popover';
|
|
@@ -33,32 +33,33 @@ 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 * as i2$1 from '@acorex/components/check-box';
|
|
36
37
|
import { AXCheckBoxModule } from '@acorex/components/check-box';
|
|
37
|
-
import * as
|
|
38
|
+
import * as i3$2 from '@acorex/components/decorators';
|
|
38
39
|
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
39
40
|
import { AXBasePageComponent } from '@acorex/components/page';
|
|
40
|
-
import * as
|
|
41
|
+
import * as i4$2 from '@acorex/components/search-box';
|
|
41
42
|
import { AXSearchBoxModule, AXSearchBoxComponent } from '@acorex/components/search-box';
|
|
42
|
-
import * as
|
|
43
|
+
import * as i5$1 from '@acorex/components/skeleton';
|
|
43
44
|
import { AXSkeletonModule } from '@acorex/components/skeleton';
|
|
44
45
|
import { AXTreeViewComponent } from '@acorex/components/tree-view';
|
|
45
46
|
import { AXPStateMessageComponent, AXPDataSelectorService, AXPWidgetPropertyViewerComponent } from '@acorex/platform/layout/components';
|
|
46
|
-
import * as i1
|
|
47
|
+
import * as i1 from '@angular/forms';
|
|
47
48
|
import { FormsModule } from '@angular/forms';
|
|
48
49
|
import * as i2$2 from '@acorex/components/badge';
|
|
49
50
|
import { AXBadgeModule } from '@acorex/components/badge';
|
|
50
|
-
import * as i5$
|
|
51
|
+
import * as i5$2 from '@acorex/components/form';
|
|
51
52
|
import { AXFormModule } from '@acorex/components/form';
|
|
53
|
+
import * as i6$1 from '@acorex/components/tag-box';
|
|
54
|
+
import { AXTagBoxModule, AXTagBoxComponent } from '@acorex/components/tag-box';
|
|
52
55
|
import { AXValidationModule } from '@acorex/core/validation';
|
|
53
56
|
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';
|
|
54
|
-
import * as i4$
|
|
57
|
+
import * as i4$3 from '@acorex/components/dropdown';
|
|
55
58
|
import { AXDropdownModule } from '@acorex/components/dropdown';
|
|
56
59
|
import * as i7 from '@acorex/components/select-box';
|
|
57
60
|
import { AXSelectBoxModule } from '@acorex/components/select-box';
|
|
58
61
|
import * as i2$3 from '@acorex/components/text-box';
|
|
59
62
|
import { AXTextBoxModule, AXTextBoxComponent } from '@acorex/components/text-box';
|
|
60
|
-
import * as i6$1 from '@acorex/components/tag-box';
|
|
61
|
-
import { AXTagBoxComponent, AXTagBoxModule } from '@acorex/components/tag-box';
|
|
62
63
|
import { transform, isEqual as isEqual$1 } from 'lodash';
|
|
63
64
|
|
|
64
65
|
function ensureListActions(ctx) {
|
|
@@ -1035,7 +1036,7 @@ class AXPCreateEntityCommand {
|
|
|
1035
1036
|
const entityRef = await this.entityService.resolve(moduleName, entityName);
|
|
1036
1037
|
let dialogRef;
|
|
1037
1038
|
try {
|
|
1038
|
-
let chain = this.entityForm.entity(`${moduleName}.${entityName}`).create(
|
|
1039
|
+
let chain = this.entityForm.entity(`${moduleName}.${entityName}`).create(data);
|
|
1039
1040
|
chain.actions((actions) => {
|
|
1040
1041
|
actions.cancel('@general:actions.cancel.title');
|
|
1041
1042
|
actions.submit('@general:actions.create.title');
|
|
@@ -1680,7 +1681,7 @@ class AXPEntityDetailPopoverComponent {
|
|
|
1680
1681
|
return importantProperties;
|
|
1681
1682
|
}
|
|
1682
1683
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityDetailPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1683
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", 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 } }, 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 </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"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type:
|
|
1684
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", 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 } }, 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 </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"], 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 }); }
|
|
1684
1685
|
}
|
|
1685
1686
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityDetailPopoverComponent, decorators: [{
|
|
1686
1687
|
type: Component,
|
|
@@ -4324,24 +4325,48 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4324
4325
|
message: {
|
|
4325
4326
|
code: 'ACTION_NOT_FOUND',
|
|
4326
4327
|
text: `Action ${commandName} not found`,
|
|
4327
|
-
}
|
|
4328
|
+
},
|
|
4328
4329
|
};
|
|
4329
4330
|
}
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4331
|
+
if (context.commandService.exists(commandName)) {
|
|
4332
|
+
// check options for evaluation
|
|
4333
|
+
await context.commandService.execute(commandName, {
|
|
4334
|
+
__context__: {
|
|
4335
|
+
entity: getEntityInfo(entityDef).source,
|
|
4336
|
+
entityInfo: {
|
|
4337
|
+
name: entityDef.name,
|
|
4338
|
+
module: entityDef.module,
|
|
4339
|
+
title: entityDef.title,
|
|
4340
|
+
parentKey: entityDef.parentKey,
|
|
4341
|
+
source: `${entityDef.module}.${entityDef.name}`,
|
|
4342
|
+
},
|
|
4343
|
+
data: action.scope == AXPEntityCommandScope.Selected
|
|
4344
|
+
? executeContext
|
|
4345
|
+
: action.options?.['process']?.data || null,
|
|
4346
|
+
options: action.options,
|
|
4347
|
+
metadata: action.metadata,
|
|
4348
|
+
},
|
|
4349
|
+
options: action.options,
|
|
4350
|
+
metadata: action.metadata,
|
|
4351
|
+
});
|
|
4352
|
+
}
|
|
4353
|
+
else {
|
|
4354
|
+
await context.workflowService.execute(commandName, {
|
|
4355
|
+
entity: getEntityInfo(entityDef).source,
|
|
4356
|
+
entityInfo: {
|
|
4357
|
+
name: entityDef.name,
|
|
4358
|
+
module: entityDef.module,
|
|
4359
|
+
title: entityDef.title,
|
|
4360
|
+
parentKey: entityDef.parentKey,
|
|
4361
|
+
source: `${entityDef.module}.${entityDef.name}`,
|
|
4362
|
+
},
|
|
4363
|
+
data: action.scope == AXPEntityCommandScope.Selected
|
|
4364
|
+
? executeContext
|
|
4365
|
+
: action.options?.['process']?.data || null,
|
|
4366
|
+
options: action.options,
|
|
4367
|
+
metadata: action.metadata,
|
|
4368
|
+
});
|
|
4369
|
+
}
|
|
4345
4370
|
return { success: true };
|
|
4346
4371
|
}
|
|
4347
4372
|
catch (error) {
|
|
@@ -4368,6 +4393,7 @@ class AXPPageListConverter extends AXPBaseRelatedEntityConverter {
|
|
|
4368
4393
|
entity: relatedEntity.entity,
|
|
4369
4394
|
showEntityActions: false,
|
|
4370
4395
|
actions: evaluatedActions,
|
|
4396
|
+
includeColumns: relatedEntity.columns,
|
|
4371
4397
|
},
|
|
4372
4398
|
},
|
|
4373
4399
|
],
|
|
@@ -4978,6 +5004,7 @@ class AXPMainEntityContentBuilder {
|
|
|
4978
5004
|
: editablePropertyNames.has(p.name);
|
|
4979
5005
|
// Check if property has its own disabled option
|
|
4980
5006
|
const hasOwnDisabled = p.schema.interface?.options?.disabled !== undefined;
|
|
5007
|
+
console.log('visible: ', p.schema.visible);
|
|
4981
5008
|
return {
|
|
4982
5009
|
type: 'grid-item-layout',
|
|
4983
5010
|
name: prefixed,
|
|
@@ -4985,7 +5012,7 @@ class AXPMainEntityContentBuilder {
|
|
|
4985
5012
|
colSpan: layout?.positions?.lg?.colSpan,
|
|
4986
5013
|
colStart: layout?.positions?.lg?.colStart,
|
|
4987
5014
|
colEnd: layout?.positions?.lg?.colEnd,
|
|
4988
|
-
|
|
5015
|
+
visible: p.schema.visible,
|
|
4989
5016
|
},
|
|
4990
5017
|
children: [
|
|
4991
5018
|
{
|
|
@@ -5275,7 +5302,7 @@ class AXPLayoutAdapterFactory {
|
|
|
5275
5302
|
const title = await dependencies.expressionEvaluator.evaluate(entity.interfaces?.master?.single?.title, rootContext);
|
|
5276
5303
|
return title;
|
|
5277
5304
|
}
|
|
5278
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutAdapterFactory, deps: [{ token: AXPRelatedEntityConverterFactory }, { token: AXPMainEntityContentBuilder }, { token: AXPLayoutAdapterBuilder }, { token: i4.AXPFilterOperatorMiddlewareService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5305
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutAdapterFactory, deps: [{ token: AXPRelatedEntityConverterFactory }, { token: AXPMainEntityContentBuilder }, { token: AXPLayoutAdapterBuilder }, { token: i4$1.AXPFilterOperatorMiddlewareService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5279
5306
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutAdapterFactory, providedIn: 'root' }); }
|
|
5280
5307
|
}
|
|
5281
5308
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLayoutAdapterFactory, decorators: [{
|
|
@@ -5283,7 +5310,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
5283
5310
|
args: [{
|
|
5284
5311
|
providedIn: 'root',
|
|
5285
5312
|
}]
|
|
5286
|
-
}], ctorParameters: () => [{ type: AXPRelatedEntityConverterFactory }, { type: AXPMainEntityContentBuilder }, { type: AXPLayoutAdapterBuilder }, { type: i4.AXPFilterOperatorMiddlewareService }] });
|
|
5313
|
+
}], ctorParameters: () => [{ type: AXPRelatedEntityConverterFactory }, { type: AXPMainEntityContentBuilder }, { type: AXPLayoutAdapterBuilder }, { type: i4$1.AXPFilterOperatorMiddlewareService }] });
|
|
5287
5314
|
|
|
5288
5315
|
const AXPLayoutDetailsViewRouteResolver = async (route, state, entityResolver = inject(AXPEntityDefinitionRegistryService), expressionEvaluator = inject(AXPExpressionEvaluatorService), session = inject(AXPSessionService), formatService = inject(AXFormatService), workflowService = inject(AXPWorkflowService), commandService = inject(AXPCommandService), layoutAdapterFactory = inject(AXPLayoutAdapterFactory)) => {
|
|
5289
5316
|
const moduleName = route.parent?.paramMap.get('module');
|
|
@@ -5905,7 +5932,6 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
5905
5932
|
this.textField = signal('title', ...(ngDevMode ? [{ debugName: "textField" }] : []));
|
|
5906
5933
|
this.valueField = signal('id', ...(ngDevMode ? [{ debugName: "valueField" }] : []));
|
|
5907
5934
|
this.allowMultiple = signal(false, ...(ngDevMode ? [{ debugName: "allowMultiple" }] : []));
|
|
5908
|
-
this.selectionBehavior = signal('all', ...(ngDevMode ? [{ debugName: "selectionBehavior" }] : []));
|
|
5909
5935
|
this.selectedValues = signal([], ...(ngDevMode ? [{ debugName: "selectedValues" }] : []));
|
|
5910
5936
|
this.searchPlaceholder = signal('@general:terms.interface.category.search.placeholder', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
|
|
5911
5937
|
this.excludedNodeId = signal(undefined, ...(ngDevMode ? [{ debugName: "excludedNodeId" }] : [])); // Node ID to disable
|
|
@@ -5924,6 +5950,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
5924
5950
|
this.noRecordsTitle = signal('', ...(ngDevMode ? [{ debugName: "noRecordsTitle" }] : []));
|
|
5925
5951
|
this.currentSearchTerm = null;
|
|
5926
5952
|
this.isRefreshing = false;
|
|
5953
|
+
this.isUpdatingSelection = false; // Flag to prevent recursive updates during batch operations
|
|
5927
5954
|
/**
|
|
5928
5955
|
* Computed property to check if we should show the "no search results" empty state.
|
|
5929
5956
|
* Returns true when search is active, not searching, and no results found.
|
|
@@ -5943,6 +5970,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
5943
5970
|
this.relevantNodeIds = new Set(); // For search filtering
|
|
5944
5971
|
this.expandedNodesBeforeSearch = []; // Store expanded nodes before search to restore after
|
|
5945
5972
|
this.nodesExpandedDuringSearch = []; // Track nodes we expanded during search
|
|
5973
|
+
this.isInitializing = false; // Flag to track if we're in initialization phase
|
|
5946
5974
|
/** Datasource callback for tree-view component. */
|
|
5947
5975
|
this.datasource = async (id) => {
|
|
5948
5976
|
if (!this.treeData || !this.treeConfig) {
|
|
@@ -5994,15 +6022,42 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
5994
6022
|
this.markNodeAsSelectedIfNeeded(node);
|
|
5995
6023
|
});
|
|
5996
6024
|
// After children load, programmatically select pre-selected nodes
|
|
6025
|
+
// Use a small delay to ensure nodes are fully added to tree structure
|
|
5997
6026
|
const treeComponent = this.tree();
|
|
5998
6027
|
if (treeComponent) {
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
const
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6028
|
+
// Use setTimeout to ensure nodes are in tree structure before selecting
|
|
6029
|
+
setTimeout(() => {
|
|
6030
|
+
const selectedIds = this.selectedNodeIds();
|
|
6031
|
+
childNodes.forEach((node) => {
|
|
6032
|
+
const nodeId = String(node['id'] ?? '');
|
|
6033
|
+
if (nodeId && selectedIds.includes(nodeId) && nodeId !== 'all') {
|
|
6034
|
+
try {
|
|
6035
|
+
// Try to find and select the node
|
|
6036
|
+
const treeNode = treeComponent.findNode(nodeId);
|
|
6037
|
+
if (treeNode) {
|
|
6038
|
+
treeComponent.selectNode(nodeId);
|
|
6039
|
+
}
|
|
6040
|
+
else {
|
|
6041
|
+
// If node not found, try again after a short delay (might still be loading)
|
|
6042
|
+
setTimeout(() => {
|
|
6043
|
+
try {
|
|
6044
|
+
const retryNode = treeComponent.findNode(nodeId);
|
|
6045
|
+
if (retryNode) {
|
|
6046
|
+
treeComponent.selectNode(nodeId);
|
|
6047
|
+
}
|
|
6048
|
+
}
|
|
6049
|
+
catch {
|
|
6050
|
+
// Node still not found, will be selected when it loads
|
|
6051
|
+
}
|
|
6052
|
+
}, 50);
|
|
6053
|
+
}
|
|
6054
|
+
}
|
|
6055
|
+
catch (error) {
|
|
6056
|
+
// Node might not be in tree yet, will be selected when it loads
|
|
6057
|
+
}
|
|
6058
|
+
}
|
|
6059
|
+
});
|
|
6060
|
+
}, 10);
|
|
6006
6061
|
}
|
|
6007
6062
|
return childNodes;
|
|
6008
6063
|
};
|
|
@@ -6021,6 +6076,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6021
6076
|
return;
|
|
6022
6077
|
}
|
|
6023
6078
|
this.loading.set(true);
|
|
6079
|
+
this.isInitializing = true; // Mark that we're in initialization phase
|
|
6024
6080
|
try {
|
|
6025
6081
|
this.treeConfig = {
|
|
6026
6082
|
entityKey: this.entityKey(),
|
|
@@ -6030,6 +6086,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6030
6086
|
this.treeData = await this.categoryTreeService.initializeCategoryTree(this.treeConfig);
|
|
6031
6087
|
if (!this.treeData) {
|
|
6032
6088
|
this.loading.set(false);
|
|
6089
|
+
this.isInitializing = false;
|
|
6033
6090
|
return;
|
|
6034
6091
|
}
|
|
6035
6092
|
// Get parentKey from entity definition
|
|
@@ -6037,13 +6094,22 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6037
6094
|
this.treeConfig.parentKey = this.treeData.categoryEntityDef.parentKey;
|
|
6038
6095
|
}
|
|
6039
6096
|
// Initialize selected nodes and load their data into cache
|
|
6097
|
+
// Wait for tree to be ready before syncing selection
|
|
6098
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
6040
6099
|
await this.updateSelectedNodes(this.selectedValues());
|
|
6100
|
+
// After initial sync, wait a bit more and sync again to catch any nodes that loaded late
|
|
6101
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
6102
|
+
const finalSelectedIds = this.selectedNodeIds();
|
|
6103
|
+
if (finalSelectedIds.length > 0) {
|
|
6104
|
+
await this.syncSelectionWithTree(finalSelectedIds);
|
|
6105
|
+
}
|
|
6041
6106
|
}
|
|
6042
6107
|
catch (error) {
|
|
6043
6108
|
console.error('Error loading entity definition:', error);
|
|
6044
6109
|
}
|
|
6045
6110
|
finally {
|
|
6046
6111
|
this.loading.set(false);
|
|
6112
|
+
this.isInitializing = false; // Mark initialization as complete
|
|
6047
6113
|
}
|
|
6048
6114
|
}
|
|
6049
6115
|
//#endregion
|
|
@@ -6499,11 +6565,22 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6499
6565
|
if (nodeData && typeof nodeData === 'object' && nodeData !== null && !Array.isArray(nodeData)) {
|
|
6500
6566
|
this.nodeDataCache.set(nodeId, nodeData);
|
|
6501
6567
|
}
|
|
6568
|
+
// NOTE: We do NOT call loadAndSelectChildrenRecursively here
|
|
6569
|
+
// The recursive selection should only happen when user explicitly selects a node via checkbox
|
|
6570
|
+
// (handled in handleCheckboxChange). This prevents intermediate parent states from
|
|
6571
|
+
// triggering unwanted sibling selections.
|
|
6502
6572
|
}
|
|
6503
6573
|
async onSelectionChange(event) {
|
|
6574
|
+
// Don't process during initialization or batch updates - let those handle it
|
|
6575
|
+
if (this.isInitializing || this.isUpdatingSelection) {
|
|
6576
|
+
return;
|
|
6577
|
+
}
|
|
6504
6578
|
// Update selected node IDs from the tree component's selection state
|
|
6579
|
+
// The tree component with intermediate-nested behavior automatically manages parent states
|
|
6505
6580
|
const selectedNodes = event.selectedNodes || [];
|
|
6506
6581
|
const selectedIds = selectedNodes.map((node) => String(node['id'] ?? '')).filter((id) => id && id !== 'all');
|
|
6582
|
+
// Sync with tree component's selection state
|
|
6583
|
+
// This includes parents that are automatically selected when all children are selected
|
|
6507
6584
|
this.selectedNodeIds.set(selectedIds);
|
|
6508
6585
|
// Cache node data for all selected nodes
|
|
6509
6586
|
selectedNodes.forEach((node) => {
|
|
@@ -6568,171 +6645,884 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6568
6645
|
}
|
|
6569
6646
|
/**
|
|
6570
6647
|
* Handles checkbox change event to toggle node selection
|
|
6648
|
+
* In multiple mode: recursively selects/deselects children
|
|
6649
|
+
* Parent states are handled automatically by tree component's intermediate-nested behavior
|
|
6571
6650
|
*/
|
|
6572
|
-
|
|
6573
|
-
|
|
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
|
-
// }
|
|
6589
|
-
//#endregion
|
|
6590
|
-
async updateSelectedNodes(selectedIds) {
|
|
6591
|
-
if (!selectedIds || selectedIds.length === 0) {
|
|
6592
|
-
this.selectedNodeIds.set([]);
|
|
6651
|
+
async handleCheckboxChange(nodeId, checked) {
|
|
6652
|
+
if (!nodeId || nodeId === 'all') {
|
|
6593
6653
|
return;
|
|
6594
6654
|
}
|
|
6595
|
-
const
|
|
6596
|
-
this.
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6655
|
+
const id = String(nodeId);
|
|
6656
|
+
const treeComponent = this.tree();
|
|
6657
|
+
if (!treeComponent) {
|
|
6658
|
+
return;
|
|
6659
|
+
}
|
|
6660
|
+
if (checked) {
|
|
6661
|
+
// Select the node and recursively select all its children
|
|
6662
|
+
await this.selectNodeAndChildren(id);
|
|
6663
|
+
}
|
|
6664
|
+
else {
|
|
6665
|
+
// Deselect the node and recursively deselect all its children
|
|
6666
|
+
await this.deselectNodeAndChildren(id);
|
|
6667
|
+
}
|
|
6668
|
+
// Note: Parent states (select/intermediate) are handled automatically by the tree component
|
|
6669
|
+
// with selectionBehavior: 'intermediate-nested'. We don't need to manually update them.
|
|
6603
6670
|
}
|
|
6604
6671
|
/**
|
|
6605
|
-
*
|
|
6606
|
-
* This is critical for pre-selected values in collapsed branches.
|
|
6672
|
+
* Selects a node and recursively selects all its children
|
|
6607
6673
|
*/
|
|
6608
|
-
async
|
|
6609
|
-
|
|
6674
|
+
async selectNodeAndChildren(nodeId) {
|
|
6675
|
+
const treeComponent = this.tree();
|
|
6676
|
+
if (!treeComponent) {
|
|
6610
6677
|
return;
|
|
6611
6678
|
}
|
|
6612
|
-
//
|
|
6613
|
-
|
|
6614
|
-
|
|
6679
|
+
// Set flag to prevent recursive updates during batch operation
|
|
6680
|
+
this.isUpdatingSelection = true;
|
|
6681
|
+
try {
|
|
6682
|
+
// Collect all nodes to select (node + all descendants)
|
|
6683
|
+
const nodesToSelect = new Set([nodeId]);
|
|
6684
|
+
await this.collectAllDescendants(nodeId, nodesToSelect);
|
|
6685
|
+
// Batch update selectedNodeIds
|
|
6686
|
+
const currentSelected = this.selectedNodeIds();
|
|
6687
|
+
const newSelected = [...currentSelected];
|
|
6688
|
+
for (const id of nodesToSelect) {
|
|
6689
|
+
if (!newSelected.includes(id)) {
|
|
6690
|
+
newSelected.push(id);
|
|
6691
|
+
}
|
|
6692
|
+
}
|
|
6693
|
+
this.selectedNodeIds.set(newSelected);
|
|
6694
|
+
// Batch select in tree component (with small delays to prevent glitches)
|
|
6695
|
+
for (const id of nodesToSelect) {
|
|
6696
|
+
try {
|
|
6697
|
+
const node = treeComponent.findNode(id);
|
|
6698
|
+
if (node) {
|
|
6699
|
+
treeComponent.selectNode(id);
|
|
6700
|
+
// Small delay to prevent overwhelming the tree component
|
|
6701
|
+
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
6702
|
+
}
|
|
6703
|
+
}
|
|
6704
|
+
catch {
|
|
6705
|
+
// Node might not be in tree yet
|
|
6706
|
+
}
|
|
6707
|
+
}
|
|
6708
|
+
}
|
|
6709
|
+
finally {
|
|
6710
|
+
this.isUpdatingSelection = false;
|
|
6711
|
+
}
|
|
6712
|
+
}
|
|
6713
|
+
/**
|
|
6714
|
+
* Collects all descendant node IDs recursively
|
|
6715
|
+
*/
|
|
6716
|
+
async collectAllDescendants(parentId, collection) {
|
|
6717
|
+
if (!this.treeData || !this.treeConfig || !parentId || parentId === 'all') {
|
|
6615
6718
|
return;
|
|
6616
6719
|
}
|
|
6617
6720
|
try {
|
|
6618
|
-
const
|
|
6619
|
-
|
|
6620
|
-
if (!categoryEntityQueryFunc) {
|
|
6721
|
+
const childNodes = await this.datasource(parentId);
|
|
6722
|
+
if (!childNodes || childNodes.length === 0) {
|
|
6621
6723
|
return;
|
|
6622
6724
|
}
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
})),
|
|
6632
|
-
logic: 'or',
|
|
6633
|
-
},
|
|
6634
|
-
};
|
|
6635
|
-
const res = await categoryEntityQueryFunc(event);
|
|
6636
|
-
if (res?.items) {
|
|
6637
|
-
// Cache the fetched node data
|
|
6638
|
-
res.items.forEach((item) => {
|
|
6639
|
-
const itemId = String(item[valueField] ?? '');
|
|
6640
|
-
if (itemId) {
|
|
6641
|
-
this.nodeDataCache.set(itemId, item);
|
|
6725
|
+
for (const childNode of childNodes) {
|
|
6726
|
+
const childId = String(childNode['id'] ?? '');
|
|
6727
|
+
if (childId && childId !== 'all' && !collection.has(childId)) {
|
|
6728
|
+
collection.add(childId);
|
|
6729
|
+
// Cache node data
|
|
6730
|
+
const nodeData = childNode['data'];
|
|
6731
|
+
if (nodeData && typeof nodeData === 'object') {
|
|
6732
|
+
this.nodeDataCache.set(childId, nodeData);
|
|
6642
6733
|
}
|
|
6643
|
-
|
|
6734
|
+
else if (childNode && typeof childNode === 'object') {
|
|
6735
|
+
const valueField = this.treeConfig.valueField || 'id';
|
|
6736
|
+
const textField = this.treeConfig.textField || 'title';
|
|
6737
|
+
const dataObj = {
|
|
6738
|
+
[valueField]: childId,
|
|
6739
|
+
[textField]: childNode['title'] ?? '',
|
|
6740
|
+
...childNode,
|
|
6741
|
+
};
|
|
6742
|
+
this.nodeDataCache.set(childId, dataObj);
|
|
6743
|
+
}
|
|
6744
|
+
// Recursively collect descendants
|
|
6745
|
+
await this.collectAllDescendants(childId, collection);
|
|
6746
|
+
}
|
|
6644
6747
|
}
|
|
6645
6748
|
}
|
|
6646
6749
|
catch (error) {
|
|
6647
|
-
console.error(
|
|
6750
|
+
console.error(`Error collecting descendants for node ${parentId}:`, error);
|
|
6648
6751
|
}
|
|
6649
6752
|
}
|
|
6650
6753
|
/**
|
|
6651
|
-
*
|
|
6652
|
-
* This ensures pre-selected nodes appear selected when the tree is rendered.
|
|
6754
|
+
* Deselects a node and recursively deselects all its children
|
|
6653
6755
|
*/
|
|
6654
|
-
|
|
6655
|
-
const
|
|
6656
|
-
if (
|
|
6756
|
+
async deselectNodeAndChildren(nodeId) {
|
|
6757
|
+
const treeComponent = this.tree();
|
|
6758
|
+
if (!treeComponent) {
|
|
6657
6759
|
return;
|
|
6658
6760
|
}
|
|
6659
|
-
//
|
|
6660
|
-
this.
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6761
|
+
// Set flag to prevent recursive updates during batch operation
|
|
6762
|
+
this.isUpdatingSelection = true;
|
|
6763
|
+
try {
|
|
6764
|
+
// Collect all nodes to deselect (node + all descendants)
|
|
6765
|
+
const nodesToDeselect = new Set([nodeId]);
|
|
6766
|
+
await this.collectAllDescendants(nodeId, nodesToDeselect);
|
|
6767
|
+
// Batch update selectedNodeIds
|
|
6768
|
+
const currentSelected = this.selectedNodeIds();
|
|
6769
|
+
const newSelected = currentSelected.filter((id) => !nodesToDeselect.has(id));
|
|
6770
|
+
this.selectedNodeIds.set(newSelected);
|
|
6771
|
+
// Batch deselect in tree component (with small delays to prevent glitches)
|
|
6772
|
+
for (const id of nodesToDeselect) {
|
|
6773
|
+
try {
|
|
6774
|
+
const node = treeComponent.findNode(id);
|
|
6775
|
+
if (node) {
|
|
6776
|
+
treeComponent.deselectNode(id);
|
|
6777
|
+
// Small delay to prevent overwhelming the tree component
|
|
6778
|
+
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
6779
|
+
}
|
|
6780
|
+
}
|
|
6781
|
+
catch {
|
|
6782
|
+
// Node might not be in tree
|
|
6783
|
+
}
|
|
6784
|
+
}
|
|
6667
6785
|
}
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
* Marks a single node as selected if it's in the selectedNodeIds list.
|
|
6671
|
-
*/
|
|
6672
|
-
markNodeAsSelectedIfNeeded(node) {
|
|
6673
|
-
const selectedIds = this.selectedNodeIds();
|
|
6674
|
-
const nodeId = String(node['id'] ?? '');
|
|
6675
|
-
if (nodeId && selectedIds.includes(nodeId)) {
|
|
6676
|
-
node['selected'] = true;
|
|
6786
|
+
finally {
|
|
6787
|
+
this.isUpdatingSelection = false;
|
|
6677
6788
|
}
|
|
6678
6789
|
}
|
|
6679
6790
|
/**
|
|
6680
|
-
*
|
|
6791
|
+
* Recursively deselects all children of a parent node
|
|
6681
6792
|
*/
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
node['disabled'] = true;
|
|
6793
|
+
async loadAndDeselectChildrenRecursively(parentId) {
|
|
6794
|
+
if (!this.treeData || !this.treeConfig || !parentId || parentId === 'all') {
|
|
6795
|
+
return;
|
|
6686
6796
|
}
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6797
|
+
const treeComponent = this.tree();
|
|
6798
|
+
if (!treeComponent) {
|
|
6799
|
+
return;
|
|
6800
|
+
}
|
|
6801
|
+
try {
|
|
6802
|
+
// Load children using datasource
|
|
6803
|
+
const childNodes = await this.datasource(parentId);
|
|
6804
|
+
if (!childNodes || childNodes.length === 0) {
|
|
6805
|
+
return;
|
|
6806
|
+
}
|
|
6807
|
+
const childIdsToDeselect = [];
|
|
6808
|
+
// Collect all child IDs
|
|
6809
|
+
for (const childNode of childNodes) {
|
|
6810
|
+
const childId = String(childNode['id'] ?? '');
|
|
6811
|
+
if (childId && childId !== 'all') {
|
|
6812
|
+
childIdsToDeselect.push(childId);
|
|
6813
|
+
}
|
|
6814
|
+
}
|
|
6815
|
+
// Remove children from selectedNodeIds
|
|
6816
|
+
const currentSelected = this.selectedNodeIds();
|
|
6817
|
+
const updatedSelected = currentSelected.filter((id) => !childIdsToDeselect.includes(id));
|
|
6818
|
+
this.selectedNodeIds.set(updatedSelected);
|
|
6819
|
+
// Deselect in tree component
|
|
6820
|
+
for (const childId of childIdsToDeselect) {
|
|
6821
|
+
try {
|
|
6822
|
+
treeComponent.deselectNode(childId);
|
|
6823
|
+
}
|
|
6824
|
+
catch {
|
|
6825
|
+
// Node might not be in tree
|
|
6826
|
+
}
|
|
6827
|
+
}
|
|
6828
|
+
// Recursively deselect children of each child
|
|
6829
|
+
await Promise.all(childIdsToDeselect.map((childId) => this.loadAndDeselectChildrenRecursively(childId)));
|
|
6830
|
+
}
|
|
6831
|
+
catch (error) {
|
|
6832
|
+
console.error(`Error deselecting children for node ${parentId}:`, error);
|
|
6693
6833
|
}
|
|
6694
6834
|
}
|
|
6695
6835
|
/**
|
|
6696
|
-
*
|
|
6836
|
+
* Updates parent states based on children selection (select/intermediate)
|
|
6837
|
+
* Called after a node is selected/deselected to update parent checkbox states
|
|
6697
6838
|
*/
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6839
|
+
async updateParentStates(changedNodeId) {
|
|
6840
|
+
if (!this.treeData || !this.treeConfig || !this.allowMultiple()) {
|
|
6841
|
+
return;
|
|
6842
|
+
}
|
|
6843
|
+
const parentKey = this.treeData.categoryEntityDef?.parentKey;
|
|
6844
|
+
if (!parentKey) {
|
|
6845
|
+
return; // No parent key means flat structure
|
|
6702
6846
|
}
|
|
6703
|
-
this.markNodesAsSelected(rootNode);
|
|
6704
|
-
// Sync selection with tree component after a short delay to ensure tree is rendered
|
|
6705
6847
|
const treeComponent = this.tree();
|
|
6706
|
-
if (treeComponent) {
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6848
|
+
if (!treeComponent) {
|
|
6849
|
+
return;
|
|
6850
|
+
}
|
|
6851
|
+
// Start from the changed node's parent and work up the tree
|
|
6852
|
+
const processedParents = new Set();
|
|
6853
|
+
let currentId = changedNodeId;
|
|
6854
|
+
// Process all parents up to root
|
|
6855
|
+
while (currentId && currentId !== 'all') {
|
|
6856
|
+
const nodeData = this.nodeDataCache.get(currentId);
|
|
6857
|
+
if (!nodeData) {
|
|
6858
|
+
break;
|
|
6859
|
+
}
|
|
6860
|
+
const parentId = nodeData[parentKey];
|
|
6861
|
+
const parentIdStr = String(parentId);
|
|
6862
|
+
if (!parentId || parentId === 'all' || parentId === currentId || processedParents.has(parentIdStr)) {
|
|
6863
|
+
break;
|
|
6864
|
+
}
|
|
6865
|
+
processedParents.add(parentIdStr);
|
|
6866
|
+
// Load all children of this parent
|
|
6867
|
+
try {
|
|
6868
|
+
const childNodes = await this.datasource(parentIdStr);
|
|
6869
|
+
if (!childNodes || childNodes.length === 0) {
|
|
6870
|
+
currentId = parentIdStr;
|
|
6871
|
+
continue;
|
|
6872
|
+
}
|
|
6873
|
+
// Get current selection state (updated after each parent change)
|
|
6874
|
+
const currentSelected = this.selectedNodeIds();
|
|
6875
|
+
const selectedSet = new Set(currentSelected);
|
|
6876
|
+
let selectedCount = 0;
|
|
6877
|
+
let totalCount = 0;
|
|
6878
|
+
// Count selected children
|
|
6879
|
+
for (const childNode of childNodes) {
|
|
6880
|
+
const childId = String(childNode['id'] ?? '');
|
|
6881
|
+
if (childId && childId !== 'all') {
|
|
6882
|
+
totalCount++;
|
|
6883
|
+
if (selectedSet.has(childId)) {
|
|
6884
|
+
selectedCount++;
|
|
6885
|
+
}
|
|
6712
6886
|
}
|
|
6713
|
-
}
|
|
6714
|
-
|
|
6887
|
+
}
|
|
6888
|
+
// Update parent selection state
|
|
6889
|
+
const isParentSelected = currentSelected.includes(parentIdStr);
|
|
6890
|
+
if (totalCount > 0) {
|
|
6891
|
+
if (selectedCount === totalCount) {
|
|
6892
|
+
// All children selected - select parent
|
|
6893
|
+
if (!isParentSelected) {
|
|
6894
|
+
this.selectedNodeIds.set([...currentSelected, parentIdStr]);
|
|
6895
|
+
try {
|
|
6896
|
+
treeComponent.selectNode(parentIdStr);
|
|
6897
|
+
}
|
|
6898
|
+
catch {
|
|
6899
|
+
// Parent might not be in tree
|
|
6900
|
+
}
|
|
6901
|
+
}
|
|
6902
|
+
}
|
|
6903
|
+
else if (selectedCount > 0) {
|
|
6904
|
+
// Some children selected - parent should be in intermediate state
|
|
6905
|
+
// The tree component handles intermediate state automatically via selectionBehavior
|
|
6906
|
+
// We just need to ensure parent is not fully selected
|
|
6907
|
+
if (isParentSelected) {
|
|
6908
|
+
// Deselect parent to show intermediate state
|
|
6909
|
+
this.selectedNodeIds.set(currentSelected.filter((id) => id !== parentIdStr));
|
|
6910
|
+
try {
|
|
6911
|
+
treeComponent.deselectNode(parentIdStr);
|
|
6912
|
+
}
|
|
6913
|
+
catch {
|
|
6914
|
+
// Parent might not be in tree
|
|
6915
|
+
}
|
|
6916
|
+
}
|
|
6917
|
+
}
|
|
6918
|
+
else {
|
|
6919
|
+
// No children selected - deselect parent
|
|
6920
|
+
if (isParentSelected) {
|
|
6921
|
+
this.selectedNodeIds.set(currentSelected.filter((id) => id !== parentIdStr));
|
|
6922
|
+
try {
|
|
6923
|
+
treeComponent.deselectNode(parentIdStr);
|
|
6924
|
+
}
|
|
6925
|
+
catch {
|
|
6926
|
+
// Parent might not be in tree
|
|
6927
|
+
}
|
|
6928
|
+
}
|
|
6929
|
+
}
|
|
6930
|
+
}
|
|
6931
|
+
// Cache parent data if not already cached
|
|
6932
|
+
if (!this.nodeDataCache.has(parentIdStr)) {
|
|
6933
|
+
const parentData = await this.fetchItemById(parentIdStr);
|
|
6934
|
+
if (parentData) {
|
|
6935
|
+
this.nodeDataCache.set(parentIdStr, parentData);
|
|
6936
|
+
}
|
|
6937
|
+
}
|
|
6938
|
+
currentId = parentIdStr;
|
|
6939
|
+
}
|
|
6940
|
+
catch (error) {
|
|
6941
|
+
console.error(`Error updating parent state for ${parentIdStr}:`, error);
|
|
6942
|
+
break;
|
|
6943
|
+
}
|
|
6715
6944
|
}
|
|
6716
6945
|
}
|
|
6717
6946
|
/**
|
|
6718
|
-
*
|
|
6947
|
+
* Recursively loads and selects all children of a parent node using the datasource
|
|
6948
|
+
* This method directly calls datasource without expanding/collapsing nodes to avoid UI glitches
|
|
6719
6949
|
*/
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
const nodeId = String(node['id'] ?? '');
|
|
6725
|
-
if (excludedId && nodeId === excludedId) {
|
|
6726
|
-
node['disabled'] = true;
|
|
6727
|
-
}
|
|
6728
|
-
if (nodeId && selectedIds.includes(nodeId)) {
|
|
6729
|
-
node['selected'] = true;
|
|
6730
|
-
}
|
|
6731
|
-
});
|
|
6732
|
-
// Sync selection with tree component
|
|
6950
|
+
async loadAndSelectChildrenRecursively(parentId) {
|
|
6951
|
+
if (!this.treeData || !this.treeConfig || !parentId || parentId === 'all') {
|
|
6952
|
+
return;
|
|
6953
|
+
}
|
|
6733
6954
|
const treeComponent = this.tree();
|
|
6734
|
-
if (treeComponent) {
|
|
6735
|
-
|
|
6955
|
+
if (!treeComponent) {
|
|
6956
|
+
return;
|
|
6957
|
+
}
|
|
6958
|
+
try {
|
|
6959
|
+
// Directly call datasource to get children data without expanding the node
|
|
6960
|
+
// This avoids UI glitches from expand/collapse operations
|
|
6961
|
+
// If node has no children, datasource will return empty array
|
|
6962
|
+
const childNodes = await this.datasource(parentId);
|
|
6963
|
+
if (!childNodes || childNodes.length === 0) {
|
|
6964
|
+
return; // No children to process
|
|
6965
|
+
}
|
|
6966
|
+
// Collect all child IDs to add to selectedNodeIds
|
|
6967
|
+
const childIdsToSelect = [];
|
|
6968
|
+
// Process all children and cache their data
|
|
6969
|
+
for (const childNode of childNodes) {
|
|
6970
|
+
const childId = String(childNode['id'] ?? '');
|
|
6971
|
+
if (childId && childId !== 'all') {
|
|
6972
|
+
childIdsToSelect.push(childId);
|
|
6973
|
+
// Cache node data for getSelectedItems
|
|
6974
|
+
// Try to get data from 'data' property first, then fallback to node itself
|
|
6975
|
+
let nodeData = childNode['data'];
|
|
6976
|
+
// If no data property, try to extract data from the node
|
|
6977
|
+
if (!nodeData || typeof nodeData !== 'object') {
|
|
6978
|
+
// Create a data object from the node properties
|
|
6979
|
+
const valueField = this.treeConfig.valueField || 'id';
|
|
6980
|
+
const textField = this.treeConfig.textField || 'title';
|
|
6981
|
+
nodeData = {
|
|
6982
|
+
[valueField]: childId,
|
|
6983
|
+
[textField]: childNode['title'] ?? '',
|
|
6984
|
+
...childNode,
|
|
6985
|
+
};
|
|
6986
|
+
}
|
|
6987
|
+
// Cache the node data
|
|
6988
|
+
if (nodeData && typeof nodeData === 'object') {
|
|
6989
|
+
this.nodeDataCache.set(childId, nodeData);
|
|
6990
|
+
}
|
|
6991
|
+
}
|
|
6992
|
+
}
|
|
6993
|
+
if (childIdsToSelect.length === 0) {
|
|
6994
|
+
return; // No valid children to select
|
|
6995
|
+
}
|
|
6996
|
+
// Update selectedNodeIds to include all children
|
|
6997
|
+
const currentSelected = this.selectedNodeIds();
|
|
6998
|
+
const newSelected = [...currentSelected];
|
|
6999
|
+
let hasNewSelections = false;
|
|
7000
|
+
for (const childId of childIdsToSelect) {
|
|
7001
|
+
if (!newSelected.includes(childId)) {
|
|
7002
|
+
newSelected.push(childId);
|
|
7003
|
+
hasNewSelections = true;
|
|
7004
|
+
}
|
|
7005
|
+
}
|
|
7006
|
+
if (hasNewSelections) {
|
|
7007
|
+
this.selectedNodeIds.set(newSelected);
|
|
7008
|
+
}
|
|
7009
|
+
// Try to select children in tree component if they're already loaded
|
|
7010
|
+
// If not loaded yet, they'll be selected when the tree loads them (via markNodeAsSelectedIfNeeded)
|
|
7011
|
+
for (const childId of childIdsToSelect) {
|
|
7012
|
+
try {
|
|
7013
|
+
// Only try to select if node exists in tree (might not be loaded if parent isn't expanded)
|
|
7014
|
+
const node = treeComponent.findNode(childId);
|
|
7015
|
+
if (node) {
|
|
7016
|
+
treeComponent.selectNode(childId);
|
|
7017
|
+
}
|
|
7018
|
+
}
|
|
7019
|
+
catch {
|
|
7020
|
+
// If selection fails, it's okay - we've already added to selectedNodeIds
|
|
7021
|
+
// The tree will sync selection when the node is loaded via datasource callback
|
|
7022
|
+
}
|
|
7023
|
+
}
|
|
7024
|
+
// Recursively load and select children of each child
|
|
7025
|
+
// Use Promise.all for parallel processing to improve performance
|
|
7026
|
+
await Promise.all(childIdsToSelect.map((childId) => this.loadAndSelectChildrenRecursively(childId)));
|
|
7027
|
+
}
|
|
7028
|
+
catch (error) {
|
|
7029
|
+
console.error(`Error loading children for node ${parentId}:`, error);
|
|
7030
|
+
}
|
|
7031
|
+
}
|
|
7032
|
+
//#endregion
|
|
7033
|
+
async updateSelectedNodes(selectedIds) {
|
|
7034
|
+
if (!selectedIds || selectedIds.length === 0) {
|
|
7035
|
+
this.selectedNodeIds.set([]);
|
|
7036
|
+
return;
|
|
7037
|
+
}
|
|
7038
|
+
const ids = selectedIds.filter((id) => id && id !== 'all');
|
|
7039
|
+
// Set flag to prevent recursive updates during initialization
|
|
7040
|
+
this.isUpdatingSelection = true;
|
|
7041
|
+
try {
|
|
7042
|
+
// Fetch node data for pre-selected items that aren't in the cache
|
|
7043
|
+
await this.loadMissingNodeData(ids);
|
|
7044
|
+
// Collect all nodes to select (pre-selected + all their descendants)
|
|
7045
|
+
const allNodesToSelect = new Set(ids);
|
|
7046
|
+
for (const nodeId of ids) {
|
|
7047
|
+
await this.collectAllDescendants(nodeId, allNodesToSelect);
|
|
7048
|
+
}
|
|
7049
|
+
// Set all selected nodes at once
|
|
7050
|
+
this.selectedNodeIds.set(Array.from(allNodesToSelect));
|
|
7051
|
+
// Expand parents of pre-selected nodes so they're visible in the tree
|
|
7052
|
+
await this.expandParentsOfSelectedNodes(Array.from(allNodesToSelect));
|
|
7053
|
+
// Sync selection with tree component - wait for tree to be ready
|
|
7054
|
+
await this.syncSelectionWithTree(Array.from(allNodesToSelect));
|
|
7055
|
+
}
|
|
7056
|
+
finally {
|
|
7057
|
+
this.isUpdatingSelection = false;
|
|
7058
|
+
}
|
|
7059
|
+
}
|
|
7060
|
+
/**
|
|
7061
|
+
* Updates all parent states based on their children's selection
|
|
7062
|
+
* Used during initialization to ensure proper parent states (select/intermediate)
|
|
7063
|
+
*/
|
|
7064
|
+
async updateAllParentStates(selectedIds) {
|
|
7065
|
+
if (!this.treeData || !this.treeConfig || !this.allowMultiple() || selectedIds.length === 0) {
|
|
7066
|
+
return;
|
|
7067
|
+
}
|
|
7068
|
+
const parentKey = this.treeData.categoryEntityDef?.parentKey;
|
|
7069
|
+
if (!parentKey) {
|
|
7070
|
+
return;
|
|
7071
|
+
}
|
|
7072
|
+
const treeComponent = this.tree();
|
|
7073
|
+
if (!treeComponent) {
|
|
7074
|
+
return;
|
|
7075
|
+
}
|
|
7076
|
+
const selectedSet = new Set(selectedIds);
|
|
7077
|
+
const processedParents = new Set();
|
|
7078
|
+
// Collect all unique parent IDs
|
|
7079
|
+
for (const selectedId of selectedIds) {
|
|
7080
|
+
if (selectedId === 'all') {
|
|
7081
|
+
continue;
|
|
7082
|
+
}
|
|
7083
|
+
const nodeData = this.nodeDataCache.get(selectedId);
|
|
7084
|
+
if (!nodeData) {
|
|
7085
|
+
continue;
|
|
7086
|
+
}
|
|
7087
|
+
let currentId = selectedId;
|
|
7088
|
+
while (currentId && currentId !== 'all') {
|
|
7089
|
+
const currentNodeData = this.nodeDataCache.get(currentId);
|
|
7090
|
+
if (!currentNodeData) {
|
|
7091
|
+
break;
|
|
7092
|
+
}
|
|
7093
|
+
const parentId = currentNodeData[parentKey];
|
|
7094
|
+
const parentIdStr = String(parentId);
|
|
7095
|
+
if (!parentId || parentId === 'all' || parentId === currentId || processedParents.has(parentIdStr)) {
|
|
7096
|
+
break;
|
|
7097
|
+
}
|
|
7098
|
+
processedParents.add(parentIdStr);
|
|
7099
|
+
currentId = parentIdStr;
|
|
7100
|
+
}
|
|
7101
|
+
}
|
|
7102
|
+
// Process parents multiple times to handle cascading parent selections
|
|
7103
|
+
// (when a parent is selected, its parent might also need to be selected)
|
|
7104
|
+
let hasChanges = true;
|
|
7105
|
+
let iterations = 0;
|
|
7106
|
+
const maxIterations = 10; // Prevent infinite loops
|
|
7107
|
+
while (hasChanges && iterations < maxIterations) {
|
|
7108
|
+
iterations++;
|
|
7109
|
+
hasChanges = false;
|
|
7110
|
+
// Update selectedSet with current selectedNodeIds
|
|
7111
|
+
const currentSelected = this.selectedNodeIds();
|
|
7112
|
+
currentSelected.forEach((id) => selectedSet.add(id));
|
|
7113
|
+
// Update each parent's state
|
|
7114
|
+
for (const parentId of processedParents) {
|
|
7115
|
+
try {
|
|
7116
|
+
const childNodes = await this.datasource(parentId);
|
|
7117
|
+
if (!childNodes || childNodes.length === 0) {
|
|
7118
|
+
continue;
|
|
7119
|
+
}
|
|
7120
|
+
let selectedCount = 0;
|
|
7121
|
+
let totalCount = 0;
|
|
7122
|
+
for (const childNode of childNodes) {
|
|
7123
|
+
const childId = String(childNode['id'] ?? '');
|
|
7124
|
+
if (childId && childId !== 'all') {
|
|
7125
|
+
totalCount++;
|
|
7126
|
+
if (selectedSet.has(childId)) {
|
|
7127
|
+
selectedCount++;
|
|
7128
|
+
}
|
|
7129
|
+
}
|
|
7130
|
+
}
|
|
7131
|
+
const isParentSelected = currentSelected.includes(parentId);
|
|
7132
|
+
if (totalCount > 0) {
|
|
7133
|
+
if (selectedCount === totalCount) {
|
|
7134
|
+
// All children selected - select parent
|
|
7135
|
+
if (!isParentSelected) {
|
|
7136
|
+
this.selectedNodeIds.set([...currentSelected, parentId]);
|
|
7137
|
+
selectedSet.add(parentId);
|
|
7138
|
+
hasChanges = true;
|
|
7139
|
+
try {
|
|
7140
|
+
treeComponent.selectNode(parentId);
|
|
7141
|
+
}
|
|
7142
|
+
catch {
|
|
7143
|
+
// Parent might not be in tree
|
|
7144
|
+
}
|
|
7145
|
+
}
|
|
7146
|
+
}
|
|
7147
|
+
else if (selectedCount > 0) {
|
|
7148
|
+
// Some children selected - parent should be in intermediate state
|
|
7149
|
+
if (isParentSelected) {
|
|
7150
|
+
// Deselect parent to show intermediate state
|
|
7151
|
+
this.selectedNodeIds.set(currentSelected.filter((id) => id !== parentId));
|
|
7152
|
+
selectedSet.delete(parentId);
|
|
7153
|
+
hasChanges = true;
|
|
7154
|
+
try {
|
|
7155
|
+
treeComponent.deselectNode(parentId);
|
|
7156
|
+
}
|
|
7157
|
+
catch {
|
|
7158
|
+
// Parent might not be in tree
|
|
7159
|
+
}
|
|
7160
|
+
}
|
|
7161
|
+
}
|
|
7162
|
+
else {
|
|
7163
|
+
// No children selected - deselect parent
|
|
7164
|
+
if (isParentSelected) {
|
|
7165
|
+
this.selectedNodeIds.set(currentSelected.filter((id) => id !== parentId));
|
|
7166
|
+
selectedSet.delete(parentId);
|
|
7167
|
+
hasChanges = true;
|
|
7168
|
+
try {
|
|
7169
|
+
treeComponent.deselectNode(parentId);
|
|
7170
|
+
}
|
|
7171
|
+
catch {
|
|
7172
|
+
// Parent might not be in tree
|
|
7173
|
+
}
|
|
7174
|
+
}
|
|
7175
|
+
}
|
|
7176
|
+
}
|
|
7177
|
+
}
|
|
7178
|
+
catch (error) {
|
|
7179
|
+
console.error(`Error updating parent state for ${parentId}:`, error);
|
|
7180
|
+
}
|
|
7181
|
+
}
|
|
7182
|
+
}
|
|
7183
|
+
}
|
|
7184
|
+
/**
|
|
7185
|
+
* Expands parents of selected nodes so they're visible when popup opens
|
|
7186
|
+
*/
|
|
7187
|
+
async expandParentsOfSelectedNodes(selectedIds) {
|
|
7188
|
+
if (!this.treeData || !this.treeConfig || selectedIds.length === 0) {
|
|
7189
|
+
return;
|
|
7190
|
+
}
|
|
7191
|
+
const parentKey = this.treeData.categoryEntityDef?.parentKey;
|
|
7192
|
+
if (!parentKey) {
|
|
7193
|
+
return; // No parent key means flat structure
|
|
7194
|
+
}
|
|
7195
|
+
const treeComponent = this.tree();
|
|
7196
|
+
if (!treeComponent) {
|
|
7197
|
+
return;
|
|
7198
|
+
}
|
|
7199
|
+
// Collect all unique parent IDs that need to be expanded
|
|
7200
|
+
const parentsToExpand = new Set();
|
|
7201
|
+
for (const selectedId of selectedIds) {
|
|
7202
|
+
if (selectedId === 'all') {
|
|
7203
|
+
continue;
|
|
7204
|
+
}
|
|
7205
|
+
const nodeData = this.nodeDataCache.get(selectedId);
|
|
7206
|
+
if (!nodeData) {
|
|
7207
|
+
continue;
|
|
7208
|
+
}
|
|
7209
|
+
const parentId = nodeData[parentKey];
|
|
7210
|
+
if (parentId && parentId !== 'all') {
|
|
7211
|
+
const parentIdStr = String(parentId);
|
|
7212
|
+
parentsToExpand.add(parentIdStr);
|
|
7213
|
+
// Also expand grandparents, etc.
|
|
7214
|
+
let currentParentId = parentIdStr;
|
|
7215
|
+
while (currentParentId) {
|
|
7216
|
+
const parentData = this.nodeDataCache.get(currentParentId);
|
|
7217
|
+
if (!parentData) {
|
|
7218
|
+
break;
|
|
7219
|
+
}
|
|
7220
|
+
const grandParentId = parentData[parentKey];
|
|
7221
|
+
if (grandParentId && grandParentId !== 'all' && grandParentId !== currentParentId) {
|
|
7222
|
+
parentsToExpand.add(String(grandParentId));
|
|
7223
|
+
currentParentId = String(grandParentId);
|
|
7224
|
+
}
|
|
7225
|
+
else {
|
|
7226
|
+
break;
|
|
7227
|
+
}
|
|
7228
|
+
}
|
|
7229
|
+
}
|
|
7230
|
+
}
|
|
7231
|
+
// Expand all parents (starting from root to leaves)
|
|
7232
|
+
const sortedParents = Array.from(parentsToExpand).sort((a, b) => {
|
|
7233
|
+
// Simple sort - expand root nodes first
|
|
7234
|
+
return a.localeCompare(b);
|
|
7235
|
+
});
|
|
7236
|
+
for (const parentId of sortedParents) {
|
|
7237
|
+
try {
|
|
7238
|
+
if (!treeComponent.isNodeExpanded(parentId)) {
|
|
7239
|
+
await treeComponent.expandNode(parentId);
|
|
7240
|
+
// Small delay to ensure children are loaded
|
|
7241
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
7242
|
+
}
|
|
7243
|
+
}
|
|
7244
|
+
catch {
|
|
7245
|
+
// Parent might not be in tree yet, ignore
|
|
7246
|
+
}
|
|
7247
|
+
}
|
|
7248
|
+
}
|
|
7249
|
+
/**
|
|
7250
|
+
* Selects parents whose all children are selected
|
|
7251
|
+
* This ensures that when all children of a parent are selected, the parent also appears selected
|
|
7252
|
+
*/
|
|
7253
|
+
async selectParentsWithAllChildrenSelected(selectedIds) {
|
|
7254
|
+
if (!this.treeData || !this.treeConfig || selectedIds.length === 0) {
|
|
7255
|
+
return;
|
|
7256
|
+
}
|
|
7257
|
+
const parentKey = this.treeData.categoryEntityDef?.parentKey;
|
|
7258
|
+
if (!parentKey) {
|
|
7259
|
+
return; // No parent key means flat structure
|
|
7260
|
+
}
|
|
7261
|
+
// Use current selectedNodeIds signal value (may have been updated)
|
|
7262
|
+
const currentSelectedIds = this.selectedNodeIds();
|
|
7263
|
+
const selectedSet = new Set(currentSelectedIds);
|
|
7264
|
+
const processedParents = new Set();
|
|
7265
|
+
const parentsToSelect = new Set();
|
|
7266
|
+
// For each selected node, check its parent
|
|
7267
|
+
for (const selectedId of currentSelectedIds) {
|
|
7268
|
+
if (selectedId === 'all') {
|
|
7269
|
+
continue;
|
|
7270
|
+
}
|
|
7271
|
+
// Get parent ID from cached data
|
|
7272
|
+
const nodeData = this.nodeDataCache.get(selectedId);
|
|
7273
|
+
if (!nodeData) {
|
|
7274
|
+
continue;
|
|
7275
|
+
}
|
|
7276
|
+
const parentId = nodeData[parentKey];
|
|
7277
|
+
if (!parentId || parentId === 'all' || processedParents.has(String(parentId))) {
|
|
7278
|
+
continue;
|
|
7279
|
+
}
|
|
7280
|
+
const parentIdStr = String(parentId);
|
|
7281
|
+
processedParents.add(parentIdStr);
|
|
7282
|
+
// Load all children of this parent
|
|
7283
|
+
try {
|
|
7284
|
+
const childNodes = await this.datasource(parentIdStr);
|
|
7285
|
+
if (!childNodes || childNodes.length === 0) {
|
|
7286
|
+
continue;
|
|
7287
|
+
}
|
|
7288
|
+
// Check if all children are selected
|
|
7289
|
+
let allChildrenSelected = true;
|
|
7290
|
+
let hasChildren = false;
|
|
7291
|
+
for (const childNode of childNodes) {
|
|
7292
|
+
const childId = String(childNode['id'] ?? '');
|
|
7293
|
+
if (childId && childId !== 'all') {
|
|
7294
|
+
hasChildren = true;
|
|
7295
|
+
if (!selectedSet.has(childId)) {
|
|
7296
|
+
allChildrenSelected = false;
|
|
7297
|
+
break;
|
|
7298
|
+
}
|
|
7299
|
+
}
|
|
7300
|
+
}
|
|
7301
|
+
// If parent has children and all are selected, mark parent for selection
|
|
7302
|
+
if (hasChildren && allChildrenSelected) {
|
|
7303
|
+
parentsToSelect.add(parentIdStr);
|
|
7304
|
+
// Cache parent data if not already cached
|
|
7305
|
+
if (!this.nodeDataCache.has(parentIdStr)) {
|
|
7306
|
+
const parentData = await this.fetchItemById(parentIdStr);
|
|
7307
|
+
if (parentData) {
|
|
7308
|
+
this.nodeDataCache.set(parentIdStr, parentData);
|
|
7309
|
+
}
|
|
7310
|
+
}
|
|
7311
|
+
}
|
|
7312
|
+
}
|
|
7313
|
+
catch (error) {
|
|
7314
|
+
console.error(`Error checking parent ${parentIdStr}:`, error);
|
|
7315
|
+
}
|
|
7316
|
+
}
|
|
7317
|
+
// Add parents to selectedNodeIds
|
|
7318
|
+
if (parentsToSelect.size > 0) {
|
|
7319
|
+
const currentSelected = this.selectedNodeIds();
|
|
7320
|
+
const newSelected = [...currentSelected];
|
|
7321
|
+
let hasNewSelections = false;
|
|
7322
|
+
for (const parentId of parentsToSelect) {
|
|
7323
|
+
if (!newSelected.includes(parentId)) {
|
|
7324
|
+
newSelected.push(parentId);
|
|
7325
|
+
hasNewSelections = true;
|
|
7326
|
+
}
|
|
7327
|
+
}
|
|
7328
|
+
if (hasNewSelections) {
|
|
7329
|
+
this.selectedNodeIds.set(newSelected);
|
|
7330
|
+
// Recursively check parents of these parents
|
|
7331
|
+
const updatedSelected = this.selectedNodeIds();
|
|
7332
|
+
await this.selectParentsWithAllChildrenSelected(updatedSelected);
|
|
7333
|
+
}
|
|
7334
|
+
}
|
|
7335
|
+
}
|
|
7336
|
+
/**
|
|
7337
|
+
* Syncs selection state with the tree component
|
|
7338
|
+
* Handles cases where nodes might not be in the tree structure yet
|
|
7339
|
+
*/
|
|
7340
|
+
async syncSelectionWithTree(selectedIds) {
|
|
7341
|
+
const treeComponent = this.tree();
|
|
7342
|
+
if (!treeComponent || selectedIds.length === 0) {
|
|
7343
|
+
return;
|
|
7344
|
+
}
|
|
7345
|
+
// Wait for tree to be fully initialized and rendered
|
|
7346
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
7347
|
+
// Try multiple times to sync selection (nodes might load progressively)
|
|
7348
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
7349
|
+
let syncedCount = 0;
|
|
7350
|
+
selectedIds.forEach((id) => {
|
|
7351
|
+
if (id && id !== 'all') {
|
|
7352
|
+
try {
|
|
7353
|
+
const node = treeComponent.findNode(id);
|
|
7354
|
+
if (node) {
|
|
7355
|
+
// Node exists in tree, select it
|
|
7356
|
+
treeComponent.selectNode(id);
|
|
7357
|
+
syncedCount++;
|
|
7358
|
+
}
|
|
7359
|
+
}
|
|
7360
|
+
catch {
|
|
7361
|
+
// Node not in tree yet - will be selected when loaded via datasource callback
|
|
7362
|
+
}
|
|
7363
|
+
}
|
|
7364
|
+
});
|
|
7365
|
+
// If all nodes are synced, we're done
|
|
7366
|
+
if (syncedCount === selectedIds.length) {
|
|
7367
|
+
break;
|
|
7368
|
+
}
|
|
7369
|
+
// Wait a bit before next attempt
|
|
7370
|
+
if (attempt < 2) {
|
|
7371
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
7372
|
+
}
|
|
7373
|
+
}
|
|
7374
|
+
// After syncing, read back from tree component to get any parents that were automatically selected
|
|
7375
|
+
// (due to intermediate-nested behavior when all children are selected)
|
|
7376
|
+
if (this.allowMultiple()) {
|
|
7377
|
+
try {
|
|
7378
|
+
const treeSelectedNodes = treeComponent.getSelectedNodes();
|
|
7379
|
+
const treeSelectedIds = treeSelectedNodes
|
|
7380
|
+
.map((node) => String(node['id'] ?? ''))
|
|
7381
|
+
.filter((id) => id && id !== 'all');
|
|
7382
|
+
// Update selectedNodeIds to match tree component's state (includes auto-selected parents)
|
|
7383
|
+
this.selectedNodeIds.set(treeSelectedIds);
|
|
7384
|
+
}
|
|
7385
|
+
catch {
|
|
7386
|
+
// Tree component might not be ready yet
|
|
7387
|
+
}
|
|
7388
|
+
}
|
|
7389
|
+
// Note: Selection state is maintained in selectedNodeIds signal
|
|
7390
|
+
// The tree component will sync selection state when nodes are loaded via datasource
|
|
7391
|
+
// We mark nodes as selected in the datasource callback by setting node.selected = true
|
|
7392
|
+
// Nodes that aren't in the tree yet will be selected when their parent is expanded
|
|
7393
|
+
}
|
|
7394
|
+
/**
|
|
7395
|
+
* Loads node data for IDs that are selected but not yet in the cache.
|
|
7396
|
+
* This is critical for pre-selected values in collapsed branches.
|
|
7397
|
+
*/
|
|
7398
|
+
async loadMissingNodeData(selectedIds) {
|
|
7399
|
+
if (!this.treeData || !this.treeConfig || selectedIds.length === 0) {
|
|
7400
|
+
return;
|
|
7401
|
+
}
|
|
7402
|
+
// Find IDs that are selected but not in cache
|
|
7403
|
+
const missingIds = selectedIds.filter((id) => !this.nodeDataCache.has(id));
|
|
7404
|
+
if (missingIds.length === 0) {
|
|
7405
|
+
return;
|
|
7406
|
+
}
|
|
7407
|
+
try {
|
|
7408
|
+
const valueField = this.treeConfig.valueField || 'id';
|
|
7409
|
+
const categoryEntityQueryFunc = this.treeData.categoryEntityQueryFunc;
|
|
7410
|
+
if (!categoryEntityQueryFunc) {
|
|
7411
|
+
return;
|
|
7412
|
+
}
|
|
7413
|
+
// Query for missing nodes by their IDs
|
|
7414
|
+
const event = {
|
|
7415
|
+
...this.treeData.basicQueryEvent,
|
|
7416
|
+
filter: {
|
|
7417
|
+
filters: missingIds.map((id) => ({
|
|
7418
|
+
field: valueField,
|
|
7419
|
+
value: id,
|
|
7420
|
+
operator: { type: 'equal' },
|
|
7421
|
+
})),
|
|
7422
|
+
logic: 'or',
|
|
7423
|
+
},
|
|
7424
|
+
};
|
|
7425
|
+
const res = await categoryEntityQueryFunc(event);
|
|
7426
|
+
if (res?.items) {
|
|
7427
|
+
// Cache the fetched node data
|
|
7428
|
+
res.items.forEach((item) => {
|
|
7429
|
+
const itemId = String(item[valueField] ?? '');
|
|
7430
|
+
if (itemId) {
|
|
7431
|
+
this.nodeDataCache.set(itemId, item);
|
|
7432
|
+
}
|
|
7433
|
+
});
|
|
7434
|
+
}
|
|
7435
|
+
}
|
|
7436
|
+
catch (error) {
|
|
7437
|
+
console.error('Error loading missing node data:', error);
|
|
7438
|
+
}
|
|
7439
|
+
}
|
|
7440
|
+
/**
|
|
7441
|
+
* Marks nodes as selected in the tree structure based on selectedNodeIds.
|
|
7442
|
+
* This ensures pre-selected nodes appear selected when the tree is rendered.
|
|
7443
|
+
*/
|
|
7444
|
+
markNodesAsSelected(node) {
|
|
7445
|
+
const selectedIds = this.selectedNodeIds();
|
|
7446
|
+
if (selectedIds.length === 0) {
|
|
7447
|
+
return;
|
|
7448
|
+
}
|
|
7449
|
+
// Mark the node itself if it's selected
|
|
7450
|
+
this.markNodeAsSelectedIfNeeded(node);
|
|
7451
|
+
// Recursively mark children
|
|
7452
|
+
const nodeChildren = node['children'];
|
|
7453
|
+
if (nodeChildren) {
|
|
7454
|
+
nodeChildren.forEach((child) => {
|
|
7455
|
+
this.markNodesAsSelected(child);
|
|
7456
|
+
});
|
|
7457
|
+
}
|
|
7458
|
+
}
|
|
7459
|
+
/**
|
|
7460
|
+
* Marks a single node as selected if it's in the selectedNodeIds list.
|
|
7461
|
+
*/
|
|
7462
|
+
markNodeAsSelectedIfNeeded(node) {
|
|
7463
|
+
const selectedIds = this.selectedNodeIds();
|
|
7464
|
+
const nodeId = String(node['id'] ?? '');
|
|
7465
|
+
if (nodeId && selectedIds.includes(nodeId)) {
|
|
7466
|
+
node['selected'] = true;
|
|
7467
|
+
}
|
|
7468
|
+
}
|
|
7469
|
+
/**
|
|
7470
|
+
* Marks a node and its children as disabled if the node ID matches the excluded ID.
|
|
7471
|
+
*/
|
|
7472
|
+
markNodeAsDisabled(node, excludedId) {
|
|
7473
|
+
const nodeId = String(node['id'] ?? '');
|
|
7474
|
+
if (nodeId === excludedId) {
|
|
7475
|
+
node['disabled'] = true;
|
|
7476
|
+
}
|
|
7477
|
+
// Recursively mark children
|
|
7478
|
+
const nodeChildren = node['children'];
|
|
7479
|
+
if (nodeChildren) {
|
|
7480
|
+
nodeChildren.forEach((child) => {
|
|
7481
|
+
this.markNodeAsDisabled(child, excludedId);
|
|
7482
|
+
});
|
|
7483
|
+
}
|
|
7484
|
+
}
|
|
7485
|
+
/**
|
|
7486
|
+
* Processes root node: marks excluded as disabled, marks selected, and syncs selection with tree component
|
|
7487
|
+
*/
|
|
7488
|
+
processRootNode(rootNode) {
|
|
7489
|
+
const excludedId = this.excludedNodeId();
|
|
7490
|
+
if (excludedId) {
|
|
7491
|
+
this.markNodeAsDisabled(rootNode, excludedId);
|
|
7492
|
+
}
|
|
7493
|
+
this.markNodesAsSelected(rootNode);
|
|
7494
|
+
// Sync selection with tree component after a short delay to ensure tree is rendered
|
|
7495
|
+
const treeComponent = this.tree();
|
|
7496
|
+
if (treeComponent) {
|
|
7497
|
+
setTimeout(() => {
|
|
7498
|
+
const selectedIds = this.selectedNodeIds();
|
|
7499
|
+
selectedIds.forEach((id) => {
|
|
7500
|
+
if (id && id !== 'all') {
|
|
7501
|
+
treeComponent.selectNode(id);
|
|
7502
|
+
}
|
|
7503
|
+
});
|
|
7504
|
+
}, 0);
|
|
7505
|
+
}
|
|
7506
|
+
}
|
|
7507
|
+
/**
|
|
7508
|
+
* Processes child nodes: marks excluded as disabled, marks selected, and syncs selection
|
|
7509
|
+
*/
|
|
7510
|
+
processChildNodes(childNodes) {
|
|
7511
|
+
const excludedId = this.excludedNodeId();
|
|
7512
|
+
const selectedIds = this.selectedNodeIds();
|
|
7513
|
+
childNodes.forEach((node) => {
|
|
7514
|
+
const nodeId = String(node['id'] ?? '');
|
|
7515
|
+
if (excludedId && nodeId === excludedId) {
|
|
7516
|
+
node['disabled'] = true;
|
|
7517
|
+
}
|
|
7518
|
+
if (nodeId && selectedIds.includes(nodeId)) {
|
|
7519
|
+
node['selected'] = true;
|
|
7520
|
+
}
|
|
7521
|
+
});
|
|
7522
|
+
// Sync selection with tree component
|
|
7523
|
+
const treeComponent = this.tree();
|
|
7524
|
+
if (treeComponent) {
|
|
7525
|
+
setTimeout(() => {
|
|
6736
7526
|
childNodes.forEach((node) => {
|
|
6737
7527
|
const nodeId = String(node['id'] ?? '');
|
|
6738
7528
|
if (nodeId && selectedIds.includes(nodeId) && nodeId !== 'all') {
|
|
@@ -6887,41 +7677,107 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6887
7677
|
const textField = this.treeConfig.textField || 'title';
|
|
6888
7678
|
return String(nodeData[textField] ?? '');
|
|
6889
7679
|
}
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
7680
|
+
/**
|
|
7681
|
+
* Checks if a node is a leaf node (has no children)
|
|
7682
|
+
*/
|
|
7683
|
+
async isLeafNode(nodeId, treeComponent) {
|
|
7684
|
+
if (!treeComponent) {
|
|
7685
|
+
// If no tree component, check if node has children by querying
|
|
7686
|
+
return await this.checkIfNodeHasChildren(nodeId);
|
|
7687
|
+
}
|
|
7688
|
+
try {
|
|
7689
|
+
const node = treeComponent.findNode(nodeId);
|
|
7690
|
+
if (!node) {
|
|
7691
|
+
// Node not found in tree, check via query
|
|
7692
|
+
return await this.checkIfNodeHasChildren(nodeId);
|
|
7693
|
+
}
|
|
7694
|
+
// Check if node has children
|
|
7695
|
+
const children = node['children'];
|
|
7696
|
+
const childrenCount = node['childrenCount'];
|
|
7697
|
+
// If children are loaded, check the array
|
|
7698
|
+
if (children !== undefined) {
|
|
7699
|
+
return !children || children.length === 0;
|
|
7700
|
+
}
|
|
7701
|
+
// If childrenCount is available, use it
|
|
7702
|
+
if (childrenCount !== undefined) {
|
|
7703
|
+
return childrenCount === 0;
|
|
7704
|
+
}
|
|
7705
|
+
// If neither is available, try to check via query
|
|
7706
|
+
return await this.checkIfNodeHasChildren(nodeId);
|
|
7707
|
+
}
|
|
7708
|
+
catch {
|
|
7709
|
+
// If findNode fails, check via query
|
|
7710
|
+
return await this.checkIfNodeHasChildren(nodeId);
|
|
7711
|
+
}
|
|
7712
|
+
}
|
|
7713
|
+
/**
|
|
7714
|
+
* Checks if a node has children by querying the data source
|
|
7715
|
+
*/
|
|
7716
|
+
async checkIfNodeHasChildren(nodeId) {
|
|
7717
|
+
if (!this.treeData?.categoryEntityQueryFunc || !this.treeConfig) {
|
|
7718
|
+
return true; // Assume leaf if we can't check
|
|
7719
|
+
}
|
|
7720
|
+
try {
|
|
7721
|
+
const parentKey = this.treeData.categoryEntityDef?.parentKey;
|
|
7722
|
+
if (!parentKey) {
|
|
7723
|
+
return true; // No parent key means flat structure, all nodes are leaves
|
|
7724
|
+
}
|
|
7725
|
+
const event = {
|
|
7726
|
+
...this.treeData.basicQueryEvent,
|
|
7727
|
+
filter: {
|
|
7728
|
+
field: parentKey,
|
|
7729
|
+
value: nodeId,
|
|
7730
|
+
operator: { type: 'equal' },
|
|
7731
|
+
},
|
|
7732
|
+
take: 1, // Only need to check if any children exist
|
|
7733
|
+
};
|
|
7734
|
+
const res = await this.treeData.categoryEntityQueryFunc(event);
|
|
7735
|
+
return !res?.items || res.items.length === 0;
|
|
6913
7736
|
}
|
|
6914
|
-
|
|
7737
|
+
catch {
|
|
7738
|
+
return true; // Assume leaf on error
|
|
7739
|
+
}
|
|
7740
|
+
}
|
|
7741
|
+
async getSelectedItems() {
|
|
7742
|
+
// Always use selectedNodeIds as the source of truth
|
|
7743
|
+
// This ensures we get all selected nodes, even if they're not in the tree structure yet
|
|
6915
7744
|
const selectedIds = this.selectedNodeIds();
|
|
6916
7745
|
if (selectedIds.length === 0) {
|
|
6917
7746
|
return [];
|
|
6918
7747
|
}
|
|
7748
|
+
const treeComponent = this.tree();
|
|
6919
7749
|
// Get node data from cache and calculate paths
|
|
7750
|
+
// For nodes not in cache, try to get from tree component
|
|
6920
7751
|
const items = await Promise.all(selectedIds.map(async (id) => {
|
|
6921
|
-
|
|
7752
|
+
// First try to get from cache
|
|
7753
|
+
let nodeData = this.nodeDataCache.get(id);
|
|
7754
|
+
// If not in cache, try to get from tree component
|
|
7755
|
+
if (!nodeData && treeComponent) {
|
|
7756
|
+
try {
|
|
7757
|
+
const node = treeComponent.findNode(id);
|
|
7758
|
+
if (node) {
|
|
7759
|
+
nodeData = node['data'] || node;
|
|
7760
|
+
// Cache it for future use
|
|
7761
|
+
if (nodeData && typeof nodeData === 'object') {
|
|
7762
|
+
this.nodeDataCache.set(id, nodeData);
|
|
7763
|
+
}
|
|
7764
|
+
}
|
|
7765
|
+
}
|
|
7766
|
+
catch {
|
|
7767
|
+
// Node not found in tree, continue with cache lookup
|
|
7768
|
+
}
|
|
7769
|
+
}
|
|
7770
|
+
// If still no data, skip this node
|
|
6922
7771
|
if (!nodeData) {
|
|
6923
7772
|
return null;
|
|
6924
7773
|
}
|
|
7774
|
+
// When selectionBehavior is intermediate-nested, only return leaf nodes
|
|
7775
|
+
if (this.allowMultiple()) {
|
|
7776
|
+
const isLeaf = await this.isLeafNode(id, treeComponent ?? null);
|
|
7777
|
+
if (!isLeaf) {
|
|
7778
|
+
return null; // Skip non-leaf nodes
|
|
7779
|
+
}
|
|
7780
|
+
}
|
|
6925
7781
|
const path = await this.calculateNodePath(id, nodeData);
|
|
6926
7782
|
return {
|
|
6927
7783
|
...nodeData,
|
|
@@ -6936,9 +7792,9 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6936
7792
|
<div class="ax-flex ax-flex-col ax-h-full">
|
|
6937
7793
|
@if (loading()) {
|
|
6938
7794
|
<div class="ax-p-4 ax-flex ax-flex-col ax-gap-3">
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
7795
|
+
@for (i of [1, 2, 3, 4]; track i) {
|
|
7796
|
+
<ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
|
|
7797
|
+
}
|
|
6942
7798
|
</div>
|
|
6943
7799
|
} @else if (treeData) {
|
|
6944
7800
|
<div class="ax-flex ax-flex-col ax-flex-1 ax-min-h-0">
|
|
@@ -6976,14 +7832,14 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6976
7832
|
[datasource]="datasource"
|
|
6977
7833
|
[dragBehavior]="'none'"
|
|
6978
7834
|
[selectMode]="allowMultiple() ? 'multiple' : 'single'"
|
|
6979
|
-
[selectionBehavior]="
|
|
7835
|
+
[selectionBehavior]="allowMultiple() ? 'intermediate-nested' : 'all'"
|
|
6980
7836
|
[showIcons]="true"
|
|
6981
7837
|
[titleField]="textField()"
|
|
6982
7838
|
[idField]="valueField()"
|
|
6983
|
-
[nodeTemplate]="itemTemplate"
|
|
6984
7839
|
(onNodeSelect)="onNodeSelect($event)"
|
|
6985
7840
|
(onSelectionChange)="onSelectionChange($event)"
|
|
6986
7841
|
(onNodeToggle)="onNodeToggle($event)"
|
|
7842
|
+
[nodeTemplate]="itemTemplate"
|
|
6987
7843
|
#tree
|
|
6988
7844
|
>
|
|
6989
7845
|
</ax-tree-view>
|
|
@@ -6992,12 +7848,16 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
6992
7848
|
@if (node) {
|
|
6993
7849
|
@let item = node.data || node;
|
|
6994
7850
|
<div class="ax-flex ax-items-center ax-gap-2 ax-w-full ax-overflow-hidden ax-p-2 ax-pe-0">
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7851
|
+
@if (allowMultiple()) {
|
|
7852
|
+
<ax-check-box
|
|
7853
|
+
[ngModel]="node['indeterminate'] ? null : node['selected'] || false"
|
|
7854
|
+
[indeterminate]="node['indeterminate'] || false"
|
|
7855
|
+
(onValueChanged)="handleCheckboxChange(node.id, $event.value)"
|
|
7856
|
+
(click)="$event.stopPropagation()"
|
|
7857
|
+
(pointerdown)="$event.stopPropagation()"
|
|
7858
|
+
[disabled]="node.disabled || node.id === 'all'"
|
|
7859
|
+
></ax-check-box>
|
|
7860
|
+
}
|
|
7001
7861
|
<ax-icon
|
|
7002
7862
|
class="fas fa-folder"
|
|
7003
7863
|
[style.color]="item.color ?? 'rgba(var(--ax-sys-color-warning-500), 1)'"
|
|
@@ -7036,7 +7896,7 @@ class AXPEntityCategoryTreeSelectorComponent extends AXBasePageComponent {
|
|
|
7036
7896
|
></ax-button>
|
|
7037
7897
|
</ax-suffix>
|
|
7038
7898
|
</ax-footer>
|
|
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:
|
|
7899
|
+
`, 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: "component", type: i2$1.AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "isLoading", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.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: i4$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: i5$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: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7040
7900
|
}
|
|
7041
7901
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryTreeSelectorComponent, decorators: [{
|
|
7042
7902
|
type: Component,
|
|
@@ -7046,9 +7906,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
7046
7906
|
<div class="ax-flex ax-flex-col ax-h-full">
|
|
7047
7907
|
@if (loading()) {
|
|
7048
7908
|
<div class="ax-p-4 ax-flex ax-flex-col ax-gap-3">
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7909
|
+
@for (i of [1, 2, 3, 4]; track i) {
|
|
7910
|
+
<ax-skeleton class="ax-w-full ax-h-6 ax-rounded-md"></ax-skeleton>
|
|
7911
|
+
}
|
|
7052
7912
|
</div>
|
|
7053
7913
|
} @else if (treeData) {
|
|
7054
7914
|
<div class="ax-flex ax-flex-col ax-flex-1 ax-min-h-0">
|
|
@@ -7086,14 +7946,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
7086
7946
|
[datasource]="datasource"
|
|
7087
7947
|
[dragBehavior]="'none'"
|
|
7088
7948
|
[selectMode]="allowMultiple() ? 'multiple' : 'single'"
|
|
7089
|
-
[selectionBehavior]="
|
|
7949
|
+
[selectionBehavior]="allowMultiple() ? 'intermediate-nested' : 'all'"
|
|
7090
7950
|
[showIcons]="true"
|
|
7091
7951
|
[titleField]="textField()"
|
|
7092
7952
|
[idField]="valueField()"
|
|
7093
|
-
[nodeTemplate]="itemTemplate"
|
|
7094
7953
|
(onNodeSelect)="onNodeSelect($event)"
|
|
7095
7954
|
(onSelectionChange)="onSelectionChange($event)"
|
|
7096
7955
|
(onNodeToggle)="onNodeToggle($event)"
|
|
7956
|
+
[nodeTemplate]="itemTemplate"
|
|
7097
7957
|
#tree
|
|
7098
7958
|
>
|
|
7099
7959
|
</ax-tree-view>
|
|
@@ -7102,12 +7962,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
7102
7962
|
@if (node) {
|
|
7103
7963
|
@let item = node.data || node;
|
|
7104
7964
|
<div class="ax-flex ax-items-center ax-gap-2 ax-w-full ax-overflow-hidden ax-p-2 ax-pe-0">
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7965
|
+
@if (allowMultiple()) {
|
|
7966
|
+
<ax-check-box
|
|
7967
|
+
[ngModel]="node['indeterminate'] ? null : node['selected'] || false"
|
|
7968
|
+
[indeterminate]="node['indeterminate'] || false"
|
|
7969
|
+
(onValueChanged)="handleCheckboxChange(node.id, $event.value)"
|
|
7970
|
+
(click)="$event.stopPropagation()"
|
|
7971
|
+
(pointerdown)="$event.stopPropagation()"
|
|
7972
|
+
[disabled]="node.disabled || node.id === 'all'"
|
|
7973
|
+
></ax-check-box>
|
|
7974
|
+
}
|
|
7111
7975
|
<ax-icon
|
|
7112
7976
|
class="fas fa-folder"
|
|
7113
7977
|
[style.color]="item.color ?? 'rgba(var(--ax-sys-color-warning-500), 1)'"
|
|
@@ -7400,7 +8264,7 @@ class AXPEntityCategoryWidgetColumnComponent extends AXPColumnWidgetComponent {
|
|
|
7400
8264
|
</div>
|
|
7401
8265
|
}
|
|
7402
8266
|
</div>
|
|
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:
|
|
8267
|
+
`, 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: i3$2.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 }); }
|
|
7404
8268
|
}
|
|
7405
8269
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetColumnComponent, decorators: [{
|
|
7406
8270
|
type: Component,
|
|
@@ -7741,7 +8605,7 @@ class AXPTruncatedBreadcrumbComponent {
|
|
|
7741
8605
|
}
|
|
7742
8606
|
}
|
|
7743
8607
|
</div>
|
|
7744
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type:
|
|
8608
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
7745
8609
|
}
|
|
7746
8610
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPTruncatedBreadcrumbComponent, decorators: [{
|
|
7747
8611
|
type: Component,
|
|
@@ -7858,6 +8722,8 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
7858
8722
|
this.selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
|
|
7859
8723
|
this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
7860
8724
|
this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
8725
|
+
this.tagBox = viewChild('tagBoxComponent', ...(ngDevMode ? [{ debugName: "tagBox" }] : []));
|
|
8726
|
+
this.searchTerm = signal(null, ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
7861
8727
|
//#endregion
|
|
7862
8728
|
//#region ---- Private Properties ----
|
|
7863
8729
|
this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : []));
|
|
@@ -7912,13 +8778,62 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
7912
8778
|
handleAddClick(e) {
|
|
7913
8779
|
this.showTreeSelector();
|
|
7914
8780
|
}
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
8781
|
+
handleValueChange(e) {
|
|
8782
|
+
if (e.isUserInteraction) {
|
|
8783
|
+
if (isNil(e.value) || isEmpty(e.value)) {
|
|
8784
|
+
this.clear();
|
|
8785
|
+
}
|
|
8786
|
+
else {
|
|
8787
|
+
const items = Array.isArray(e.value) ? e.value : [e.value];
|
|
8788
|
+
this.setItems(items);
|
|
8789
|
+
}
|
|
8790
|
+
}
|
|
8791
|
+
}
|
|
8792
|
+
handleOnBlur(e) {
|
|
8793
|
+
setTimeout(() => {
|
|
8794
|
+
if (!this.isOpen()) {
|
|
8795
|
+
this.clearInput();
|
|
8796
|
+
}
|
|
8797
|
+
}, 100);
|
|
8798
|
+
}
|
|
8799
|
+
async handleKeyUp(e) {
|
|
8800
|
+
const keyEvent = e.nativeEvent;
|
|
8801
|
+
const value = this.tagBox()?.inputValue() ?? '';
|
|
8802
|
+
this.searchTerm.set(value);
|
|
8803
|
+
if ((keyEvent.code == 'Enter' || keyEvent.code == 'NumpadEnter') && value) {
|
|
8804
|
+
this.isLoading.set(true);
|
|
8805
|
+
// For category widget, always open selector on Enter
|
|
8806
|
+
this.showTreeSelector();
|
|
8807
|
+
this.isLoading.set(false);
|
|
8808
|
+
}
|
|
8809
|
+
if (keyEvent.code == 'ArrowDown') {
|
|
8810
|
+
this.showTreeSelector();
|
|
8811
|
+
}
|
|
7918
8812
|
}
|
|
7919
8813
|
handleClearClick() {
|
|
7920
8814
|
this.clear();
|
|
7921
8815
|
}
|
|
8816
|
+
async handleRemoveItem(event, index) {
|
|
8817
|
+
event.stopPropagation();
|
|
8818
|
+
if (this.disabled()) {
|
|
8819
|
+
return;
|
|
8820
|
+
}
|
|
8821
|
+
const currentItems = this.selectedItems();
|
|
8822
|
+
if (index < 0 || index >= currentItems.length) {
|
|
8823
|
+
return;
|
|
8824
|
+
}
|
|
8825
|
+
const filteredItems = currentItems.filter((_, i) => i !== index);
|
|
8826
|
+
if (filteredItems.length === 0) {
|
|
8827
|
+
this.clear();
|
|
8828
|
+
}
|
|
8829
|
+
else {
|
|
8830
|
+
await this.setItems(filteredItems);
|
|
8831
|
+
}
|
|
8832
|
+
}
|
|
8833
|
+
clearInput() {
|
|
8834
|
+
this.tagBox()?.inputValue.set('');
|
|
8835
|
+
this.searchTerm.set('');
|
|
8836
|
+
}
|
|
7922
8837
|
async showTreeSelector() {
|
|
7923
8838
|
this.isOpen.set(true);
|
|
7924
8839
|
const currentValue = this.getValue();
|
|
@@ -7989,24 +8904,12 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
7989
8904
|
}
|
|
7990
8905
|
finally {
|
|
7991
8906
|
this.isOpen.set(false);
|
|
7992
|
-
|
|
7993
|
-
}
|
|
7994
|
-
async removeItem(item) {
|
|
7995
|
-
if (this.disabled()) {
|
|
7996
|
-
return;
|
|
7997
|
-
}
|
|
7998
|
-
const currentItems = this.selectedItems();
|
|
7999
|
-
const itemId = get(item, this.valueField());
|
|
8000
|
-
const filteredItems = currentItems.filter((i) => get(i, this.valueField()) !== itemId);
|
|
8001
|
-
if (filteredItems.length === 0) {
|
|
8002
|
-
this.clear();
|
|
8003
|
-
}
|
|
8004
|
-
else {
|
|
8005
|
-
await this.setItems(filteredItems);
|
|
8907
|
+
this.tagBox()?.focus();
|
|
8006
8908
|
}
|
|
8007
8909
|
}
|
|
8008
8910
|
clear() {
|
|
8009
8911
|
this.setValue(null);
|
|
8912
|
+
this.clearInput();
|
|
8010
8913
|
this.selectedItems.set([]);
|
|
8011
8914
|
this.cdr.markForCheck();
|
|
8012
8915
|
}
|
|
@@ -8088,6 +8991,7 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
8088
8991
|
return;
|
|
8089
8992
|
}
|
|
8090
8993
|
items = castArray(items);
|
|
8994
|
+
this.clearInput();
|
|
8091
8995
|
// Ensure all items have paths
|
|
8092
8996
|
const itemsWithPaths = await Promise.all(items.map(async (item) => {
|
|
8093
8997
|
// If item already has a path array, return it as is
|
|
@@ -8229,47 +9133,78 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
8229
9133
|
return { ...item, path: pathArray };
|
|
8230
9134
|
}
|
|
8231
9135
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetEditComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
8232
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityCategoryWidgetEditComponent, isStandalone: true, selector: "axp-entity-category-widget-edit", usesInheritance: true, ngImport: i0, template: `
|
|
8233
|
-
<
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
9136
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPEntityCategoryWidgetEditComponent, isStandalone: true, selector: "axp-entity-category-widget-edit", viewQueries: [{ propertyName: "tagBox", first: true, predicate: ["tagBoxComponent"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
9137
|
+
<ax-tag-box
|
|
9138
|
+
#tagBoxComponent
|
|
9139
|
+
[tagTemplate]="tagTemplate"
|
|
9140
|
+
[ngModel]="selectedItems()"
|
|
9141
|
+
[textField]="displayField()"
|
|
9142
|
+
[valueField]="valueField()"
|
|
9143
|
+
(onValueChanged)="handleValueChange($event)"
|
|
9144
|
+
[placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
|
|
9145
|
+
[addOnEnter]="false"
|
|
9146
|
+
[addOnComma]="false"
|
|
9147
|
+
[readonly]="true"
|
|
9148
|
+
[disabled]="disabled()"
|
|
9149
|
+
(onKeyUp)="handleKeyUp($event)"
|
|
9150
|
+
(onBlur)="handleOnBlur($event)"
|
|
9151
|
+
>
|
|
9152
|
+
@for (validation of validationRules(); track $index) {
|
|
9153
|
+
<ax-validation-rule
|
|
9154
|
+
[rule]="validation.rule"
|
|
9155
|
+
[message]="validation.options?.message"
|
|
9156
|
+
[options]="validation.options"
|
|
9157
|
+
></ax-validation-rule>
|
|
9158
|
+
}
|
|
9159
|
+
@if (selectedItems().length > 1 || allowClear()) {
|
|
9160
|
+
<ax-clear-button (click)="handleClearClick()"></ax-clear-button>
|
|
8250
9161
|
}
|
|
8251
9162
|
|
|
8252
|
-
<
|
|
8253
|
-
<ax-button
|
|
8254
|
-
[text]="'@general:actions.add.title' | translate | async"
|
|
8255
|
-
color="primary"
|
|
8256
|
-
[disabled]="isLoading() || disabled()"
|
|
8257
|
-
(onClick)="handleAddClick($event)"
|
|
8258
|
-
>
|
|
9163
|
+
<ax-suffix>
|
|
9164
|
+
<ax-button color="ghost" look="blank" [disabled]="isLoading() || disabled()" (onClick)="handleAddClick($event)">
|
|
8259
9165
|
@if (isLoading()) {
|
|
8260
9166
|
<ax-loading></ax-loading>
|
|
8261
9167
|
} @else {
|
|
8262
|
-
<ax-icon icon="far fa-
|
|
9168
|
+
<ax-icon icon="far fa-search"></ax-icon>
|
|
8263
9169
|
}
|
|
8264
9170
|
</ax-button>
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
9171
|
+
</ax-suffix>
|
|
9172
|
+
</ax-tag-box>
|
|
9173
|
+
<ng-template #tagTemplate let-item let-index="index">
|
|
9174
|
+
<div class="ax-inline-flex ax-items-center ax-gap-1.5 ax-rounded-md ax-px-3 ax-py-1 ax-text-sm ax-surface">
|
|
9175
|
+
<axp-truncated-breadcrumb
|
|
9176
|
+
[attr.data-color]="item.color"
|
|
9177
|
+
[sections]="getItemPath(item)"
|
|
9178
|
+
[characterLimit]="characterLimit()"
|
|
9179
|
+
[sectionLimit]="sectionLimit()"
|
|
9180
|
+
></axp-truncated-breadcrumb>
|
|
9181
|
+
<button type="button" (click)="handleRemoveItem($event, index)">
|
|
9182
|
+
<ax-icon class="ax-icon ax-icon-close"></ax-icon>
|
|
9183
|
+
</button>
|
|
8271
9184
|
</div>
|
|
8272
|
-
|
|
9185
|
+
</ng-template>
|
|
9186
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i3$2.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: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "directive", type: i5$2.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "ngmodule", type: AXTagBoxModule }, { kind: "component", type: i6$1.AXTagBoxComponent, selector: "ax-tag-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "allowNull", "type", "look", "addOnComma", "addOnEnter", "valueField", "textField", "readonlyField", "allowDuplicateValues", "tagTemplate"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onTagClick", "onTagDblClick", "onTagContextMenu"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPTruncatedBreadcrumbComponent, selector: "axp-truncated-breadcrumb", inputs: ["sections", "characterLimit", "sectionLimit", "separatorIcon", "ellipsisIcon", "eyeIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9187
|
+
}
|
|
9188
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetEditComponent, decorators: [{
|
|
9189
|
+
type: Component,
|
|
9190
|
+
args: [{
|
|
9191
|
+
selector: 'axp-entity-category-widget-edit',
|
|
9192
|
+
template: `
|
|
9193
|
+
<ax-tag-box
|
|
9194
|
+
#tagBoxComponent
|
|
9195
|
+
[tagTemplate]="tagTemplate"
|
|
9196
|
+
[ngModel]="selectedItems()"
|
|
9197
|
+
[textField]="displayField()"
|
|
9198
|
+
[valueField]="valueField()"
|
|
9199
|
+
(onValueChanged)="handleValueChange($event)"
|
|
9200
|
+
[placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
|
|
9201
|
+
[addOnEnter]="false"
|
|
9202
|
+
[addOnComma]="false"
|
|
9203
|
+
[readonly]="true"
|
|
9204
|
+
[disabled]="disabled()"
|
|
9205
|
+
(onKeyUp)="handleKeyUp($event)"
|
|
9206
|
+
(onBlur)="handleOnBlur($event)"
|
|
9207
|
+
>
|
|
8273
9208
|
@for (validation of validationRules(); track $index) {
|
|
8274
9209
|
<ax-validation-rule
|
|
8275
9210
|
[rule]="validation.rule"
|
|
@@ -8277,76 +9212,49 @@ class AXPEntityCategoryWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
8277
9212
|
[options]="validation.options"
|
|
8278
9213
|
></ax-validation-rule>
|
|
8279
9214
|
}
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
}
|
|
8283
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetEditComponent, decorators: [{
|
|
8284
|
-
type: Component,
|
|
8285
|
-
args: [{
|
|
8286
|
-
selector: 'axp-entity-category-widget-edit',
|
|
8287
|
-
template: `
|
|
8288
|
-
<div class="ax-flex ax-flex-col ax-gap-3">
|
|
8289
|
-
@if (selectedItems().length > 0) {
|
|
8290
|
-
<div class="ax-flex ax-flex-col ax-gap-2">
|
|
8291
|
-
@for (item of selectedItems(); track getItemId(item)) {
|
|
8292
|
-
<div class="ax-flex ax-items-center ax-gap-2 ax-p-2 ax-border ax-primary-lightest ax-rounded-xl">
|
|
8293
|
-
<axp-truncated-breadcrumb
|
|
8294
|
-
[sections]="getItemPath(item)"
|
|
8295
|
-
[characterLimit]="characterLimit()"
|
|
8296
|
-
[sectionLimit]="sectionLimit()"
|
|
8297
|
-
class="ax-flex-1"
|
|
8298
|
-
></axp-truncated-breadcrumb>
|
|
8299
|
-
<ax-button color="ghost" look="blank" class="ax-xs" (onClick)="handleRemoveItemClick($event, item)">
|
|
8300
|
-
<ax-icon icon="ax-icon ax-icon-close"></ax-icon>
|
|
8301
|
-
</ax-button>
|
|
8302
|
-
</div>
|
|
8303
|
-
}
|
|
8304
|
-
</div>
|
|
9215
|
+
@if (selectedItems().length > 1 || allowClear()) {
|
|
9216
|
+
<ax-clear-button (click)="handleClearClick()"></ax-clear-button>
|
|
8305
9217
|
}
|
|
8306
9218
|
|
|
8307
|
-
<
|
|
8308
|
-
<ax-button
|
|
8309
|
-
[text]="'@general:actions.add.title' | translate | async"
|
|
8310
|
-
color="primary"
|
|
8311
|
-
[disabled]="isLoading() || disabled()"
|
|
8312
|
-
(onClick)="handleAddClick($event)"
|
|
8313
|
-
>
|
|
9219
|
+
<ax-suffix>
|
|
9220
|
+
<ax-button color="ghost" look="blank" [disabled]="isLoading() || disabled()" (onClick)="handleAddClick($event)">
|
|
8314
9221
|
@if (isLoading()) {
|
|
8315
9222
|
<ax-loading></ax-loading>
|
|
8316
9223
|
} @else {
|
|
8317
|
-
<ax-icon icon="far fa-
|
|
9224
|
+
<ax-icon icon="far fa-search"></ax-icon>
|
|
8318
9225
|
}
|
|
8319
9226
|
</ax-button>
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
9227
|
+
</ax-suffix>
|
|
9228
|
+
</ax-tag-box>
|
|
9229
|
+
<ng-template #tagTemplate let-item let-index="index">
|
|
9230
|
+
<div class="ax-inline-flex ax-items-center ax-gap-1.5 ax-rounded-md ax-px-3 ax-py-1 ax-text-sm ax-surface">
|
|
9231
|
+
<axp-truncated-breadcrumb
|
|
9232
|
+
[attr.data-color]="item.color"
|
|
9233
|
+
[sections]="getItemPath(item)"
|
|
9234
|
+
[characterLimit]="characterLimit()"
|
|
9235
|
+
[sectionLimit]="sectionLimit()"
|
|
9236
|
+
></axp-truncated-breadcrumb>
|
|
9237
|
+
<button type="button" (click)="handleRemoveItem($event, index)">
|
|
9238
|
+
<ax-icon class="ax-icon ax-icon-close"></ax-icon>
|
|
9239
|
+
</button>
|
|
8326
9240
|
</div>
|
|
8327
|
-
|
|
8328
|
-
@for (validation of validationRules(); track $index) {
|
|
8329
|
-
<ax-validation-rule
|
|
8330
|
-
[rule]="validation.rule"
|
|
8331
|
-
[message]="validation.options?.message"
|
|
8332
|
-
[options]="validation.options"
|
|
8333
|
-
></ax-validation-rule>
|
|
8334
|
-
}
|
|
8335
|
-
</div>
|
|
9241
|
+
</ng-template>
|
|
8336
9242
|
`,
|
|
8337
9243
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
8338
9244
|
imports: [
|
|
8339
9245
|
CommonModule,
|
|
9246
|
+
FormsModule,
|
|
8340
9247
|
AXButtonModule,
|
|
8341
9248
|
AXDecoratorModule,
|
|
8342
9249
|
AXLoadingModule,
|
|
8343
9250
|
AXValidationModule,
|
|
8344
9251
|
AXFormModule,
|
|
9252
|
+
AXTagBoxModule,
|
|
8345
9253
|
AXTranslationModule,
|
|
8346
9254
|
AXPTruncatedBreadcrumbComponent,
|
|
8347
9255
|
],
|
|
8348
9256
|
}]
|
|
8349
|
-
}] });
|
|
9257
|
+
}], propDecorators: { tagBox: [{ type: i0.ViewChild, args: ['tagBoxComponent', { isSignal: true }] }] } });
|
|
8350
9258
|
|
|
8351
9259
|
var entityCategoryWidgetEdit_component = /*#__PURE__*/Object.freeze({
|
|
8352
9260
|
__proto__: null,
|
|
@@ -8448,7 +9356,7 @@ class AXPEntityCategoryWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
8448
9356
|
<span class="ax-text-muted">---</span>
|
|
8449
9357
|
}
|
|
8450
9358
|
}
|
|
8451
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type:
|
|
9359
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8452
9360
|
}
|
|
8453
9361
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityCategoryWidgetViewComponent, decorators: [{
|
|
8454
9362
|
type: Component,
|
|
@@ -8942,6 +9850,8 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
8942
9850
|
this.entityListTableService = inject(AXPEntityListTableService);
|
|
8943
9851
|
this.entityListToolbarService = inject(AXPEntityListToolbarService);
|
|
8944
9852
|
this.deviceService = inject(AXPDeviceService);
|
|
9853
|
+
this.commandService = inject(AXPCommandService);
|
|
9854
|
+
this.eventService = inject(AXPBroadcastEventService);
|
|
8945
9855
|
this.isMounted = signal(false, ...(ngDevMode ? [{ debugName: "isMounted" }] : []));
|
|
8946
9856
|
this.entity = signal(null, ...(ngDevMode ? [{ debugName: "entity" }] : []));
|
|
8947
9857
|
this.listNode = signal(null, ...(ngDevMode ? [{ debugName: "listNode" }] : []));
|
|
@@ -9024,17 +9934,21 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
9024
9934
|
return actions;
|
|
9025
9935
|
}, ...(ngDevMode ? [{ debugName: "secondaryActions" }] : []));
|
|
9026
9936
|
//#region ---- Query Change Handler ----
|
|
9937
|
+
this.queries = undefined;
|
|
9027
9938
|
this.#effect = effect(() => {
|
|
9028
|
-
|
|
9939
|
+
//TODO: this is a temporary solution to handle the query changes; this should be removed when the query changes are handled in the widget core;
|
|
9940
|
+
if (this.getValue()?.toolbar) {
|
|
9941
|
+
this.queries = this.getValue()?.toolbar;
|
|
9942
|
+
}
|
|
9029
9943
|
const listInstance = this.listWidget()?.instance;
|
|
9030
9944
|
// const dataSource = this.listWidget()?.options()['dataSource'] as AXDataSource;
|
|
9031
9945
|
const dataSource = listInstance?.options()?.['dataSource'];
|
|
9032
9946
|
const isMounted = this.isMounted();
|
|
9033
|
-
if (!this.hasRequiredDependencies(dataSource, queries, listInstance)) {
|
|
9947
|
+
if (!this.hasRequiredDependencies(dataSource, this.queries, listInstance)) {
|
|
9034
9948
|
return;
|
|
9035
9949
|
}
|
|
9036
9950
|
untracked(() => {
|
|
9037
|
-
this.handleQueryChanges(queries, dataSource, listInstance, isMounted);
|
|
9951
|
+
this.handleQueryChanges(this.queries, dataSource, listInstance, isMounted);
|
|
9038
9952
|
});
|
|
9039
9953
|
}, ...(ngDevMode ? [{ debugName: "#effect" }] : []));
|
|
9040
9954
|
//#endregion
|
|
@@ -9067,23 +9981,43 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
9067
9981
|
});
|
|
9068
9982
|
const command = commandName.split('&')[0];
|
|
9069
9983
|
// const options = await this.evaluateExpressions(action?.options, data);
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9084
|
-
|
|
9984
|
+
if (this.commandService.exists(command)) {
|
|
9985
|
+
await this.commandService.execute(command, {
|
|
9986
|
+
__context__: {
|
|
9987
|
+
entity: this.entitySource(),
|
|
9988
|
+
entityInfo: {
|
|
9989
|
+
name: this.entity()?.name,
|
|
9990
|
+
module: this.entity()?.module,
|
|
9991
|
+
title: this.entity()?.title,
|
|
9992
|
+
parentKey: this.entity()?.parentKey,
|
|
9993
|
+
source: `${this.entity()?.module}.${this.entity()?.name}`,
|
|
9994
|
+
},
|
|
9995
|
+
data: action?.scope == AXPEntityCommandScope.Selected
|
|
9996
|
+
? this.selectedItems()
|
|
9997
|
+
: action?.options?.['process']?.data || null,
|
|
9998
|
+
options: action?.options,
|
|
9999
|
+
metadata: action?.metadata,
|
|
10000
|
+
},
|
|
10001
|
+
});
|
|
10002
|
+
}
|
|
10003
|
+
else {
|
|
10004
|
+
await this.workflow.execute(command, {
|
|
10005
|
+
entity: this.entitySource(),
|
|
10006
|
+
entityInfo: {
|
|
10007
|
+
name: this.entity()?.name,
|
|
10008
|
+
module: this.entity()?.module,
|
|
10009
|
+
title: this.entity()?.title,
|
|
10010
|
+
parentKey: this.entity()?.parentKey,
|
|
10011
|
+
source: `${this.entity()?.module}.${this.entity()?.name}`,
|
|
10012
|
+
},
|
|
10013
|
+
data: action?.scope == AXPEntityCommandScope.Selected
|
|
10014
|
+
? this.selectedItems()
|
|
10015
|
+
: action?.options?.['process']?.data || null,
|
|
10016
|
+
options: action?.options,
|
|
10017
|
+
metadata: action?.metadata,
|
|
10018
|
+
});
|
|
10019
|
+
}
|
|
9085
10020
|
}
|
|
9086
|
-
//#region ---- Query Change Handler ----
|
|
9087
10021
|
#effect;
|
|
9088
10022
|
/**
|
|
9089
10023
|
* Validates that all required dependencies are available
|
|
@@ -9216,6 +10150,14 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
9216
10150
|
this.listWidget()?.instance.call('refresh');
|
|
9217
10151
|
}
|
|
9218
10152
|
});
|
|
10153
|
+
this.eventService
|
|
10154
|
+
.listen(AXPEntityEventsKeys.REFRESH_LAYOUT)
|
|
10155
|
+
.pipe(takeUntil(this.destroyed))
|
|
10156
|
+
.subscribe((e) => {
|
|
10157
|
+
if (e.data.name == `${this.entity()?.module}.${this.entity()?.name}`) {
|
|
10158
|
+
this.listWidget()?.instance.call('refresh');
|
|
10159
|
+
}
|
|
10160
|
+
});
|
|
9219
10161
|
const listWidget = (await this.layoutService.waitForWidget(`${this.entitySource()}-tab-list_table`, 500));
|
|
9220
10162
|
if (listWidget?.api && typeof listWidget.api === 'function') {
|
|
9221
10163
|
const onSelectionChange = listWidget.api()['onSelectionChange'];
|
|
@@ -9344,7 +10286,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
9344
10286
|
></ng-container>
|
|
9345
10287
|
}
|
|
9346
10288
|
</div>
|
|
9347
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type:
|
|
10289
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.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: AXPWidgetCoreModule }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { 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: "component", type: i3.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i3.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i4$3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9348
10290
|
}
|
|
9349
10291
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityListWidgetViewComponent, decorators: [{
|
|
9350
10292
|
type: Component,
|
|
@@ -9915,7 +10857,7 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
9915
10857
|
<span class="ax-text-muted">---</span>
|
|
9916
10858
|
}
|
|
9917
10859
|
}
|
|
9918
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type:
|
|
10860
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9919
10861
|
}
|
|
9920
10862
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLookupWidgetViewComponent, decorators: [{
|
|
9921
10863
|
type: Component,
|
|
@@ -10167,6 +11109,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
10167
11109
|
this.disabled = computed(() => this.options()['disabled'], ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
10168
11110
|
this.columns = computed(() => this.options()['columns'] ?? [], ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
10169
11111
|
this.textField = computed(() => this.options()['textField'] ?? '', ...(ngDevMode ? [{ debugName: "textField" }] : []));
|
|
11112
|
+
this.hasClearButton = computed(() => this.options()['hasClearButton'] ?? false, ...(ngDevMode ? [{ debugName: "hasClearButton" }] : []));
|
|
10170
11113
|
this.customFilter = computed(() => this.options()['filter'], ...(ngDevMode ? [{ debugName: "customFilter" }] : []));
|
|
10171
11114
|
this.multiple = computed(() => (this.options()['multiple'] ?? false), ...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
10172
11115
|
this.look = computed(() => this.options()['look'] ?? 'lookup', ...(ngDevMode ? [{ debugName: "look" }] : []));
|
|
@@ -10563,6 +11506,9 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
10563
11506
|
[multiple]="multiple()"
|
|
10564
11507
|
(onValueChanged)="selectBoxValueChange($event)"
|
|
10565
11508
|
>
|
|
11509
|
+
@if (hasClearButton()) {
|
|
11510
|
+
<ax-clear-button></ax-clear-button>
|
|
11511
|
+
}
|
|
10566
11512
|
<ax-search-box
|
|
10567
11513
|
[placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
|
|
10568
11514
|
(onValueChanged)="handleSearchInputChange($event)"
|
|
@@ -10631,9 +11577,9 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
10631
11577
|
</ng-template>
|
|
10632
11578
|
}
|
|
10633
11579
|
}
|
|
10634
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1
|
|
11580
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type:
|
|
10635
11581
|
//
|
|
10636
|
-
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:
|
|
11582
|
+
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: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i3$2.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: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "directive", type: i5$2.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "ngmodule", type: AXTagBoxModule }, { kind: "component", type: i6$1.AXTagBoxComponent, selector: "ax-tag-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "allowNull", "type", "look", "addOnComma", "addOnEnter", "valueField", "textField", "readonlyField", "allowDuplicateValues", "tagTemplate"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onTagClick", "onTagDblClick", "onTagContextMenu"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "component", type: i7.AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "component", type: 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
10637
11583
|
}
|
|
10638
11584
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLookupWidgetEditComponent, decorators: [{
|
|
10639
11585
|
type: Component,
|
|
@@ -10652,6 +11598,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
10652
11598
|
[multiple]="multiple()"
|
|
10653
11599
|
(onValueChanged)="selectBoxValueChange($event)"
|
|
10654
11600
|
>
|
|
11601
|
+
@if (hasClearButton()) {
|
|
11602
|
+
<ax-clear-button></ax-clear-button>
|
|
11603
|
+
}
|
|
10655
11604
|
<ax-search-box
|
|
10656
11605
|
[placeholder]="selectedItems().length ? '' : searchPlaceholderText()"
|
|
10657
11606
|
(onValueChanged)="handleSearchInputChange($event)"
|
|
@@ -11006,7 +11955,7 @@ class AXPWidgetSelectorWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
11006
11955
|
<axp-widget-property-viewer [widget]="selectedWidgetNode()!" (onChanged)="handleChangeWidget($event)">
|
|
11007
11956
|
</axp-widget-property-viewer>
|
|
11008
11957
|
}
|
|
11009
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1
|
|
11958
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i2$3.AXTextBoxComponent, selector: "ax-text-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "maxLength", "allowNull", "type", "autoComplete", "look", "mask-options", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { 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: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$2.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: AXLoadingModule }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "directive", type: i5$2.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "component", type: AXPWidgetPropertyViewerComponent, selector: "axp-widget-property-viewer", inputs: ["widget", "mode"], outputs: ["onChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
11010
11959
|
}
|
|
11011
11960
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWidgetSelectorWidgetEditComponent, decorators: [{
|
|
11012
11961
|
type: Component,
|
|
@@ -11525,7 +12474,7 @@ class AXPEntityModule {
|
|
|
11525
12474
|
},
|
|
11526
12475
|
});
|
|
11527
12476
|
}
|
|
11528
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityModule, deps: [{ token: i1$
|
|
12477
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityModule, deps: [{ token: i1$1.AXPAppStartUpService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
11529
12478
|
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityModule, imports: [RouterModule, i2$4.AXPWorkflowModule, i3$1.AXPWidgetCoreModule] }); }
|
|
11530
12479
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPEntityModule, providers: [
|
|
11531
12480
|
{
|
|
@@ -11550,11 +12499,11 @@ class AXPEntityModule {
|
|
|
11550
12499
|
useValue: columnWidthMiddlewareProvider,
|
|
11551
12500
|
multi: true,
|
|
11552
12501
|
},
|
|
11553
|
-
{
|
|
11554
|
-
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
},
|
|
12502
|
+
// {
|
|
12503
|
+
// provide: AXP_ENTITY_MODIFIER,
|
|
12504
|
+
// useValue: layoutOrderingMiddlewareProvider,
|
|
12505
|
+
// multi: true,
|
|
12506
|
+
// },
|
|
11558
12507
|
provideCommandSetups([
|
|
11559
12508
|
{
|
|
11560
12509
|
key: 'Entity:OpenDetails',
|
|
@@ -11686,11 +12635,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
11686
12635
|
useValue: columnWidthMiddlewareProvider,
|
|
11687
12636
|
multi: true,
|
|
11688
12637
|
},
|
|
11689
|
-
{
|
|
11690
|
-
|
|
11691
|
-
|
|
11692
|
-
|
|
11693
|
-
},
|
|
12638
|
+
// {
|
|
12639
|
+
// provide: AXP_ENTITY_MODIFIER,
|
|
12640
|
+
// useValue: layoutOrderingMiddlewareProvider,
|
|
12641
|
+
// multi: true,
|
|
12642
|
+
// },
|
|
11694
12643
|
provideCommandSetups([
|
|
11695
12644
|
{
|
|
11696
12645
|
key: 'Entity:OpenDetails',
|
|
@@ -11717,7 +12666,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
11717
12666
|
]),
|
|
11718
12667
|
],
|
|
11719
12668
|
}]
|
|
11720
|
-
}], ctorParameters: () => [{ type: i1$
|
|
12669
|
+
}], ctorParameters: () => [{ type: i1$1.AXPAppStartUpService }, { type: i0.Injector }] });
|
|
11721
12670
|
|
|
11722
12671
|
//#endregion
|
|
11723
12672
|
//#region ---- Get Entity Details Query ----
|
|
@@ -11871,7 +12820,7 @@ function entityDetailsCreateActions(parentId) {
|
|
|
11871
12820
|
return {
|
|
11872
12821
|
title: '@general:actions.create.title',
|
|
11873
12822
|
command: {
|
|
11874
|
-
name: '
|
|
12823
|
+
name: 'Entity:Create',
|
|
11875
12824
|
options: {
|
|
11876
12825
|
process: {
|
|
11877
12826
|
redirect: false,
|
|
@@ -11948,7 +12897,7 @@ function entityDetailsReferenceCreateActions(type) {
|
|
|
11948
12897
|
{
|
|
11949
12898
|
title: '@general:actions.create.title',
|
|
11950
12899
|
command: {
|
|
11951
|
-
name: '
|
|
12900
|
+
name: 'Entity:Create',
|
|
11952
12901
|
options: {
|
|
11953
12902
|
process: {
|
|
11954
12903
|
redirect: false,
|