@memberjunction/ng-explorer-core 5.22.0 → 5.24.0

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.
Files changed (91) hide show
  1. package/dist/app-routing.module.d.ts.map +1 -1
  2. package/dist/app-routing.module.js +1 -3
  3. package/dist/app-routing.module.js.map +1 -1
  4. package/dist/generated/lazy-feature-config.d.ts +1 -1
  5. package/dist/generated/lazy-feature-config.d.ts.map +1 -1
  6. package/dist/generated/lazy-feature-config.js +5 -2
  7. package/dist/generated/lazy-feature-config.js.map +1 -1
  8. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +49 -49
  9. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -1
  10. package/dist/lib/oauth/oauth-callback.component.js +6 -6
  11. package/dist/lib/oauth/oauth-callback.component.js.map +1 -1
  12. package/dist/lib/oauth/oauth.module.d.ts +2 -3
  13. package/dist/lib/oauth/oauth.module.d.ts.map +1 -1
  14. package/dist/lib/oauth/oauth.module.js +0 -4
  15. package/dist/lib/oauth/oauth.module.js.map +1 -1
  16. package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts +6 -25
  17. package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts.map +1 -1
  18. package/dist/lib/resource-wrappers/chat-collections-resource.component.js +30 -124
  19. package/dist/lib/resource-wrappers/chat-collections-resource.component.js.map +1 -1
  20. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +7 -23
  21. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
  22. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +50 -142
  23. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
  24. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts +3 -19
  25. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts.map +1 -1
  26. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js +16 -98
  27. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js.map +1 -1
  28. package/dist/lib/resource-wrappers/list-detail-resource.component.d.ts +3 -1
  29. package/dist/lib/resource-wrappers/list-detail-resource.component.d.ts.map +1 -1
  30. package/dist/lib/resource-wrappers/list-detail-resource.component.js +3 -0
  31. package/dist/lib/resource-wrappers/list-detail-resource.component.js.map +1 -1
  32. package/dist/lib/resource-wrappers/notifications-resource.component.js +1 -0
  33. package/dist/lib/resource-wrappers/notifications-resource.component.js.map +1 -1
  34. package/dist/lib/resource-wrappers/view-resource.component.d.ts +13 -11
  35. package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
  36. package/dist/lib/resource-wrappers/view-resource.component.js +80 -89
  37. package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
  38. package/dist/lib/services/startup-validation.service.d.ts.map +1 -1
  39. package/dist/lib/services/startup-validation.service.js +0 -3
  40. package/dist/lib/services/startup-validation.service.js.map +1 -1
  41. package/dist/lib/shell/components/header/app-nav.component.d.ts.map +1 -1
  42. package/dist/lib/shell/components/header/app-nav.component.js +18 -3
  43. package/dist/lib/shell/components/header/app-nav.component.js.map +1 -1
  44. package/dist/lib/shell/components/tabs/component-cache-manager.d.ts +45 -16
  45. package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
  46. package/dist/lib/shell/components/tabs/component-cache-manager.js +57 -35
  47. package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
  48. package/dist/lib/shell/components/tabs/tab-container.component.d.ts +33 -0
  49. package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
  50. package/dist/lib/shell/components/tabs/tab-container.component.js +99 -17
  51. package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
  52. package/dist/lib/shell/services/settings-dialog.service.d.ts +8 -8
  53. package/dist/lib/shell/services/settings-dialog.service.d.ts.map +1 -1
  54. package/dist/lib/shell/services/settings-dialog.service.js +20 -26
  55. package/dist/lib/shell/services/settings-dialog.service.js.map +1 -1
  56. package/dist/lib/shell/shell.component.d.ts.map +1 -1
  57. package/dist/lib/shell/shell.component.js +17 -17
  58. package/dist/lib/shell/shell.component.js.map +1 -1
  59. package/dist/lib/shell/shell.module.d.ts +4 -5
  60. package/dist/lib/shell/shell.module.d.ts.map +1 -1
  61. package/dist/lib/shell/shell.module.js +4 -8
  62. package/dist/lib/shell/shell.module.js.map +1 -1
  63. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +72 -71
  64. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
  65. package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js +11 -11
  66. package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js.map +1 -1
  67. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.d.ts +36 -12
  68. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.d.ts.map +1 -1
  69. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js +78 -50
  70. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js.map +1 -1
  71. package/dist/lib/single-dashboard/single-dashboard.component.d.ts +12 -5
  72. package/dist/lib/single-dashboard/single-dashboard.component.d.ts.map +1 -1
  73. package/dist/lib/single-dashboard/single-dashboard.component.js +44 -55
  74. package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
  75. package/dist/lib/single-list-detail/single-list-detail.component.d.ts +10 -2
  76. package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
  77. package/dist/lib/single-list-detail/single-list-detail.component.js +313 -243
  78. package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
  79. package/dist/module.d.ts +51 -63
  80. package/dist/module.d.ts.map +1 -1
  81. package/dist/module.js +35 -80
  82. package/dist/module.js.map +1 -1
  83. package/dist/public-api.d.ts +0 -1
  84. package/dist/public-api.d.ts.map +1 -1
  85. package/dist/public-api.js +0 -1
  86. package/dist/public-api.js.map +1 -1
  87. package/package.json +38 -47
  88. package/dist/lib/generic/form-toolbar.d.ts +0 -8
  89. package/dist/lib/generic/form-toolbar.d.ts.map +0 -1
  90. package/dist/lib/generic/form-toolbar.js +0 -114
  91. package/dist/lib/generic/form-toolbar.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"tab-container.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/shell/components/tabs/tab-container.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tab-container.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/shell/components/tabs/tab-container.component.ts"],"names":[],"mappings":"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"}
@@ -119,6 +119,8 @@ export class TabContainerComponent {
119
119
  // This avoids the 20px height issue when GL header is hidden
120
120
  useSingleResourceMode = false;
121
121
  singleResourceComponentRef = null;
122
+ /** Cache identity of the current single-resource component for detachment */
123
+ singleResourceCacheIdentity = null;
122
124
  previousTabBarVisible = null;
123
125
  currentSingleResourceSignature = null; // Track loaded content signature to avoid unnecessary reloads
124
126
  isCreatingInitialTabs = false; // Flag to prevent syncTabsWithConfiguration during initial tab creation
@@ -166,8 +168,17 @@ export class TabContainerComponent {
166
168
  if (activeTab) {
167
169
  const signature = this.getTabContentSignature(activeTab);
168
170
  if (signature !== this.currentSingleResourceSignature) {
171
+ // DO NOT call saveCurrentComponentQueryParams() here — by the time this
172
+ // subscription fires, OpenTab has already replaced the tab config with the
173
+ // new nav item's config, so queryParams are gone. The cache entry already
174
+ // has the correct queryParams from the most recent unchanged-signature save.
169
175
  this.loadSingleResourceContent();
170
176
  }
177
+ else {
178
+ // Signature unchanged — sync queryParams to cache entry so it stays current.
179
+ // This catches incremental queryParam updates (e.g., user selects a conversation).
180
+ this.saveCurrentComponentQueryParams();
181
+ }
171
182
  }
172
183
  }
173
184
  else if (this.layoutRestorationComplete && !this.isCreatingInitialTabs) {
@@ -331,7 +342,9 @@ export class TabContainerComponent {
331
342
  const shouldUseSingleResourceMode = !tabBarVisible;
332
343
  if (shouldUseSingleResourceMode !== this.useSingleResourceMode) {
333
344
  this.useSingleResourceMode = shouldUseSingleResourceMode;
334
- this.cdr.detectChanges();
345
+ // Defer detectChanges to next microtask to avoid ExpressionChangedAfterItHasBeenCheckedError
346
+ // when this handler fires during an already-running change detection cycle.
347
+ Promise.resolve().then(() => this.cdr.detectChanges());
335
348
  if (this.useSingleResourceMode) {
336
349
  // Transitioning to single-resource mode
337
350
  // **CRITICAL FIX**: Wait for the template to render directContentContainer
@@ -412,7 +425,6 @@ export class TabContainerComponent {
412
425
  // Get the container element
413
426
  const container = this.directContentContainer?.nativeElement;
414
427
  if (!container) {
415
- console.warn('Direct content container not available yet, retrying...');
416
428
  // Retry after view is updated
417
429
  setTimeout(() => this.loadSingleResourceContent(), 50);
418
430
  return;
@@ -430,13 +442,26 @@ export class TabContainerComponent {
430
442
  if (cached) {
431
443
  // Clean up previous single-resource component (if different)
432
444
  this.cleanupSingleResourceComponent();
433
- // Detach from tab tracking (it was attached to a tab in Golden Layout)
434
- this.cacheManager.markAsDetached(activeTab.id);
445
+ // Mark cached component as attached to this tab (it was detached / available for reuse).
446
+ // IMPORTANT: We use markAsAttached here, NOT markAsDetached — the component is being
447
+ // reattached to the DOM and should NOT be eligible for LRU eviction.
448
+ this.cacheManager.markAsAttached(driverClass, resourceData.ResourceRecordID || '', activeTab.applicationId, activeTab.id);
435
449
  // Reattach the cached wrapper element to single-resource container
436
450
  cached.wrapperElement.style.height = "100%"; // Ensure full height
437
451
  container.appendChild(cached.wrapperElement);
438
- // Store reference for cleanup
452
+ // Store reference and identity for cleanup/detachment
439
453
  this.singleResourceComponentRef = cached.componentRef;
454
+ this.singleResourceCacheIdentity = { driverClass, recordId: resourceData.ResourceRecordID || '', appId: activeTab.applicationId, tabId: activeTab.id };
455
+ // Restore saved queryParams to the tab config so the URL reflects
456
+ // the component's preserved state (e.g., selected conversation, collection drill-down).
457
+ if (cached.savedQueryParams) {
458
+ this.workspaceManager.UpdateTabConfiguration(activeTab.id, {
459
+ queryParams: cached.savedQueryParams
460
+ });
461
+ // Do NOT clear savedQueryParams here — the else branch (unchanged-signature saves)
462
+ // will keep it current while the component is active. Clearing it would cause the
463
+ // queryParams to be lost on the next detach/reattach cycle.
464
+ }
440
465
  return;
441
466
  }
442
467
  // Get the component registration (with lazy loading fallback via ClassFactory)
@@ -460,13 +485,16 @@ export class TabContainerComponent {
460
485
  instance.LoadCompleteEvent = () => {
461
486
  this.emitFirstLoadCompleteOnce();
462
487
  };
463
- // Wire up display name change for single-resource mode
464
- // Use a closure that resolves the tab ID at call time, not at wire-up time,
465
- // because the tab may not be active yet when the component is first created.
488
+ // Wire up display name change for single-resource mode.
489
+ // Guard: only update the title if THIS component is the currently displayed one.
490
+ // Without this guard, cached components (detached but alive) can fire this callback
491
+ // and overwrite the active tab's title with a stale name.
466
492
  instance.DisplayNameChangedEvent = (newName) => {
467
- const tabId = this.workspaceManager.GetActiveTabId();
468
- if (tabId) {
469
- this.workspaceManager.UpdateTabTitle(tabId, newName);
493
+ if (this.singleResourceComponentRef?.instance === instance) {
494
+ const tabId = this.workspaceManager.GetActiveTabId();
495
+ if (tabId) {
496
+ this.workspaceManager.UpdateTabTitle(tabId, newName);
497
+ }
470
498
  }
471
499
  };
472
500
  // Get the native element and append to container
@@ -476,22 +504,76 @@ export class TabContainerComponent {
476
504
  if (container.children?.length > 0) {
477
505
  container.children[0].style.height = "100%";
478
506
  }
479
- // Store reference for cleanup
507
+ // Cache the component for reuse when switching between nav items within the same app.
508
+ // Without this, every nav switch creates a brand new component from scratch.
509
+ const wrapperElement = nativeElement;
510
+ this.cacheManager.cacheComponent(componentRef, wrapperElement, resourceData, activeTab.id);
511
+ // Store reference and identity for cleanup/detachment
480
512
  this.singleResourceComponentRef = componentRef;
513
+ this.singleResourceCacheIdentity = { driverClass, recordId: resourceData.ResourceRecordID || '', appId: activeTab.applicationId, tabId: activeTab.id };
481
514
  }
482
515
  /**
483
516
  * Clean up single-resource mode component
484
517
  */
518
+ /**
519
+ * Detaches the current single-resource component from the DOM and marks it as
520
+ * available for reuse in the component cache.
521
+ *
522
+ * ╔══════════════════════════════════════════════════════════════════════════╗
523
+ * ║ ⚠️ DO NOT DESTROY THE COMPONENT HERE — INTENTIONAL DESIGN CHOICE ⚠️ ║
524
+ * ║ ║
525
+ * ║ The component is DETACHED from the DOM, NOT destroyed. It stays alive ║
526
+ * ║ in the ComponentCacheManager with its full Angular state preserved ║
527
+ * ║ (properties, subscriptions, loaded data, scroll position, etc). ║
528
+ * ║ ║
529
+ * ║ When the user returns to this tab, the cached component is reattached ║
530
+ * ║ instantly — no data reload, no API calls, no flash of empty content. ║
531
+ * ║ ║
532
+ * ║ Destroying components here "for memory optimization" is a net ║
533
+ * ║ NEGATIVE: the reload on return is far more expensive (DB queries, ║
534
+ * ║ API calls, re-rendering) than keeping the component in memory. ║
535
+ * ║ The LRU eviction in ComponentCacheManager handles memory limits — ║
536
+ * ║ when MaxDetachedComponents is exceeded, the LEAST recently used ║
537
+ * ║ components are evicted automatically. ║
538
+ * ║ ║
539
+ * ║ If you think memory is a problem, adjust MaxDetachedComponents ║
540
+ * ║ instead of destroying components here. ║
541
+ * ╚══════════════════════════════════════════════════════════════════════════╝
542
+ */
543
+ /**
544
+ * Save the currently displayed component's queryParams to its cache entry.
545
+ * Called on every config change so the cache entry always has the latest queryParams,
546
+ * even after the tab config is overwritten by a new nav item.
547
+ */
548
+ saveCurrentComponentQueryParams() {
549
+ if (!this.singleResourceCacheIdentity)
550
+ return;
551
+ const { tabId } = this.singleResourceCacheIdentity;
552
+ const tab = this.workspaceManager.GetTab(tabId);
553
+ const qp = tab?.configuration?.['queryParams'];
554
+ const cached = this.cacheManager.getComponentByTabId(tabId);
555
+ if (cached) {
556
+ cached.savedQueryParams = (qp && Object.keys(qp).length > 0) ? { ...qp } : undefined;
557
+ }
558
+ }
485
559
  cleanupSingleResourceComponent() {
486
560
  if (this.singleResourceComponentRef) {
487
- this.appRef.detachView(this.singleResourceComponentRef.hostView);
488
- this.singleResourceComponentRef.destroy();
561
+ if (this.singleResourceCacheIdentity) {
562
+ const { driverClass, recordId, appId } = this.singleResourceCacheIdentity;
563
+ // Mark as DETACHED by resource identity — the ONE consistent key used everywhere.
564
+ this.cacheManager.markAsDetached(driverClass, recordId, appId);
565
+ }
489
566
  this.singleResourceComponentRef = null;
567
+ this.singleResourceCacheIdentity = null;
490
568
  }
491
- // Clear the container
569
+ // Remove children from the container. This detaches the wrapper DOM element
570
+ // without destroying the Angular component — it lives on in the cache.
571
+ // Using removeChild (not innerHTML='') to avoid aggressive DOM cleanup.
492
572
  const container = this.directContentContainer?.nativeElement;
493
573
  if (container) {
494
- container.innerHTML = '';
574
+ while (container.firstChild) {
575
+ container.removeChild(container.firstChild);
576
+ }
495
577
  }
496
578
  }
497
579
  /**
@@ -842,7 +924,7 @@ export class TabContainerComponent {
842
924
  */
843
925
  cleanupTabComponent(tabId) {
844
926
  // First, try to detach from cache (preserves component for reuse)
845
- const cachedInfo = this.cacheManager.markAsDetached(tabId);
927
+ const cachedInfo = this.cacheManager.findAndDetachByTabId(tabId);
846
928
  if (cachedInfo) {
847
929
  // Remove from legacy componentRefs but keep in cache
848
930
  this.componentRefs.delete(tabId);