@acorex/platform 20.9.3 → 20.9.6

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.
@@ -12,7 +12,7 @@ import { AXDecoratorModule } from '@acorex/components/decorators';
12
12
  import * as i5 from '@acorex/components/dropdown';
13
13
  import { AXDropdownModule } from '@acorex/components/dropdown';
14
14
  import { AXDropdownButtonModule } from '@acorex/components/dropdown-button';
15
- import { AXPTabNavigationService, AXPStickyDirective, AXPCommonSettings, AXPHomePageService, AXPSettingsService, AXPTabPreviewService, AXPUnsavedChangesConfirmService, AXPBrowserTitleService, axpJoinTabTitleSegments, normalizeRouterUrl, AXP_HOME_TAB_KEY, axpResolveTabKey, axpIsEntityDetailsViewRoute, axpNavigateAppPath, AXPNotFoundError, AXP_NOT_FOUND_ROUTE, AXPUnsavedChangesPopstateService, AXP_ENTITY_DELETED_WORKFLOW_EVENT_TYPE, createUnsavedChangesCanDeactivateGuard } from '@acorex/platform/common';
15
+ import { AXPTabNavigationService, AXPStickyDirective, AXPCommonSettings, AXPHomePageService, AXPSettingsService, AXPTabPreviewService, AXPUnsavedChangesConfirmService, AXPBrowserTitleService, axpJoinTabTitleSegments, normalizeRouterUrl, AXP_HOME_TAB_KEY, axpResolveTabKey, axpIsEntityListPath, axpGetEntityListReturnUrl, axpIsEntityDetailsViewRoute, AXPNotFoundError, AXP_NOT_FOUND_ROUTE, AXPUnsavedChangesPopstateService, AXP_ENTITY_DELETED_WORKFLOW_EVENT_TYPE, createUnsavedChangesCanDeactivateGuard } from '@acorex/platform/common';
16
16
  import * as i8 from '@acorex/platform/core';
17
17
  import { AXPDeviceService, AXPComponentSlotModule, AXPDebugService, OVERLAY_DETAILS_VIEW_TRACE_NS, AXPExpressionEvaluatorService, AXPContextEvalFactory, normalizeKeyboardShortcuts, AXPContextStore, AXPBroadcastEventService, AXPKeyboardShortcutRegistry, FORM_DIRTY_TRACE_NS } from '@acorex/platform/core';
18
18
  import * as i1 from '@acorex/cdk/drawer';
@@ -35,7 +35,7 @@ import { filter } from 'rxjs/operators';
35
35
  import { AXBasePageComponent } from '@acorex/components/page';
36
36
  import { getSmart, summarizeFormContextDirtyDiff, AXPKeyboardShortcutPriority } from '@acorex/platform/contracts';
37
37
  import { AXPPageStatus } from '@acorex/platform/layout/widget-core-contracts';
38
- import { AXPEntityCommandScope } from '@acorex/platform/layout/entity-contracts';
38
+ import { AXPEntityCommandScope, buildPageListTableWidgetId, isPageListWidgetName } from '@acorex/platform/layout/entity-contracts';
39
39
  import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
40
40
  import { AXBadgeModule } from '@acorex/components/badge';
41
41
  import { AXButtonGroupModule } from '@acorex/components/button-group';
@@ -882,6 +882,29 @@ async function buildEvaluatedPageContentsForRootContext(currentPage, rootContext
882
882
  return { evaluatedPageContent, evaluatedTabContentsById };
883
883
  }
884
884
  //#endregion
885
+ //#region ---- Entity list return URL (breadcrumb / back navigation) ----
886
+ /** Restores query params on the entity list breadcrumb when returning from details. */
887
+ function applyEntityListReturnUrlToBreadcrumb(item, moduleName, entityName) {
888
+ if (!moduleName || !entityName || item.command?.name !== 'navigate') {
889
+ return item;
890
+ }
891
+ const options = item.command.options;
892
+ const path = options?.path;
893
+ if (typeof path !== 'string' || !axpIsEntityListPath(path)) {
894
+ return item;
895
+ }
896
+ return {
897
+ ...item,
898
+ command: {
899
+ ...item.command,
900
+ options: {
901
+ ...options,
902
+ path: axpGetEntityListReturnUrl(moduleName, entityName, path),
903
+ },
904
+ },
905
+ };
906
+ }
907
+ //#endregion
885
908
  const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
886
909
  const state = {
887
910
  adapter: null,
@@ -942,7 +965,7 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
942
965
  const evaluatedByTab = store.evaluatedTabContentsById();
943
966
  return evaluatedByTab[tab.id] ?? [];
944
967
  }),
945
- })), withMethods((store, evaluatorService = inject(AXPExpressionEvaluatorService), contextEvalFactory = inject(AXPContextEvalFactory), router = inject(Router), route = inject(ActivatedRoute), deviceService = inject(AXPDeviceService), formatService = inject(AXFormatService), toastService = inject(AXToastService), translateService = inject(AXTranslationService), settingsService = inject(AXPSettingsService), layout = inject(AXPLayoutThemeService), adapterLoader = inject(AXP_LAYOUT_DETAILS_VIEW_ADAPTER_LOADER)) => {
968
+ })), withMethods((store, evaluatorService = inject(AXPExpressionEvaluatorService), contextEvalFactory = inject(AXPContextEvalFactory), router = inject(Router), route = inject(ActivatedRoute), deviceService = inject(AXPDeviceService), formatService = inject(AXFormatService), toastService = inject(AXToastService), translateService = inject(AXTranslationService), settingsService = inject(AXPSettingsService), layout = inject(AXPLayoutThemeService), adapterLoader = inject(AXP_LAYOUT_DETAILS_VIEW_ADAPTER_LOADER), tabNavigation = inject(AXPTabNavigationService)) => {
946
969
  const resolvePageFromId = (adapter, pageId) => {
947
970
  if (pageId) {
948
971
  return adapter.pages.find((p) => p.id === pageId) ?? null;
@@ -1212,6 +1235,15 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1212
1235
  }
1213
1236
  return formatService.format(value, 'string', store.context()) ?? '';
1214
1237
  }
1238
+ /** Resolves the list URL with query params captured before opening details. */
1239
+ const resolveListReturnPath = (fallbackPath) => {
1240
+ const moduleName = route.parent?.snapshot.paramMap.get('module');
1241
+ const entityName = route.snapshot.paramMap.get('entity');
1242
+ if (!moduleName || !entityName) {
1243
+ return fallbackPath;
1244
+ }
1245
+ return axpGetEntityListReturnUrl(moduleName, entityName, fallbackPath);
1246
+ };
1215
1247
  return {
1216
1248
  async loadAdapter(adapter) {
1217
1249
  patchState(store, { adapter });
@@ -1535,7 +1567,9 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1535
1567
  title: await resolveBreadcrumbTitleFields(currentPageLabel, pageScope, store.context()),
1536
1568
  });
1537
1569
  }
1538
- return breadcrumbs;
1570
+ const moduleName = route.parent?.snapshot.paramMap.get('module') ?? null;
1571
+ const entityName = route.snapshot.paramMap.get('entity') ?? null;
1572
+ return breadcrumbs.map((item) => applyEntityListReturnUrlToBreadcrumb(item, moduleName, entityName));
1539
1573
  },
1540
1574
  /** Aligns view-model context with the container after revert/commit (saved baseline). */
1541
1575
  applySavedState(context) {
@@ -1634,9 +1668,11 @@ const AXPLayoutDetailsViewViewModel = signalStore(withState(() => {
1634
1668
  },
1635
1669
  async goToListPage() {
1636
1670
  const exitUrl = store.adapter()?.exitUrl;
1637
- if (exitUrl) {
1638
- await axpNavigateAppPath(router, exitUrl);
1671
+ if (!exitUrl) {
1672
+ return;
1639
1673
  }
1674
+ const path = resolveListReturnPath(exitUrl);
1675
+ await tabNavigation.navigate(path);
1640
1676
  },
1641
1677
  };
1642
1678
  }));
@@ -1868,8 +1904,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1868
1904
  }]
1869
1905
  }], propDecorators: { componentKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentKey", required: true }] }], rootContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "rootContext", required: false }] }], pageConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageConfig", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], componentReady: [{ type: i0.Output, args: ["componentReady"] }] } });
1870
1906
 
1871
- /** Registered id of the data-list inside related-entity `page-list` sidebar pages. */
1872
- const PAGE_LIST_TABLE_WIDGET_ID = 'page-list_table';
1873
1907
  class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1874
1908
  constructor() {
1875
1909
  super(...arguments);
@@ -1931,13 +1965,14 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1931
1965
  }));
1932
1966
  }, ...(ngDevMode ? [{ debugName: "#sidebarTabsIndicatorEffect" }] : /* istanbul ignore next */ []));
1933
1967
  /**
1934
- * Binds list selection whenever `page-list_table` registers (including after remount).
1968
+ * Binds list selection whenever the active page-list data-list registers (including after remount).
1935
1969
  * `find()` / `waitForWidget()` can return a destroyed instance; registration always carries the live widget.
1936
1970
  */
1937
1971
  this.#pageListSelectionBindEffect = effect((onCleanup) => {
1938
1972
  const pageId = this.vm.currentPage()?.id;
1939
1973
  const isPageReady = this.vm.isPageReady();
1940
- if (!pageId || this.vm.showPages() || !isPageReady || this.getActivePageComponentKey()) {
1974
+ const tableWidgetId = this.activePageListTableWidgetId();
1975
+ if (!pageId || this.vm.showPages() || !isPageReady || this.getActivePageComponentKey() || !tableWidgetId) {
1941
1976
  return;
1942
1977
  }
1943
1978
  this.vm.currentPageContent();
@@ -1955,13 +1990,13 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
1955
1990
  this.onSelectionChangeSubscription = undefined;
1956
1991
  });
1957
1992
  const registrationSub = builder.widgetRegistered$.subscribe(({ id, widget }) => {
1958
- if (id !== PAGE_LIST_TABLE_WIDGET_ID) {
1993
+ if (id !== tableWidgetId) {
1959
1994
  return;
1960
1995
  }
1961
1996
  this.attachSelectionToListWidget(pageId, generation, widget);
1962
1997
  });
1963
1998
  onCleanup(() => registrationSub.unsubscribe());
1964
- const existing = builder.getWidget(PAGE_LIST_TABLE_WIDGET_ID);
1999
+ const existing = builder.getWidget(tableWidgetId);
1965
2000
  if (existing) {
1966
2001
  untracked(() => this.attachSelectionToListWidget(pageId, generation, existing));
1967
2002
  }
@@ -2197,7 +2232,7 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2197
2232
  /** Syncs the line indicator when the active page changes programmatically. */
2198
2233
  #sidebarTabsIndicatorEffect;
2199
2234
  /**
2200
- * Binds list selection whenever `page-list_table` registers (including after remount).
2235
+ * Binds list selection whenever the active page-list data-list registers (including after remount).
2201
2236
  * `find()` / `waitForWidget()` can return a destroyed instance; registration always carries the live widget.
2202
2237
  */
2203
2238
  #pageListSelectionBindEffect;
@@ -2326,14 +2361,25 @@ class AXPLayoutDetailsViewComponent extends AXPPageLayoutBaseComponent {
2326
2361
  this.footerPrimaryActions.set(footerPrimaryActions);
2327
2362
  this.footerSecondaryActions.set(footerSecondaryActions);
2328
2363
  }
2329
- /** Whether the active page hosts a related-entity list (`page-list` widget). */
2364
+ /** Whether the active page hosts a related-entity list (`page-list` layout widget). */
2330
2365
  pageHasEntityListWidget() {
2331
- return this.vm.currentPageContent().some((item) => {
2332
- if ('type' in item && item.type === 'component') {
2333
- return false;
2366
+ return this.findPageListWidgetNameInContent(this.vm.currentPageContent()) != null;
2367
+ }
2368
+ /** Data-list widget id for the active related-entity `page-list` page, if any. */
2369
+ activePageListTableWidgetId() {
2370
+ const widgetName = this.findPageListWidgetNameInContent(this.vm.currentPageContent());
2371
+ return widgetName ? buildPageListTableWidgetId(widgetName) : null;
2372
+ }
2373
+ findPageListWidgetNameInContent(content) {
2374
+ for (const item of content) {
2375
+ if (AXPLayoutDetailsViewComponent.isComponentPageContent(item)) {
2376
+ continue;
2334
2377
  }
2335
- return item.name === 'page-list';
2336
- });
2378
+ if (isPageListWidgetName(item.name)) {
2379
+ return item.name ?? null;
2380
+ }
2381
+ }
2382
+ return null;
2337
2383
  }
2338
2384
  /** Subscribes to the live data-list selection stream for Selected-scope header actions. */
2339
2385
  attachSelectionToListWidget(pageId, generation, widget) {