@acorex/platform 21.0.0-next.64 → 21.0.0-next.67
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-common.mjs +94 -18
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-core.mjs +42 -1
- package/fesm2022/acorex-platform-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +29 -7
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-components.mjs +282 -108
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity-attachments-page.component-BaTS183I.mjs +383 -0
- package/fesm2022/acorex-platform-layout-entity-attachments-page.component-BaTS183I.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-file-list-popup.component-CDYAGBku.mjs → acorex-platform-layout-entity-file-list-popup.component-_yrP5SQe.mjs} +15 -18
- package/fesm2022/acorex-platform-layout-entity-file-list-popup.component-_yrP5SQe.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-entity.mjs +3339 -301
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +0 -1
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +1377 -4
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widgets.mjs +8938 -11693
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-default-entity-master-create-view.component-Cx1lLUaR.mjs → acorex-platform-themes-default-entity-master-create-view.component-CWLfNqV0.mjs} +3 -3
- package/fesm2022/{acorex-platform-themes-default-entity-master-create-view.component-Cx1lLUaR.mjs.map → acorex-platform-themes-default-entity-master-create-view.component-CWLfNqV0.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-themes-default-entity-master-modify-view.component-AOrcgjDF.mjs → acorex-platform-themes-default-entity-master-modify-view.component-C7cT82K2.mjs} +3 -3
- package/fesm2022/{acorex-platform-themes-default-entity-master-modify-view.component-AOrcgjDF.mjs.map → acorex-platform-themes-default-entity-master-modify-view.component-C7cT82K2.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-BfCeUU5F.mjs → acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs} +4 -4
- package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-BfCeUU5F.mjs.map → acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs.map} +1 -1
- package/fesm2022/acorex-platform-themes-default.mjs +685 -287
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-shared-settings.provider-BgXYCFia.mjs → acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs} +29 -2
- package/fesm2022/acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared.mjs +94 -24
- package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
- package/fesm2022/acorex-platform-workflow.mjs +176 -26
- package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
- package/package.json +1 -1
- package/types/acorex-platform-common.d.ts +74 -10
- package/types/acorex-platform-core.d.ts +63 -2
- package/types/acorex-platform-layout-builder.d.ts +7 -1
- package/types/acorex-platform-layout-components.d.ts +162 -36
- package/types/acorex-platform-layout-entity.d.ts +704 -14
- package/types/acorex-platform-layout-views.d.ts +28 -0
- package/types/acorex-platform-layout-widget-core.d.ts +156 -3
- package/types/acorex-platform-layout-widgets.d.ts +29 -393
- package/types/acorex-platform-themes-default.d.ts +137 -30
- package/types/acorex-platform-themes-shared.d.ts +23 -1
- package/types/acorex-platform-workflow.d.ts +91 -4
- package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CDYAGBku.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-settings.provider-BgXYCFia.mjs.map +0 -1
|
@@ -16,7 +16,7 @@ import { AXPLayoutRendererComponent, AXPLayoutBuilderService, AXP_PREVIEW_WIDGET
|
|
|
16
16
|
import * as i1 from '@angular/common';
|
|
17
17
|
import { CommonModule, NgTemplateOutlet, isPlatformBrowser, AsyncPipe } from '@angular/common';
|
|
18
18
|
import * as i0 from '@angular/core';
|
|
19
|
-
import { input, ChangeDetectionStrategy, ViewEncapsulation, Component, inject, signal, effect, computed, InjectionToken, Injectable, Directive, viewChild, contentChild, ElementRef, output, afterNextRender, model, untracked, DestroyRef, PLATFORM_ID, linkedSignal, HostListener, ViewChildren, EventEmitter, Output, TemplateRef, contentChildren, Input } from '@angular/core';
|
|
19
|
+
import { input, ChangeDetectionStrategy, ViewEncapsulation, Component, inject, signal, effect, computed, InjectionToken, Injectable, Directive, viewChild, contentChild, ElementRef, output, afterNextRender, model, untracked, DestroyRef, PLATFORM_ID, linkedSignal, HostListener, ViewChildren, EventEmitter, Output, TemplateRef, contentChildren, ChangeDetectorRef, Input } from '@angular/core';
|
|
20
20
|
import { AXAccordionCdkModule } from '@acorex/cdk/accordion';
|
|
21
21
|
import { AXTagModule } from '@acorex/components/tag';
|
|
22
22
|
import * as i1$1 from '@acorex/components/avatar';
|
|
@@ -24,9 +24,10 @@ import { AXAvatarModule } from '@acorex/components/avatar';
|
|
|
24
24
|
import * as i3$1 from '@acorex/components/image';
|
|
25
25
|
import { AXImageModule } from '@acorex/components/image';
|
|
26
26
|
import { isNil, isEmpty, cloneDeep, isEqual, get, unionBy, sortBy, isArray, set, merge, capitalize } from 'lodash-es';
|
|
27
|
-
import { SIGNAL, signalSetFn } from '@angular/core/primitives/signals';
|
|
28
27
|
import * as i1$3 from '@acorex/components/badge';
|
|
29
28
|
import { AXBadgeComponent, AXBadgeModule } from '@acorex/components/badge';
|
|
29
|
+
import { AXPLayoutThemeService, AXPMenuVerticalMode } from '@acorex/platform/themes/shared';
|
|
30
|
+
import { SIGNAL, signalSetFn } from '@angular/core/primitives/signals';
|
|
30
31
|
import * as i6 from '@acorex/components/dropdown';
|
|
31
32
|
import { AXDropdownModule } from '@acorex/components/dropdown';
|
|
32
33
|
import * as i5 from '@acorex/components/search-box';
|
|
@@ -64,7 +65,7 @@ import { AXSelectionListModule } from '@acorex/components/selection-list';
|
|
|
64
65
|
import * as i5$1 from '@acorex/components/tag-box';
|
|
65
66
|
import { AXTagBoxModule } from '@acorex/components/tag-box';
|
|
66
67
|
import { AXCalendarService } from '@acorex/core/date-time';
|
|
67
|
-
import { AXPFilterOperatorMiddlewareService, AXPSettingsService, ALL_DEFAULT_OPERATORS, AXPFileStorageService, withDefaultMultiLanguageOnWidgetProperty, AXPDefaultMultiLanguageConfigService } from '@acorex/platform/common';
|
|
68
|
+
import { AXPFilterOperatorMiddlewareService, AXPSettingsService, ALL_DEFAULT_OPERATORS, AXPFileStorageService, withDefaultMultiLanguageOnWidgetProperty, AXPDefaultMultiLanguageConfigService, AXP_PLATFORM_CONFIG_TOKEN } from '@acorex/platform/common';
|
|
68
69
|
import { Subject, filter, BehaviorSubject, timer, takeUntil } from 'rxjs';
|
|
69
70
|
import * as i1$7 from '@acorex/components/image-editor';
|
|
70
71
|
import { AXImageEditorContainerComponent, AXImageEditorModule } from '@acorex/components/image-editor';
|
|
@@ -381,17 +382,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
381
382
|
class AXPTaskBadgeDirective {
|
|
382
383
|
constructor() {
|
|
383
384
|
this.badgeService = inject(AXPTaskBadgeService);
|
|
384
|
-
this.host = inject(AXBadgeComponent);
|
|
385
|
+
this.host = inject(AXBadgeComponent);
|
|
385
386
|
this.hostElement = this.host.getHostElement();
|
|
387
|
+
this.themeStore = inject(AXPLayoutThemeService);
|
|
386
388
|
this.badgeKey = input(undefined, ...(ngDevMode ? [{ debugName: "badgeKey" }] : /* istanbul ignore next */ []));
|
|
387
389
|
this.count = input(0, { ...(ngDevMode ? { debugName: "count" } : /* istanbul ignore next */ {}), alias: 'axp-task-badge' });
|
|
388
|
-
this.
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
390
|
+
this.actualCount = computed(() => {
|
|
391
|
+
const inputCount = this.count();
|
|
392
|
+
if (inputCount) {
|
|
393
|
+
return inputCount;
|
|
394
|
+
}
|
|
395
|
+
const key = this.badgeKey();
|
|
396
|
+
if (!key) {
|
|
397
|
+
return 0;
|
|
398
|
+
}
|
|
399
|
+
return this.badgeService.getCount(key)();
|
|
400
|
+
}, ...(ngDevMode ? [{ debugName: "actualCount" }] : /* istanbul ignore next */ []));
|
|
401
|
+
this.badgeText = computed(() => {
|
|
402
|
+
const count = this.actualCount();
|
|
403
|
+
if (!count) {
|
|
404
|
+
return '';
|
|
405
|
+
}
|
|
406
|
+
const isCompact = this.themeStore.menuVerticalMode() === 'compact';
|
|
407
|
+
return isCompact ? '' : count.toString();
|
|
408
|
+
}, ...(ngDevMode ? [{ debugName: "badgeText" }] : /* istanbul ignore next */ []));
|
|
392
409
|
this.#eff = effect(() => {
|
|
393
|
-
|
|
394
|
-
|
|
410
|
+
const count = this.actualCount();
|
|
411
|
+
this.setValueOfInputSignal(this.host.text, this.badgeText());
|
|
412
|
+
if (!count) {
|
|
395
413
|
this.hostElement.style.display = 'none';
|
|
396
414
|
}
|
|
397
415
|
else {
|
|
@@ -991,9 +1009,9 @@ class AXPCategoryTreeComponent {
|
|
|
991
1009
|
};
|
|
992
1010
|
this.collapseChange.emit(entity);
|
|
993
1011
|
this.events().onCollapseChange?.(entity);
|
|
994
|
-
// Load children
|
|
995
|
-
|
|
996
|
-
if (
|
|
1012
|
+
// Load children when the node has not been loaded yet (independent of expand event timing).
|
|
1013
|
+
const hasUnloadedChildren = (node.childrenCount ?? 0) > 0 && (!node.children || node.children.length === 0);
|
|
1014
|
+
if (node.id !== 'root' && hasUnloadedChildren && this.dataSource().loadChildNodes) {
|
|
997
1015
|
await this.loadChildNodes(node.id);
|
|
998
1016
|
}
|
|
999
1017
|
}
|
|
@@ -1123,7 +1141,7 @@ class AXPCategoryTreeComponent {
|
|
|
1123
1141
|
this.isLoading.set(false);
|
|
1124
1142
|
}
|
|
1125
1143
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCategoryTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1126
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPCategoryTreeComponent, isStandalone: true, selector: "axp-category-tree", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, events: { classPropertyName: "events", publicName: "events", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodeClick: "nodeClick", nodeSelect: "nodeSelect", nodeCreate: "nodeCreate", nodeUpdate: "nodeUpdate", nodeDelete: "nodeDelete", searchChange: "searchChange", collapseChange: "collapseChange" }, viewQueries: [{ propertyName: "tree", first: true, predicate: ["tree"], descendants: true, isSignal: true }], ngImport: i0, template: "<axp-layout-header>\n <axp-layout-toolbar>\n @if (config().searchable) {\n <ax-search-box\n (onValueChanged)=\"handleSearchChange($event)\"\n [delayTime]=\"300\"\n [placeholder]=\"config().searchPlaceholder! | translate | async\"\n >\n </ax-search-box>\n }\n </axp-layout-toolbar>\n</axp-layout-header>\n\n<axp-layout-content>\n @if (isLoading()) {\n <div class=\"ax-p-4 ax-flex ax-flex-col ax-gap-3\" [class.ax-pt-2]=\"config().searchable\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n </div>\n } @else if (treeItems()[0].children?.length) {\n <div class=\"ax-px-4 ax-max-h-[calc(100vh-250px)] ax-overflow-auto\" [class.ax-pt-2]=\"config().searchable\">\n <ax-tree-view-legacy\n (onNodeClick)=\"handleNodeClick($event)\"\n (onCollapsedChanged)=\"handleCollapseChanged($event)\"\n [showCheckbox]=\"config().showCheckbox || false\"\n [itemTemplate]=\"itemTemplate\"\n #treeRef\n [textField]=\"config().textField || 'title'\"\n [valueField]=\"config().valueField || 'id'\"\n [expandedField]=\"config().expandedField || 'expand'\"\n [items]=\"treeItems()\"\n #tree\n >\n </ax-tree-view-legacy>\n </div>\n } @else {\n <axp-state-message\n [icon]=\"config().emptyStateIcon || 'fa-light fa-folder-open'\"\n [title]=\"emptyStateTitle()\"\n [description]=\"emptyStateDescription()\"\n >\n @if (actions().canCreate) {\n <ax-button\n slot=\"actions\"\n (onClick)=\"handleCreateRootClick($event)\"\n look=\"solid\"\n color=\"primary\"\n [text]=\"(actions().createLabel || '@general:actions.add-new.title' | translate | async)!\"\n >\n <ax-icon class=\"fas fa-plus\"></ax-icon>\n </ax-button>\n }\n </axp-state-message>\n }\n\n <ng-template #itemTemplate let-item>\n @let textField = config().textField || 'title';\n @let rawTitle = item[textField] ?? item.title;\n <div class=\"ax-flex ax-items-center ax-justify-between ax-w-full ax-gap-2 ax-overflow-hidden\">\n <div class=\"ax-flex ax-items-center ax-gap-2 ax-min-w-0\">\n <ax-icon class=\"fas ax-text-warning fa-folder\"></ax-icon>\n <span class=\"ax-truncate\">\n @if (item.id === 'root') {\n {{ categoryTreeRootTitleI18nKey | translate | async }}\n } @else {\n {{ rawTitle | translate | async }}\n }\n </span>\n </div>\n @if (item.id && item.id !== 'root') {\n @if (actions().canCreateChild || actions().canUpdate || actions().canDelete) {\n <div class=\"ax-flex ax-items-center ax-gap-1\">\n <ax-button class=\"ax-xs\" color=\"default\" look=\"blank\" (onClick)=\"$event.nativeEvent.stopPropagation()\">\n <ax-icon class=\"fas fa-ellipsis-v\"></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @if (actions().canCreateChild) {\n <ax-button-item\n (onClick)=\"handleCreateChildClick(item, $event)\"\n look=\"blank\"\n color=\"default\"\n [text]=\"\n (actions().createChildLabel || '@general:actions.add-new-child.title' | translate | async)!\n \"\n >\n <ax-icon class=\"fas fa-plus\"></ax-icon>\n </ax-button-item>\n }\n @if (actions().canUpdate) {\n <ax-button-item\n (onClick)=\"handleUpdateNodeClick(item, $event)\"\n look=\"blank\"\n [text]=\"(actions().updateLabel || '@general:actions.edit.title' | translate | async)!\"\n >\n <ax-icon class=\"fas fa-pen\"></ax-icon>\n </ax-button-item>\n }\n @if (actions().canDelete) {\n <ax-button-item\n (onClick)=\"handleDeleteNodeClick(item, $event)\"\n color=\"danger\"\n look=\"blank\"\n [text]=\"(actions().deleteLabel || '@general:actions.delete.title' | translate | async)!\"\n >\n <ax-icon class=\"fas fa-trash\"></ax-icon>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n } @else if (item.id === 'root' && actions().canCreate) {\n <div class=\"ax-flex ax-items-center ax-gap-1\">\n <ax-button class=\"ax-xs\" (onClick)=\"handleCreateRootClick($event)\" look=\"blank\" color=\"default\">\n <ax-icon class=\"fas fa-plus\"></ax-icon>\n </ax-button>\n </div>\n }\n </div>\n </ng-template>\n</axp-layout-content>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTreeViewLegacyModule }, { kind: "component", type: i2$2.AXTreeViewLegacyComponent, selector: "ax-tree-view-legacy", inputs: ["items", "showCheckbox", "hasCheckboxField", "selectionMode", "selectionBehavior", "selectionScope", "focusNodeEnabled", "valueField", "textField", "visibleField", "disableField", "hasChildField", "selectedField", "expandedField", "tooltipField", "childrenField", "activeField", "indeterminateField", "parentField", "iconField", "toggleIcons", "look", "showEmptyNodeMassage", "itemTemplate", "emptyTemplate", "expandOn"], outputs: ["onSelectionChanged", "onItemSelectedChanged", "onNodeClick", "onCollapsedChanged", "onNodedbClick"] }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i2.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: "\n\n axp-page-content, \n axp-page-footer-container,\n axp-page-footer,\n axp-page-header,\n axp-page-header-container,\n axp-page-toolbar,\n\n axp-layout-content, \n axp-layout-page-content, \n\n axp-layout-sections,\n axp-layout-body,\n axp-layout-page-body,\n axp-layout-prefix,\n axp-layout-suffix,\n axp-layout-title-bar,\n axp-layout-title, \n axp-layout-title-actions, \n axp-layout-nav-button, \n axp-layout-description, \n axp-layout-breadcrumbs,\n axp-layout-list-action,\n " }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i5.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: "component", type: AXPThemeLayoutHeaderComponent, selector: "axp-layout-header" }, { kind: "component", type: AXPThemeLayoutToolbarComponent, selector: "axp-layout-toolbar" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.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: i1$2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$2.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i6.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "look"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
1144
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPCategoryTreeComponent, isStandalone: true, selector: "axp-category-tree", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, events: { classPropertyName: "events", publicName: "events", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodeClick: "nodeClick", nodeSelect: "nodeSelect", nodeCreate: "nodeCreate", nodeUpdate: "nodeUpdate", nodeDelete: "nodeDelete", searchChange: "searchChange", collapseChange: "collapseChange" }, viewQueries: [{ propertyName: "tree", first: true, predicate: ["tree"], descendants: true, isSignal: true }], ngImport: i0, template: "<axp-layout-header>\n <axp-layout-toolbar>\n @if (config().searchable) {\n <ax-search-box\n (onValueChanged)=\"handleSearchChange($event)\"\n [delayTime]=\"300\"\n [placeholder]=\"config().searchPlaceholder! | translate | async\"\n >\n </ax-search-box>\n }\n </axp-layout-toolbar>\n</axp-layout-header>\n\n<axp-layout-content>\n @if (isLoading()) {\n <div class=\"ax-p-4 ax-flex ax-flex-col ax-gap-3\" [class.ax-pt-2]=\"config().searchable\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n </div>\n } @else if (treeItems()[0].children?.length) {\n <div class=\"ax-px-4 ax-flex-1 ax-min-h-0 ax-min-w-0 ax-overflow-y-auto ax-overflow-x-hidden\" [class.ax-pt-2]=\"config().searchable\">\n <ax-tree-view-legacy\n (onNodeClick)=\"handleNodeClick($event)\"\n (onCollapsedChanged)=\"handleCollapseChanged($event)\"\n [showCheckbox]=\"config().showCheckbox || false\"\n [itemTemplate]=\"itemTemplate\"\n #treeRef\n [textField]=\"config().textField || 'title'\"\n [valueField]=\"config().valueField || 'id'\"\n [expandedField]=\"config().expandedField || 'expand'\"\n [items]=\"treeItems()\"\n #tree\n >\n </ax-tree-view-legacy>\n </div>\n } @else {\n <axp-state-message\n [icon]=\"config().emptyStateIcon || 'fa-light fa-folder-open'\"\n [title]=\"emptyStateTitle()\"\n [description]=\"emptyStateDescription()\"\n >\n @if (actions().canCreate) {\n <ax-button\n slot=\"actions\"\n (onClick)=\"handleCreateRootClick($event)\"\n look=\"solid\"\n color=\"primary\"\n [text]=\"(actions().createLabel || '@general:actions.add-new.title' | translate | async)!\"\n >\n <ax-icon class=\"fas fa-plus\"></ax-icon>\n </ax-button>\n }\n </axp-state-message>\n }\n\n <ng-template #itemTemplate let-item>\n @let textField = config().textField || 'title';\n @let rawTitle = item[textField] ?? item.title;\n <div class=\"ax-flex ax-items-center ax-justify-between ax-w-full ax-gap-2 ax-overflow-hidden\">\n <div class=\"ax-flex ax-items-center ax-gap-2 ax-min-w-0\">\n <ax-icon class=\"fas ax-text-warning fa-folder\"></ax-icon>\n <span class=\"ax-truncate\">\n @if (item.id === 'root') {\n {{ categoryTreeRootTitleI18nKey | translate | async }}\n } @else {\n {{ rawTitle | translate | async }}\n }\n </span>\n </div>\n @if (item.id && item.id !== 'root') {\n @if (actions().canCreateChild || actions().canUpdate || actions().canDelete) {\n <div class=\"ax-flex ax-items-center ax-gap-1\">\n <ax-button class=\"ax-xs\" color=\"default\" look=\"blank\" (onClick)=\"$event.nativeEvent.stopPropagation()\">\n <ax-icon class=\"fas fa-ellipsis-v\"></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @if (actions().canCreateChild) {\n <ax-button-item\n (onClick)=\"handleCreateChildClick(item, $event)\"\n look=\"blank\"\n color=\"default\"\n [text]=\"\n (actions().createChildLabel || '@general:actions.add-new-child.title' | translate | async)!\n \"\n >\n <ax-icon class=\"fas fa-plus\"></ax-icon>\n </ax-button-item>\n }\n @if (actions().canUpdate) {\n <ax-button-item\n (onClick)=\"handleUpdateNodeClick(item, $event)\"\n look=\"blank\"\n [text]=\"(actions().updateLabel || '@general:actions.edit.title' | translate | async)!\"\n >\n <ax-icon class=\"fas fa-pen\"></ax-icon>\n </ax-button-item>\n }\n @if (actions().canDelete) {\n <ax-button-item\n (onClick)=\"handleDeleteNodeClick(item, $event)\"\n color=\"danger\"\n look=\"blank\"\n [text]=\"(actions().deleteLabel || '@general:actions.delete.title' | translate | async)!\"\n >\n <ax-icon class=\"fas fa-trash\"></ax-icon>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n } @else if (item.id === 'root' && actions().canCreate) {\n <div class=\"ax-flex ax-items-center ax-gap-1\">\n <ax-button class=\"ax-xs\" (onClick)=\"handleCreateRootClick($event)\" look=\"blank\" color=\"default\">\n <ax-icon class=\"fas fa-plus\"></ax-icon>\n </ax-button>\n </div>\n }\n </div>\n </ng-template>\n</axp-layout-content>\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0;min-width:0;overflow:hidden}axp-layout-content{display:flex;flex:1;flex-direction:column;min-height:0;min-width:0;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTreeViewLegacyModule }, { kind: "component", type: i2$2.AXTreeViewLegacyComponent, selector: "ax-tree-view-legacy", inputs: ["items", "showCheckbox", "hasCheckboxField", "selectionMode", "selectionBehavior", "selectionScope", "focusNodeEnabled", "valueField", "textField", "visibleField", "disableField", "hasChildField", "selectedField", "expandedField", "tooltipField", "childrenField", "activeField", "indeterminateField", "parentField", "iconField", "toggleIcons", "look", "showEmptyNodeMassage", "itemTemplate", "emptyTemplate", "expandOn"], outputs: ["onSelectionChanged", "onItemSelectedChanged", "onNodeClick", "onCollapsedChanged", "onNodedbClick"] }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i2.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: "\n\n axp-page-content, \n axp-page-footer-container,\n axp-page-footer,\n axp-page-header,\n axp-page-header-container,\n axp-page-toolbar,\n\n axp-layout-content, \n axp-layout-page-content, \n\n axp-layout-sections,\n axp-layout-body,\n axp-layout-page-body,\n axp-layout-prefix,\n axp-layout-suffix,\n axp-layout-title-bar,\n axp-layout-title, \n axp-layout-title-actions, \n axp-layout-nav-button, \n axp-layout-description, \n axp-layout-breadcrumbs,\n axp-layout-list-action,\n " }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i5.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: "component", type: AXPThemeLayoutHeaderComponent, selector: "axp-layout-header" }, { kind: "component", type: AXPThemeLayoutToolbarComponent, selector: "axp-layout-toolbar" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.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: i1$2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$2.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i6.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "look"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
1127
1145
|
}
|
|
1128
1146
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCategoryTreeComponent, decorators: [{
|
|
1129
1147
|
type: Component,
|
|
@@ -1140,7 +1158,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
1140
1158
|
AXButtonModule,
|
|
1141
1159
|
AXDropdownModule,
|
|
1142
1160
|
AXPStateMessageComponent,
|
|
1143
|
-
], template: "<axp-layout-header>\n <axp-layout-toolbar>\n @if (config().searchable) {\n <ax-search-box\n (onValueChanged)=\"handleSearchChange($event)\"\n [delayTime]=\"300\"\n [placeholder]=\"config().searchPlaceholder! | translate | async\"\n >\n </ax-search-box>\n }\n </axp-layout-toolbar>\n</axp-layout-header>\n\n<axp-layout-content>\n @if (isLoading()) {\n <div class=\"ax-p-4 ax-flex ax-flex-col ax-gap-3\" [class.ax-pt-2]=\"config().searchable\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n </div>\n } @else if (treeItems()[0].children?.length) {\n <div class=\"ax-px-4 ax-
|
|
1161
|
+
], template: "<axp-layout-header>\n <axp-layout-toolbar>\n @if (config().searchable) {\n <ax-search-box\n (onValueChanged)=\"handleSearchChange($event)\"\n [delayTime]=\"300\"\n [placeholder]=\"config().searchPlaceholder! | translate | async\"\n >\n </ax-search-box>\n }\n </axp-layout-toolbar>\n</axp-layout-header>\n\n<axp-layout-content>\n @if (isLoading()) {\n <div class=\"ax-p-4 ax-flex ax-flex-col ax-gap-3\" [class.ax-pt-2]=\"config().searchable\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded-md\"></ax-skeleton>\n </div>\n } @else if (treeItems()[0].children?.length) {\n <div class=\"ax-px-4 ax-flex-1 ax-min-h-0 ax-min-w-0 ax-overflow-y-auto ax-overflow-x-hidden\" [class.ax-pt-2]=\"config().searchable\">\n <ax-tree-view-legacy\n (onNodeClick)=\"handleNodeClick($event)\"\n (onCollapsedChanged)=\"handleCollapseChanged($event)\"\n [showCheckbox]=\"config().showCheckbox || false\"\n [itemTemplate]=\"itemTemplate\"\n #treeRef\n [textField]=\"config().textField || 'title'\"\n [valueField]=\"config().valueField || 'id'\"\n [expandedField]=\"config().expandedField || 'expand'\"\n [items]=\"treeItems()\"\n #tree\n >\n </ax-tree-view-legacy>\n </div>\n } @else {\n <axp-state-message\n [icon]=\"config().emptyStateIcon || 'fa-light fa-folder-open'\"\n [title]=\"emptyStateTitle()\"\n [description]=\"emptyStateDescription()\"\n >\n @if (actions().canCreate) {\n <ax-button\n slot=\"actions\"\n (onClick)=\"handleCreateRootClick($event)\"\n look=\"solid\"\n color=\"primary\"\n [text]=\"(actions().createLabel || '@general:actions.add-new.title' | translate | async)!\"\n >\n <ax-icon class=\"fas fa-plus\"></ax-icon>\n </ax-button>\n }\n </axp-state-message>\n }\n\n <ng-template #itemTemplate let-item>\n @let textField = config().textField || 'title';\n @let rawTitle = item[textField] ?? item.title;\n <div class=\"ax-flex ax-items-center ax-justify-between ax-w-full ax-gap-2 ax-overflow-hidden\">\n <div class=\"ax-flex ax-items-center ax-gap-2 ax-min-w-0\">\n <ax-icon class=\"fas ax-text-warning fa-folder\"></ax-icon>\n <span class=\"ax-truncate\">\n @if (item.id === 'root') {\n {{ categoryTreeRootTitleI18nKey | translate | async }}\n } @else {\n {{ rawTitle | translate | async }}\n }\n </span>\n </div>\n @if (item.id && item.id !== 'root') {\n @if (actions().canCreateChild || actions().canUpdate || actions().canDelete) {\n <div class=\"ax-flex ax-items-center ax-gap-1\">\n <ax-button class=\"ax-xs\" color=\"default\" look=\"blank\" (onClick)=\"$event.nativeEvent.stopPropagation()\">\n <ax-icon class=\"fas fa-ellipsis-v\"></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @if (actions().canCreateChild) {\n <ax-button-item\n (onClick)=\"handleCreateChildClick(item, $event)\"\n look=\"blank\"\n color=\"default\"\n [text]=\"\n (actions().createChildLabel || '@general:actions.add-new-child.title' | translate | async)!\n \"\n >\n <ax-icon class=\"fas fa-plus\"></ax-icon>\n </ax-button-item>\n }\n @if (actions().canUpdate) {\n <ax-button-item\n (onClick)=\"handleUpdateNodeClick(item, $event)\"\n look=\"blank\"\n [text]=\"(actions().updateLabel || '@general:actions.edit.title' | translate | async)!\"\n >\n <ax-icon class=\"fas fa-pen\"></ax-icon>\n </ax-button-item>\n }\n @if (actions().canDelete) {\n <ax-button-item\n (onClick)=\"handleDeleteNodeClick(item, $event)\"\n color=\"danger\"\n look=\"blank\"\n [text]=\"(actions().deleteLabel || '@general:actions.delete.title' | translate | async)!\"\n >\n <ax-icon class=\"fas fa-trash\"></ax-icon>\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n } @else if (item.id === 'root' && actions().canCreate) {\n <div class=\"ax-flex ax-items-center ax-gap-1\">\n <ax-button class=\"ax-xs\" (onClick)=\"handleCreateRootClick($event)\" look=\"blank\" color=\"default\">\n <ax-icon class=\"fas fa-plus\"></ax-icon>\n </ax-button>\n </div>\n }\n </div>\n </ng-template>\n</axp-layout-content>\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0;min-width:0;overflow:hidden}axp-layout-content{display:flex;flex:1;flex-direction:column;min-height:0;min-width:0;overflow:hidden}\n"] }]
|
|
1144
1162
|
}], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], events: [{ type: i0.Input, args: [{ isSignal: true, alias: "events", required: false }] }], nodeClick: [{ type: i0.Output, args: ["nodeClick"] }], nodeSelect: [{ type: i0.Output, args: ["nodeSelect"] }], nodeCreate: [{ type: i0.Output, args: ["nodeCreate"] }], nodeUpdate: [{ type: i0.Output, args: ["nodeUpdate"] }], nodeDelete: [{ type: i0.Output, args: ["nodeDelete"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }], collapseChange: [{ type: i0.Output, args: ["collapseChange"] }], tree: [{ type: i0.ViewChild, args: ['tree', { isSignal: true }] }] } });
|
|
1145
1163
|
|
|
1146
1164
|
//#region ---- Tree Node Interface ----
|
|
@@ -1574,14 +1592,9 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1574
1592
|
this.config = signal({
|
|
1575
1593
|
title: '',
|
|
1576
1594
|
dataSource: null,
|
|
1577
|
-
columns: [],
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
initialSearchTerm: undefined,
|
|
1581
|
-
parentField: undefined,
|
|
1582
|
-
allowCreate: 'none',
|
|
1583
|
-
filters: undefined,
|
|
1584
|
-
selectedItemIds: undefined
|
|
1595
|
+
grid: { columns: [] },
|
|
1596
|
+
selection: { mode: 'single' },
|
|
1597
|
+
create: { mode: 'none' },
|
|
1585
1598
|
}, ...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
|
|
1586
1599
|
this.searchTerm = '';
|
|
1587
1600
|
this.searchPlaceholderText = signal('', ...(ngDevMode ? [{ debugName: "searchPlaceholderText" }] : /* istanbul ignore next */ []));
|
|
@@ -1590,6 +1603,8 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1590
1603
|
this.initialSelectionApplied = false;
|
|
1591
1604
|
this.userHasInteracted = false;
|
|
1592
1605
|
this.isApplyingInitialSelection = false;
|
|
1606
|
+
/** Suppresses stale grid selection events while a single-mode row click is being applied. */
|
|
1607
|
+
this.rowClickSelectionSync = false;
|
|
1593
1608
|
this.initialSelectedItems = []; // Track initial selection to calculate difference
|
|
1594
1609
|
// Category Filter State
|
|
1595
1610
|
this.activeCategoryFilter = signal(null, ...(ngDevMode ? [{ debugName: "activeCategoryFilter" }] : /* istanbul ignore next */ []));
|
|
@@ -1599,12 +1614,23 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1599
1614
|
//#region ---- Services & Dependencies ----
|
|
1600
1615
|
this.translationService = inject(AXTranslationService);
|
|
1601
1616
|
//#region ---- Computed Properties ----
|
|
1602
|
-
this.
|
|
1617
|
+
this.allowUnselect = computed(() => this.config().selection?.allowUnselect ?? true, ...(ngDevMode ? [{ debugName: "allowUnselect" }] : /* istanbul ignore next */ []));
|
|
1618
|
+
this.allowSelect = computed(() => {
|
|
1619
|
+
if (this.allowUnselect()) {
|
|
1620
|
+
return true;
|
|
1621
|
+
}
|
|
1622
|
+
return this.selectedItems().length > 0;
|
|
1623
|
+
}, ...(ngDevMode ? [{ debugName: "allowSelect" }] : /* istanbul ignore next */ []));
|
|
1603
1624
|
this.selectedCount = computed(() => this.selectedItems().length, ...(ngDevMode ? [{ debugName: "selectedCount" }] : /* istanbul ignore next */ []));
|
|
1604
1625
|
this.hasSearch = computed(() => {
|
|
1605
|
-
const searchFields = this.config().
|
|
1626
|
+
const searchFields = this.config().search?.fields;
|
|
1606
1627
|
return searchFields && searchFields.length > 0;
|
|
1607
1628
|
}, ...(ngDevMode ? [{ debugName: "hasSearch" }] : /* istanbul ignore next */ []));
|
|
1629
|
+
this.selectionMode = computed(() => this.config().selection?.mode ?? 'single', ...(ngDevMode ? [{ debugName: "selectionMode" }] : /* istanbul ignore next */ []));
|
|
1630
|
+
this.categoryEnabled = computed(() => {
|
|
1631
|
+
const category = this.config().category;
|
|
1632
|
+
return !!category && category.enabled !== false && !!category.dataSource;
|
|
1633
|
+
}, ...(ngDevMode ? [{ debugName: "categoryEnabled" }] : /* istanbul ignore next */ []));
|
|
1608
1634
|
// Category Tree Configuration
|
|
1609
1635
|
this.categoryTreeConfig = computed(() => ({
|
|
1610
1636
|
textField: 'title',
|
|
@@ -1623,12 +1649,26 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1623
1649
|
canDelete: false,
|
|
1624
1650
|
canCreateChild: false,
|
|
1625
1651
|
}), ...(ngDevMode ? [{ debugName: "categoryTreeActions" }] : /* istanbul ignore next */ []));
|
|
1652
|
+
this.hasRowActionPrimary = computed(() => this.config().rowActions?.hasPrimary() ?? false, ...(ngDevMode ? [{ debugName: "hasRowActionPrimary" }] : /* istanbul ignore next */ []));
|
|
1653
|
+
this.hasRowActionDropdown = computed(() => this.config().rowActions?.hasDropdown() ?? false, ...(ngDevMode ? [{ debugName: "hasRowActionDropdown" }] : /* istanbul ignore next */ []));
|
|
1654
|
+
this.primaryRowActionItems = computed(() => (this.config().rowActions?.getPrimaryItems() ?? []), ...(ngDevMode ? [{ debugName: "primaryRowActionItems" }] : /* istanbul ignore next */ []));
|
|
1655
|
+
this.primaryRowActionColumnWidth = computed(() => {
|
|
1656
|
+
const count = this.primaryRowActionItems().length;
|
|
1657
|
+
return count > 0 ? `${count * 70}px` : '60px';
|
|
1658
|
+
}, ...(ngDevMode ? [{ debugName: "primaryRowActionColumnWidth" }] : /* istanbul ignore next */ []));
|
|
1659
|
+
this.getDropdownRowActionItems = (rowData) => {
|
|
1660
|
+
const handler = this.config().rowActions;
|
|
1661
|
+
if (!handler) {
|
|
1662
|
+
return Promise.resolve([]);
|
|
1663
|
+
}
|
|
1664
|
+
return handler.getDropdownItems(rowData).then((items) => items);
|
|
1665
|
+
};
|
|
1626
1666
|
effect(() => {
|
|
1627
|
-
const searchFields = this.config().
|
|
1667
|
+
const searchFields = this.config().search?.fields;
|
|
1628
1668
|
void this.updateSearchPlaceholder(searchFields);
|
|
1629
1669
|
});
|
|
1630
1670
|
effect(() => {
|
|
1631
|
-
const initialTerm = this.config().
|
|
1671
|
+
const initialTerm = this.config().search?.initial ?? '';
|
|
1632
1672
|
if (!this.initialSearchApplied && initialTerm && initialTerm.trim().length > 0) {
|
|
1633
1673
|
this.initialSearchApplied = true;
|
|
1634
1674
|
this.searchTerm = initialTerm;
|
|
@@ -1658,23 +1698,32 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1658
1698
|
this.close({ items: [e.data] });
|
|
1659
1699
|
}
|
|
1660
1700
|
handleRowClick(e) {
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
// In single selection mode, update selectedItems directly since grid doesn't fire selectedRowsChange
|
|
1664
|
-
if (this.config().selectionMode === 'single') {
|
|
1665
|
-
this.selectedItems.set([e.data]);
|
|
1701
|
+
if (!this.isSingleSelectionMode()) {
|
|
1702
|
+
return;
|
|
1666
1703
|
}
|
|
1667
|
-
|
|
1668
|
-
|
|
1704
|
+
const clicked = e.data;
|
|
1705
|
+
const current = this.selectedItems();
|
|
1706
|
+
const clickedKey = this.getRowKey(clicked);
|
|
1707
|
+
const isAlreadySelected = current.length === 1 && this.getRowKey(current[0]) === clickedKey;
|
|
1708
|
+
const nextSelection = this.allowUnselect() && isAlreadySelected ? [] : [clicked];
|
|
1709
|
+
this.rowClickSelectionSync = true;
|
|
1710
|
+
this.applySingleSelection(nextSelection, true);
|
|
1669
1711
|
}
|
|
1670
1712
|
async handleSelectedRowsChange(rows) {
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1713
|
+
if (this.rowClickSelectionSync) {
|
|
1714
|
+
return;
|
|
1715
|
+
}
|
|
1716
|
+
let newSelection = rows || [];
|
|
1717
|
+
if (this.isSingleSelectionMode()) {
|
|
1718
|
+
const clamped = this.clampSingleSelection(newSelection);
|
|
1719
|
+
if (!isEqual(clamped, newSelection) && !this.isApplyingInitialSelection) {
|
|
1720
|
+
this.syncGridSingleSelection(clamped);
|
|
1721
|
+
}
|
|
1722
|
+
newSelection = clamped;
|
|
1723
|
+
}
|
|
1674
1724
|
if (!this.isApplyingInitialSelection) {
|
|
1675
1725
|
this.userHasInteracted = true;
|
|
1676
1726
|
}
|
|
1677
|
-
// Always update selectedItems from data table selection
|
|
1678
1727
|
this.selectedItems.set(newSelection);
|
|
1679
1728
|
}
|
|
1680
1729
|
handleChangeSearchValue(e) {
|
|
@@ -1685,12 +1734,12 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1685
1734
|
}
|
|
1686
1735
|
}
|
|
1687
1736
|
async handleCreateNewClick(mode) {
|
|
1688
|
-
const onCreate = this.config().onCreate;
|
|
1737
|
+
const onCreate = this.config().create?.onCreate;
|
|
1689
1738
|
if (!onCreate)
|
|
1690
1739
|
return;
|
|
1691
1740
|
const createdItem = await onCreate(mode);
|
|
1692
1741
|
if (createdItem) {
|
|
1693
|
-
if (this.
|
|
1742
|
+
if (this.selectionMode() === 'multiple') {
|
|
1694
1743
|
const currentSelection = this.selectedItems();
|
|
1695
1744
|
const newSelection = [...currentSelection, createdItem];
|
|
1696
1745
|
this.selectedItems.set(newSelection);
|
|
@@ -1718,9 +1767,26 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1718
1767
|
await this.grid().expandRow(row);
|
|
1719
1768
|
}
|
|
1720
1769
|
}
|
|
1770
|
+
async handleRowActionClick(event) {
|
|
1771
|
+
const handler = this.config().rowActions;
|
|
1772
|
+
if (!handler || this.grid()?.dataSource.isLoading) {
|
|
1773
|
+
return;
|
|
1774
|
+
}
|
|
1775
|
+
if (event.setLoading) {
|
|
1776
|
+
event.setLoading(true);
|
|
1777
|
+
}
|
|
1778
|
+
try {
|
|
1779
|
+
await handler.execute(event.name, event.data);
|
|
1780
|
+
}
|
|
1781
|
+
finally {
|
|
1782
|
+
if (event.setLoading) {
|
|
1783
|
+
event.setLoading(false);
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1721
1787
|
// Category Filter Event Handlers
|
|
1722
1788
|
handleCategoryFilterClick(node) {
|
|
1723
|
-
const categoryConfig = this.config().
|
|
1789
|
+
const categoryConfig = this.config().category;
|
|
1724
1790
|
// Get the filter value from the node
|
|
1725
1791
|
const filterValue = node.id;
|
|
1726
1792
|
// Store active filter state
|
|
@@ -1734,7 +1800,7 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1734
1800
|
clearCategoryFilter() {
|
|
1735
1801
|
this.activeCategoryFilter.set(null);
|
|
1736
1802
|
// Apply only base filters (without category filter)
|
|
1737
|
-
const baseFilters = this.config().
|
|
1803
|
+
const baseFilters = this.config().filter?.value;
|
|
1738
1804
|
if (baseFilters) {
|
|
1739
1805
|
this.config().dataSource.filter(baseFilters);
|
|
1740
1806
|
}
|
|
@@ -1745,15 +1811,75 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1745
1811
|
}
|
|
1746
1812
|
//#endregion
|
|
1747
1813
|
//#region ---- Private Methods ----
|
|
1814
|
+
getRowKey(row) {
|
|
1815
|
+
const dataSource = this.config().dataSource;
|
|
1816
|
+
const keyField = dataSource.config?.key ?? 'id';
|
|
1817
|
+
return String(row?.[keyField] ?? '');
|
|
1818
|
+
}
|
|
1819
|
+
isSingleSelectionMode() {
|
|
1820
|
+
return this.selectionMode() === 'single';
|
|
1821
|
+
}
|
|
1822
|
+
applySingleSelection(selection, force = false) {
|
|
1823
|
+
const clamped = this.clampSingleSelection(selection);
|
|
1824
|
+
if (!force && isEqual(clamped, this.selectedItems())) {
|
|
1825
|
+
this.clearRowClickSelectionSync();
|
|
1826
|
+
return;
|
|
1827
|
+
}
|
|
1828
|
+
this.userHasInteracted = true;
|
|
1829
|
+
this.selectedItems.set(clamped);
|
|
1830
|
+
this.syncGridSingleSelection(clamped);
|
|
1831
|
+
}
|
|
1832
|
+
clearRowClickSelectionSync() {
|
|
1833
|
+
this.rowClickSelectionSync = false;
|
|
1834
|
+
}
|
|
1835
|
+
/**
|
|
1836
|
+
* Keeps at most one row when single mode uses checkboxes.
|
|
1837
|
+
*/
|
|
1838
|
+
clampSingleSelection(newSelection) {
|
|
1839
|
+
if (newSelection.length <= 1) {
|
|
1840
|
+
return newSelection;
|
|
1841
|
+
}
|
|
1842
|
+
const prev = this.selectedItems();
|
|
1843
|
+
const prevKeys = new Set(prev.map((row) => this.getRowKey(row)));
|
|
1844
|
+
const added = newSelection.filter((row) => !prevKeys.has(this.getRowKey(row)));
|
|
1845
|
+
if (added.length > 0) {
|
|
1846
|
+
return [added[added.length - 1]];
|
|
1847
|
+
}
|
|
1848
|
+
return [newSelection[newSelection.length - 1]];
|
|
1849
|
+
}
|
|
1850
|
+
syncGridSingleSelection(selection) {
|
|
1851
|
+
const grid = this.grid();
|
|
1852
|
+
if (!grid) {
|
|
1853
|
+
this.clearRowClickSelectionSync();
|
|
1854
|
+
return;
|
|
1855
|
+
}
|
|
1856
|
+
queueMicrotask(() => {
|
|
1857
|
+
this.isApplyingInitialSelection = true;
|
|
1858
|
+
try {
|
|
1859
|
+
if (selection.length === 1 && grid.selectRows) {
|
|
1860
|
+
grid.selectRows(selection[0]);
|
|
1861
|
+
}
|
|
1862
|
+
else if (selection.length === 0) {
|
|
1863
|
+
grid.selectedRows = [];
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
finally {
|
|
1867
|
+
setTimeout(() => {
|
|
1868
|
+
this.isApplyingInitialSelection = false;
|
|
1869
|
+
this.clearRowClickSelectionSync();
|
|
1870
|
+
}, 0);
|
|
1871
|
+
}
|
|
1872
|
+
});
|
|
1873
|
+
}
|
|
1748
1874
|
applySearchFilter(searchTerm) {
|
|
1749
|
-
const searchFields = this.config().
|
|
1875
|
+
const searchFields = this.config().search?.fields;
|
|
1750
1876
|
if (!searchFields || searchFields.length === 0) {
|
|
1751
1877
|
return;
|
|
1752
1878
|
}
|
|
1753
1879
|
const normalizedTerm = isNil(searchTerm) ? '' : `${searchTerm}`.trim();
|
|
1754
1880
|
if (isEmpty(normalizedTerm)) {
|
|
1755
1881
|
// Apply only base filters when search is cleared
|
|
1756
|
-
const baseFilters = this.config().
|
|
1882
|
+
const baseFilters = this.config().filter?.value;
|
|
1757
1883
|
if (baseFilters) {
|
|
1758
1884
|
this.config().dataSource.filter(baseFilters);
|
|
1759
1885
|
}
|
|
@@ -1764,7 +1890,7 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1764
1890
|
return;
|
|
1765
1891
|
}
|
|
1766
1892
|
// Get base filters from config
|
|
1767
|
-
const baseFilters = this.config().
|
|
1893
|
+
const baseFilters = this.config().filter?.value;
|
|
1768
1894
|
// Create search filters for all configured fields
|
|
1769
1895
|
const searchFilters = searchFields.map((field) => ({
|
|
1770
1896
|
field: field.name,
|
|
@@ -1791,7 +1917,7 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1791
1917
|
}
|
|
1792
1918
|
applyFilterAndSort() {
|
|
1793
1919
|
// Apply base filters from config
|
|
1794
|
-
const baseFilters = this.config().
|
|
1920
|
+
const baseFilters = this.config().filter?.value;
|
|
1795
1921
|
if (baseFilters) {
|
|
1796
1922
|
this.config().dataSource.filter(baseFilters);
|
|
1797
1923
|
this.config().dataSource.refresh();
|
|
@@ -1799,7 +1925,7 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1799
1925
|
}
|
|
1800
1926
|
applyCategoryFilter(filterValue, categoryConfig) {
|
|
1801
1927
|
if (isNil(filterValue) || filterValue === 'root') {
|
|
1802
|
-
const baseFilters = this.config().
|
|
1928
|
+
const baseFilters = this.config().filter?.value;
|
|
1803
1929
|
if (baseFilters) {
|
|
1804
1930
|
this.config().dataSource.filter(baseFilters);
|
|
1805
1931
|
}
|
|
@@ -1810,12 +1936,12 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1810
1936
|
return;
|
|
1811
1937
|
}
|
|
1812
1938
|
// Get base filters from config
|
|
1813
|
-
const baseFilters = this.config().
|
|
1939
|
+
const baseFilters = this.config().filter?.value;
|
|
1814
1940
|
// Create category filter
|
|
1815
1941
|
const categoryFilter = {
|
|
1816
|
-
field: categoryConfig.
|
|
1942
|
+
field: categoryConfig.filter.field,
|
|
1817
1943
|
value: filterValue,
|
|
1818
|
-
operator: { type: categoryConfig.
|
|
1944
|
+
operator: { type: categoryConfig.filter.operator || 'contains' }
|
|
1819
1945
|
};
|
|
1820
1946
|
// Merge base filters with category filter
|
|
1821
1947
|
const allFilters = baseFilters ? [baseFilters, categoryFilter] : [categoryFilter];
|
|
@@ -1866,7 +1992,7 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1866
1992
|
if (this.initialSelectionApplied || this.userHasInteracted) {
|
|
1867
1993
|
return;
|
|
1868
1994
|
}
|
|
1869
|
-
const selectedIds = this.config().selectedItemIds;
|
|
1995
|
+
const selectedIds = this.config().selection?.selectedItemIds;
|
|
1870
1996
|
if (!selectedIds || selectedIds.length === 0) {
|
|
1871
1997
|
// No initial selection, so initialSelectedItems should be empty
|
|
1872
1998
|
this.initialSelectedItems = [];
|
|
@@ -1885,7 +2011,7 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1885
2011
|
const keyField = dataSourceAny.config?.key || 'id';
|
|
1886
2012
|
const byKeyMethod = dataSourceAny.config?.byKey;
|
|
1887
2013
|
// First, try to find items in already loaded grid data
|
|
1888
|
-
|
|
2014
|
+
let itemsToSelect = [];
|
|
1889
2015
|
const maxAttempts = 10; // Try for up to 1 second (10 * 100ms)
|
|
1890
2016
|
let attempts = 0;
|
|
1891
2017
|
const missingIds = [];
|
|
@@ -1949,28 +2075,28 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1949
2075
|
}
|
|
1950
2076
|
}
|
|
1951
2077
|
}
|
|
2078
|
+
if (this.isSingleSelectionMode() && itemsToSelect.length > 1) {
|
|
2079
|
+
itemsToSelect = [itemsToSelect[0]];
|
|
2080
|
+
}
|
|
1952
2081
|
// Only mark as applied if we found items to select
|
|
1953
2082
|
if (itemsToSelect.length > 0) {
|
|
1954
|
-
// Store initial selected items for later comparison
|
|
1955
2083
|
this.initialSelectedItems = [...itemsToSelect];
|
|
1956
|
-
// Set flag to indicate we're applying initial selection
|
|
1957
2084
|
this.isApplyingInitialSelection = true;
|
|
1958
2085
|
try {
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
2086
|
+
if (this.isSingleSelectionMode()) {
|
|
2087
|
+
this.rowClickSelectionSync = true;
|
|
2088
|
+
this.selectedItems.set(itemsToSelect);
|
|
2089
|
+
this.syncGridSingleSelection(itemsToSelect);
|
|
2090
|
+
}
|
|
2091
|
+
else {
|
|
2092
|
+
this.selectedItems.set(itemsToSelect);
|
|
2093
|
+
if (this.grid()?.selectRows) {
|
|
1967
2094
|
this.grid().selectRows(...itemsToSelect);
|
|
1968
2095
|
}
|
|
1969
2096
|
}
|
|
1970
2097
|
this.initialSelectionApplied = true;
|
|
1971
2098
|
}
|
|
1972
2099
|
finally {
|
|
1973
|
-
// Reset flag after a short delay to allow the event to process
|
|
1974
2100
|
setTimeout(() => {
|
|
1975
2101
|
this.isApplyingInitialSelection = false;
|
|
1976
2102
|
}, 50);
|
|
@@ -1988,11 +2114,11 @@ class AXPDataSelectorComponent extends AXBasePageComponent {
|
|
|
1988
2114
|
}
|
|
1989
2115
|
}
|
|
1990
2116
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1991
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPDataSelectorComponent, isStandalone: true, selector: "axp-data-selector", viewQueries: [{ propertyName: "grid", first: true, predicate: ["grid"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"axp-data-selector\">\n <!-- Main Content Area -->\n <div class=\"axp-data-selector-content\" [class.with-category-filter]=\"
|
|
2117
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPDataSelectorComponent, isStandalone: true, selector: "axp-data-selector", viewQueries: [{ propertyName: "grid", first: true, predicate: ["grid"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"axp-data-selector\">\n <!-- Main Content Area -->\n <div class=\"axp-data-selector-content\" [class.with-category-filter]=\"categoryEnabled()\">\n <!-- Category Filter Side Panel -->\n @if (categoryEnabled()) {\n <div class=\"axp-category-filter-panel\" [style.width]=\"config().category?.width || '300px'\">\n <axp-category-tree [dataSource]=\"config().category!.dataSource\" [config]=\"categoryTreeConfig()\"\n [actions]=\"categoryTreeActions()\" (nodeClick)=\"handleCategoryFilterClick($event)\">\n </axp-category-tree>\n </div>\n }\n\n <!-- Main Data Area -->\n <div class=\"axp-main-data-area\">\n @if (hasSearch()) {\n <div class=\"ax-w-full ax-mb-2\">\n <ax-search-box [placeholder]=\"searchPlaceholderText()\" [value]=\"searchTerm\"\n (onValueChanged)=\"handleChangeSearchValue($event)\" [axAutoFocus]=\"true\">\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </div>\n }\n <ax-data-table #grid [showFooter]=\"false\" class=\"ax-flex-1 ax-min-h-0\" [paging]=\"true\"\n [loading]=\"{ enabled: true, animation: true }\" [dataSource]=\"config().dataSource\"\n [parentField]=\"config().grid.parentField\" [selectedRows]=\"selectedItems()\"\n (selectedRowsChange)=\"handleSelectedRowsChange($event)\" (onRowClick)=\"handleRowClick($event)\"\n (onRowDbClick)=\"handleRowDbClick($event)\">\n <ax-select-column fixed=\"start\" [width]=\"'50px'\"></ax-select-column>\n\n @for (col of config().grid.columns; track col.name) {\n @if (col.visible) {\n <axp-widget-column-renderer [expandHandler]=\"$index === 0 && config().grid.parentField ? true : false\"\n [caption]=\"col.title | translate | async\" [customWidth]=\"col.width || ''\" [node]=\"{\n path: col.dataPath || col.name,\n type: col.widget.type,\n options: col.widget.options\n }\">\n </axp-widget-column-renderer>\n }\n }\n @if (hasRowActionPrimary()) {\n <ax-command-column fixed=\"end\" [width]=\"primaryRowActionColumnWidth()\" [items]=\"primaryRowActionItems()\"\n (onItemClick)=\"handleRowActionClick($event)\">\n </ax-command-column>\n }\n @if (hasRowActionDropdown()) {\n <ax-dropdown-command-column fixed=\"end\" [width]=\"'60px'\" [items]=\"getDropdownRowActionItems\"\n (onItemClick)=\"handleRowActionClick($event)\">\n </ax-dropdown-command-column>\n }\n </ax-data-table>\n </div>\n </div>\n</div>\n\n<ax-footer>\n <ax-prefix>\n @if ((config().create?.mode === 'full' || config().create?.mode === 'quick') && config().create?.onCreate) {\n <ax-button look=\"twotone\" color=\"primary\" [text]=\"'@general:actions.create.title' | translate | async\"\n (onClick)=\"handleCreateNewClick(config().create?.mode === 'quick' ? 'quick' : 'full')\">\n <ax-prefix>\n <ax-icon icon=\"far fa-plus\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </ax-prefix>\n <ax-suffix>\n <ax-button look=\"solid\" [text]=\"('@general:actions.close.title' | translate | async)!\"\n (onClick)=\"handleCloseClick()\">\n </ax-button>\n <ax-button look=\"solid\" color=\"primary\" [text]=\"('@general:actions.select.title' | translate | async)!\"\n (onClick)=\"handleSelectClick()\" [disabled]=\"allowSelect() === false\">\n <!-- @if (selectionMode() === 'multiple' && selectedCount() > 0) {\n <ax-badge [text]=\"selectedCount().toString()\" color=\"accent1\"\n class=\"ax-absolute ax-end-[2px] ax-top-[2px]\"></ax-badge>\n } -->\n </ax-button>\n </ax-suffix>\n</ax-footer>\n", styles: ["axp-data-selector{display:flex;flex-direction:column;flex:1;min-height:0;height:100%;overflow:hidden}.ax-expand-handler{cursor:pointer;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:8px}.ax-expand-handler:hover{opacity:.8}.ax-expand-handler.ax-invisible{visibility:hidden}.ax-overflow-hidden{overflow:hidden}.ax-flex{display:flex}.ax-flex-col{flex-direction:column}.ax-gap-4{gap:1rem}.ax-p-4{padding:1rem}.ax-w-full{width:100%}.axp-data-selector{display:flex;flex-direction:column;flex:1;min-height:0;overflow:hidden}.axp-data-selector-content{display:flex;flex:1;min-height:0;overflow:hidden}.axp-data-selector-content.with-category-filter .axp-main-data-area{flex:1;min-width:0;min-height:0;overflow:hidden}.axp-data-selector .axp-category-filter-panel{display:flex;flex-direction:column;border-right:1px solid var(--border-color);padding:1rem;background:var(--surface-color);flex-shrink:0;min-height:0;min-width:0;overflow:hidden}.axp-data-selector .axp-category-filter-panel axp-category-tree{display:flex;flex:1;flex-direction:column;min-height:0;min-width:0;overflow:hidden}.axp-data-selector .axp-main-data-area{flex:1;min-width:0;min-height:0;overflow:hidden;padding:1rem;display:flex;flex-direction:column;gap:1rem}.axp-data-selector .axp-main-data-area ax-data-table{flex:1;min-height:0;height:100%;display:flex;flex-direction:column;overflow:hidden}.axp-data-selector .axp-main-data-area .ax-search-box{width:100%;flex-shrink:0}.ax-popup:has(axp-data-selector){display:flex;flex-direction:column;height:90vh;max-height:90vh;overflow:hidden}.ax-popup:has(axp-data-selector) .ax-popup-main-container{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;overflow:hidden}.ax-popup:has(axp-data-selector) .ax-popup-body-container{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;overflow:hidden!important}.ax-popup:has(axp-data-selector) .ax-popup-footer-container{flex-shrink:0}@media(min-width:320px)and (max-width:640px){.ax-popup.ax-popup-sm:has(axp-data-selector),.ax-popup.ax-popup-md:has(axp-data-selector),.ax-popup.ax-popup-lg:has(axp-data-selector){height:90vh!important;max-height:90vh!important}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXCommonModule }, { kind: "directive", type: i1$6.AXAutoFocusDirective, selector: "[axAutoFocus]", inputs: ["axAutoFocus", "axAutoFocusTime"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.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: AXFormModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDataTableModule }, { kind: "component", type: i4$1.AXDataTableComponent, selector: "ax-data-table", inputs: ["dataSource", "selectedRows", "parentField", "hasChildrenField", "rowDetailsTemplate", "rowTemplate", "emptyTemplate", "noDataTemplate", "alternative", "showHeader", "fixedHeader", "showFooter", "fixedFooter", "itemHeight", "allowReordering", "paging", "fetchDataMode", "loading", "focusedRow"], outputs: ["selectedRowsChange", "focusedRowChange", "onRowClick", "onRowDbClick", "onColumnsOrderChanged", "onColumnSizeChanged", "onPageChanged"] }, { kind: "component", type: i4$1.AXRowSelectColumnComponent, selector: "ax-select-column", inputs: ["width", "caption", "fixed"] }, { kind: "component", type: i4$1.AXRowCommandColumnComponent, selector: "ax-command-column", inputs: ["width", "caption", "fixed", "footerTemplate", "items"], outputs: ["onItemClick"] }, { kind: "component", type: i4$1.AXRowDropdownCommandColumnComponent, selector: "ax-dropdown-command-column", inputs: ["width", "caption", "fixed", "footerTemplate", "emptyStateTemplate", "emptyStateText", "items"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i5.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: AXPWidgetCoreModule }, { kind: "component", type: i3$3.AXPWidgetColumnRendererComponent, selector: "axp-widget-column-renderer", inputs: ["caption", "customExpandIcon", "customCollapseIcon", "customWidth", "node", "footerTemplate", "expandHandler", "sortEnabled", "headerSortDirection", "headerSortPriority", "cellTemplate", "headerTemplate"], outputs: ["sortToggle"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: AXPCategoryTreeComponent, selector: "axp-category-tree", inputs: ["dataSource", "config", "actions", "events"], outputs: ["nodeClick", "nodeSelect", "nodeCreate", "nodeUpdate", "nodeDelete", "searchChange", "collapseChange"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
1992
2118
|
}
|
|
1993
2119
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSelectorComponent, decorators: [{
|
|
1994
2120
|
type: Component,
|
|
1995
|
-
args: [{ selector: 'axp-data-selector', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
2121
|
+
args: [{ selector: 'axp-data-selector', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
|
|
1996
2122
|
CommonModule,
|
|
1997
2123
|
AXCommonModule,
|
|
1998
2124
|
AXButtonModule,
|
|
@@ -2005,7 +2131,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2005
2131
|
AXTranslationModule,
|
|
2006
2132
|
AXBadgeModule,
|
|
2007
2133
|
AXPCategoryTreeComponent,
|
|
2008
|
-
], inputs: [], template: "<div class=\"axp-data-selector\">\n <!-- Main Content Area -->\n <div class=\"axp-data-selector-content\" [class.with-category-filter]=\"
|
|
2134
|
+
], inputs: [], template: "<div class=\"axp-data-selector\">\n <!-- Main Content Area -->\n <div class=\"axp-data-selector-content\" [class.with-category-filter]=\"categoryEnabled()\">\n <!-- Category Filter Side Panel -->\n @if (categoryEnabled()) {\n <div class=\"axp-category-filter-panel\" [style.width]=\"config().category?.width || '300px'\">\n <axp-category-tree [dataSource]=\"config().category!.dataSource\" [config]=\"categoryTreeConfig()\"\n [actions]=\"categoryTreeActions()\" (nodeClick)=\"handleCategoryFilterClick($event)\">\n </axp-category-tree>\n </div>\n }\n\n <!-- Main Data Area -->\n <div class=\"axp-main-data-area\">\n @if (hasSearch()) {\n <div class=\"ax-w-full ax-mb-2\">\n <ax-search-box [placeholder]=\"searchPlaceholderText()\" [value]=\"searchTerm\"\n (onValueChanged)=\"handleChangeSearchValue($event)\" [axAutoFocus]=\"true\">\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </div>\n }\n <ax-data-table #grid [showFooter]=\"false\" class=\"ax-flex-1 ax-min-h-0\" [paging]=\"true\"\n [loading]=\"{ enabled: true, animation: true }\" [dataSource]=\"config().dataSource\"\n [parentField]=\"config().grid.parentField\" [selectedRows]=\"selectedItems()\"\n (selectedRowsChange)=\"handleSelectedRowsChange($event)\" (onRowClick)=\"handleRowClick($event)\"\n (onRowDbClick)=\"handleRowDbClick($event)\">\n <ax-select-column fixed=\"start\" [width]=\"'50px'\"></ax-select-column>\n\n @for (col of config().grid.columns; track col.name) {\n @if (col.visible) {\n <axp-widget-column-renderer [expandHandler]=\"$index === 0 && config().grid.parentField ? true : false\"\n [caption]=\"col.title | translate | async\" [customWidth]=\"col.width || ''\" [node]=\"{\n path: col.dataPath || col.name,\n type: col.widget.type,\n options: col.widget.options\n }\">\n </axp-widget-column-renderer>\n }\n }\n @if (hasRowActionPrimary()) {\n <ax-command-column fixed=\"end\" [width]=\"primaryRowActionColumnWidth()\" [items]=\"primaryRowActionItems()\"\n (onItemClick)=\"handleRowActionClick($event)\">\n </ax-command-column>\n }\n @if (hasRowActionDropdown()) {\n <ax-dropdown-command-column fixed=\"end\" [width]=\"'60px'\" [items]=\"getDropdownRowActionItems\"\n (onItemClick)=\"handleRowActionClick($event)\">\n </ax-dropdown-command-column>\n }\n </ax-data-table>\n </div>\n </div>\n</div>\n\n<ax-footer>\n <ax-prefix>\n @if ((config().create?.mode === 'full' || config().create?.mode === 'quick') && config().create?.onCreate) {\n <ax-button look=\"twotone\" color=\"primary\" [text]=\"'@general:actions.create.title' | translate | async\"\n (onClick)=\"handleCreateNewClick(config().create?.mode === 'quick' ? 'quick' : 'full')\">\n <ax-prefix>\n <ax-icon icon=\"far fa-plus\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </ax-prefix>\n <ax-suffix>\n <ax-button look=\"solid\" [text]=\"('@general:actions.close.title' | translate | async)!\"\n (onClick)=\"handleCloseClick()\">\n </ax-button>\n <ax-button look=\"solid\" color=\"primary\" [text]=\"('@general:actions.select.title' | translate | async)!\"\n (onClick)=\"handleSelectClick()\" [disabled]=\"allowSelect() === false\">\n <!-- @if (selectionMode() === 'multiple' && selectedCount() > 0) {\n <ax-badge [text]=\"selectedCount().toString()\" color=\"accent1\"\n class=\"ax-absolute ax-end-[2px] ax-top-[2px]\"></ax-badge>\n } -->\n </ax-button>\n </ax-suffix>\n</ax-footer>\n", styles: ["axp-data-selector{display:flex;flex-direction:column;flex:1;min-height:0;height:100%;overflow:hidden}.ax-expand-handler{cursor:pointer;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:8px}.ax-expand-handler:hover{opacity:.8}.ax-expand-handler.ax-invisible{visibility:hidden}.ax-overflow-hidden{overflow:hidden}.ax-flex{display:flex}.ax-flex-col{flex-direction:column}.ax-gap-4{gap:1rem}.ax-p-4{padding:1rem}.ax-w-full{width:100%}.axp-data-selector{display:flex;flex-direction:column;flex:1;min-height:0;overflow:hidden}.axp-data-selector-content{display:flex;flex:1;min-height:0;overflow:hidden}.axp-data-selector-content.with-category-filter .axp-main-data-area{flex:1;min-width:0;min-height:0;overflow:hidden}.axp-data-selector .axp-category-filter-panel{display:flex;flex-direction:column;border-right:1px solid var(--border-color);padding:1rem;background:var(--surface-color);flex-shrink:0;min-height:0;min-width:0;overflow:hidden}.axp-data-selector .axp-category-filter-panel axp-category-tree{display:flex;flex:1;flex-direction:column;min-height:0;min-width:0;overflow:hidden}.axp-data-selector .axp-main-data-area{flex:1;min-width:0;min-height:0;overflow:hidden;padding:1rem;display:flex;flex-direction:column;gap:1rem}.axp-data-selector .axp-main-data-area ax-data-table{flex:1;min-height:0;height:100%;display:flex;flex-direction:column;overflow:hidden}.axp-data-selector .axp-main-data-area .ax-search-box{width:100%;flex-shrink:0}.ax-popup:has(axp-data-selector){display:flex;flex-direction:column;height:90vh;max-height:90vh;overflow:hidden}.ax-popup:has(axp-data-selector) .ax-popup-main-container{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;overflow:hidden}.ax-popup:has(axp-data-selector) .ax-popup-body-container{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;overflow:hidden!important}.ax-popup:has(axp-data-selector) .ax-popup-footer-container{flex-shrink:0}@media(min-width:320px)and (max-width:640px){.ax-popup.ax-popup-sm:has(axp-data-selector),.ax-popup.ax-popup-md:has(axp-data-selector),.ax-popup.ax-popup-lg:has(axp-data-selector){height:90vh!important;max-height:90vh!important}}\n"] }]
|
|
2009
2135
|
}], ctorParameters: () => [], propDecorators: { grid: [{ type: i0.ViewChild, args: ['grid', { isSignal: true }] }] } });
|
|
2010
2136
|
|
|
2011
2137
|
var dataSelector_component = /*#__PURE__*/Object.freeze({
|
|
@@ -2027,38 +2153,29 @@ class AXPDataSelectorService {
|
|
|
2027
2153
|
*/
|
|
2028
2154
|
async open(config) {
|
|
2029
2155
|
const component = await Promise.resolve().then(function () { return dataSelector_component; }).then(c => c.AXPDataSelectorComponent);
|
|
2030
|
-
// Create a copy of config to avoid mutating the original
|
|
2031
2156
|
const processedConfig = { ...config };
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2157
|
+
if (processedConfig.filter?.value) {
|
|
2158
|
+
processedConfig.filter = {
|
|
2159
|
+
...processedConfig.filter,
|
|
2160
|
+
value: await this.expressionService.evaluate(processedConfig.filter.value),
|
|
2161
|
+
};
|
|
2035
2162
|
}
|
|
2036
|
-
|
|
2037
|
-
|
|
2163
|
+
processedConfig.grid = {
|
|
2164
|
+
...processedConfig.grid,
|
|
2165
|
+
columns: this.applyColumnWidths(processedConfig.grid.columns),
|
|
2166
|
+
};
|
|
2167
|
+
const categoryActive = processedConfig.category?.enabled !== false && !!processedConfig.category?.dataSource;
|
|
2038
2168
|
const result = await this.popupService.open(component, {
|
|
2039
2169
|
title: processedConfig.title,
|
|
2040
|
-
size:
|
|
2041
|
-
'lg'
|
|
2042
|
-
: (processedConfig.columns.length > 3 ? 'lg' : 'md'),
|
|
2170
|
+
size: categoryActive
|
|
2171
|
+
? 'lg'
|
|
2172
|
+
: (processedConfig.grid.columns.length > 3 ? 'lg' : 'md'),
|
|
2043
2173
|
data: {
|
|
2044
2174
|
config: signal(processedConfig)
|
|
2045
2175
|
}
|
|
2046
2176
|
});
|
|
2047
2177
|
return result.data || null;
|
|
2048
2178
|
}
|
|
2049
|
-
/**
|
|
2050
|
-
* Open data selector with category filter
|
|
2051
|
-
*/
|
|
2052
|
-
async openWithCategoryFilter(config, categoryFilterConfig) {
|
|
2053
|
-
const enhancedConfig = {
|
|
2054
|
-
...config,
|
|
2055
|
-
categoryFilter: {
|
|
2056
|
-
enabled: true,
|
|
2057
|
-
...categoryFilterConfig
|
|
2058
|
-
}
|
|
2059
|
-
};
|
|
2060
|
-
return this.open(enhancedConfig);
|
|
2061
|
-
}
|
|
2062
2179
|
//#endregion
|
|
2063
2180
|
//#region ---- Private Methods ----
|
|
2064
2181
|
/**
|
|
@@ -2066,11 +2183,9 @@ class AXPDataSelectorService {
|
|
|
2066
2183
|
*/
|
|
2067
2184
|
applyColumnWidths(columns) {
|
|
2068
2185
|
return columns.map((column) => {
|
|
2069
|
-
// Skip if column already has a width
|
|
2070
2186
|
if (column.width) {
|
|
2071
2187
|
return column;
|
|
2072
2188
|
}
|
|
2073
|
-
// Convert to IColumnWithWidth interface for width resolution
|
|
2074
2189
|
const columnWithWidth = {
|
|
2075
2190
|
name: column.name,
|
|
2076
2191
|
width: column.width,
|
|
@@ -2078,7 +2193,6 @@ class AXPDataSelectorService {
|
|
|
2078
2193
|
type: column.widget.type,
|
|
2079
2194
|
},
|
|
2080
2195
|
};
|
|
2081
|
-
// Resolve width using column width service
|
|
2082
2196
|
const resolvedWidth = this.columnWidthService.resolveWidth(columnWithWidth);
|
|
2083
2197
|
if (resolvedWidth) {
|
|
2084
2198
|
return {
|
|
@@ -4769,45 +4883,69 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
4769
4883
|
|
|
4770
4884
|
class AXPLogoComponent {
|
|
4771
4885
|
constructor() {
|
|
4886
|
+
this.isCompactLogo = false;
|
|
4887
|
+
this.compactLogoSize = 32;
|
|
4772
4888
|
this.platform = inject(AXPlatform);
|
|
4889
|
+
this.themeStore = inject(AXPLayoutThemeService);
|
|
4890
|
+
this.platformConfig = inject(AXP_PLATFORM_CONFIG_TOKEN);
|
|
4891
|
+
this.cdr = inject(ChangeDetectorRef);
|
|
4892
|
+
effect(() => {
|
|
4893
|
+
this.themeStore.menuVerticalMode();
|
|
4894
|
+
this.updateActiveSource();
|
|
4895
|
+
});
|
|
4773
4896
|
}
|
|
4774
4897
|
ngOnInit() {
|
|
4775
|
-
this.setLogoType();
|
|
4776
4898
|
this.platform.themeMode$.subscribe(() => {
|
|
4777
|
-
this.
|
|
4899
|
+
this.updateActiveSource();
|
|
4778
4900
|
});
|
|
4779
4901
|
}
|
|
4780
4902
|
ngOnChanges() {
|
|
4781
|
-
this.
|
|
4903
|
+
this.inputSource = this.source;
|
|
4904
|
+
this.updateActiveSource();
|
|
4905
|
+
}
|
|
4906
|
+
updateActiveSource() {
|
|
4907
|
+
const compactIcon = this.themeStore.menuVerticalMode() === AXPMenuVerticalMode.Compact
|
|
4908
|
+
? this.platformConfig.logo?.icon
|
|
4909
|
+
: undefined;
|
|
4910
|
+
if (compactIcon?.dark) {
|
|
4911
|
+
this.activeSource = compactIcon.dark;
|
|
4912
|
+
}
|
|
4913
|
+
else if (compactIcon) {
|
|
4914
|
+
this.activeSource = compactIcon.light;
|
|
4915
|
+
}
|
|
4916
|
+
else if (this.inputSource?.dark && this.inputSource?.light) {
|
|
4917
|
+
this.activeSource = this.platform.isDark() ? this.inputSource.dark : this.inputSource.light;
|
|
4918
|
+
}
|
|
4919
|
+
else {
|
|
4920
|
+
this.activeSource = this.inputSource;
|
|
4921
|
+
}
|
|
4922
|
+
this.isCompactLogo =
|
|
4923
|
+
this.themeStore.menuVerticalMode() === AXPMenuVerticalMode.Compact && !!compactIcon;
|
|
4782
4924
|
this.setLogoType();
|
|
4925
|
+
this.cdr.markForCheck();
|
|
4783
4926
|
}
|
|
4784
4927
|
setLogoType() {
|
|
4785
4928
|
switch (true) {
|
|
4786
|
-
case this.
|
|
4929
|
+
case this.activeSource instanceof AXPImageUrlLogoConfig:
|
|
4787
4930
|
this.logoType = 'url';
|
|
4788
4931
|
break;
|
|
4789
|
-
case this.
|
|
4932
|
+
case this.activeSource instanceof AXPComponentLogoConfig:
|
|
4790
4933
|
this.logoType = 'component';
|
|
4791
4934
|
break;
|
|
4792
|
-
case this.
|
|
4935
|
+
case this.activeSource instanceof AXPIconLogoConfig:
|
|
4793
4936
|
this.logoType = 'icon';
|
|
4794
4937
|
break;
|
|
4795
4938
|
default:
|
|
4796
4939
|
break;
|
|
4797
4940
|
}
|
|
4798
4941
|
}
|
|
4799
|
-
setLogoTheme() {
|
|
4800
|
-
if (this.source && this.source.dark && this.source.light) {
|
|
4801
|
-
this.source = this.platform.isDark() ? this.source.dark : this.source.light;
|
|
4802
|
-
}
|
|
4803
|
-
}
|
|
4804
4942
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLogoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4805
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLogoComponent, isStandalone: true, selector: "axp-logo", inputs: { source: "source" }, host: { classAttribute: "ax-flex ax-justify-center" }, usesOnChanges: true, ngImport: i0, template: "@switch (logoType) {
|
|
4943
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLogoComponent, isStandalone: true, selector: "axp-logo", inputs: { source: "source" }, host: { classAttribute: "ax-flex ax-justify-center" }, usesOnChanges: true, ngImport: i0, template: "@switch (logoType) {\n @case ('url') {\n <ax-image\n [width]=\"isCompactLogo ? compactLogoSize : activeSource.width\"\n [height]=\"isCompactLogo ? compactLogoSize : activeSource.height\"\n [src]=\"activeSource.url\"\n ></ax-image>\n }\n @case ('component') {\n <ng-container *ngComponentOutlet=\"activeSource.component\"></ng-container>\n }\n @case ('icon') {\n <i [class]=\"activeSource.icon\" [style.color]=\"activeSource.color\"></i>\n }\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: AXImageModule }, { kind: "component", type: i3$1.AXImageComponent, selector: "ax-image", inputs: ["width", "height", "overlayMode", "src", "alt", "priority", "lazy"], outputs: ["onLoad", "onError"] }, { kind: "ngmodule", type: AXDecoratorModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4806
4944
|
}
|
|
4807
4945
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLogoComponent, decorators: [{
|
|
4808
4946
|
type: Component,
|
|
4809
|
-
args: [{ selector: 'axp-logo', imports: [CommonModule, AXImageModule, AXDecoratorModule], host: { class: 'ax-flex ax-justify-center' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "@switch (logoType) {
|
|
4810
|
-
}], propDecorators: { source: [{
|
|
4947
|
+
args: [{ selector: 'axp-logo', imports: [CommonModule, AXImageModule, AXDecoratorModule], host: { class: 'ax-flex ax-justify-center' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "@switch (logoType) {\n @case ('url') {\n <ax-image\n [width]=\"isCompactLogo ? compactLogoSize : activeSource.width\"\n [height]=\"isCompactLogo ? compactLogoSize : activeSource.height\"\n [src]=\"activeSource.url\"\n ></ax-image>\n }\n @case ('component') {\n <ng-container *ngComponentOutlet=\"activeSource.component\"></ng-container>\n }\n @case ('icon') {\n <i [class]=\"activeSource.icon\" [style.color]=\"activeSource.color\"></i>\n }\n}\n" }]
|
|
4948
|
+
}], ctorParameters: () => [], propDecorators: { source: [{
|
|
4811
4949
|
type: Input
|
|
4812
4950
|
}] } });
|
|
4813
4951
|
|
|
@@ -6213,7 +6351,7 @@ class AXPResourceAppointmentComponent {
|
|
|
6213
6351
|
this.resourceAppointmentService.executeCommand(event.item.data?.command, providerName);
|
|
6214
6352
|
}
|
|
6215
6353
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPResourceAppointmentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6216
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPResourceAppointmentComponent, isStandalone: true, selector: "axp-resource-appointment", inputs: { showResourceHeaders: { classPropertyName: "showResourceHeaders", publicName: "showResourceHeaders", isSignal: true, isRequired: false, transformFunction: null }, showUnassignedAppointments: { classPropertyName: "showUnassignedAppointments", publicName: "showUnassignedAppointments", isSignal: true, isRequired: false, transformFunction: null }, providerName: { classPropertyName: "providerName", publicName: "providerName", isSignal: true, isRequired: false, transformFunction: null } }, providers: [AXPResourceAppointmentService], viewQueries: [{ propertyName: "contextMenu", first: true, predicate: ["contextMenu"], descendants: true, isSignal: true }, { propertyName: "schedulerRef", first: true, predicate: ["scheduler"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"axp-resource-appointment__container ax-flex ax-flex-col ax-min-h-0 ax-h-full\">\n @if (isReady()) {\n <!-- TODO: Add weekly view 'timeline-weekly' -->\n <ax-scheduler\n #scheduler\n [views]=\"['timeline-day', 'timeline-month']\"\n [dataSource]=\"schedulerAppointments()\"\n [resources]=\"schedulerResources()\"\n [startingDate]=\"currentDate()\"\n [selectedView]=\"currentView()\"\n [draggable]=\"false\"\n (onRangeChanged)=\"handleRangeChanged($event)\"\n class=\"axp-resource-appointment__scheduler ax-bg-lightest dark:ax-bg-darkest ax-flex-1\"\n ></ax-scheduler>\n\n <ax-context-menu\n #contextMenu\n [closeOn]=\"'leave'\"\n [orientation]=\"'vertical'\"\n (onOpening)=\"handleContextMenuOpening($event)\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n ></ax-context-menu>\n } @else {\n <div class=\"axp-resource-appointment__loading ax-flex ax-items-center ax-justify-center ax-w-full ax-h-full\">\n <ax-loading></ax-loading>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.axp-resource-appointment__scheduler{--ax-comp-scheduler-width: 100%;width:100%;height:100%;min-height:400px}.axp-resource-appointment__loading{min-height:300px}\n"], dependencies: [{ kind: "ngmodule", type: AXCommonModule }, { kind: "ngmodule", type: AXMenuModule }, { kind: "component", type: i1$8.AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2$8.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "component", type: AXSchedulerComponent, selector: "ax-scheduler", inputs: ["calendar", "startingDate", "endDayHour", "startDayHour", "hasHeader", "readonly", "draggable", "hasActions", "dragStartDelay", "weekend", "allowFullScreen", "multiDayViewDaysCount", "showResourceHeaders", "showCurrentTimeIndicator", "scrollToCurrentTimeIndicator", "showUnassignedAppointments", "resources", "resourceTemplate", "firstDayOfWeek", "tooltipTemplate", "dataSource", "holidays", "views", "selectedView"], outputs: ["selectedViewChange", "onDataLoaded", "onRangeChanged", "onSlotClicked", "onSlotDblClicked", "onSlotRightClick", "onAppointmentDrop", "onActionClick", "onAppointmentClicked", "onAppointmentDblClicked", "onAppointmentRightClick"] }, { kind: "ngmodule", type: AXButtonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
6354
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPResourceAppointmentComponent, isStandalone: true, selector: "axp-resource-appointment", inputs: { showResourceHeaders: { classPropertyName: "showResourceHeaders", publicName: "showResourceHeaders", isSignal: true, isRequired: false, transformFunction: null }, showUnassignedAppointments: { classPropertyName: "showUnassignedAppointments", publicName: "showUnassignedAppointments", isSignal: true, isRequired: false, transformFunction: null }, providerName: { classPropertyName: "providerName", publicName: "providerName", isSignal: true, isRequired: false, transformFunction: null } }, providers: [AXPResourceAppointmentService], viewQueries: [{ propertyName: "contextMenu", first: true, predicate: ["contextMenu"], descendants: true, isSignal: true }, { propertyName: "schedulerRef", first: true, predicate: ["scheduler"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"axp-resource-appointment__container ax-flex ax-flex-col ax-min-h-0 ax-h-full\">\n @if (isReady()) {\n <!-- TODO: Add weekly view 'timeline-weekly' -->\n <ax-scheduler\n #scheduler\n [views]=\"['timeline-day', 'timeline-month']\"\n [dataSource]=\"schedulerAppointments()\"\n [resources]=\"schedulerResources()\"\n [startingDate]=\"currentDate()\"\n [selectedView]=\"currentView()\"\n [draggable]=\"false\"\n (onRangeChanged)=\"handleRangeChanged($event)\"\n class=\"axp-resource-appointment__scheduler ax-bg-lightest dark:ax-bg-darkest ax-flex-1\"\n ></ax-scheduler>\n\n <ax-context-menu\n #contextMenu\n [closeOn]=\"'leave'\"\n [orientation]=\"'vertical'\"\n (onOpening)=\"handleContextMenuOpening($event)\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n ></ax-context-menu>\n } @else {\n <div class=\"axp-resource-appointment__loading ax-flex ax-items-center ax-justify-center ax-w-full ax-h-full\">\n <ax-loading></ax-loading>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.axp-resource-appointment__scheduler{--ax-comp-scheduler-width: 100%;width:100%;height:100%;min-height:400px}.axp-resource-appointment__loading{min-height:300px}\n"], dependencies: [{ kind: "ngmodule", type: AXCommonModule }, { kind: "ngmodule", type: AXMenuModule }, { kind: "component", type: i1$8.AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "closeOnRouteChange", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2$8.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "component", type: AXSchedulerComponent, selector: "ax-scheduler", inputs: ["calendar", "startingDate", "endDayHour", "startDayHour", "hasHeader", "readonly", "draggable", "hasActions", "dragStartDelay", "weekend", "allowFullScreen", "multiDayViewDaysCount", "showResourceHeaders", "showCurrentTimeIndicator", "scrollToCurrentTimeIndicator", "showUnassignedAppointments", "resources", "resourceTemplate", "firstDayOfWeek", "tooltipTemplate", "dataSource", "holidays", "views", "selectedView"], outputs: ["selectedViewChange", "onDataLoaded", "onRangeChanged", "onSlotClicked", "onSlotDblClicked", "onSlotRightClick", "onAppointmentDrop", "onActionClick", "onAppointmentClicked", "onAppointmentDblClicked", "onAppointmentRightClick"] }, { kind: "ngmodule", type: AXButtonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
6217
6355
|
}
|
|
6218
6356
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPResourceAppointmentComponent, decorators: [{
|
|
6219
6357
|
type: Component,
|
|
@@ -6232,6 +6370,12 @@ class AXPSectionItemsBuilderComponent {
|
|
|
6232
6370
|
this.readonlyMode = input(false, { ...(ngDevMode ? { debugName: "readonlyMode" } : /* istanbul ignore next */ {}), alias: 'readonly' });
|
|
6233
6371
|
this.valueChange = output();
|
|
6234
6372
|
this.vm = signal({ sections: [] }, ...(ngDevMode ? [{ debugName: "vm" }] : /* istanbul ignore next */ []));
|
|
6373
|
+
/** Snapshot from the last external `[value]` sync (load, discard, save refresh). */
|
|
6374
|
+
this.baseline = signal({ sections: [] }, ...(ngDevMode ? [{ debugName: "baseline" }] : /* istanbul ignore next */ []));
|
|
6375
|
+
/** Set on local {@link commit}; cleared on external sync or {@link markClean}. */
|
|
6376
|
+
this.pendingCommitSnapshot = null;
|
|
6377
|
+
/** True when the live model differs from the external baseline. */
|
|
6378
|
+
this.isDirty = computed(() => !isEqual(this.normalizeValue(this.vm()), this.baseline()), ...(ngDevMode ? [{ debugName: "isDirty" }] : /* istanbul ignore next */ []));
|
|
6235
6379
|
this.sectionsModel = computed(() => this.normalizeValue(this.vm()), ...(ngDevMode ? [{ debugName: "sectionsModel" }] : /* istanbul ignore next */ []));
|
|
6236
6380
|
this.sectionRows = computed(() => {
|
|
6237
6381
|
const def = this.definition();
|
|
@@ -6251,10 +6395,31 @@ class AXPSectionItemsBuilderComponent {
|
|
|
6251
6395
|
return this.sectionsModel().sections.length > min;
|
|
6252
6396
|
}, ...(ngDevMode ? [{ debugName: "canRemoveSection" }] : /* istanbul ignore next */ []));
|
|
6253
6397
|
effect(() => {
|
|
6254
|
-
const
|
|
6255
|
-
untracked(() => this.
|
|
6398
|
+
const normalized = this.normalizeValue(cloneDeep(this.value()));
|
|
6399
|
+
const current = untracked(() => this.normalizeValue(this.vm()));
|
|
6400
|
+
if (isEqual(normalized, current)) {
|
|
6401
|
+
this.pendingCommitSnapshot = null;
|
|
6402
|
+
return;
|
|
6403
|
+
}
|
|
6404
|
+
if (this.pendingCommitSnapshot != null) {
|
|
6405
|
+
untracked(() => this.vm.set(normalized));
|
|
6406
|
+
if (isEqual(normalized, this.baseline())) {
|
|
6407
|
+
this.pendingCommitSnapshot = null;
|
|
6408
|
+
this.baseline.set(cloneDeep(normalized));
|
|
6409
|
+
}
|
|
6410
|
+
return;
|
|
6411
|
+
}
|
|
6412
|
+
untracked(() => {
|
|
6413
|
+
this.vm.set(normalized);
|
|
6414
|
+
this.baseline.set(cloneDeep(normalized));
|
|
6415
|
+
});
|
|
6256
6416
|
});
|
|
6257
6417
|
}
|
|
6418
|
+
/** Align dirty baseline to the current model (call after save). */
|
|
6419
|
+
markClean() {
|
|
6420
|
+
this.baseline.set(cloneDeep(this.normalizeValue(this.vm())));
|
|
6421
|
+
this.pendingCommitSnapshot = null;
|
|
6422
|
+
}
|
|
6258
6423
|
/**
|
|
6259
6424
|
* Opens add-section flow (same as primary "Add section" control). For page commands / ViewChild.
|
|
6260
6425
|
*/
|
|
@@ -6489,6 +6654,7 @@ class AXPSectionItemsBuilderComponent {
|
|
|
6489
6654
|
commit(next) {
|
|
6490
6655
|
const normalized = this.normalizeValue(next);
|
|
6491
6656
|
this.vm.set(normalized);
|
|
6657
|
+
this.pendingCommitSnapshot = cloneDeep(normalized);
|
|
6492
6658
|
this.valueChange.emit(normalized);
|
|
6493
6659
|
}
|
|
6494
6660
|
normalizeValue(v) {
|
|
@@ -7396,6 +7562,14 @@ class AXPStandardSectionItemsBuilderComponent {
|
|
|
7396
7562
|
async addSection() {
|
|
7397
7563
|
await this.inner()?.addSection();
|
|
7398
7564
|
}
|
|
7565
|
+
/** Whether the builder model differs from the last external baseline. */
|
|
7566
|
+
isDirty() {
|
|
7567
|
+
return this.inner()?.isDirty() ?? false;
|
|
7568
|
+
}
|
|
7569
|
+
/** Clears dirty state by aligning baseline to the current model. */
|
|
7570
|
+
markClean() {
|
|
7571
|
+
this.inner()?.markClean();
|
|
7572
|
+
}
|
|
7399
7573
|
isDuplicateSectionName(value, key, excludeSectionId) {
|
|
7400
7574
|
const n = key.trim().toLowerCase();
|
|
7401
7575
|
if (!n)
|