@acorex-platform/framework-client 2.0.0-next.23 → 2.0.0-next.25
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-layout-entity-acorex-platform-framework-client-layout-entity-DFOMh7gJ.mjs → acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-Bte8Trz3.mjs} +275 -35
- package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-Bte8Trz3.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-_o_CUDxU.mjs → acorex-platform-framework-client-layout-entity-attachments-page.component-bCZHSHRa.mjs} +2 -2
- package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-_o_CUDxU.mjs.map → acorex-platform-framework-client-layout-entity-attachments-page.component-bCZHSHRa.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-entity-bulk-entity.command-DN1eNwqP.mjs → acorex-platform-framework-client-layout-entity-bulk-entity.command-BRN0AcG-.mjs} +2 -2
- package/fesm2022/{acorex-platform-framework-client-layout-entity-bulk-entity.command-DN1eNwqP.mjs.map → acorex-platform-framework-client-layout-entity-bulk-entity.command-BRN0AcG-.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-Dyn_JDo9.mjs → acorex-platform-framework-client-layout-entity-file-list-popup.component-BXAl2p0t.mjs} +2 -2
- package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-Dyn_JDo9.mjs.map → acorex-platform-framework-client-layout-entity-file-list-popup.component-BXAl2p0t.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-Z6B4WJXJ.mjs → acorex-platform-framework-client-layout-entity-gallery-page.component-Cc2kuwvV.mjs} +2 -2
- package/fesm2022/{acorex-platform-framework-client-layout-entity-gallery-page.component-Z6B4WJXJ.mjs.map → acorex-platform-framework-client-layout-entity-gallery-page.component-Cc2kuwvV.mjs.map} +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-entity.mjs +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-CELbt6ig.mjs → acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-DRh91YCL.mjs} +26 -5
- package/fesm2022/acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-DRh91YCL.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-BSjcMKNA.mjs → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-Ddx_b04d.mjs} +2 -2
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-BSjcMKNA.mjs.map → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-Ddx_b04d.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-Co5_b33I.mjs → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-DqIuIn76.mjs} +2 -2
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-Co5_b33I.mjs.map → acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-DqIuIn76.mjs.map} +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs +1 -1
- package/fesm2022/acorex-platform-framework-client-themes-default.mjs +168 -81
- package/fesm2022/acorex-platform-framework-client-themes-default.mjs.map +1 -1
- package/package.json +2 -2
- package/types/acorex-platform-framework-client-layout-entity.d.ts +61 -2
- package/types/acorex-platform-framework-client-layout-widgets.d.ts +2 -0
- package/types/acorex-platform-framework-client-themes-default.d.ts +4 -5
- package/fesm2022/acorex-platform-framework-client-layout-entity-acorex-platform-framework-client-layout-entity-DFOMh7gJ.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-layout-widgets-acorex-platform-framework-client-layout-widgets-CELbt6ig.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';
|
|
@@ -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
|
}
|
|
@@ -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(),
|
|
@@ -2469,6 +2526,12 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2469
2526
|
this.syncListViewQueryParam(currentViewName);
|
|
2470
2527
|
}
|
|
2471
2528
|
});
|
|
2529
|
+
effect(() => {
|
|
2530
|
+
if (!this.vm.listTransitionLoading()) {
|
|
2531
|
+
return;
|
|
2532
|
+
}
|
|
2533
|
+
this.showTableLoadingPlaceholders();
|
|
2534
|
+
});
|
|
2472
2535
|
effect(() => {
|
|
2473
2536
|
const currentViewName = this.vm.view().name;
|
|
2474
2537
|
if (!this.listHostReady()) {
|
|
@@ -2811,6 +2874,7 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2811
2874
|
});
|
|
2812
2875
|
}
|
|
2813
2876
|
async applyVisibleListRefresh(resetPagination, refreshTargetId, highlightRowId) {
|
|
2877
|
+
const epoch = this.vm.viewSwitchEpoch();
|
|
2814
2878
|
traceEntityMasterList('list-view', 'refresh event received', () => ({
|
|
2815
2879
|
viewName: this.vm.view().name,
|
|
2816
2880
|
activeListLayout: this.vm.activeListLayout(),
|
|
@@ -2835,12 +2899,16 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2835
2899
|
else {
|
|
2836
2900
|
await this.reloadListData(resetPagination);
|
|
2837
2901
|
}
|
|
2902
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2903
|
+
return;
|
|
2904
|
+
}
|
|
2838
2905
|
if (typeof highlightRowId === 'string' || typeof highlightRowId === 'number') {
|
|
2839
2906
|
await this.highlightRowById(highlightRowId);
|
|
2840
2907
|
}
|
|
2841
2908
|
traceEntityMasterList('list-view', 'refresh event handled', () => this.buildListHostTraceSnapshot());
|
|
2842
2909
|
}
|
|
2843
2910
|
async reloadListData(resetPagination = false) {
|
|
2911
|
+
const epoch = this.vm.viewSwitchEpoch();
|
|
2844
2912
|
traceEntityMasterList('list-view', 'reloadListData start', () => ({
|
|
2845
2913
|
resetPagination,
|
|
2846
2914
|
activeListLayout: this.vm.activeListLayout(),
|
|
@@ -2849,12 +2917,22 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2849
2917
|
hasCardList: !!this.cardList(),
|
|
2850
2918
|
dataSource: buildDataSourceTraceSnapshot(this.vm.dataSource),
|
|
2851
2919
|
}));
|
|
2920
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2921
|
+
return;
|
|
2922
|
+
}
|
|
2852
2923
|
if (!resetPagination && !this.vm.isCardHostLayout()) {
|
|
2853
2924
|
await this.vm.ensureListPagingResolved();
|
|
2925
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2926
|
+
return;
|
|
2927
|
+
}
|
|
2854
2928
|
this.vm.applyPagingToDataSourceWithoutLoad();
|
|
2855
2929
|
}
|
|
2930
|
+
if (!this.vm.isViewSwitchCurrent(epoch)) {
|
|
2931
|
+
return;
|
|
2932
|
+
}
|
|
2856
2933
|
if (this.vm.isCardHostLayout()) {
|
|
2857
2934
|
await this.cardList()?.reload(true);
|
|
2935
|
+
this.vm.finishListTransition(epoch);
|
|
2858
2936
|
// Shared DS load updates table rows via onChanged but not isRefreshCalled; prepare for a later table switch.
|
|
2859
2937
|
this.acknowledgeManualTableReady();
|
|
2860
2938
|
traceEntityMasterList('list-view', 'reloadListData complete (card)', () => this.buildListHostTraceSnapshot());
|
|
@@ -2862,21 +2940,59 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2862
2940
|
}
|
|
2863
2941
|
const grid = this.grid();
|
|
2864
2942
|
if (grid) {
|
|
2865
|
-
|
|
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));
|
|
2866
2950
|
grid.refresh({ reset: resetPagination });
|
|
2867
|
-
|
|
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);
|
|
2868
2965
|
if (!resetPagination) {
|
|
2869
2966
|
this.scheduleSyncGridPagerUi();
|
|
2870
2967
|
}
|
|
2871
2968
|
this.scheduleRestoreExpandedRows();
|
|
2872
2969
|
}
|
|
2873
2970
|
else {
|
|
2874
|
-
const
|
|
2971
|
+
const watch = watchNextDataSourceLoad(this.vm.dataSource, () => this.vm.isViewSwitchCurrent(epoch));
|
|
2875
2972
|
this.vm.dataSource.refresh({ reset: resetPagination });
|
|
2876
|
-
|
|
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);
|
|
2877
2987
|
}
|
|
2878
2988
|
traceEntityMasterList('list-view', 'reloadListData complete (table)', () => this.buildListHostTraceSnapshot());
|
|
2879
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
|
+
}
|
|
2880
2996
|
/**
|
|
2881
2997
|
* Manual-mode table gates the body on `isRefreshCalled` (set only by `grid.refresh()`).
|
|
2882
2998
|
* Card loads use shared `dataSource.refresh()`, so rows/totalCount update while the gate stays closed.
|
|
@@ -2904,35 +3020,6 @@ class AXPEntityMasterListViewComponent extends AXPPageLayoutBaseComponent {
|
|
|
2904
3020
|
dataSource: buildDataSourceTraceSnapshot(this.vm.dataSource),
|
|
2905
3021
|
};
|
|
2906
3022
|
}
|
|
2907
|
-
/**
|
|
2908
|
-
* Waits until a `refresh()` load cycle completes (loading started, then finished with data).
|
|
2909
|
-
*/
|
|
2910
|
-
waitForDataSourceLoad(dataSource) {
|
|
2911
|
-
return new Promise((resolve) => {
|
|
2912
|
-
let settled = false;
|
|
2913
|
-
const finish = () => {
|
|
2914
|
-
if (settled) {
|
|
2915
|
-
return;
|
|
2916
|
-
}
|
|
2917
|
-
settled = true;
|
|
2918
|
-
clearTimeout(timeoutId);
|
|
2919
|
-
loadingSub.unsubscribe();
|
|
2920
|
-
changedSub.unsubscribe();
|
|
2921
|
-
resolve();
|
|
2922
|
-
};
|
|
2923
|
-
const changedSub = dataSource.onChanged.subscribe(() => {
|
|
2924
|
-
if (!dataSource.isLoading) {
|
|
2925
|
-
queueMicrotask(finish);
|
|
2926
|
-
}
|
|
2927
|
-
});
|
|
2928
|
-
const loadingSub = dataSource.onLoadingChanged.subscribe((isLoading) => {
|
|
2929
|
-
if (!isLoading) {
|
|
2930
|
-
queueMicrotask(finish);
|
|
2931
|
-
}
|
|
2932
|
-
});
|
|
2933
|
-
const timeoutId = setTimeout(finish, 10_000);
|
|
2934
|
-
});
|
|
2935
|
-
}
|
|
2936
3023
|
grid() {
|
|
2937
3024
|
return this.dataTable()?.grid();
|
|
2938
3025
|
}
|