@acorex-platform/framework-client 2.0.0-next.3 → 2.0.0-next.31
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-framework-client-auth.mjs +8 -9
- package/fesm2022/acorex-platform-framework-client-auth.mjs.map +1 -1
- package/fesm2022/{acorex-platform-framework-client-common-common-settings.provider-ChU2tvyt.mjs → acorex-platform-framework-client-common-common-settings.provider-Biu0_ryw.mjs} +35 -2
- package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-Biu0_ryw.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-common.mjs +1387 -538
- package/fesm2022/acorex-platform-framework-client-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-core.mjs +7 -2
- package/fesm2022/acorex-platform-framework-client-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-builder.mjs +20 -0
- package/fesm2022/acorex-platform-framework-client-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-components.mjs +520 -142
- package/fesm2022/acorex-platform-framework-client-layout-components.mjs.map +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-DaOvPoNI.mjs → acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-DmkFxSuJ.mjs} +1084 -223
- package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-DmkFxSuJ.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-BU7KEfyF.mjs → acorex-platform-framework-client-layout-entity-attachments-page.component-BV5WLQVo.mjs} +2 -2
- package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-BU7KEfyF.mjs.map → acorex-platform-framework-client-layout-entity-attachments-page.component-BV5WLQVo.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-entity-bulk-entity.command-Boq0MUFK.mjs → acorex-platform-framework-client-layout-entity-bulk-entity.command-O8zdiHRH.mjs} +2 -2
- package/fesm2022/{acorex-platform-framework-client-layout-entity-bulk-entity.command-Boq0MUFK.mjs.map → acorex-platform-framework-client-layout-entity-bulk-entity.command-O8zdiHRH.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-CMoFkzhf.mjs → acorex-platform-framework-client-layout-entity-file-list-popup.component-B3-0gJTQ.mjs} +4 -4
- package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-CMoFkzhf.mjs.map → acorex-platform-framework-client-layout-entity-file-list-popup.component-B3-0gJTQ.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-Bre8friL.mjs → acorex-platform-framework-client-layout-entity-gallery-page.component-CjfLUBPZ.mjs} +2 -2
- package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-Bre8friL.mjs.map → acorex-platform-framework-client-layout-entity-gallery-page.component-CjfLUBPZ.mjs.map} +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-entity.mjs +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-views.mjs +94 -17
- package/fesm2022/acorex-platform-framework-client-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs +285 -184
- package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs.map +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-1UJh0Qj4.mjs → acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-CpmGqDUE.mjs} +1167 -265
- package/fesm2022/acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-CpmGqDUE.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-layout-widgets-filter-default-operators-widget-edit.component-DOEn58--.mjs +103 -0
- package/fesm2022/acorex-platform-framework-client-layout-widgets-filter-default-operators-widget-edit.component-DOEn58--.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-SHCgo4UC.mjs → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-XgjDH9Oc.mjs} +3 -3
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-SHCgo4UC.mjs.map → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-XgjDH9Oc.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BYsrp8LT.mjs → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-DDczHmAA.mjs} +2 -2
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BYsrp8LT.mjs.map → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-DDczHmAA.mjs.map} +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs +1 -1
- package/fesm2022/acorex-platform-framework-client-realtime.mjs +49 -7
- package/fesm2022/acorex-platform-framework-client-realtime.mjs.map +1 -1
- package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-create-view.component-DwCoz2Du.mjs → acorex-platform-framework-client-themes-default-entity-master-create-view.component-DPU6jTDk.mjs} +8 -2
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DPU6jTDk.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BCyFK60f.mjs → acorex-platform-framework-client-themes-default-entity-master-modify-view.component-CLdQJ8e8.mjs} +8 -2
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-CLdQJ8e8.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-themes-default-error-401.component-1lfBpY_d.mjs → acorex-platform-framework-client-themes-default-error-401.component-DszlyIaw.mjs} +5 -11
- package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-DszlyIaw.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-themes-default-error-404.component-BeWyRCJr.mjs → acorex-platform-framework-client-themes-default-error-404.component-BusKNAit.mjs} +5 -11
- package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-BusKNAit.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-themes-default-error-offline.component-PvveUj5c.mjs → acorex-platform-framework-client-themes-default-error-offline.component-Abf14p44.mjs} +15 -4
- package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-Abf14p44.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-themes-default-error-page-go-home-B9VmB9Vt.mjs +19 -0
- package/fesm2022/acorex-platform-framework-client-themes-default-error-page-go-home-B9VmB9Vt.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-themes-default.mjs +306 -129
- package/fesm2022/acorex-platform-framework-client-themes-default.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-themes-shared.mjs +11 -5
- package/fesm2022/acorex-platform-framework-client-themes-shared.mjs.map +1 -1
- package/i18n/en-AU/general.json +32 -4
- package/i18n/en-AU/layout.json +2 -1
- package/i18n/en-AU/platform-layout-widgets.json +7 -1
- package/i18n/en-US/general.json +32 -4
- package/i18n/en-US/layout.json +2 -1
- package/i18n/en-US/platform-layout-widgets.json +7 -1
- package/i18n/fa-IR/general.json +32 -4
- package/i18n/fa-IR/layout.json +2 -1
- package/i18n/fa-IR/platform-layout-widgets.json +7 -1
- package/package.json +6 -6
- package/types/acorex-platform-framework-client-auth.d.ts +21 -11
- package/types/acorex-platform-framework-client-common.d.ts +230 -14
- package/types/acorex-platform-framework-client-layout-components.d.ts +47 -6
- package/types/acorex-platform-framework-client-layout-entity.d.ts +187 -35
- package/types/acorex-platform-framework-client-layout-views.d.ts +15 -0
- package/types/acorex-platform-framework-client-layout-widget-core.d.ts +64 -14
- package/types/acorex-platform-framework-client-layout-widgets.d.ts +145 -9
- package/types/acorex-platform-framework-client-realtime.d.ts +5 -0
- package/types/acorex-platform-framework-client-themes-default.d.ts +16 -5
- package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-ChU2tvyt.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-DaOvPoNI.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-1UJh0Qj4.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DwCoz2Du.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BCyFK60f.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-1lfBpY_d.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-BeWyRCJr.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-PvveUj5c.mjs.map +0 -1
|
@@ -30,13 +30,13 @@ import { AXUnsubscriber } from '@acorex/core/utils';
|
|
|
30
30
|
import { AXPAuthModule, AXPSessionService, AXPSessionStatus } from '@acorex-platform/framework-client/auth';
|
|
31
31
|
import * as i1$3 from '@acorex-platform/framework-client/core';
|
|
32
32
|
import { AXPEntityBroadcastService, AXPDeviceService, AXHighlightService, AXPPageContextRegistry, AXPPageContextPriority, AXPComponentSlotModule, AXPKeyboardShortcutRegistry, AXPLogoComponent, AXPBroadcastEventService, AXPContextStore } from '@acorex-platform/framework-client/core';
|
|
33
|
-
import { getDataSourcePageIndex, applyDataSourcePagingWithoutLoad, AXPEntityCardComponent, AXPEntityCardSkeletonComponent, AXP_CATEGORY_TREE_ROOT_TITLE_I18N_KEY, AXPEntityDefinitionRegistryService, AXPCategoryTreeService, traceEntityMasterList, buildDataSourceTraceSnapshot, AXPEntityListViewColumnViewModel, getEntityInfo, axpRunEntityListPageContextAction, axpBuildEntityListPageContextSnapshot, restoreEntityListExpandedRows, AXP_ENTITY_CONFIG_TOKEN } from '@acorex-platform/framework-client/layout/entity';
|
|
33
|
+
import { getDataSourcePageIndex, applyDataSourcePagingWithoutLoad, watchNextDataSourceLoad, AXPEntityCardComponent, AXPEntityCardSkeletonComponent, AXP_CATEGORY_TREE_ROOT_TITLE_I18N_KEY, AXPEntityDefinitionRegistryService, AXPCategoryTreeService, traceEntityMasterList, buildDataSourceTraceSnapshot, AXPEntityListViewColumnViewModel, getEntityInfo, axpRunEntityListPageContextAction, axpBuildEntityListPageContextSnapshot, restoreEntityListExpandedRows, AXP_ENTITY_CONFIG_TOKEN } from '@acorex-platform/framework-client/layout/entity';
|
|
34
34
|
import { mergeInfiniteScrollPage, AXPInfiniteScrollDirective, AXPStateMessageComponent, AXPThemeLayoutBlockComponent, AXPThemeLayoutHeaderComponent, AXPThemeLayoutToolbarComponent, AXPQueryViewSaveDialogService, AXPEntityListStylingDialogService, AXPQueryFiltersComponent, AXPQuerySortsComponent, AXPQueryViewSaveButtonComponent, AXPQueryViewTabsComponent, AXPQueryColumnsComponent, AXPThemeLayoutStartSideComponent, AXPTaskBadgeService, AXPMenuBadgeHelper, AXPTaskBadgeDirective, provideFileChooserHooks } from '@acorex-platform/framework-client/layout/components';
|
|
35
35
|
import { resolveEntityCardAvatarPath, listEntityMasterStylingLockedRules, withQueryViewFilterVisibility, queryViewConditionsToFilterQueries } from '@acorex-platform/framework-shared/entity';
|
|
36
36
|
import * as i1 from '@angular/common';
|
|
37
37
|
import { CommonModule, AsyncPipe } from '@angular/common';
|
|
38
38
|
import * as i0 from '@angular/core';
|
|
39
|
-
import { input, signal, computed,
|
|
39
|
+
import { input, signal, computed, effect, untracked, viewChild, afterRenderEffect, ChangeDetectionStrategy, Component, inject, ViewChild, Input, ViewEncapsulation, afterNextRender, Injector, output, DestroyRef, ElementRef, NgModule } from '@angular/core';
|
|
40
40
|
import { get, isEqual, sortBy } from 'lodash-es';
|
|
41
41
|
import * as i7$1 from '@acorex-platform/framework-client/layout/widget-core';
|
|
42
42
|
import { AXPWidgetCoreModule } from '@acorex-platform/framework-client/layout/widget-core';
|
|
@@ -48,7 +48,7 @@ import { RouterModule, Router, ActivatedRoute, NavigationStart, NavigationEnd, R
|
|
|
48
48
|
import { Subject, takeUntil, filter, combineLatest, firstValueFrom, take } from 'rxjs';
|
|
49
49
|
import { runtimeCommandPayloadData, isThemeSurfaceClass, isRuntimeHexSurfaceClass, AXP_THEME_SURFACE_STYLES, createRandomUuid, AXPKeyboardShortcutPriority } from '@acorex-platform/framework-shared/core';
|
|
50
50
|
import * as i1$2 from '@acorex/core/platform';
|
|
51
|
-
import { AXPSettingsService, AXPCommonSettings, axpIsEntityListRoute, axpReplaceEntityListRouteQueryParams, axpIsEntityListPath, AXPTabNavigationService, AXPTabPreviewService, AXP_HOME_TAB_KEY, axpResolveTabTitleParts, AXPMenuService, AXPMenuVisibilityService, axpMenuPathsMatch, AXPPlatformBrandingService, AXPTabRouteCacheRegistry, axpResolveTabKeyFromSnapshot,
|
|
51
|
+
import { AXPSettingsService, AXPCommonSettings, axpIsEntityListRoute, axpReplaceEntityListRouteQueryParams, axpIsEntityListPath, AXPTabNavigationService, AXPTabPreviewService, AXP_HOME_TAB_KEY, axpResolveTabTitleParts, AXPMenuService, AXPMenuVisibilityService, axpMenuPathsMatch, AXPPlatformBrandingService, AXPTabRouteCacheRegistry, axpResolveTabKeyFromSnapshot, axpSnapshotDeclaresTabScope, axpPathFromSnapshot, axpEntityListNavigationTabKey, axpIsTabEligibleUrl, axpInTabErrorSourceUrl, axpResolveTabKey, axpResolveTabKeyFromRouteConfig, AXP_PROTECTED_ROUTE_GUARDS, AXPCommonModule } from '@acorex-platform/framework-client/common';
|
|
52
52
|
import { DragDropModule, CdkDropList, CdkDrag, CdkDragHandle, CdkDragPreview } from '@angular/cdk/drag-drop';
|
|
53
53
|
import { AXDropdownButtonModule } from '@acorex/components/dropdown-button';
|
|
54
54
|
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageLayoutBase } from '@acorex-platform/framework-client/layout/views';
|
|
@@ -74,6 +74,7 @@ import { AXResizableDirective } from '@acorex/cdk/resizable';
|
|
|
74
74
|
const LOAD_MORE_SKELETON_COUNT = 3;
|
|
75
75
|
//#endregion
|
|
76
76
|
class AXPEntityMasterListCardListComponent {
|
|
77
|
+
#viewTransitionEffect;
|
|
77
78
|
//#endregion
|
|
78
79
|
//#region ----- Lifecycle -----
|
|
79
80
|
constructor() {
|
|
@@ -112,6 +113,19 @@ class AXPEntityMasterListCardListComponent {
|
|
|
112
113
|
...(ngDevMode ? [{ debugName: "showListStatus" }] : /* istanbul ignore next */ []));
|
|
113
114
|
this.skeletonCount = computed(() => Math.max(this.pageSize(), 1), /* @ts-ignore */
|
|
114
115
|
...(ngDevMode ? [{ debugName: "skeletonCount" }] : /* istanbul ignore next */ []));
|
|
116
|
+
this.#viewTransitionEffect = effect(() => {
|
|
117
|
+
const vm = this.vm();
|
|
118
|
+
if (!vm.listTransitionLoading?.()) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
untracked(() => {
|
|
122
|
+
this.items.set([]);
|
|
123
|
+
this.hasMore.set(false);
|
|
124
|
+
this.loading.set(true);
|
|
125
|
+
this.loadingMore.set(false);
|
|
126
|
+
});
|
|
127
|
+
}, /* @ts-ignore */
|
|
128
|
+
...(ngDevMode ? [{ debugName: "#viewTransitionEffect" }] : /* istanbul ignore next */ []));
|
|
115
129
|
this.loadMoreSkeletonPlaceholders = Array.from({ length: LOAD_MORE_SKELETON_COUNT }, (_, index) => index);
|
|
116
130
|
this.showSkeletonAvatar = computed(() => {
|
|
117
131
|
if (this.vm().cardLayout()?.header?.avatar) {
|
|
@@ -345,9 +359,14 @@ class AXPEntityMasterListCardListComponent {
|
|
|
345
359
|
}
|
|
346
360
|
async loadPage(reset) {
|
|
347
361
|
const vm = this.vm();
|
|
362
|
+
const switchEpoch = vm.viewSwitchEpoch?.() ?? null;
|
|
363
|
+
const stillCurrent = () => this.isListSwitchCurrent(vm, switchEpoch);
|
|
348
364
|
const take = this.resolvePageSize(vm);
|
|
349
365
|
this.pageSize.set(take);
|
|
350
366
|
const skip = reset ? 0 : this.items().length;
|
|
367
|
+
if (!stillCurrent()) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
351
370
|
this.appending = !reset;
|
|
352
371
|
if (reset) {
|
|
353
372
|
this.items.set([]);
|
|
@@ -359,17 +378,41 @@ class AXPEntityMasterListCardListComponent {
|
|
|
359
378
|
}
|
|
360
379
|
applyDataSourcePagingWithoutLoad(vm.dataSource, { take, skip });
|
|
361
380
|
invalidateDataSourceFetchedPages(vm.dataSource);
|
|
381
|
+
if (!stillCurrent()) {
|
|
382
|
+
this.appending = false;
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const watch = watchNextDataSourceLoad(vm.dataSource, stillCurrent);
|
|
362
386
|
try {
|
|
363
|
-
const dataReady = this.waitForDataSourceLoad(vm.dataSource);
|
|
364
387
|
vm.dataSource.refresh({ reset });
|
|
365
|
-
|
|
388
|
+
if (!stillCurrent()) {
|
|
389
|
+
watch.stop();
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
if (vm.dataSource.isLoading) {
|
|
393
|
+
await watch.promise;
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
watch.stop();
|
|
397
|
+
}
|
|
398
|
+
if (!stillCurrent()) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
366
401
|
this.applyPageFromDataSource(reset);
|
|
367
402
|
}
|
|
368
403
|
finally {
|
|
369
404
|
this.appending = false;
|
|
370
|
-
|
|
371
|
-
|
|
405
|
+
if (stillCurrent()) {
|
|
406
|
+
this.loading.set(false);
|
|
407
|
+
this.loadingMore.set(false);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
isListSwitchCurrent(vm, epoch) {
|
|
412
|
+
if (epoch == null || vm.viewSwitchEpoch == null) {
|
|
413
|
+
return true;
|
|
372
414
|
}
|
|
415
|
+
return vm.viewSwitchEpoch() === epoch;
|
|
373
416
|
}
|
|
374
417
|
applyPageFromDataSource(reset) {
|
|
375
418
|
const ds = this.vm().dataSource;
|
|
@@ -386,32 +429,6 @@ class AXPEntityMasterListCardListComponent {
|
|
|
386
429
|
resolvePageSize(vm) {
|
|
387
430
|
return vm.getResolvedListPaging().take || vm.dataSource.config.pageSize || 10;
|
|
388
431
|
}
|
|
389
|
-
waitForDataSourceLoad(dataSource) {
|
|
390
|
-
return new Promise((resolve) => {
|
|
391
|
-
let settled = false;
|
|
392
|
-
const finish = () => {
|
|
393
|
-
if (settled) {
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
settled = true;
|
|
397
|
-
clearTimeout(timeoutId);
|
|
398
|
-
loadingSub.unsubscribe();
|
|
399
|
-
changedSub.unsubscribe();
|
|
400
|
-
resolve();
|
|
401
|
-
};
|
|
402
|
-
const changedSub = dataSource.onChanged.subscribe(() => {
|
|
403
|
-
if (!dataSource.isLoading) {
|
|
404
|
-
queueMicrotask(finish);
|
|
405
|
-
}
|
|
406
|
-
});
|
|
407
|
-
const loadingSub = dataSource.onLoadingChanged.subscribe((isLoading) => {
|
|
408
|
-
if (!isLoading) {
|
|
409
|
-
queueMicrotask(finish);
|
|
410
|
-
}
|
|
411
|
-
});
|
|
412
|
-
const timeoutId = setTimeout(finish, 10_000);
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
432
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPEntityMasterListCardListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
416
433
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPEntityMasterListCardListComponent, isStandalone: true, selector: "axp-entity-master-list-card-list", inputs: { vm: { classPropertyName: "vm", publicName: "vm", isSignal: true, isRequired: true, transformFunction: null }, userStylingRules: { classPropertyName: "userStylingRules", publicName: "userStylingRules", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "cardGrid", first: true, predicate: ["cardGrid"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"axp-entity-card-list\" [class.axp-entity-card-list--rows]=\"isRowLayout()\">\n @if (loading() && !items().length) {\n <!-- ----- Skeleton cards while the first page is fetched ----- -->\n <div class=\"axp-entity-card-list__grid\" aria-busy=\"true\" aria-live=\"polite\">\n @for (index of skeletonPlaceholders(); track index) {\n <div class=\"axp-entity-card-list__cell\">\n <axp-entity-card-skeleton\n [fieldCount]=\"skeletonFieldCount()\"\n [badgeCount]=\"skeletonBadgeCount()\"\n [showContent]=\"true\"\n [showFooter]=\"skeletonShowFooter()\"\n [rowLayout]=\"isRowLayout()\"\n [showAvatar]=\"showSkeletonAvatar()\"\n [fillHost]=\"true\"\n />\n </div>\n }\n </div>\n } @else if (!items().length) {\n <!-- ----- Empty state when the list has no rows ----- -->\n <div class=\"axp-entity-card-list__empty\">\n <axp-state-message\n icon=\"fa-light fa-clipboard-list\"\n [title]=\"'@general:empty-states.no-records-found.title'\"\n [description]=\"'@general:empty-states.no-records-found.description'\"\n ></axp-state-message>\n </div>\n } @else {\n <!-- ----- Accumulated card grid with infinite scroll ----- -->\n <div #cardGrid class=\"axp-entity-card-list__grid\">\n @for (row of items(); track trackRow($index, row)) {\n <!--->\n <!-- ----- Render a card when the row record is present ----- -->\n @if (row) {\n <div class=\"axp-entity-card-list__cell\">\n <axp-entity-card\n [entity]=\"vm().entityDef\"\n [layout]=\"vm().cardLayout()\"\n [row]=\"row\"\n [fields]=\"vm().cardFields()\"\n [userStylingRules]=\"userStylingRules()\"\n [variant]=\"isRowLayout() ? 'row' : 'card'\"\n [interactive]=\"true\"\n [fillHost]=\"true\"\n [extraExpanded]=\"isCardExpanded(row)\"\n [showSelection]=\"showSelection()\"\n [selected]=\"isRowSelected(row)\"\n [showNewBadge]=\"isRowHighlighted(row)\"\n [primaryActions]=\"vm().primaryRowActions()\"\n [secondaryActionLoader]=\"loadSecondaryActions\"\n (extraExpandedChange)=\"onCardExtraExpanded($index, $event)\"\n (selectionChange)=\"onRowSelectionChange(row, $event)\"\n (commandClick)=\"onCommandClick($event, row)\"\n />\n </div>\n }\n }\n <!--->\n <!-- ----- Skeleton cards while the next chunk is fetched ----- -->\n @if (loadingMore()) {\n @for (index of loadMoreSkeletonPlaceholders; track index) {\n <div class=\"axp-entity-card-list__cell\">\n <axp-entity-card-skeleton\n [fieldCount]=\"skeletonFieldCount()\"\n [badgeCount]=\"skeletonBadgeCount()\"\n [showContent]=\"true\"\n [showFooter]=\"skeletonShowFooter()\"\n [rowLayout]=\"isRowLayout()\"\n [showAvatar]=\"showSkeletonAvatar()\"\n [fillHost]=\"true\"\n />\n </div>\n }\n }\n <div\n axpInfiniteScroll\n class=\"axp-entity-card-list__sentinel\"\n [axpInfiniteScrollEnabled]=\"canLoadMore()\"\n (axpInfiniteScrollReached)=\"onInfiniteScrollReached()\"\n ></div>\n </div>\n <!--------------------------------------------------------------->\n <!-- ----- Compact loaded count, pinned under the scrolling grid ----- -->\n @if (showListStatus()) {\n <div class=\"axp-entity-card-list__status\" aria-live=\"polite\">\n {{\n '@general:terms.interface.list-range'\n | translate: { params: { loaded: loadedCount(), total: totalCount() } }\n | async\n }}\n </div>\n }\n }\n</div>\n", styles: ["@layer properties;:host.axp-entity-list-host{display:flex;height:100%;min-height:0px;flex-direction:column;overflow:hidden}.axp-entity-card-list{display:flex;min-height:0px;flex:1;flex-direction:column;gap:var(--spacing, .25rem);padding-inline:calc(var(--spacing, .25rem) * 3)}.axp-entity-card-list .axp-entity-card-list__empty{display:flex;min-height:0px;flex:1;align-items:center;justify-content:center;border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px;--tw-border-style: dashed;border-style:dashed;border-color:rgba(var(--ax-sys-color-lightest-surface))}.axp-entity-card-list .axp-entity-card-list__grid{display:grid;min-height:0px;flex:1;grid-template-columns:repeat(1,minmax(0,1fr));align-items:stretch;gap:calc(var(--spacing, .25rem) * 2);overflow:auto;align-content:start;grid-auto-rows:auto}@media(width>=48rem){.axp-entity-card-list .axp-entity-card-list__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(width>=80rem){.axp-entity-card-list .axp-entity-card-list__grid{grid-template-columns:repeat(3,minmax(0,1fr))}}.axp-entity-card-list .axp-entity-card-list__cell{display:flex;min-width:0;flex-direction:column}.axp-entity-card-list .axp-entity-card-list__cell>axp-entity-card,.axp-entity-card-list .axp-entity-card-list__cell>axp-entity-card-skeleton{display:flex;width:100%;min-width:0;flex:1 1 auto;flex-direction:column}.axp-entity-card-list.axp-entity-card-list--rows .axp-entity-card-list__grid{grid-template-columns:repeat(1,minmax(0,1fr));gap:calc(var(--spacing, .25rem) * 2)}@media(width>=48rem){.axp-entity-card-list.axp-entity-card-list--rows .axp-entity-card-list__grid{grid-template-columns:repeat(1,minmax(0,1fr))}}@media(width>=80rem){.axp-entity-card-list.axp-entity-card-list--rows .axp-entity-card-list__grid{grid-template-columns:repeat(1,minmax(0,1fr))}}.axp-entity-card-list .axp-entity-card-list__sentinel{grid-column:1 / -1;height:1px;width:100%}.axp-entity-card-list .axp-entity-card-list__status{display:flex;flex-shrink:0;align-items:center;justify-content:flex-end;padding-top:calc(var(--spacing, .25rem) * .5);padding-bottom:var(--spacing, .25rem);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));color:rgba(var(--ax-sys-color-text-default))}@supports (color: color-mix(in lab,red,red)){.axp-entity-card-list .axp-entity-card-list__status{color:color-mix(in oklab,rgba(var(--ax-sys-color-text-default)) 80%,transparent)}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXPEntityCardComponent, selector: "axp-entity-card", inputs: ["entity", "layout", "row", "fields", "userStylingRules", "variant", "interactive", "embedded", "elevated", "disableLookupPopover", "fillHost", "extraExpanded", "selected", "showNewBadge", "showSelection", "showClose", "primaryActions", "primaryActionLook", "secondaryActionLoader"], outputs: ["extraExpandedChange", "selectionChange", "commandClick", "closeClick"] }, { kind: "component", type: AXPEntityCardSkeletonComponent, selector: "axp-entity-card-skeleton", inputs: ["fieldCount", "badgeCount", "showFooter", "showHeaderMenu", "showContent", "rowLayout", "showAvatar", "fillHost", "embedded", "elevated"] }, { kind: "directive", type: AXPInfiniteScrollDirective, selector: "[axpInfiniteScroll]", inputs: ["axpInfiniteScrollEnabled", "axpInfiniteScrollRoot", "axpInfiniteScrollRootMargin", "axpInfiniteScrollThreshold"], outputs: ["axpInfiniteScrollReached"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
417
434
|
}
|
|
@@ -619,7 +636,7 @@ class AXPEntityDetailListViewComponent {
|
|
|
619
636
|
this.destroy();
|
|
620
637
|
}
|
|
621
638
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPEntityDetailListViewComponent, deps: [{ token: i1$1.AXActionSheetService }, { token: i2$1.AXUnsubscriber }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
622
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPEntityDetailListViewComponent, isStandalone: true, selector: "axp-entity-detail-list-view", inputs: { vm: ["viewModel", "vm"] }, providers: [AXUnsubscriber], viewQueries: [{ propertyName: "listDisplayModePopover", first: true, predicate: ["listDisplayModePopover"], descendants: true, isSignal: true }, { propertyName: "grid", first: true, predicate: ["grid"], descendants: true }], ngImport: i0, template: "<div class=\"flex p-2\">\n <div class=\"flex flex-col items-stretch gap-3 flex-1 overflow-auto min-h-72\">\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex justify-start items-center gap-4\">\n @if (vm.hasSelectedItems()) {\n <div class=\"flex gap-3 items-center h-10\">\n <span class=\"text-xl font-bold\">\n {{ vm.selectedItems().length }}\n {{ '@general:terms.items-selected' | translate | async }}\n </span>\n <span\n (click)=\"vm.clearSelection()\"\n class=\"text-sm text-primary-500 underline cursor-pointer\"\n >{{ '@general:actions.unselect.title' | translate | async }}</span\n >\n </div>\n } @else {\n @if (vm.hasInlineFilters() && !deviceService.isSmall()) {\n <div class=\"w-72\">\n <ax-search-box\n [placeholder]=\"\n ('@general:widgets.lookup.search' | translate | async) + vm.inlineFiltersPlaceholders().join(', ')\n \"\n (onValueChanged)=\"handleChangeSearchValue($event)\"\n ><ax-clear-button></ax-clear-button\n ></ax-search-box>\n </div>\n }\n }\n </div>\n </div>\n <div class=\"flex items-center gap-3\">\n @if (showListDisplayModeControl()) {\n <div>\n <ax-button [iconOnly]=\"true\" #listDisplayButton [color]=\"'default'\">\n <i [class]=\"listDisplayModeButtonIcon()\"></i>\n </ax-button>\n <ax-popover\n [adaptivityEnabled]=\"true\"\n [offsetY]=\"10\"\n [target]=\"listDisplayButton\"\n [openOn]=\"'toggle'\"\n [closeOn]=\"'clickOut'\"\n #listDisplayModePopover\n >\n <div class=\"lightest-surface shadow-md border md:w-72 w-full rounded-md\">\n <ax-header class=\"border-b lighter-surface rounded-t-md p-4 font-bold\">\n {{ '@general:terms.interface.list-display' | translate | async }}\n </ax-header>\n <div class=\"py-2 px-2\">\n <ax-button-item-list>\n @if (hasTableListDisplayOption()) {\n <ax-button-item\n [text]=\"('@general:terms.interface.table-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'table'\"\n (onClick)=\"setListDisplayMode('table')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-table\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n @if (hasTableListDisplayOption() && (hasCardListDisplayOption() || hasRowListDisplayOption())) {\n <ax-divider />\n }\n @if (hasCardListDisplayOption()) {\n <!-- ----- Card grid presentation ----- -->\n <ax-button-item\n [text]=\"('@general:terms.interface.card-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'card'\"\n (onClick)=\"setListDisplayMode('card')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-grid-2\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n @if (hasRowListDisplayOption()) {\n <!-- ----- Horizontal row-list presentation ----- -->\n <ax-button-item\n [text]=\"('@general:terms.interface.row-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'row'\"\n (onClick)=\"setListDisplayMode('row')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-grip-lines\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </div>\n </div>\n </ax-popover>\n </div>\n }\n @for (tr of toolbarPrimaryActions(); track $index) {\n <ax-button\n [text]=\"(tr.title | translate | async)!\"\n [color]=\"tr.color\"\n [disabled]=\"tr.disabled\"\n (onClick)=\"vm.executeCommand(tr.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"tr.icon\"> </ax-icon>\n </ax-prefix>\n </ax-button>\n }\n @if (toolbarSecondaryActions().length) {\n <ax-button\n [text]=\"deviceService.isSmall() ? null : ('@general:terms.interface.actions' | translate | async)\"\n [color]=\"'default'\"\n >\n <ax-prefix>\n <i class=\"fa-solid fa-ellipsis-vertical\"></i>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (tr of toolbarSecondaryActions(); track $index) {\n <ng-container>\n @if (tr.separated && !$first) {\n <ax-divider></ax-divider>\n }\n <ax-button-item\n [text]=\"(tr.title | translate | async)!\"\n class=\"font-semibold text-{{ tr.color }}\"\n (onClick)=\"vm.executeCommand(tr.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"tr.icon\"> </ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ng-container>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n </div>\n </div>\n\n @if (vm.enabledListLayouts().includes('table')) {\n <div class=\"flex flex-1 pt-0 overflow-auto max-w-full w-full\" [class.hidden]=\"vm.activeListLayout() !== 'table'\">\n <ax-data-table\n #grid\n [showFooter]=\"false\"\n class=\"flex-1\"\n [paging]=\"true\"\n [fetchDataMode]=\"'manual'\"\n [parentField]=\"vm.parentKey()\"\n [loading]=\"{ enabled: true, animation: true }\"\n [dataSource]=\"vm.dataSource\"\n (selectedRowsChange)=\"handleSelectedRowsChange($event)\"\n (onRowDbClick)=\"handleRowDbClick($event)\"\n >\n @if (vm.showIndexColumn()) {\n <ax-index-column\n [caption]=\"('@general:terms.common.row-number' | translate | async)!\"\n fixed=\"start\"\n [width]=\"'80px'\"\n [padZero]=\"false\"\n ></ax-index-column>\n }\n @if (vm.selectedScopeActionsCount()) {\n <ax-select-column fixed=\"start\" [width]=\"'50px'\"></ax-select-column>\n }\n @for (col of vm.columns(); track col.name) {\n @if (col.visible) {\n <axp-widget-column-renderer\n [expandHandler]=\"$index === 0 && vm.parentKey() ? true : false\"\n [caption]=\"(col.title | translate | async)!\"\n [node]=\"col.node()\"\n ></axp-widget-column-renderer>\n }\n }\n @if (getCommandRowItems().length) {\n <ax-command-column\n fixed=\"end\"\n [width]=\"getCommandRowItems().length * 60 + 'px'\"\n [items]=\"getCommandRowItems()\"\n (onItemClick)=\"handleRowCommandClick($event)\"\n ></ax-command-column>\n }\n @if (dropdownRowItems().length) {\n <ax-dropdown-command-column\n fixed=\"end\"\n [width]=\"'60px'\"\n [items]=\"getDropdownRowItems\"\n (onItemClick)=\"handleRowCommandClick($event)\"\n ></ax-dropdown-command-column>\n }\n </ax-data-table>\n </div>\n }\n @if (vm.enabledListLayouts().includes('card') || vm.enabledListLayouts().includes('row')) {\n <axp-entity-master-list-card-list\n class=\"axp-entity-list-host w-full min-h-0 flex-1\"\n [class.hidden]=\"!vm.isCardHostLayout()\"\n [vm]=\"vm\"\n ></axp-entity-master-list-card-list>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "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: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$2.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i2$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: AXBadgeModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i5.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i6.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "closeOnNavigation", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXActionSheetModule }, { kind: "ngmodule", type: AXDrawerModule }, { kind: "ngmodule", type: AXDialogModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXTabsModule }, { kind: "ngmodule", type: AXTooltipModule }, { kind: "ngmodule", type: AXBreadcrumbsModule }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i7.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: AXDataTableModule }, { kind: "component", type: i8.AXDataTableComponent, selector: "ax-data-table", inputs: ["dataSource", "selectedRows", "parentField", "hasChildrenField", "rowDetailsTemplate", "rowCssClass", "cellCssClass", "highlightText", "look", "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: i8.AXRowIndexColumnComponent, selector: "ax-index-column", inputs: ["width", "caption", "fixed", "footerTemplate", "padZero"] }, { kind: "component", type: i8.AXRowSelectColumnComponent, selector: "ax-select-column", inputs: ["width", "caption", "fixed", "advanceSelect"] }, { kind: "component", type: i8.AXRowCommandColumnComponent, selector: "ax-command-column", inputs: ["width", "caption", "fixed", "footerTemplate", "items"], outputs: ["onItemClick"] }, { kind: "component", type: i8.AXRowDropdownCommandColumnComponent, selector: "ax-dropdown-command-column", inputs: ["width", "caption", "fixed", "footerTemplate", "emptyStateTemplate", "emptyStateText", "items"], outputs: ["onItemClick"] }, { kind: "ngmodule", type:
|
|
639
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPEntityDetailListViewComponent, isStandalone: true, selector: "axp-entity-detail-list-view", inputs: { vm: ["viewModel", "vm"] }, providers: [AXUnsubscriber], viewQueries: [{ propertyName: "listDisplayModePopover", first: true, predicate: ["listDisplayModePopover"], descendants: true, isSignal: true }, { propertyName: "grid", first: true, predicate: ["grid"], descendants: true }], ngImport: i0, template: "<div class=\"flex p-2\">\n <div class=\"flex flex-col items-stretch gap-3 flex-1 overflow-auto min-h-72\">\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"flex justify-between items-center\">\n <div class=\"flex justify-start items-center gap-4\">\n @if (vm.hasSelectedItems()) {\n <div class=\"flex gap-3 items-center h-10\">\n <span class=\"text-xl font-bold\">\n {{ vm.selectedItems().length }}\n {{ '@general:terms.items-selected' | translate | async }}\n </span>\n <span\n (click)=\"vm.clearSelection()\"\n class=\"text-sm text-primary-500 underline cursor-pointer\"\n >{{ '@general:actions.unselect.title' | translate | async }}</span\n >\n </div>\n } @else {\n @if (vm.hasInlineFilters() && !deviceService.isSmall()) {\n <div class=\"w-72\">\n <ax-search-box\n [placeholder]=\"\n ('@general:widgets.lookup.search' | translate | async) + vm.inlineFiltersPlaceholders().join(', ')\n \"\n (onValueChanged)=\"handleChangeSearchValue($event)\"\n ><ax-clear-button></ax-clear-button\n ></ax-search-box>\n </div>\n }\n }\n </div>\n </div>\n <div class=\"flex items-center gap-3\">\n @if (showListDisplayModeControl()) {\n <div>\n <ax-button [iconOnly]=\"true\" #listDisplayButton [color]=\"'default'\">\n <i [class]=\"listDisplayModeButtonIcon()\"></i>\n </ax-button>\n <ax-popover\n [adaptivityEnabled]=\"true\"\n [offsetY]=\"10\"\n [target]=\"listDisplayButton\"\n [openOn]=\"'toggle'\"\n [closeOn]=\"'clickOut'\"\n #listDisplayModePopover\n >\n <div class=\"lightest-surface shadow-md border md:w-72 w-full rounded-md\">\n <ax-header class=\"border-b lighter-surface rounded-t-md p-4 font-bold\">\n {{ '@general:terms.interface.list-display' | translate | async }}\n </ax-header>\n <div class=\"py-2 px-2\">\n <ax-button-item-list>\n @if (hasTableListDisplayOption()) {\n <ax-button-item\n [text]=\"('@general:terms.interface.table-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'table'\"\n (onClick)=\"setListDisplayMode('table')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-table\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n @if (hasTableListDisplayOption() && (hasCardListDisplayOption() || hasRowListDisplayOption())) {\n <ax-divider />\n }\n @if (hasCardListDisplayOption()) {\n <!-- ----- Card grid presentation ----- -->\n <ax-button-item\n [text]=\"('@general:terms.interface.card-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'card'\"\n (onClick)=\"setListDisplayMode('card')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-grid-2\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n @if (hasRowListDisplayOption()) {\n <!-- ----- Horizontal row-list presentation ----- -->\n <ax-button-item\n [text]=\"('@general:terms.interface.row-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'row'\"\n (onClick)=\"setListDisplayMode('row')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-grip-lines\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n </ax-button-item-list>\n </div>\n </div>\n </ax-popover>\n </div>\n }\n @for (tr of toolbarPrimaryActions(); track $index) {\n <ax-button\n [text]=\"(tr.title | translate | async)!\"\n [color]=\"tr.color\"\n [disabled]=\"tr.disabled\"\n (onClick)=\"vm.executeCommand(tr.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"tr.icon\"> </ax-icon>\n </ax-prefix>\n </ax-button>\n }\n @if (toolbarSecondaryActions().length) {\n <ax-button\n [text]=\"deviceService.isSmall() ? null : ('@general:terms.interface.actions' | translate | async)\"\n [color]=\"'default'\"\n >\n <ax-prefix>\n <i class=\"fa-solid fa-ellipsis-vertical\"></i>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (tr of toolbarSecondaryActions(); track $index) {\n <ng-container>\n @if (tr.separated && !$first) {\n <ax-divider></ax-divider>\n }\n <ax-button-item\n [text]=\"(tr.title | translate | async)!\"\n class=\"font-semibold text-{{ tr.color }}\"\n (onClick)=\"vm.executeCommand(tr.name)\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"tr.icon\"> </ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ng-container>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n </div>\n </div>\n\n @if (vm.enabledListLayouts().includes('table')) {\n <div class=\"flex flex-1 pt-0 overflow-auto max-w-full w-full\" [class.hidden]=\"vm.activeListLayout() !== 'table'\">\n <ax-data-table\n #grid\n [showFooter]=\"false\"\n class=\"flex-1\"\n [paging]=\"true\"\n [fetchDataMode]=\"'manual'\"\n [parentField]=\"vm.parentKey()\"\n [loading]=\"{ enabled: true, animation: true }\"\n [dataSource]=\"vm.dataSource\"\n (selectedRowsChange)=\"handleSelectedRowsChange($event)\"\n (onRowDbClick)=\"handleRowDbClick($event)\"\n >\n @if (vm.showIndexColumn()) {\n <ax-index-column\n [caption]=\"('@general:terms.common.row-number' | translate | async)!\"\n fixed=\"start\"\n [width]=\"'80px'\"\n [padZero]=\"false\"\n ></ax-index-column>\n }\n @if (vm.selectedScopeActionsCount()) {\n <ax-select-column fixed=\"start\" [width]=\"'50px'\"></ax-select-column>\n }\n @for (col of vm.columns(); track col.name) {\n @if (col.visible) {\n <axp-widget-column-renderer\n [expandHandler]=\"$index === 0 && vm.parentKey() ? true : false\"\n [caption]=\"(col.title | translate | async)!\"\n [node]=\"col.node()\"\n ></axp-widget-column-renderer>\n }\n }\n @if (getCommandRowItems().length) {\n <ax-command-column\n fixed=\"end\"\n [width]=\"getCommandRowItems().length * 60 + 'px'\"\n [items]=\"getCommandRowItems()\"\n (onItemClick)=\"handleRowCommandClick($event)\"\n ></ax-command-column>\n }\n @if (dropdownRowItems().length) {\n <ax-dropdown-command-column\n fixed=\"end\"\n [width]=\"'60px'\"\n [items]=\"getDropdownRowItems\"\n (onItemClick)=\"handleRowCommandClick($event)\"\n ></ax-dropdown-command-column>\n }\n </ax-data-table>\n </div>\n }\n @if (vm.enabledListLayouts().includes('card') || vm.enabledListLayouts().includes('row')) {\n <axp-entity-master-list-card-list\n class=\"axp-entity-list-host w-full min-h-0 flex-1\"\n [class.hidden]=\"!vm.isCardHostLayout()\"\n [vm]=\"vm\"\n ></axp-entity-master-list-card-list>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "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: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$2.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }, { kind: "component", type: i2$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: AXBadgeModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i5.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i6.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "restoreFocusOnClose", "openAfter", "closeAfter", "closeOnScroll", "closeOnNavigation", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXActionSheetModule }, { kind: "ngmodule", type: AXDrawerModule }, { kind: "ngmodule", type: AXDialogModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXTabsModule }, { kind: "ngmodule", type: AXTooltipModule }, { kind: "ngmodule", type: AXBreadcrumbsModule }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: i7.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: AXDataTableModule }, { kind: "component", type: i8.AXDataTableComponent, selector: "ax-data-table", inputs: ["dataSource", "selectedRows", "parentField", "hasChildrenField", "rowDetailsTemplate", "rowCssClass", "cellCssClass", "highlightText", "look", "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: i8.AXRowIndexColumnComponent, selector: "ax-index-column", inputs: ["width", "caption", "fixed", "footerTemplate", "padZero"] }, { kind: "component", type: i8.AXRowSelectColumnComponent, selector: "ax-select-column", inputs: ["width", "caption", "fixed", "advanceSelect"] }, { kind: "component", type: i8.AXRowCommandColumnComponent, selector: "ax-command-column", inputs: ["width", "caption", "fixed", "footerTemplate", "items"], outputs: ["onItemClick"] }, { kind: "component", type: i8.AXRowDropdownCommandColumnComponent, selector: "ax-dropdown-command-column", inputs: ["width", "caption", "fixed", "footerTemplate", "emptyStateTemplate", "emptyStateText", "items"], outputs: ["onItemClick"] }, { kind: "ngmodule", type:
|
|
623
640
|
//
|
|
624
641
|
AXPWidgetCoreModule }, { kind: "component", type: i7$1.AXPWidgetColumnRendererComponent, selector: "axp-widget-column-renderer", inputs: ["caption", "customExpandIcon", "customCollapseIcon", "customWidth", "columnKey", "node", "footerTemplate", "expandHandler", "sortEnabled", "headerSortDirection", "headerSortPriority", "columnFixed", "cellTemplate", "headerTemplate"], outputs: ["sortToggle"] }, { kind: "ngmodule", type: AXPWidgetsModule }, { kind: "ngmodule", type: AXPAuthModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPEntityMasterListCardListComponent, selector: "axp-entity-master-list-card-list", inputs: ["vm", "userStylingRules"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
625
642
|
}
|
|
@@ -1738,6 +1755,8 @@ class AXPEntityMasterToolbarViewComponent {
|
|
|
1738
1755
|
this.translationService = inject(AXTranslationService);
|
|
1739
1756
|
this.toastService = inject(AXToastService);
|
|
1740
1757
|
this.isInitializing = false;
|
|
1758
|
+
/** Which `runInitialListLoad` currently owns `isInitializing`. */
|
|
1759
|
+
this.initializingToken = null;
|
|
1741
1760
|
this.pendingInitialSorts = true;
|
|
1742
1761
|
this.filterTriggerMode = 'manual';
|
|
1743
1762
|
this.sortMenuOpen = signal(false, /* @ts-ignore */
|
|
@@ -1818,9 +1837,14 @@ class AXPEntityMasterToolbarViewComponent {
|
|
|
1818
1837
|
return;
|
|
1819
1838
|
}
|
|
1820
1839
|
untracked(() => {
|
|
1821
|
-
this.
|
|
1840
|
+
const loadOwnsGate = this.initializingToken != null;
|
|
1841
|
+
if (!loadOwnsGate) {
|
|
1842
|
+
this.isInitializing = true;
|
|
1843
|
+
}
|
|
1822
1844
|
this.setInitialFiltersFromSettingsOrView();
|
|
1823
|
-
|
|
1845
|
+
if (!loadOwnsGate) {
|
|
1846
|
+
this.isInitializing = false;
|
|
1847
|
+
}
|
|
1824
1848
|
});
|
|
1825
1849
|
}, /* @ts-ignore */
|
|
1826
1850
|
...(ngDevMode ? [{ debugName: "#listInstanceFiltersEffect" }] : /* istanbul ignore next */ []));
|
|
@@ -1870,23 +1894,42 @@ class AXPEntityMasterToolbarViewComponent {
|
|
|
1870
1894
|
* Applies persisted view/filters/sorts once after query-filters syncs `initialFilters`.
|
|
1871
1895
|
* Avoids a second list query from `scheduleApply` plus a follow-up `onFiltersChanged` emit.
|
|
1872
1896
|
*/
|
|
1873
|
-
async runInitialListLoad() {
|
|
1897
|
+
async runInitialListLoad(viewSwitchEpoch) {
|
|
1898
|
+
const stillCurrent = () => viewSwitchEpoch == null || this.vm.isViewSwitchCurrent(viewSwitchEpoch);
|
|
1899
|
+
if (!stillCurrent()) {
|
|
1900
|
+
return;
|
|
1901
|
+
}
|
|
1902
|
+
const token = viewSwitchEpoch ?? -1;
|
|
1874
1903
|
traceEntityMasterList('toolbar', 'runInitialListLoad start', () => ({
|
|
1875
1904
|
viewName: this.vm.view().name,
|
|
1876
1905
|
activeListLayout: this.vm.activeListLayout(),
|
|
1877
1906
|
dataSource: buildDataSourceTraceSnapshot(this.vm.dataSource),
|
|
1878
1907
|
}));
|
|
1879
1908
|
this.isInitializing = true;
|
|
1909
|
+
this.initializingToken = token;
|
|
1880
1910
|
this.pendingInitialSorts = true;
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1911
|
+
try {
|
|
1912
|
+
this.setInitialFiltersFromSettingsOrView();
|
|
1913
|
+
this.filtersDefinitions.set(this.vm.filterDefinitions());
|
|
1914
|
+
this.filtersReady.set(true);
|
|
1915
|
+
await this.waitForQueryFiltersSync();
|
|
1916
|
+
if (!stillCurrent()) {
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
await this.vm.applyFilterAndSort({
|
|
1920
|
+
resetPagination: viewSwitchEpoch != null,
|
|
1921
|
+
viewSwitchEpoch,
|
|
1922
|
+
forceReload: viewSwitchEpoch != null,
|
|
1923
|
+
});
|
|
1924
|
+
if (!stillCurrent()) {
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1927
|
+
this.previousFilterQueries.set(this.vm.filterQueries());
|
|
1928
|
+
this.stripFiltersFromRouteQueryParam();
|
|
1929
|
+
}
|
|
1930
|
+
finally {
|
|
1931
|
+
this.releaseInitializing(token);
|
|
1932
|
+
}
|
|
1890
1933
|
traceEntityMasterList('toolbar', 'runInitialListLoad complete', () => ({
|
|
1891
1934
|
viewName: this.vm.view().name,
|
|
1892
1935
|
activeListLayout: this.vm.activeListLayout(),
|
|
@@ -1894,6 +1937,15 @@ class AXPEntityMasterToolbarViewComponent {
|
|
|
1894
1937
|
dataSource: buildDataSourceTraceSnapshot(this.vm.dataSource),
|
|
1895
1938
|
}));
|
|
1896
1939
|
}
|
|
1940
|
+
/** Drops the init gate only if a newer load has not taken it. */
|
|
1941
|
+
releaseInitializing(token) {
|
|
1942
|
+
if (this.initializingToken !== token) {
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
this.isInitializing = false;
|
|
1946
|
+
this.pendingInitialSorts = false;
|
|
1947
|
+
this.initializingToken = null;
|
|
1948
|
+
}
|
|
1897
1949
|
/** Waits until query-filters has rendered and synced converted `initialFilters`. */
|
|
1898
1950
|
waitForQueryFiltersSync() {
|
|
1899
1951
|
return new Promise((resolve) => {
|
|
@@ -1950,21 +2002,26 @@ class AXPEntityMasterToolbarViewComponent {
|
|
|
1950
2002
|
}, 50);
|
|
1951
2003
|
}
|
|
1952
2004
|
async onViewChanged(view) {
|
|
2005
|
+
const switchingView = view.name !== this.vm.view().name;
|
|
2006
|
+
const viewSwitchEpoch = switchingView ? this.vm.beginViewSwitch() : undefined;
|
|
1953
2007
|
traceEntityMasterList('toolbar', 'view tab changed', () => ({
|
|
1954
2008
|
previousViewName: this.vm.view().name,
|
|
1955
2009
|
nextViewName: view.name,
|
|
1956
2010
|
activeListLayout: this.vm.activeListLayout(),
|
|
1957
2011
|
dataSource: buildDataSourceTraceSnapshot(this.vm.dataSource),
|
|
1958
2012
|
}));
|
|
1959
|
-
await this.vm.setView(view.name);
|
|
2013
|
+
await this.vm.setView(view.name, viewSwitchEpoch);
|
|
2014
|
+
if (viewSwitchEpoch != null && !this.vm.isViewSwitchCurrent(viewSwitchEpoch)) {
|
|
2015
|
+
return;
|
|
2016
|
+
}
|
|
1960
2017
|
if (axpIsEntityListRoute(this.router)) {
|
|
1961
|
-
|
|
1962
|
-
// Prevent queryParamSub from re-applying the same view change while initial load runs.
|
|
2018
|
+
// Mark the next URL before replaceUrl so the queryParam emission does not start a second switch.
|
|
1963
2019
|
this.vm.markRouteQueryContextSynced(this.activeRoute.snapshot.queryParamMap, {
|
|
1964
2020
|
view: view.name,
|
|
1965
2021
|
});
|
|
2022
|
+
axpReplaceEntityListRouteQueryParams(this.router, { view: view.name });
|
|
1966
2023
|
}
|
|
1967
|
-
await this.runInitialListLoad();
|
|
2024
|
+
await this.runInitialListLoad(viewSwitchEpoch);
|
|
1968
2025
|
traceEntityMasterList('toolbar', 'view tab change handled', () => ({
|
|
1969
2026
|
viewName: this.vm.view().name,
|
|
1970
2027
|
activeListLayout: this.vm.activeListLayout(),
|
|
@@ -2165,7 +2222,7 @@ class AXPEntityMasterToolbarViewComponent {
|
|
|
2165
2222
|
.join('|');
|
|
2166
2223
|
}
|
|
2167
2224
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPEntityMasterToolbarViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2168
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPEntityMasterToolbarViewComponent, isStandalone: true, selector: "axp-entity-master-toolbar-view", inputs: { vm: ["viewModel", "vm"] }, host: { classAttribute: "w-full" }, viewQueries: [{ propertyName: "viewPopover", first: true, predicate: ["viewPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "<axp-query-view-tabs\n id=\"axp-toolbar-view-selector\"\n [views]=\"viewQueries()\"\n [selectedView]=\"selectedViewQuery()\"\n (selectedViewChange)=\"onViewChanged($event)\"\n (edit)=\"onEditQueryView($event)\"\n (remove)=\"onDeleteQueryView($event)\"\n></axp-query-view-tabs>\n<div\n class=\"axp-entity-master-toolbar__row flex w-full flex-wrap items-center border-b border-light\"\n [class.min-w-0]=\"deviceService.isSmall()\"\n [class.gap-2]=\"!deviceService.isSmall()\"\n [class.gap-1]=\"deviceService.isSmall()\"\n>\n <!-- ----- Filter chips, search, and Ctrl+F stay on the leading edge ----- -->\n @if (filtersReady()) {\n <axp-query-filters\n id=\"axp-toolbar-filters\"\n class=\"min-w-0 flex-1\"\n [filtersDefinitions]=\"filtersDefinitions()\"\n [initialFilters]=\"initialFilters()\"\n [quickSearch]=\"true\"\n [mode]=\"vm.filterMode()\"\n [sortPresets]=\"mobileSortPresets()\"\n [activeSortPresetName]=\"activeSortPresetName()\"\n (onFiltersChanged)=\"onFiltersChanged($event)\"\n (onSortPresetSelected)=\"onSortPresetSelected($event)\"\n ></axp-query-filters>\n }\n\n <div\n class=\"axp-toolbar-list-tools ms-auto flex shrink-0 items-center gap-1\"\n >\n <!-- ----- Apply pending filters when the list is in manual apply mode ----- -->\n @if (filterTriggerMode === 'manual' && isFiltersDirty()) {\n <ax-button\n id=\"axp-toolbar-btn-filter\"\n [title]=\"'@general:actions.apply.title'\"\n [iconOnly]=\"true\"\n [color]=\"'primary'\"\n (onClick)=\"applyFilters()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-search\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button>\n }\n <!-- ----- Save View appears when the list layout is dirty ----- -->\n <axp-query-view-save-button\n [visible]=\"vm.canSaveActiveQueryView()\"\n (save)=\"onSaveQueryView()\"\n ></axp-query-view-save-button>\n\n <!-- ----- Sort stays a direct button on larger screens ----- -->\n @if (vm.canSort() && !deviceService.isSmall()) {\n <div class=\"axp-toolbar-btn-host\">\n <ax-button\n id=\"axp-toolbar-btn-sort\"\n class=\"axp-toolbar-btn axp-toolbar-btn-sort\"\n [class.axp-toolbar-btn--active]=\"activeSortCount() > 0\"\n [look]=\"'outline'\"\n [iconOnly]=\"true\"\n [color]=\"activeSortCount() > 0 ? 'primary' : 'default'\"\n [attr.aria-expanded]=\"sortMenuOpen()\"\n [attr.aria-haspopup]=\"'dialog'\"\n [title]=\"\n (activeSortCount() > 0\n ? ('@general:terms.interface.sort.button-active' | translate: { params: { count: activeSortCount() } } | async)\n : ('@general:actions.sort.title' | translate | async)) ?? ''\n \"\n #sortButton\n >\n <ax-prefix>\n <i class=\"fa-light fa-sort-amount-up\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button>\n <ax-popover\n id=\"axp-popover-sort\"\n [adaptivityEnabled]=\"true\"\n [offsetY]=\"8\"\n [target]=\"sortButton\"\n [openOn]=\"'toggle'\"\n [closeOn]=\"'clickOut'\"\n (onOpened)=\"sortMenuOpen.set(true)\"\n (onClosed)=\"sortMenuOpen.set(false)\"\n #sortPopover\n >\n <div class=\"axp-toolbar-popover lightest-surface shadow-md border md:w-96 w-full rounded-md overflow-hidden\">\n <axp-query-sorts\n [sortDefinitions]=\"sortDefinitions()\"\n [sortPresets]=\"vm.sortPresets()\"\n [defaultSortQueries]=\"defaultSortQueries()\"\n (sortQueriesChange)=\"onSortQueriesChange($event)\"\n [initialSortQueries]=\"sortQueries()\"\n ></axp-query-sorts>\n </div>\n </ax-popover>\n </div>\n }\n\n <!-- ----- On small screens this button also holds sort and category ----- -->\n <div class=\"axp-toolbar-btn-host\">\n <ax-button\n id=\"axp-toolbar-btn-view\"\n class=\"axp-toolbar-btn axp-toolbar-btn-view\"\n [class.axp-toolbar-btn--open]=\"viewMenuOpen()\"\n [class.axp-toolbar-btn--active]=\"deviceService.isSmall() && activeSortCount() > 0\"\n [look]=\"'outline'\"\n [iconOnly]=\"true\"\n [color]=\"deviceService.isSmall() && activeSortCount() > 0 ? 'primary' : 'default'\"\n [attr.aria-expanded]=\"viewMenuOpen()\"\n [attr.aria-haspopup]=\"'menu'\"\n [title]=\"((deviceService.isSmall()\n ? '@general:terms.interface.view.list-options'\n : '@general:terms.interface.view.menu-button') | translate | async) ?? ''\"\n #viewButton\n >\n <ax-prefix>\n <i class=\"fa-light fa-sliders\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button>\n <ax-popover\n id=\"axp-popover-view\"\n [adaptivityEnabled]=\"true\"\n [offsetY]=\"8\"\n [target]=\"viewButton\"\n [openOn]=\"'toggle'\"\n [closeOn]=\"'clickOut'\"\n (onOpened)=\"onViewMenuOpened()\"\n (onClosed)=\"onViewMenuClosed()\"\n #viewPopover\n >\n <div\n class=\"axp-toolbar-popover axp-toolbar-view-menu lightest-surface shadow-md border max-w-full overflow-hidden\"\n [class.w-72]=\"!deviceService.isSmall()\"\n [class.rounded-md]=\"!deviceService.isSmall()\"\n [class.w-full]=\"deviceService.isSmall()\"\n [class.axp-toolbar-view-menu--sheet]=\"deviceService.isSmall()\"\n >\n <!-- ----- Nested sort panel on small screens ----- -->\n @if (viewMenuPanel() === 'sort') {\n <div class=\"axp-toolbar-view-menu__header flex items-center justify-between gap-2 border-b border-light px-3 py-2\">\n <ax-button\n class=\"ax-sm\"\n [look]=\"'blank'\"\n [color]=\"'default'\"\n [title]=\"('@general:actions.back.title' | translate | async) ?? ''\"\n (onClick)=\"viewMenuPanel.set('root')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-chevron-left rtl:rotate-180\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button>\n <span class=\"min-w-0 flex-1 truncate font-bold\">\n {{ '@general:terms.interface.sort.title' | translate | async }}\n </span>\n <ax-button\n class=\"ax-sm\"\n [look]=\"'blank'\"\n [color]=\"'primary'\"\n [disabled]=\"!canResetSorts()\"\n [text]=\"'@general:terms.interface.sort.clear' | translate | async\"\n (onClick)=\"resetSortsFromMenu()\"\n ></ax-button>\n </div>\n <div class=\"axp-toolbar-view-menu__body axp-toolbar-sort-panel\">\n <axp-query-sorts\n [sortDefinitions]=\"sortDefinitions()\"\n [sortPresets]=\"vm.sortPresets()\"\n [defaultSortQueries]=\"defaultSortQueries()\"\n (sortQueriesChange)=\"onSortQueriesChange($event)\"\n [initialSortQueries]=\"sortQueries()\"\n ></axp-query-sorts>\n </div>\n }\n <!-- ----- Nested column visibility panel ----- -->\n @else if (viewMenuPanel() === 'columns') {\n <div class=\"axp-toolbar-view-menu__header flex items-center justify-between gap-2 border-b border-light px-3 py-2\">\n <ax-button\n class=\"ax-sm\"\n [look]=\"'blank'\"\n [color]=\"'default'\"\n [title]=\"('@general:actions.back.title' | translate | async) ?? ''\"\n (onClick)=\"viewMenuPanel.set('root')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-chevron-left rtl:rotate-180\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button>\n <span class=\"min-w-0 flex-1 truncate font-bold\">\n {{ '@general:terms.common.columns' | translate | async }}\n </span>\n <ax-button\n class=\"ax-sm\"\n [look]=\"'blank'\"\n [color]=\"'primary'\"\n [text]=\"'@general:actions.reset.title' | translate | async\"\n (onClick)=\"resetViewColumns()\"\n ></ax-button>\n </div>\n <div class=\"axp-toolbar-view-menu__body px-4 py-3\">\n <axp-query-columns\n [columns]=\"vm.columns()\"\n [constrainHeight]=\"false\"\n (columnsChange)=\"onColumnsChange($event)\"\n ></axp-query-columns>\n </div>\n }\n <!-- ----- Root presentation menu ----- -->\n @else {\n <div class=\"axp-toolbar-view-menu__header border-b border-light px-4 py-3 font-bold\">\n {{ (deviceService.isSmall()\n ? '@general:terms.interface.view.list-options'\n : '@general:terms.interface.view.menu-title') | translate | async }}\n </div>\n <div class=\"axp-toolbar-view-menu__body py-2\">\n <!--------------------------------------------------------------->\n <!-- ----- Sort opens the sort panel on small screens ----- -->\n @if (deviceService.isSmall() && vm.canSort()) {\n <div class=\"axp-toolbar-view-menu__section-label px-4\">\n {{ '@general:actions.sort.title' | translate | async }}\n </div>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"(activeSortCount() > 0\n ? ('@general:terms.interface.sort.button-active' | translate: { params: { count: activeSortCount() } } | async)\n : ('@general:terms.interface.sort.title' | translate | async))!\"\n (onClick)=\"openViewSortPanel()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-sort-amount-up\" aria-hidden=\"true\"></i>\n </ax-prefix>\n <ax-suffix>\n <i class=\"fa-light fa-chevron-right rtl:rotate-180\" aria-hidden=\"true\"></i>\n </ax-suffix>\n </ax-button-item>\n </ax-button-item-list>\n <ax-divider />\n }\n <!-- ----- Display mode ----- -->\n @if (showListDisplayModeControl()) {\n <div class=\"axp-toolbar-view-menu__section-label px-4\">\n {{ '@general:terms.interface.view.display-mode' | translate | async }}\n </div>\n <ax-button-item-list>\n @if (hasTableListDisplayOption()) {\n <ax-button-item\n [text]=\"('@general:terms.interface.table-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'table'\"\n (onClick)=\"setListDisplayMode('table')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-table\" aria-hidden=\"true\"></i>\n </ax-prefix>\n <!--->\n <!-- ----- Selected table layout ----- -->\n @if (listDisplayMode() === 'table') {\n <ax-suffix>\n <i class=\"fa-light fa-check\" aria-hidden=\"true\"></i>\n </ax-suffix>\n }\n </ax-button-item>\n }\n @if (hasCardListDisplayOption()) {\n <!-- ----- Card grid presentation ----- -->\n <ax-button-item\n [text]=\"('@general:terms.interface.card-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'card'\"\n (onClick)=\"setListDisplayMode('card')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-grid-2\" aria-hidden=\"true\"></i>\n </ax-prefix>\n <!--->\n <!-- ----- Selected card layout ----- -->\n @if (listDisplayMode() === 'card') {\n <ax-suffix>\n <i class=\"fa-light fa-check\" aria-hidden=\"true\"></i>\n </ax-suffix>\n }\n </ax-button-item>\n }\n @if (hasRowListDisplayOption()) {\n <!-- ----- Horizontal row-list presentation ----- -->\n <ax-button-item\n [text]=\"('@general:terms.interface.row-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'row'\"\n (onClick)=\"setListDisplayMode('row')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-grip-lines\" aria-hidden=\"true\"></i>\n </ax-prefix>\n <!--->\n <!-- ----- Selected row layout ----- -->\n @if (listDisplayMode() === 'row') {\n <ax-suffix>\n <i class=\"fa-light fa-check\" aria-hidden=\"true\"></i>\n </ax-suffix>\n }\n </ax-button-item>\n }\n </ax-button-item-list>\n }\n\n <!-- ----- Columns ----- -->\n @if (showColumnsControl()) {\n <!--->\n <!-- ----- Divider when a display-mode section is already shown ----- -->\n @if (showListDisplayModeControl()) {\n <ax-divider />\n }\n <div class=\"axp-toolbar-view-menu__section-label px-4\">\n {{ '@general:terms.common.columns' | translate | async }}\n </div>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"('@general:terms.interface.view.manage-columns' | translate | async)!\"\n (onClick)=\"openViewColumnsPanel()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-table-columns\" aria-hidden=\"true\"></i>\n </ax-prefix>\n <ax-suffix>\n <i class=\"fa-light fa-chevron-right rtl:rotate-180\" aria-hidden=\"true\"></i>\n </ax-suffix>\n </ax-button-item>\n </ax-button-item-list>\n }\n\n <!-- ----- Appearance / row highlight ----- -->\n <!--->\n <!-- ----- Divider when earlier presentation sections are present ----- -->\n @if (showListDisplayModeControl() || showColumnsControl()) {\n <ax-divider />\n }\n <div class=\"axp-toolbar-view-menu__section-label px-4\">\n {{ '@general:terms.interface.appearance' | translate | async }}\n </div>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"('@general:terms.interface.styling.title' | translate | async)!\"\n (onClick)=\"openListStylingFromViewMenu()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-palette\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n <!--------------------------------------------------------------->\n <!-- ----- Category opens the navigation drawer on small screens ----- -->\n @if (deviceService.isSmall() && vm.entityDef.category) {\n <ax-divider />\n <ax-button-item-list>\n <ax-button-item\n [text]=\"('@general:terms.interface.category.title' | translate | async)!\"\n (onClick)=\"openCategoryFromViewMenu()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-bars\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n }\n </div>\n }\n </div>\n </ax-popover>\n </div>\n </div>\n</div>\n", styles: ["@layer properties;.axp-entity-master-toolbar__row{box-sizing:border-box;min-height:2.875rem;padding-block:.1875rem}.axp-toolbar-list-tools{width:max-content;flex:0 0 auto}.axp-toolbar-btn-host{display:inline-flex;width:max-content;flex:0 0 auto;position:relative}.axp-toolbar-btn.ax-button,.axp-toolbar-btn{flex:0 0 auto;width:max-content}.axp-toolbar-btn.ax-button-icon,.axp-toolbar-btn.ax-button-icon button{box-sizing:border-box;height:var(--ax-sys-size-base);min-height:var(--ax-sys-size-base);max-height:var(--ax-sys-size-base);min-width:var(--ax-sys-size-base);max-width:var(--ax-sys-size-base);width:var(--ax-sys-size-base)}.axp-toolbar-btn-sort.ax-button-icon button i{font-size:1em}.axp-toolbar-btn--active button{background-color:rgba(var(--ax-sys-color-primary-surface))}@supports (color: color-mix(in lab,red,red)){.axp-toolbar-btn--active button{background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-surface)) 10%,transparent)}}.axp-toolbar-view-menu__section-label{padding-inline:var(--spacing, .25rem);padding-top:var(--spacing, .25rem);padding-bottom:var(--spacing, .25rem);font-size:10px;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wider, .05em);letter-spacing:var(--tracking-wider, .05em);color:var(--color-neutral-400, oklch(70.8% 0 none));text-transform:uppercase}.axp-toolbar-popover{display:flex;max-height:min(28rem,70vh);flex-direction:column;overflow:hidden}.axp-toolbar-view-menu__header{flex-shrink:0}.axp-toolbar-view-menu__body{min-height:0px;flex:1;overflow-x:hidden;overflow-y:auto}.axp-toolbar-view-menu__body .ax-sorted-list{max-height:none;overflow:visible}.axp-toolbar-sort-panel .axp-query-sorts__header{display:none}.axp-toolbar-view-menu--sheet{width:100%;max-width:100%;border-radius:0;border-inline:0}@media(max-width:600px){.axp-entity-master-toolbar__row{padding-block:.375rem;padding-inline:.25rem}axp-query-filters>.flex{padding-block:0}.axp-toolbar-list-tools{justify-content:flex-end}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-tracking: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "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: AXDecoratorModule }, { kind: "component", type: i2$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: AXTranslationModule }, { kind: "component", type: AXPQueryFiltersComponent, selector: "axp-query-filters", inputs: ["filtersDefinitions", "initialFilters", "mode", "quickSearch", "sortPresets", "activeSortPresetName"], outputs: ["onFiltersChanged", "onSortPresetSelected"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i6.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "closeOnNavigation", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "component", type: AXPQuerySortsComponent, selector: "axp-query-sorts", inputs: ["sortDefinitions", "sortPresets", "initialSortQueries", "defaultSortQueries"], outputs: ["sortDefinitionsChange", "sortQueriesChange"] }, { kind: "component", type: AXPQueryViewSaveButtonComponent, selector: "axp-query-view-save-button", inputs: ["visible"], outputs: ["save"] }, { kind: "component", type: AXPQueryViewTabsComponent, selector: "axp-query-view-tabs", inputs: ["views", "selectedView"], outputs: ["selectedViewChange", "edit", "remove"] }, { kind: "component", type: AXPQueryColumnsComponent, selector: "axp-query-columns", inputs: ["columns", "constrainHeight"], outputs: ["columnsChange"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
2225
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPEntityMasterToolbarViewComponent, isStandalone: true, selector: "axp-entity-master-toolbar-view", inputs: { vm: ["viewModel", "vm"] }, host: { classAttribute: "w-full" }, viewQueries: [{ propertyName: "viewPopover", first: true, predicate: ["viewPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "<axp-query-view-tabs\n id=\"axp-toolbar-view-selector\"\n [views]=\"viewQueries()\"\n [selectedView]=\"selectedViewQuery()\"\n (selectedViewChange)=\"onViewChanged($event)\"\n (edit)=\"onEditQueryView($event)\"\n (remove)=\"onDeleteQueryView($event)\"\n></axp-query-view-tabs>\n<div\n class=\"axp-entity-master-toolbar__row flex w-full flex-wrap items-center border-b border-light\"\n [class.min-w-0]=\"deviceService.isSmall()\"\n [class.gap-2]=\"!deviceService.isSmall()\"\n [class.gap-1]=\"deviceService.isSmall()\"\n>\n <!-- ----- Filter chips, search, and Ctrl+F stay on the leading edge ----- -->\n @if (filtersReady()) {\n <axp-query-filters\n id=\"axp-toolbar-filters\"\n class=\"min-w-0 flex-1\"\n [filtersDefinitions]=\"filtersDefinitions()\"\n [initialFilters]=\"initialFilters()\"\n [quickSearch]=\"true\"\n [mode]=\"vm.filterMode()\"\n [sortPresets]=\"mobileSortPresets()\"\n [activeSortPresetName]=\"activeSortPresetName()\"\n (onFiltersChanged)=\"onFiltersChanged($event)\"\n (onSortPresetSelected)=\"onSortPresetSelected($event)\"\n ></axp-query-filters>\n }\n\n <div\n class=\"axp-toolbar-list-tools ms-auto flex shrink-0 items-center gap-1\"\n >\n <!-- ----- Apply pending filters when the list is in manual apply mode ----- -->\n @if (filterTriggerMode === 'manual' && isFiltersDirty()) {\n <ax-button\n id=\"axp-toolbar-btn-filter\"\n [title]=\"'@general:actions.apply.title'\"\n [iconOnly]=\"true\"\n [color]=\"'primary'\"\n (onClick)=\"applyFilters()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-search\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button>\n }\n <!-- ----- Save View appears when the list layout is dirty ----- -->\n <axp-query-view-save-button\n [visible]=\"vm.canSaveActiveQueryView()\"\n (save)=\"onSaveQueryView()\"\n ></axp-query-view-save-button>\n\n <!-- ----- Sort stays a direct button on larger screens ----- -->\n @if (vm.canSort() && !deviceService.isSmall()) {\n <div class=\"axp-toolbar-btn-host\">\n <ax-button\n id=\"axp-toolbar-btn-sort\"\n class=\"axp-toolbar-btn axp-toolbar-btn-sort\"\n [class.axp-toolbar-btn--active]=\"activeSortCount() > 0\"\n [look]=\"'outline'\"\n [iconOnly]=\"true\"\n [color]=\"activeSortCount() > 0 ? 'primary' : 'default'\"\n [attr.aria-expanded]=\"sortMenuOpen()\"\n [attr.aria-haspopup]=\"'dialog'\"\n [title]=\"\n (activeSortCount() > 0\n ? ('@general:terms.interface.sort.button-active' | translate: { params: { count: activeSortCount() } } | async)\n : ('@general:actions.sort.title' | translate | async)) ?? ''\n \"\n #sortButton\n >\n <ax-prefix>\n <i class=\"fa-light fa-sort-amount-up\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button>\n <ax-popover\n id=\"axp-popover-sort\"\n [adaptivityEnabled]=\"true\"\n [offsetY]=\"8\"\n [target]=\"sortButton\"\n [openOn]=\"'toggle'\"\n [closeOn]=\"'clickOut'\"\n (onOpened)=\"sortMenuOpen.set(true)\"\n (onClosed)=\"sortMenuOpen.set(false)\"\n #sortPopover\n >\n <div class=\"axp-toolbar-popover lightest-surface shadow-md border md:w-96 w-full rounded-md overflow-hidden\">\n <axp-query-sorts\n [sortDefinitions]=\"sortDefinitions()\"\n [sortPresets]=\"vm.sortPresets()\"\n [defaultSortQueries]=\"defaultSortQueries()\"\n (sortQueriesChange)=\"onSortQueriesChange($event)\"\n [initialSortQueries]=\"sortQueries()\"\n ></axp-query-sorts>\n </div>\n </ax-popover>\n </div>\n }\n\n <!-- ----- On small screens this button also holds sort and category ----- -->\n <div class=\"axp-toolbar-btn-host\">\n <ax-button\n id=\"axp-toolbar-btn-view\"\n class=\"axp-toolbar-btn axp-toolbar-btn-view\"\n [class.axp-toolbar-btn--open]=\"viewMenuOpen()\"\n [class.axp-toolbar-btn--active]=\"deviceService.isSmall() && activeSortCount() > 0\"\n [look]=\"'outline'\"\n [iconOnly]=\"true\"\n [color]=\"deviceService.isSmall() && activeSortCount() > 0 ? 'primary' : 'default'\"\n [attr.aria-expanded]=\"viewMenuOpen()\"\n [attr.aria-haspopup]=\"'menu'\"\n [title]=\"((deviceService.isSmall()\n ? '@general:terms.interface.view.list-options'\n : '@general:terms.interface.view.menu-button') | translate | async) ?? ''\"\n #viewButton\n >\n <ax-prefix>\n <i class=\"fa-light fa-sliders\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button>\n <ax-popover\n id=\"axp-popover-view\"\n [adaptivityEnabled]=\"true\"\n [offsetY]=\"8\"\n [target]=\"viewButton\"\n [openOn]=\"'toggle'\"\n [closeOn]=\"'clickOut'\"\n (onOpened)=\"onViewMenuOpened()\"\n (onClosed)=\"onViewMenuClosed()\"\n #viewPopover\n >\n <div\n class=\"axp-toolbar-popover axp-toolbar-view-menu lightest-surface shadow-md border max-w-full overflow-hidden\"\n [class.w-72]=\"!deviceService.isSmall()\"\n [class.rounded-md]=\"!deviceService.isSmall()\"\n [class.w-full]=\"deviceService.isSmall()\"\n [class.axp-toolbar-view-menu--sheet]=\"deviceService.isSmall()\"\n >\n <!-- ----- Nested sort panel on small screens ----- -->\n @if (viewMenuPanel() === 'sort') {\n <div class=\"axp-toolbar-view-menu__header flex items-center justify-between gap-2 border-b border-light px-3 py-2\">\n <ax-button\n class=\"ax-sm\"\n [look]=\"'blank'\"\n [color]=\"'default'\"\n [title]=\"('@general:actions.back.title' | translate | async) ?? ''\"\n (onClick)=\"viewMenuPanel.set('root')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-chevron-left rtl:rotate-180\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button>\n <span class=\"min-w-0 flex-1 truncate font-bold\">\n {{ '@general:terms.interface.sort.title' | translate | async }}\n </span>\n <ax-button\n class=\"ax-sm\"\n [look]=\"'blank'\"\n [color]=\"'primary'\"\n [disabled]=\"!canResetSorts()\"\n [text]=\"'@general:terms.interface.sort.clear' | translate | async\"\n (onClick)=\"resetSortsFromMenu()\"\n ></ax-button>\n </div>\n <div class=\"axp-toolbar-view-menu__body axp-toolbar-sort-panel\">\n <axp-query-sorts\n [sortDefinitions]=\"sortDefinitions()\"\n [sortPresets]=\"vm.sortPresets()\"\n [defaultSortQueries]=\"defaultSortQueries()\"\n (sortQueriesChange)=\"onSortQueriesChange($event)\"\n [initialSortQueries]=\"sortQueries()\"\n ></axp-query-sorts>\n </div>\n }\n <!-- ----- Nested column visibility panel ----- -->\n @else if (viewMenuPanel() === 'columns') {\n <div class=\"axp-toolbar-view-menu__header flex items-center justify-between gap-2 border-b border-light px-3 py-2\">\n <ax-button\n class=\"ax-sm\"\n [look]=\"'blank'\"\n [color]=\"'default'\"\n [title]=\"('@general:actions.back.title' | translate | async) ?? ''\"\n (onClick)=\"viewMenuPanel.set('root')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-chevron-left rtl:rotate-180\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button>\n <span class=\"min-w-0 flex-1 truncate font-bold\">\n {{ '@general:terms.common.columns' | translate | async }}\n </span>\n <ax-button\n class=\"ax-sm\"\n [look]=\"'blank'\"\n [color]=\"'primary'\"\n [text]=\"'@general:actions.reset.title' | translate | async\"\n (onClick)=\"resetViewColumns()\"\n ></ax-button>\n </div>\n <div class=\"axp-toolbar-view-menu__body px-4 py-3\">\n <axp-query-columns\n [columns]=\"vm.columns()\"\n [constrainHeight]=\"false\"\n (columnsChange)=\"onColumnsChange($event)\"\n ></axp-query-columns>\n </div>\n }\n <!-- ----- Root presentation menu ----- -->\n @else {\n <div class=\"axp-toolbar-view-menu__header border-b border-light px-4 py-3 font-bold\">\n {{ (deviceService.isSmall()\n ? '@general:terms.interface.view.list-options'\n : '@general:terms.interface.view.menu-title') | translate | async }}\n </div>\n <div class=\"axp-toolbar-view-menu__body py-2\">\n <!--------------------------------------------------------------->\n <!-- ----- Sort opens the sort panel on small screens ----- -->\n @if (deviceService.isSmall() && vm.canSort()) {\n <div class=\"axp-toolbar-view-menu__section-label px-4\">\n {{ '@general:actions.sort.title' | translate | async }}\n </div>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"(activeSortCount() > 0\n ? ('@general:terms.interface.sort.button-active' | translate: { params: { count: activeSortCount() } } | async)\n : ('@general:terms.interface.sort.title' | translate | async))!\"\n (onClick)=\"openViewSortPanel()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-sort-amount-up\" aria-hidden=\"true\"></i>\n </ax-prefix>\n <ax-suffix>\n <i class=\"fa-light fa-chevron-right rtl:rotate-180\" aria-hidden=\"true\"></i>\n </ax-suffix>\n </ax-button-item>\n </ax-button-item-list>\n <ax-divider />\n }\n <!-- ----- Display mode ----- -->\n @if (showListDisplayModeControl()) {\n <div class=\"axp-toolbar-view-menu__section-label px-4\">\n {{ '@general:terms.interface.view.display-mode' | translate | async }}\n </div>\n <ax-button-item-list>\n @if (hasTableListDisplayOption()) {\n <ax-button-item\n [text]=\"('@general:terms.interface.table-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'table'\"\n (onClick)=\"setListDisplayMode('table')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-table\" aria-hidden=\"true\"></i>\n </ax-prefix>\n <!--->\n <!-- ----- Selected table layout ----- -->\n @if (listDisplayMode() === 'table') {\n <ax-suffix>\n <i class=\"fa-light fa-check\" aria-hidden=\"true\"></i>\n </ax-suffix>\n }\n </ax-button-item>\n }\n @if (hasCardListDisplayOption()) {\n <!-- ----- Card grid presentation ----- -->\n <ax-button-item\n [text]=\"('@general:terms.interface.card-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'card'\"\n (onClick)=\"setListDisplayMode('card')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-grid-2\" aria-hidden=\"true\"></i>\n </ax-prefix>\n <!--->\n <!-- ----- Selected card layout ----- -->\n @if (listDisplayMode() === 'card') {\n <ax-suffix>\n <i class=\"fa-light fa-check\" aria-hidden=\"true\"></i>\n </ax-suffix>\n }\n </ax-button-item>\n }\n @if (hasRowListDisplayOption()) {\n <!-- ----- Horizontal row-list presentation ----- -->\n <ax-button-item\n [text]=\"('@general:terms.interface.row-view' | translate | async)!\"\n [selected]=\"listDisplayMode() === 'row'\"\n (onClick)=\"setListDisplayMode('row')\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-grip-lines\" aria-hidden=\"true\"></i>\n </ax-prefix>\n <!--->\n <!-- ----- Selected row layout ----- -->\n @if (listDisplayMode() === 'row') {\n <ax-suffix>\n <i class=\"fa-light fa-check\" aria-hidden=\"true\"></i>\n </ax-suffix>\n }\n </ax-button-item>\n }\n </ax-button-item-list>\n }\n\n <!-- ----- Columns ----- -->\n @if (showColumnsControl()) {\n <!--->\n <!-- ----- Divider when a display-mode section is already shown ----- -->\n @if (showListDisplayModeControl()) {\n <ax-divider />\n }\n <div class=\"axp-toolbar-view-menu__section-label px-4\">\n {{ '@general:terms.common.columns' | translate | async }}\n </div>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"('@general:terms.interface.view.manage-columns' | translate | async)!\"\n (onClick)=\"openViewColumnsPanel()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-table-columns\" aria-hidden=\"true\"></i>\n </ax-prefix>\n <ax-suffix>\n <i class=\"fa-light fa-chevron-right rtl:rotate-180\" aria-hidden=\"true\"></i>\n </ax-suffix>\n </ax-button-item>\n </ax-button-item-list>\n }\n\n <!-- ----- Appearance / row highlight ----- -->\n <!--->\n <!-- ----- Divider when earlier presentation sections are present ----- -->\n @if (showListDisplayModeControl() || showColumnsControl()) {\n <ax-divider />\n }\n <div class=\"axp-toolbar-view-menu__section-label px-4\">\n {{ '@general:terms.interface.appearance' | translate | async }}\n </div>\n <ax-button-item-list>\n <ax-button-item\n [text]=\"('@general:terms.interface.styling.title' | translate | async)!\"\n (onClick)=\"openListStylingFromViewMenu()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-palette\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n <!--------------------------------------------------------------->\n <!-- ----- Category opens the navigation drawer on small screens ----- -->\n @if (deviceService.isSmall() && vm.entityDef.category) {\n <ax-divider />\n <ax-button-item-list>\n <ax-button-item\n [text]=\"('@general:terms.interface.category.title' | translate | async)!\"\n (onClick)=\"openCategoryFromViewMenu()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-bars\" aria-hidden=\"true\"></i>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n }\n </div>\n }\n </div>\n </ax-popover>\n </div>\n </div>\n</div>\n", styles: ["@layer properties;.axp-entity-master-toolbar__row{box-sizing:border-box;min-height:2.875rem;padding-block:.1875rem}.axp-toolbar-list-tools{width:max-content;flex:0 0 auto}.axp-toolbar-btn-host{display:inline-flex;width:max-content;flex:0 0 auto;position:relative}.axp-toolbar-btn.ax-button,.axp-toolbar-btn{flex:0 0 auto;width:max-content}.axp-toolbar-btn.ax-button-icon,.axp-toolbar-btn.ax-button-icon button{box-sizing:border-box;height:var(--ax-sys-size-base);min-height:var(--ax-sys-size-base);max-height:var(--ax-sys-size-base);min-width:var(--ax-sys-size-base);max-width:var(--ax-sys-size-base);width:var(--ax-sys-size-base)}.axp-toolbar-btn-sort.ax-button-icon button i{font-size:1em}.axp-toolbar-btn--active button{background-color:rgba(var(--ax-sys-color-primary-surface))}@supports (color: color-mix(in lab,red,red)){.axp-toolbar-btn--active button{background-color:color-mix(in oklab,rgba(var(--ax-sys-color-primary-surface)) 10%,transparent)}}.axp-toolbar-view-menu__section-label{padding-inline:var(--spacing, .25rem);padding-top:var(--spacing, .25rem);padding-bottom:var(--spacing, .25rem);font-size:10px;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wider, .05em);letter-spacing:var(--tracking-wider, .05em);color:var(--color-neutral-400, oklch(70.8% 0 none));text-transform:uppercase}.axp-toolbar-popover{display:flex;max-height:min(28rem,70vh);flex-direction:column;overflow:hidden}.axp-toolbar-view-menu__header{flex-shrink:0}.axp-toolbar-view-menu__body{min-height:0px;flex:1;overflow-x:hidden;overflow-y:auto}.axp-toolbar-view-menu__body .ax-sorted-list{max-height:none;overflow:visible}.axp-toolbar-sort-panel .axp-query-sorts__header{display:none}.axp-toolbar-view-menu--sheet{width:100%;max-width:100%;border-radius:0;border-inline:0}@media(max-width:600px){.axp-entity-master-toolbar__row{padding-block:.375rem;padding-inline:.25rem}axp-query-filters>.flex{padding-block:0}.axp-toolbar-list-tools{justify-content:flex-end}}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight: initial;--tw-tracking: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "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: AXDecoratorModule }, { kind: "component", type: i2$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: AXTranslationModule }, { kind: "component", type: AXPQueryFiltersComponent, selector: "axp-query-filters", inputs: ["filtersDefinitions", "initialFilters", "mode", "quickSearch", "sortPresets", "activeSortPresetName"], outputs: ["onFiltersChanged", "onSortPresetSelected"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i6.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "visualContextScope", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "restoreFocusOnClose", "openAfter", "closeAfter", "closeOnScroll", "closeOnNavigation", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "component", type: AXPQuerySortsComponent, selector: "axp-query-sorts", inputs: ["sortDefinitions", "sortPresets", "initialSortQueries", "defaultSortQueries"], outputs: ["sortDefinitionsChange", "sortQueriesChange"] }, { kind: "component", type: AXPQueryViewSaveButtonComponent, selector: "axp-query-view-save-button", inputs: ["visible"], outputs: ["save"] }, { kind: "component", type: AXPQueryViewTabsComponent, selector: "axp-query-view-tabs", inputs: ["views", "selectedView"], outputs: ["selectedViewChange", "edit", "remove"] }, { kind: "component", type: AXPQueryColumnsComponent, selector: "axp-query-columns", inputs: ["columns", "constrainHeight"], outputs: ["columnsChange"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
2169
2226
|
}
|
|
2170
2227
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPEntityMasterToolbarViewComponent, decorators: [{
|
|
2171
2228
|
type: Component,
|
|
@@ -2433,6 +2490,8 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2433
2490
|
this.listHostReady = signal(false, /* @ts-ignore */
|
|
2434
2491
|
...(ngDevMode ? [{ debugName: "listHostReady" }] : /* istanbul ignore next */ []));
|
|
2435
2492
|
this.previousAppTabActive = false;
|
|
2493
|
+
/** List refresh that arrived while this route tab was cached in the background. */
|
|
2494
|
+
this.pendingBackgroundListRefresh = null;
|
|
2436
2495
|
this.lastEvaluatedViewName = null;
|
|
2437
2496
|
this.componentDestroyed = new Subject();
|
|
2438
2497
|
this.isRestoringExpandedRows = false;
|
|
@@ -2450,33 +2509,10 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2450
2509
|
const highlightRowId = e.meta?.highlightRowId;
|
|
2451
2510
|
const resetPagination = e.meta?.resetPagination === true || (highlightRowId != null && refreshTargetId == null);
|
|
2452
2511
|
if (e.action == 'refresh') {
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
activeListLayout: this.vm.activeListLayout(),
|
|
2456
|
-
resetPagination,
|
|
2457
|
-
refreshTargetId,
|
|
2458
|
-
highlightRowId,
|
|
2459
|
-
hasGrid: !!this.grid(),
|
|
2460
|
-
hasCardList: !!this.cardList(),
|
|
2461
|
-
dataSource: buildDataSourceTraceSnapshot(this.vm.dataSource),
|
|
2462
|
-
}));
|
|
2463
|
-
if (highlightRowId == null) {
|
|
2464
|
-
this.cardList()?.clearCardHighlight();
|
|
2465
|
-
}
|
|
2466
|
-
if (resetPagination) {
|
|
2467
|
-
this.vm.resetListPagingSkip();
|
|
2468
|
-
}
|
|
2469
|
-
if (refreshTargetId) {
|
|
2470
|
-
await this.grid()?.refreshItemChildren(refreshTargetId);
|
|
2471
|
-
this.updateParentHasChildAfterRefresh(refreshTargetId);
|
|
2472
|
-
}
|
|
2473
|
-
else {
|
|
2474
|
-
await this.reloadListData(resetPagination);
|
|
2475
|
-
}
|
|
2476
|
-
if (highlightRowId != null) {
|
|
2477
|
-
await this.highlightRowById(highlightRowId);
|
|
2512
|
+
if (this.deferListRefreshUntilTabVisible(resetPagination, refreshTargetId, highlightRowId)) {
|
|
2513
|
+
return;
|
|
2478
2514
|
}
|
|
2479
|
-
|
|
2515
|
+
await this.applyVisibleListRefresh(resetPagination, refreshTargetId, highlightRowId);
|
|
2480
2516
|
}
|
|
2481
2517
|
});
|
|
2482
2518
|
effect(() => {
|
|
@@ -2490,6 +2526,12 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2490
2526
|
this.syncListViewQueryParam(currentViewName);
|
|
2491
2527
|
}
|
|
2492
2528
|
});
|
|
2529
|
+
effect(() => {
|
|
2530
|
+
if (!this.vm.listTransitionLoading()) {
|
|
2531
|
+
return;
|
|
2532
|
+
}
|
|
2533
|
+
this.showTableLoadingPlaceholders();
|
|
2534
|
+
});
|
|
2493
2535
|
effect(() => {
|
|
2494
2536
|
const currentViewName = this.vm.view().name;
|
|
2495
2537
|
if (!this.listHostReady()) {
|
|
@@ -2553,9 +2595,11 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2553
2595
|
activeTabKey,
|
|
2554
2596
|
viewName: this.vm.view().name,
|
|
2555
2597
|
activeListLayout: this.vm.activeListLayout(),
|
|
2598
|
+
pendingRefresh: this.pendingBackgroundListRefresh != null,
|
|
2556
2599
|
...this.buildListHostTraceSnapshot(),
|
|
2557
2600
|
}));
|
|
2558
2601
|
this.pageContextRegistry.activate(this.pageContextRegistrationId);
|
|
2602
|
+
this.flushBackgroundListRefresh();
|
|
2559
2603
|
});
|
|
2560
2604
|
this.registerPageContext();
|
|
2561
2605
|
}
|
|
@@ -2784,7 +2828,87 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2784
2828
|
axpReplaceEntityListRouteQueryParams(this.router, { view: viewName });
|
|
2785
2829
|
});
|
|
2786
2830
|
}
|
|
2831
|
+
/** True when this cached list is not the visible route tab. */
|
|
2832
|
+
isListTabInBackground() {
|
|
2833
|
+
if (this.tabNavigation.effectiveMode() !== 'tabular') {
|
|
2834
|
+
return false;
|
|
2835
|
+
}
|
|
2836
|
+
const pageTabKey = this.getPageTabKey();
|
|
2837
|
+
if (!pageTabKey) {
|
|
2838
|
+
return false;
|
|
2839
|
+
}
|
|
2840
|
+
return this.tabNavigation.activeKey() !== pageTabKey;
|
|
2841
|
+
}
|
|
2842
|
+
/**
|
|
2843
|
+
* A detached list keeps its grid, but a refresh while it is off-screen does not
|
|
2844
|
+
* repaint when the tab is shown again. Hold the latest refresh until then.
|
|
2845
|
+
*/
|
|
2846
|
+
deferListRefreshUntilTabVisible(resetPagination, refreshTargetId, highlightRowId) {
|
|
2847
|
+
if (!this.isListTabInBackground()) {
|
|
2848
|
+
return false;
|
|
2849
|
+
}
|
|
2850
|
+
const previous = this.pendingBackgroundListRefresh;
|
|
2851
|
+
this.pendingBackgroundListRefresh = {
|
|
2852
|
+
resetPagination: resetPagination || (previous?.resetPagination ?? false),
|
|
2853
|
+
refreshTargetId,
|
|
2854
|
+
highlightRowId: highlightRowId ?? previous?.highlightRowId,
|
|
2855
|
+
};
|
|
2856
|
+
return true;
|
|
2857
|
+
}
|
|
2858
|
+
/** Applies a refresh that was queued while this list tab was in the background. */
|
|
2859
|
+
flushBackgroundListRefresh() {
|
|
2860
|
+
const pending = this.pendingBackgroundListRefresh;
|
|
2861
|
+
if (!pending) {
|
|
2862
|
+
return;
|
|
2863
|
+
}
|
|
2864
|
+
this.pendingBackgroundListRefresh = null;
|
|
2865
|
+
queueMicrotask(() => {
|
|
2866
|
+
if (this.listQueryParamSyncDisabled) {
|
|
2867
|
+
return;
|
|
2868
|
+
}
|
|
2869
|
+
if (this.isListTabInBackground()) {
|
|
2870
|
+
this.pendingBackgroundListRefresh = pending;
|
|
2871
|
+
return;
|
|
2872
|
+
}
|
|
2873
|
+
void this.applyVisibleListRefresh(pending.resetPagination, pending.refreshTargetId, pending.highlightRowId);
|
|
2874
|
+
});
|
|
2875
|
+
}
|
|
2876
|
+
async applyVisibleListRefresh(resetPagination, refreshTargetId, highlightRowId) {
|
|
2877
|
+
const epoch = this.vm.viewSwitchEpoch();
|
|
2878
|
+
traceEntityMasterList('list-view', 'refresh event received', () => ({
|
|
2879
|
+
viewName: this.vm.view().name,
|
|
2880
|
+
activeListLayout: this.vm.activeListLayout(),
|
|
2881
|
+
resetPagination,
|
|
2882
|
+
refreshTargetId,
|
|
2883
|
+
highlightRowId,
|
|
2884
|
+
hasGrid: !!this.grid(),
|
|
2885
|
+
hasCardList: !!this.cardList(),
|
|
2886
|
+
dataSource: buildDataSourceTraceSnapshot(this.vm.dataSource),
|
|
2887
|
+
}));
|
|
2888
|
+
if (highlightRowId == null) {
|
|
2889
|
+
this.cardList()?.clearCardHighlight();
|
|
2890
|
+
}
|
|
2891
|
+
if (resetPagination) {
|
|
2892
|
+
this.vm.resetListPagingSkip();
|
|
2893
|
+
}
|
|
2894
|
+
if (typeof refreshTargetId === 'string' || typeof refreshTargetId === 'number') {
|
|
2895
|
+
const parentId = String(refreshTargetId);
|
|
2896
|
+
await this.grid()?.refreshItemChildren(parentId);
|
|
2897
|
+
this.updateParentHasChildAfterRefresh(parentId);
|
|
2898
|
+
}
|
|
2899
|
+
else {
|
|
2900
|
+
await this.reloadListData(resetPagination);
|
|
2901
|
+
}
|
|
2902
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2903
|
+
return;
|
|
2904
|
+
}
|
|
2905
|
+
if (typeof highlightRowId === 'string' || typeof highlightRowId === 'number') {
|
|
2906
|
+
await this.highlightRowById(highlightRowId);
|
|
2907
|
+
}
|
|
2908
|
+
traceEntityMasterList('list-view', 'refresh event handled', () => this.buildListHostTraceSnapshot());
|
|
2909
|
+
}
|
|
2787
2910
|
async reloadListData(resetPagination = false) {
|
|
2911
|
+
const epoch = this.vm.viewSwitchEpoch();
|
|
2788
2912
|
traceEntityMasterList('list-view', 'reloadListData start', () => ({
|
|
2789
2913
|
resetPagination,
|
|
2790
2914
|
activeListLayout: this.vm.activeListLayout(),
|
|
@@ -2793,12 +2917,22 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2793
2917
|
hasCardList: !!this.cardList(),
|
|
2794
2918
|
dataSource: buildDataSourceTraceSnapshot(this.vm.dataSource),
|
|
2795
2919
|
}));
|
|
2920
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2921
|
+
return;
|
|
2922
|
+
}
|
|
2796
2923
|
if (!resetPagination && !this.vm.isCardHostLayout()) {
|
|
2797
2924
|
await this.vm.ensureListPagingResolved();
|
|
2925
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2926
|
+
return;
|
|
2927
|
+
}
|
|
2798
2928
|
this.vm.applyPagingToDataSourceWithoutLoad();
|
|
2799
2929
|
}
|
|
2930
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2931
|
+
return;
|
|
2932
|
+
}
|
|
2800
2933
|
if (this.vm.isCardHostLayout()) {
|
|
2801
2934
|
await this.cardList()?.reload(true);
|
|
2935
|
+
this.vm.finishListTransition(epoch);
|
|
2802
2936
|
// Shared DS load updates table rows via onChanged but not isRefreshCalled; prepare for a later table switch.
|
|
2803
2937
|
this.acknowledgeManualTableReady();
|
|
2804
2938
|
traceEntityMasterList('list-view', 'reloadListData complete (card)', () => this.buildListHostTraceSnapshot());
|
|
@@ -2806,21 +2940,59 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2806
2940
|
}
|
|
2807
2941
|
const grid = this.grid();
|
|
2808
2942
|
if (grid) {
|
|
2809
|
-
|
|
2943
|
+
if (resetPagination || this.vm.listTransitionLoading()) {
|
|
2944
|
+
this.showTableLoadingPlaceholders();
|
|
2945
|
+
}
|
|
2946
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2947
|
+
return;
|
|
2948
|
+
}
|
|
2949
|
+
const watch = watchNextDataSourceLoad(grid.dataSource, () => this.vm.isViewSwitchCurrent(epoch));
|
|
2810
2950
|
grid.refresh({ reset: resetPagination });
|
|
2811
|
-
|
|
2951
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2952
|
+
watch.stop();
|
|
2953
|
+
return;
|
|
2954
|
+
}
|
|
2955
|
+
if (grid.dataSource.isLoading) {
|
|
2956
|
+
await watch.promise;
|
|
2957
|
+
}
|
|
2958
|
+
else {
|
|
2959
|
+
watch.stop();
|
|
2960
|
+
}
|
|
2961
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2962
|
+
return;
|
|
2963
|
+
}
|
|
2964
|
+
this.vm.finishListTransition(epoch);
|
|
2812
2965
|
if (!resetPagination) {
|
|
2813
2966
|
this.scheduleSyncGridPagerUi();
|
|
2814
2967
|
}
|
|
2815
2968
|
this.scheduleRestoreExpandedRows();
|
|
2816
2969
|
}
|
|
2817
2970
|
else {
|
|
2818
|
-
const
|
|
2971
|
+
const watch = watchNextDataSourceLoad(this.vm.dataSource, () => this.vm.isViewSwitchCurrent(epoch));
|
|
2819
2972
|
this.vm.dataSource.refresh({ reset: resetPagination });
|
|
2820
|
-
|
|
2973
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2974
|
+
watch.stop();
|
|
2975
|
+
return;
|
|
2976
|
+
}
|
|
2977
|
+
if (this.vm.dataSource.isLoading) {
|
|
2978
|
+
await watch.promise;
|
|
2979
|
+
}
|
|
2980
|
+
else {
|
|
2981
|
+
watch.stop();
|
|
2982
|
+
}
|
|
2983
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2984
|
+
return;
|
|
2985
|
+
}
|
|
2986
|
+
this.vm.finishListTransition(epoch);
|
|
2821
2987
|
}
|
|
2822
2988
|
traceEntityMasterList('list-view', 'reloadListData complete (table)', () => this.buildListHostTraceSnapshot());
|
|
2823
2989
|
}
|
|
2990
|
+
/** Skeleton rows so an empty previous result does not stay on screen while the next page loads. */
|
|
2991
|
+
showTableLoadingPlaceholders() {
|
|
2992
|
+
const grid = this.grid();
|
|
2993
|
+
const pageSize = this.vm.dataSource.pageSize || 10;
|
|
2994
|
+
grid?.displayedRows?.set(new Array(pageSize));
|
|
2995
|
+
}
|
|
2824
2996
|
/**
|
|
2825
2997
|
* Manual-mode table gates the body on `isRefreshCalled` (set only by `grid.refresh()`).
|
|
2826
2998
|
* Card loads use shared `dataSource.refresh()`, so rows/totalCount update while the gate stays closed.
|
|
@@ -2848,35 +3020,6 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2848
3020
|
dataSource: buildDataSourceTraceSnapshot(this.vm.dataSource),
|
|
2849
3021
|
};
|
|
2850
3022
|
}
|
|
2851
|
-
/**
|
|
2852
|
-
* Waits until a `refresh()` load cycle completes (loading started, then finished with data).
|
|
2853
|
-
*/
|
|
2854
|
-
waitForDataSourceLoad(dataSource) {
|
|
2855
|
-
return new Promise((resolve) => {
|
|
2856
|
-
let settled = false;
|
|
2857
|
-
const finish = () => {
|
|
2858
|
-
if (settled) {
|
|
2859
|
-
return;
|
|
2860
|
-
}
|
|
2861
|
-
settled = true;
|
|
2862
|
-
clearTimeout(timeoutId);
|
|
2863
|
-
loadingSub.unsubscribe();
|
|
2864
|
-
changedSub.unsubscribe();
|
|
2865
|
-
resolve();
|
|
2866
|
-
};
|
|
2867
|
-
const changedSub = dataSource.onChanged.subscribe(() => {
|
|
2868
|
-
if (!dataSource.isLoading) {
|
|
2869
|
-
queueMicrotask(finish);
|
|
2870
|
-
}
|
|
2871
|
-
});
|
|
2872
|
-
const loadingSub = dataSource.onLoadingChanged.subscribe((isLoading) => {
|
|
2873
|
-
if (!isLoading) {
|
|
2874
|
-
queueMicrotask(finish);
|
|
2875
|
-
}
|
|
2876
|
-
});
|
|
2877
|
-
const timeoutId = setTimeout(finish, 10_000);
|
|
2878
|
-
});
|
|
2879
|
-
}
|
|
2880
3023
|
grid() {
|
|
2881
3024
|
return this.dataTable()?.grid();
|
|
2882
3025
|
}
|
|
@@ -4424,7 +4567,7 @@ class AXPEntityReuseStrategy {
|
|
|
4424
4567
|
//#endregion
|
|
4425
4568
|
//#region ---- Detach / Attach ----
|
|
4426
4569
|
shouldDetach(route) {
|
|
4427
|
-
if (!this.routeCache.isEnabled() || !this.isTabCacheRoute(route)) {
|
|
4570
|
+
if (!this.routeCache.isEnabled() || !this.routeCache.canCache() || !this.isTabCacheRoute(route)) {
|
|
4428
4571
|
return false;
|
|
4429
4572
|
}
|
|
4430
4573
|
const scopedKey = this.scopedTabKeyFor(route);
|
|
@@ -4452,7 +4595,10 @@ class AXPEntityReuseStrategy {
|
|
|
4452
4595
|
}
|
|
4453
4596
|
}
|
|
4454
4597
|
shouldAttach(route) {
|
|
4455
|
-
if (!this.routeCache.isEnabled() ||
|
|
4598
|
+
if (!this.routeCache.isEnabled() ||
|
|
4599
|
+
!this.routeCache.canCache() ||
|
|
4600
|
+
this.routeCache.isAttachSuspended() ||
|
|
4601
|
+
!this.isTabCacheRoute(route)) {
|
|
4456
4602
|
return false;
|
|
4457
4603
|
}
|
|
4458
4604
|
const key = this.routeCacheKeyFor(route);
|
|
@@ -4478,12 +4624,19 @@ class AXPEntityReuseStrategy {
|
|
|
4478
4624
|
if (reuseConfig === false) {
|
|
4479
4625
|
return false;
|
|
4480
4626
|
}
|
|
4627
|
+
// Same component route under a different scoped tab (settings user ↔ tenant) must remount.
|
|
4628
|
+
// Otherwise one page instance keeps the first scope's tab key and overwrites every scope title.
|
|
4629
|
+
if (this.routeCache.isEnabled() &&
|
|
4630
|
+
future.routeConfig &&
|
|
4631
|
+
future.routeConfig === curr.routeConfig &&
|
|
4632
|
+
axpResolveTabKeyFromSnapshot(future) !== axpResolveTabKeyFromSnapshot(curr)) {
|
|
4633
|
+
return false;
|
|
4634
|
+
}
|
|
4481
4635
|
// `reuse: true` on sibling routes under the same scoped tab (e.g. chat '' ↔ :id).
|
|
4482
4636
|
if (reuseConfig === true) {
|
|
4483
|
-
// Same route node
|
|
4484
|
-
//
|
|
4485
|
-
//
|
|
4486
|
-
// siblings get compared directly — a path-only match would wrongly keep the previous content.
|
|
4637
|
+
// Same route node inside one scoped tab (settings group changes keep `setting-page`).
|
|
4638
|
+
// Config reference equality: an empty-path child of settings and of chat can share a path
|
|
4639
|
+
// string, and a path-only match would keep the previous content.
|
|
4487
4640
|
if (future.routeConfig && future.routeConfig === curr.routeConfig) {
|
|
4488
4641
|
return true;
|
|
4489
4642
|
}
|
|
@@ -4498,6 +4651,11 @@ class AXPEntityReuseStrategy {
|
|
|
4498
4651
|
if (future.routeConfig !== curr.routeConfig) {
|
|
4499
4652
|
return false;
|
|
4500
4653
|
}
|
|
4654
|
+
// Simple mode keeps one list component and swaps navigation query params in place.
|
|
4655
|
+
// Tabular mode caches each menu, so a different `mode` or `list` must not reuse that component.
|
|
4656
|
+
if (this.routeCache.isEnabled() && this.entityListNavigationChanged(future, curr)) {
|
|
4657
|
+
return false;
|
|
4658
|
+
}
|
|
4501
4659
|
if (typeof reuseConfig === 'string') {
|
|
4502
4660
|
const paramsChanged = this.haveParamsChanged(future, curr);
|
|
4503
4661
|
const queryParamsChanged = this.haveQueryParamsChanged(future, curr);
|
|
@@ -4551,11 +4709,11 @@ class AXPEntityReuseStrategy {
|
|
|
4551
4709
|
const config = shell.routeConfig;
|
|
4552
4710
|
return !!(config?.children?.length || config?.loadChildren);
|
|
4553
4711
|
}
|
|
4554
|
-
/** Nearest ancestor route
|
|
4712
|
+
/** Nearest ancestor whose own route config declares `data.tab = true` (not inherited data). */
|
|
4555
4713
|
findScopedAncestor(route) {
|
|
4556
4714
|
for (let index = route.pathFromRoot.length - 1; index >= 0; index--) {
|
|
4557
4715
|
const snapshot = route.pathFromRoot[index];
|
|
4558
|
-
if (
|
|
4716
|
+
if (axpSnapshotDeclaresTabScope(snapshot)) {
|
|
4559
4717
|
return snapshot;
|
|
4560
4718
|
}
|
|
4561
4719
|
}
|
|
@@ -4594,12 +4752,13 @@ class AXPEntityReuseStrategy {
|
|
|
4594
4752
|
const config = route.routeConfig;
|
|
4595
4753
|
return !!(route.component || config?.component || config?.loadComponent);
|
|
4596
4754
|
}
|
|
4597
|
-
/** Cache key — scoped tab path for shells, full leaf path otherwise
|
|
4755
|
+
/** Cache key — scoped tab path for shells, full leaf path otherwise, plus entity-list `list`. */
|
|
4598
4756
|
routeCacheKeyFor(route) {
|
|
4599
4757
|
if (!this.isTabCacheRoute(route)) {
|
|
4600
4758
|
return null;
|
|
4601
4759
|
}
|
|
4602
|
-
const
|
|
4760
|
+
const basePath = this.findScopedShellRoute(route) ? axpResolveTabKeyFromSnapshot(route) : axpPathFromSnapshot(route);
|
|
4761
|
+
const path = axpEntityListNavigationTabKey(basePath, route.queryParams);
|
|
4603
4762
|
return axpIsTabEligibleUrl(path) ? path : null;
|
|
4604
4763
|
}
|
|
4605
4764
|
/** Scoped tab key — matches open tab descriptors (`data.tab = true`). */
|
|
@@ -4622,11 +4781,27 @@ class AXPEntityReuseStrategy {
|
|
|
4622
4781
|
if (!navigation?.finalUrl) {
|
|
4623
4782
|
return true;
|
|
4624
4783
|
}
|
|
4625
|
-
const
|
|
4626
|
-
const
|
|
4784
|
+
const targetUrl = router.serializeUrl(navigation.finalUrl);
|
|
4785
|
+
const errorSource = axpInTabErrorSourceUrl(targetUrl);
|
|
4786
|
+
if (errorSource) {
|
|
4787
|
+
return currentScoped !== axpResolveTabKey(router, errorSource);
|
|
4788
|
+
}
|
|
4789
|
+
const targetPath = targetUrl.split('?')[0].split('#')[0];
|
|
4790
|
+
const futureBase = axpResolveTabKeyFromRouteConfig(router.config, targetPath) ??
|
|
4627
4791
|
(targetPath.startsWith('/') ? targetPath : `/${targetPath}`);
|
|
4792
|
+
const futureScoped = axpEntityListNavigationTabKey(futureBase, targetUrl);
|
|
4628
4793
|
return currentScoped !== futureScoped;
|
|
4629
4794
|
}
|
|
4795
|
+
/** True when two activations of the entity list route belong to different menus (`mode`, `list`, …). */
|
|
4796
|
+
entityListNavigationChanged(future, curr) {
|
|
4797
|
+
const futurePath = axpPathFromSnapshot(future);
|
|
4798
|
+
const currPath = axpPathFromSnapshot(curr);
|
|
4799
|
+
if (!axpIsEntityListPath(futurePath) && !axpIsEntityListPath(currPath)) {
|
|
4800
|
+
return false;
|
|
4801
|
+
}
|
|
4802
|
+
return (axpEntityListNavigationTabKey(futurePath, future.queryParams) !==
|
|
4803
|
+
axpEntityListNavigationTabKey(currPath, curr.queryParams));
|
|
4804
|
+
}
|
|
4630
4805
|
haveParamsChanged(future, curr) {
|
|
4631
4806
|
const futureParams = future.params;
|
|
4632
4807
|
const currParams = curr.params;
|
|
@@ -4682,18 +4857,20 @@ function routesFacory() {
|
|
|
4682
4857
|
},
|
|
4683
4858
|
{
|
|
4684
4859
|
path: 'error',
|
|
4860
|
+
data: { rootLayout: true },
|
|
4861
|
+
loadComponent: () => Promise.resolve().then(function () { return rootLayout_component; }).then((c) => c.AXPRootLayoutComponent),
|
|
4685
4862
|
children: [
|
|
4686
4863
|
{
|
|
4687
4864
|
path: 'offline',
|
|
4688
|
-
loadComponent: () => import('./acorex-platform-framework-client-themes-default-error-offline.component-
|
|
4865
|
+
loadComponent: () => import('./acorex-platform-framework-client-themes-default-error-offline.component-Abf14p44.mjs').then((c) => c.AXPErrorOfflineComponent),
|
|
4689
4866
|
},
|
|
4690
4867
|
{
|
|
4691
4868
|
path: '404',
|
|
4692
|
-
loadComponent: () => import('./acorex-platform-framework-client-themes-default-error-404.component-
|
|
4869
|
+
loadComponent: () => import('./acorex-platform-framework-client-themes-default-error-404.component-BusKNAit.mjs').then((c) => c.AXPError404Component),
|
|
4693
4870
|
},
|
|
4694
4871
|
{
|
|
4695
4872
|
path: '401',
|
|
4696
|
-
loadComponent: () => import('./acorex-platform-framework-client-themes-default-error-401.component-
|
|
4873
|
+
loadComponent: () => import('./acorex-platform-framework-client-themes-default-error-401.component-DszlyIaw.mjs').then((c) => c.AXPError401Component),
|
|
4697
4874
|
},
|
|
4698
4875
|
],
|
|
4699
4876
|
},
|
|
@@ -4725,9 +4902,9 @@ class AXPDefaultThemeModule {
|
|
|
4725
4902
|
single: () => import('./acorex-platform-framework-client-themes-default-entity-master-single-view.component-2Re1-MvA.mjs').then((c) => c.AXPEntityMasterSingleViewComponent),
|
|
4726
4903
|
details: () => import('@acorex-platform/framework-client/layout/views').then((c) => c.AXPLayoutDetailsViewComponent),
|
|
4727
4904
|
///
|
|
4728
|
-
create: () => import('./acorex-platform-framework-client-themes-default-entity-master-create-view.component-
|
|
4905
|
+
create: () => import('./acorex-platform-framework-client-themes-default-entity-master-create-view.component-DPU6jTDk.mjs').then((c) => c.AXPEntityMasterCreateViewComponent),
|
|
4729
4906
|
///
|
|
4730
|
-
modify: () => import('./acorex-platform-framework-client-themes-default-entity-master-modify-view.component-
|
|
4907
|
+
modify: () => import('./acorex-platform-framework-client-themes-default-entity-master-modify-view.component-CLdQJ8e8.mjs').then((c) => c.AXPEntityMasterModifyViewComponent),
|
|
4731
4908
|
//
|
|
4732
4909
|
list: () => Promise.resolve().then(function () { return entityMasterListView_component; }).then((c) => c.AXPEntityMasterListViewComponent),
|
|
4733
4910
|
},
|
|
@@ -4762,9 +4939,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
4762
4939
|
single: () => import('./acorex-platform-framework-client-themes-default-entity-master-single-view.component-2Re1-MvA.mjs').then((c) => c.AXPEntityMasterSingleViewComponent),
|
|
4763
4940
|
details: () => import('@acorex-platform/framework-client/layout/views').then((c) => c.AXPLayoutDetailsViewComponent),
|
|
4764
4941
|
///
|
|
4765
|
-
create: () => import('./acorex-platform-framework-client-themes-default-entity-master-create-view.component-
|
|
4942
|
+
create: () => import('./acorex-platform-framework-client-themes-default-entity-master-create-view.component-DPU6jTDk.mjs').then((c) => c.AXPEntityMasterCreateViewComponent),
|
|
4766
4943
|
///
|
|
4767
|
-
modify: () => import('./acorex-platform-framework-client-themes-default-entity-master-modify-view.component-
|
|
4944
|
+
modify: () => import('./acorex-platform-framework-client-themes-default-entity-master-modify-view.component-CLdQJ8e8.mjs').then((c) => c.AXPEntityMasterModifyViewComponent),
|
|
4768
4945
|
//
|
|
4769
4946
|
list: () => Promise.resolve().then(function () { return entityMasterListView_component; }).then((c) => c.AXPEntityMasterListViewComponent),
|
|
4770
4947
|
},
|