@memberjunction/ng-dashboards 5.32.0 → 5.34.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 (95) hide show
  1. package/dist/AI/components/agents/agent-editor.component.js +2 -2
  2. package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
  3. package/dist/Admin/admin-data-schema.component.d.ts +16 -0
  4. package/dist/Admin/admin-data-schema.component.d.ts.map +1 -0
  5. package/dist/Admin/admin-data-schema.component.js +136 -0
  6. package/dist/Admin/admin-data-schema.component.js.map +1 -0
  7. package/dist/Admin/admin-dev-tools-resource.component.d.ts +14 -0
  8. package/dist/Admin/admin-dev-tools-resource.component.d.ts.map +1 -0
  9. package/dist/Admin/admin-dev-tools-resource.component.js +162 -0
  10. package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -0
  11. package/dist/Admin/admin-identity-access.component.d.ts +15 -0
  12. package/dist/Admin/admin-identity-access.component.d.ts.map +1 -0
  13. package/dist/Admin/admin-identity-access.component.js +156 -0
  14. package/dist/Admin/admin-identity-access.component.js.map +1 -0
  15. package/dist/Admin/admin-monitoring.component.d.ts +15 -0
  16. package/dist/Admin/admin-monitoring.component.d.ts.map +1 -0
  17. package/dist/Admin/admin-monitoring.component.js +130 -0
  18. package/dist/Admin/admin-monitoring.component.js.map +1 -0
  19. package/dist/Admin/base-admin-container.component.d.ts +80 -0
  20. package/dist/Admin/base-admin-container.component.d.ts.map +1 -0
  21. package/dist/Admin/base-admin-container.component.js +198 -0
  22. package/dist/Admin/base-admin-container.component.js.map +1 -0
  23. package/dist/Admin/index.d.ts +6 -0
  24. package/dist/Admin/index.d.ts.map +1 -0
  25. package/dist/Admin/index.js +6 -0
  26. package/dist/Admin/index.js.map +1 -0
  27. package/dist/ComponentStudio/components/workspace/component-preview.component.js +1 -1
  28. package/dist/ComponentStudio/components/workspace/component-preview.component.js.map +1 -1
  29. package/dist/ComponentStudio/services/component-studio-state.service.d.ts +28 -8
  30. package/dist/ComponentStudio/services/component-studio-state.service.d.ts.map +1 -1
  31. package/dist/ComponentStudio/services/component-studio-state.service.js +45 -27
  32. package/dist/ComponentStudio/services/component-studio-state.service.js.map +1 -1
  33. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts +18 -3
  34. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts.map +1 -1
  35. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +51 -11
  36. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js.map +1 -1
  37. package/dist/DataExplorer/data-explorer-dashboard.component.js +2 -2
  38. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  39. package/dist/DevTools/app-state-inspector.component.d.ts +53 -0
  40. package/dist/DevTools/app-state-inspector.component.d.ts.map +1 -0
  41. package/dist/DevTools/app-state-inspector.component.js +301 -0
  42. package/dist/DevTools/app-state-inspector.component.js.map +1 -0
  43. package/dist/DevTools/class-registry.component.d.ts +64 -0
  44. package/dist/DevTools/class-registry.component.d.ts.map +1 -0
  45. package/dist/DevTools/class-registry.component.js +423 -0
  46. package/dist/DevTools/class-registry.component.js.map +1 -0
  47. package/dist/DevTools/dev-tools-prefs.d.ts +21 -0
  48. package/dist/DevTools/dev-tools-prefs.d.ts.map +1 -0
  49. package/dist/DevTools/dev-tools-prefs.js +48 -0
  50. package/dist/DevTools/dev-tools-prefs.js.map +1 -0
  51. package/dist/DevTools/event-monitor.component.d.ts +78 -0
  52. package/dist/DevTools/event-monitor.component.d.ts.map +1 -0
  53. package/dist/DevTools/event-monitor.component.js +659 -0
  54. package/dist/DevTools/event-monitor.component.js.map +1 -0
  55. package/dist/DevTools/graphql-console.component.d.ts +153 -0
  56. package/dist/DevTools/graphql-console.component.d.ts.map +1 -0
  57. package/dist/DevTools/graphql-console.component.js +1463 -0
  58. package/dist/DevTools/graphql-console.component.js.map +1 -0
  59. package/dist/DevTools/index.d.ts +8 -0
  60. package/dist/DevTools/index.d.ts.map +1 -0
  61. package/dist/DevTools/index.js +8 -0
  62. package/dist/DevTools/index.js.map +1 -0
  63. package/dist/DevTools/layout-inspector.component.d.ts +42 -0
  64. package/dist/DevTools/layout-inspector.component.d.ts.map +1 -0
  65. package/dist/DevTools/layout-inspector.component.js +208 -0
  66. package/dist/DevTools/layout-inspector.component.js.map +1 -0
  67. package/dist/DevTools/lazy-module-status.component.d.ts +65 -0
  68. package/dist/DevTools/lazy-module-status.component.d.ts.map +1 -0
  69. package/dist/DevTools/lazy-module-status.component.js +388 -0
  70. package/dist/DevTools/lazy-module-status.component.js.map +1 -0
  71. package/dist/DevTools/settings-explorer.component.d.ts +55 -0
  72. package/dist/DevTools/settings-explorer.component.d.ts.map +1 -0
  73. package/dist/DevTools/settings-explorer.component.js +394 -0
  74. package/dist/DevTools/settings-explorer.component.js.map +1 -0
  75. package/dist/Integration/components/widgets/integration-card.component.js +2 -2
  76. package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
  77. package/dist/Integration/components/widgets/run-history-panel.component.js +2 -2
  78. package/dist/Integration/components/widgets/run-history-panel.component.js.map +1 -1
  79. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +134 -1
  80. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -1
  81. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +1227 -24
  82. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  83. package/dist/SystemDiagnostics/system-diagnostics.component.js +4 -4
  84. package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
  85. package/dist/Testing/components/testing-runs.component.js +3 -3
  86. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  87. package/dist/core-dashboards.module.d.ts +45 -34
  88. package/dist/core-dashboards.module.d.ts.map +1 -1
  89. package/dist/core-dashboards.module.js +57 -0
  90. package/dist/core-dashboards.module.js.map +1 -1
  91. package/dist/public-api.d.ts +2 -0
  92. package/dist/public-api.d.ts.map +1 -1
  93. package/dist/public-api.js +2 -0
  94. package/dist/public-api.js.map +1 -1
  95. package/package.json +52 -52
@@ -6,8 +6,8 @@ import * as i0 from "@angular/core";
6
6
  import * as i1 from "@angular/forms";
7
7
  import * as i2 from "@memberjunction/ng-trees";
8
8
  const _c0 = ["entityTree"];
9
- const _forTrack0 = ($index, $item) => $item.displayName;
10
- const _forTrack1 = ($index, $item) => $item.compositeKeyString;
9
+ const _forTrack0 = ($index, $item) => $item.entityName;
10
+ const _forTrack1 = ($index, $item) => $item.entityName + "|" + $item.compositeKeyString;
11
11
  function NavigationPanelComponent_Conditional_3_Conditional_6_Template(rf, ctx) { if (rf & 1) {
12
12
  i0.ɵɵelementStart(0, "span", 10);
13
13
  i0.ɵɵtext(1);
@@ -59,7 +59,7 @@ function NavigationPanelComponent_Conditional_3_Conditional_8_Conditional_2_For_
59
59
  function NavigationPanelComponent_Conditional_3_Conditional_8_Conditional_2_Template(rf, ctx) { if (rf & 1) {
60
60
  i0.ɵɵelementStart(0, "div", 19)(1, "div", 20);
61
61
  i0.ɵɵrepeaterCreate(2, NavigationPanelComponent_Conditional_3_Conditional_8_Conditional_2_For_3_Template, 4, 4, "div", 21, _forTrack0);
62
- i0.ɵɵrepeaterCreate(4, NavigationPanelComponent_Conditional_3_Conditional_8_Conditional_2_For_5_Template, 4, 4, "div", 21, _forTrack0);
62
+ i0.ɵɵrepeaterCreate(4, NavigationPanelComponent_Conditional_3_Conditional_8_Conditional_2_For_5_Template, 4, 4, "div", 21, _forTrack1);
63
63
  i0.ɵɵelementEnd()();
64
64
  } if (rf & 2) {
65
65
  const ctx_r1 = i0.ɵɵnextContext(3);
@@ -264,6 +264,11 @@ function NavigationPanelComponent_Conditional_4_Template(rf, ctx) { if (rf & 1)
264
264
  i0.ɵɵtextInterpolate(ctx_r1.entities.length);
265
265
  } }
266
266
  export class NavigationPanelComponent extends BaseAngularComponent {
267
+ cdr;
268
+ constructor(cdr) {
269
+ super();
270
+ this.cdr = cdr;
271
+ }
267
272
  entities = [];
268
273
  selectedEntityName = null;
269
274
  favorites = [];
@@ -327,6 +332,23 @@ export class NavigationPanelComponent extends BaseAngularComponent {
327
332
  if (changes['applicationIdFilter']) {
328
333
  this.updateTreeBranchFilter();
329
334
  }
335
+ if (changes['recentItems']) {
336
+ this.timestampLabelCache.clear();
337
+ }
338
+ }
339
+ ngOnInit() {
340
+ this.timestampRefreshHandle = setInterval(() => {
341
+ if (this.timestampLabelCache.size === 0)
342
+ return;
343
+ this.timestampLabelCache.clear();
344
+ this.cdr.markForCheck();
345
+ }, 30000);
346
+ }
347
+ ngOnDestroy() {
348
+ if (this.timestampRefreshHandle !== undefined) {
349
+ clearInterval(this.timestampRefreshHandle);
350
+ this.timestampRefreshHandle = undefined;
351
+ }
330
352
  }
331
353
  /**
332
354
  * Update the selected entity IDs for tree highlighting when selected entity changes
@@ -511,12 +533,30 @@ export class NavigationPanelComponent extends BaseAngularComponent {
511
533
  return `fa-solid fa-${icon}`;
512
534
  }
513
535
  /**
514
- * Format recent item timestamp
536
+ * Cache of formatted relative-time labels keyed by timestamp epoch ms.
537
+ * Stable within a change-detection cycle (avoids NG0100 from `now`-dependent
538
+ * values shifting between dirty-check and verify passes). Cleared on a coarse
539
+ * interval so the displayed label still updates over time.
540
+ */
541
+ timestampLabelCache = new Map();
542
+ timestampRefreshHandle;
543
+ /**
544
+ * Format recent item timestamp. Cached per-timestamp so the same value is
545
+ * returned across change-detection passes within a single tick — recomputed
546
+ * on a 30-second interval (see `ngOnInit`).
515
547
  */
516
548
  formatTimestamp(timestamp) {
517
- const date = new Date(timestamp);
518
- const now = new Date();
519
- const diffMs = now.getTime() - date.getTime();
549
+ const epoch = new Date(timestamp).getTime();
550
+ const cached = this.timestampLabelCache.get(epoch);
551
+ if (cached !== undefined) {
552
+ return cached;
553
+ }
554
+ const label = this.computeRelativeLabel(epoch);
555
+ this.timestampLabelCache.set(epoch, label);
556
+ return label;
557
+ }
558
+ computeRelativeLabel(epoch) {
559
+ const diffMs = Date.now() - epoch;
520
560
  const diffMins = Math.floor(diffMs / 60000);
521
561
  if (diffMins < 1)
522
562
  return 'Just now';
@@ -528,7 +568,7 @@ export class NavigationPanelComponent extends BaseAngularComponent {
528
568
  const diffDays = Math.floor(diffHours / 24);
529
569
  if (diffDays < 7)
530
570
  return `${diffDays}d ago`;
531
- return date.toLocaleDateString();
571
+ return new Date(epoch).toLocaleDateString();
532
572
  }
533
573
  /**
534
574
  * Get icon for a recent item based on its entity
@@ -560,7 +600,7 @@ export class NavigationPanelComponent extends BaseAngularComponent {
560
600
  }
561
601
  return 'fa-solid fa-file-alt';
562
602
  }
563
- static ɵfac = /*@__PURE__*/ (() => { let ɵNavigationPanelComponent_BaseFactory; return function NavigationPanelComponent_Factory(__ngFactoryType__) { return (ɵNavigationPanelComponent_BaseFactory || (ɵNavigationPanelComponent_BaseFactory = i0.ɵɵgetInheritedFactory(NavigationPanelComponent)))(__ngFactoryType__ || NavigationPanelComponent); }; })();
603
+ static ɵfac = function NavigationPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || NavigationPanelComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
564
604
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: NavigationPanelComponent, selectors: [["mj-explorer-navigation-panel"]], viewQuery: function NavigationPanelComponent_Query(rf, ctx) { if (rf & 1) {
565
605
  i0.ɵɵviewQuery(_c0, 5);
566
606
  } if (rf & 2) {
@@ -585,8 +625,8 @@ export class NavigationPanelComponent extends BaseAngularComponent {
585
625
  }
586
626
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(NavigationPanelComponent, [{
587
627
  type: Component,
588
- args: [{ standalone: false, selector: 'mj-explorer-navigation-panel', template: "<div class=\"navigation-panel-container\" [class.collapsed]=\"collapsed\">\n <!-- Collapse Toggle -->\n <button class=\"collapse-toggle\" (click)=\"onToggleCollapse()\" [title]=\"collapsed ? 'Expand' : 'Collapse'\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"collapsed\" [class.fa-chevron-left]=\"!collapsed\"></i>\n </button>\n\n @if (!collapsed) {\n <div class=\"panel-content\">\n <!-- Favorites Section -->\n <div class=\"section favorites-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('favorites')\">\n <i class=\"fa-solid fa-star section-icon\"></i>\n <span class=\"section-title\">Favorites</span>\n @if (favoriteRecords.length + favoriteEntities.length > 0) {\n <span class=\"section-count\">({{ favoriteRecords.length + favoriteEntities.length }})</span>\n }\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"favoritesSectionExpanded\" [class.fa-chevron-right]=\"!favoritesSectionExpanded\"></i>\n </div>\n\n @if (favoritesSectionExpanded) {\n <div class=\"section-content scrollable-section\">\n @if (favoriteRecords.length + favoriteEntities.length === 0) {\n <div class=\"empty-section\">\n <span>No favorites yet</span>\n </div>\n } @else {\n <div class=\"scrollable-list\">\n <div class=\"scrollable-list-inner\">\n @for (favorite of favoriteEntities; track favorite.displayName) {\n <div class=\"nav-item\" (click)=\"onFavoriteClick(favorite)\" [title]=\"favorite.entityName ? favorite.entityName + ' - ' + favorite.displayName : favorite.displayName\">\n <i [class]=\"getFavoriteIcon(favorite)\"></i>\n <span class=\"nav-item-label\">{{ favorite.displayName }}</span>\n </div>\n }\n @for (favorite of favoriteRecords; track favorite.displayName) {\n <div class=\"nav-item\" (click)=\"onFavoriteClick(favorite)\" [title]=\"favorite.entityName ? favorite.entityName + ' - ' + favorite.displayName : favorite.displayName\">\n <i [class]=\"getFavoriteIcon(favorite)\"></i>\n <span class=\"nav-item-label\">{{ favorite.displayName }}</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Recent Items Section -->\n <div class=\"section recent-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('recent')\">\n <i class=\"fa-solid fa-clock section-icon\"></i>\n <span class=\"section-title\">Recent</span>\n @if (filteredRecentItems.length > 0) {\n <span class=\"section-count\">({{ filteredRecentItems.length }})</span>\n }\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"recentSectionExpanded\" [class.fa-chevron-right]=\"!recentSectionExpanded\"></i>\n </div>\n\n @if (recentSectionExpanded) {\n <div class=\"section-content scrollable-section\">\n @if (filteredRecentItems.length === 0) {\n <div class=\"empty-section\">\n <span>No recent items</span>\n </div>\n } @else {\n <div class=\"scrollable-list\">\n <div class=\"scrollable-list-inner\">\n @for (item of filteredRecentItems; track item.compositeKeyString) {\n <div class=\"nav-item\" (click)=\"onRecentClick(item)\" [title]=\"item.entityName + ' - ' + item.displayName\">\n <i [class]=\"getRecentItemIcon(item)\"></i>\n <div class=\"nav-item-content\">\n <span class=\"nav-item-label\">{{ item.displayName }}</span>\n <span class=\"nav-item-meta\">{{ formatTimestamp(item.timestamp) }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Entities Section (ng-tree) -->\n <div class=\"section entities-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('entities')\">\n <i class=\"fa-solid fa-database section-icon\"></i>\n <span class=\"section-title\">Entities</span>\n <span class=\"section-count\">({{ entities.length }})</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"entitiesSectionExpanded\" [class.fa-chevron-right]=\"!entitiesSectionExpanded\"></i>\n </div>\n\n @if (entitiesSectionExpanded) {\n <div class=\"section-content entity-tree-container\">\n <!-- Entity Search -->\n <div class=\"entity-search\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search entities...\"\n [(ngModel)]=\"entitySearchTerm\"\n (ngModelChange)=\"onEntitySearchChanged()\"\n />\n @if (entitySearchTerm) {\n <button class=\"clear-search\" (click)=\"clearEntitySearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n\n <!-- Entity Tree -->\n <mj-tree\n #entityTree\n [BranchConfig]=\"treeBranchConfig\"\n [LeafConfig]=\"treeLeafConfig\"\n [SelectionMode]=\"'single'\"\n [SelectableTypes]=\"'leaf'\"\n [SelectedIDs]=\"selectedEntityIds\"\n [ShowIcons]=\"true\"\n [ShowExpandCollapseAll]=\"false\"\n [AnimateExpandCollapse]=\"true\"\n [EmptyMessage]=\"entitySearchTerm ? 'No matches for: ' + entitySearchTerm : 'No entities available'\"\n [EmptyIcon]=\"'fa-solid fa-database'\"\n (SelectionChange)=\"onTreeEntitySelected($event)\">\n </mj-tree>\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- Collapsed State - Show Icons Only -->\n <div class=\"collapsed-icons\">\n <button class=\"icon-btn\" title=\"Favorites\" (click)=\"onCollapsedIconClick('favorites')\">\n <i class=\"fa-solid fa-star\"></i>\n @if (favoriteRecords.length + favoriteEntities.length > 0) {\n <span class=\"collapsed-badge\">{{ favoriteRecords.length + favoriteEntities.length }}</span>\n }\n </button>\n <button class=\"icon-btn\" title=\"Recent\" (click)=\"onCollapsedIconClick('recent')\">\n <i class=\"fa-solid fa-clock\"></i>\n @if (filteredRecentItems.length > 0) {\n <span class=\"collapsed-badge\">{{ filteredRecentItems.length }}</span>\n }\n </button>\n <button class=\"icon-btn\" title=\"Entities\" (click)=\"onCollapsedIconClick('entities')\">\n <i class=\"fa-solid fa-database\"></i>\n <span class=\"collapsed-badge\">{{ entities.length }}</span>\n </button>\n </div>\n }\n</div>\n", styles: [".navigation-panel-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0; /* Critical for nested flex scrolling */\n position: relative;\n background: var(--mj-bg-surface);\n box-shadow: 1px 0 3px rgba(0, 0, 0, 0.05);\n}\n.navigation-panel-container.collapsed {\n align-items: center;\n padding-top: 48px;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.panel-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.collapse-toggle {\n position: absolute;\n top: 12px;\n right: 12px;\n width: 28px;\n height: 28px;\n border: none;\n background: var(--mj-bg-surface-card);\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n z-index: 10;\n}\n.collapse-toggle:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n.collapsed .collapse-toggle {\n right: auto;\n left: 50%;\n transform: translateX(-50%);\n background: transparent;\n}\n.collapsed .collapse-toggle:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.panel-content {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n padding-top: 48px;\n min-height: 0; /* Allow flex children to shrink below content size */\n}\n\n.section {\n flex-shrink: 0;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n/* Scrollable sections (Favorites, Recent) - allow them to shrink and scroll */\n.section.favorites-section,\n.section.recent-section {\n display: flex;\n flex-direction: column;\n min-height: 0;\n max-height: 200px; /* Limit height so entities section has room */\n}\n\n.section.entities-section {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n border-bottom: none;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s ease;\n background: var(--mj-bg-surface-card);\n}\n.section-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.section-icon {\n width: 20px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-right: 10px;\n}\n\n.section-title {\n flex: 1;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n color: var(--mj-text-muted);\n}\n\n.section-count {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-right: 8px;\n font-weight: 500;\n}\n\n.expand-icon {\n font-size: 10px;\n color: var(--mj-text-muted);\n transition: transform 0.15s ease;\n}\n\n.section-content {\n padding: 8px 12px 12px 12px;\n background: var(--mj-bg-surface);\n}\n\n/* Scrollable section content for Favorites and Recent */\n.section-content.scrollable-section {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n}\n\n.scrollable-list {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n padding-right: 4px;\n}\n.scrollable-list::-webkit-scrollbar {\n width: 6px;\n}\n.scrollable-list::-webkit-scrollbar-track {\n background: transparent;\n}\n.scrollable-list::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 3px;\n}\n.scrollable-list::-webkit-scrollbar-thumb:hover {\n background: var(--mj-border-strong);\n}\n\n.scrollable-list-inner {\n /* Inner container grows naturally based on content */\n}\n\n.entities-section .section-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0; /* Allow content to shrink */\n overflow: hidden;\n}\n\n.entity-tree-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n}\n\n.entity-tree-container mj-tree {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n}\n\n.empty-section {\n padding: 20px 16px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n font-style: italic;\n}\n\n.nav-item {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n gap: 10px;\n margin-bottom: 2px;\n}\n.nav-item:hover {\n background: var(--mj-bg-surface-card);\n}\n.nav-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n.nav-item.selected i {\n color: var(--mj-brand-primary);\n}\n.nav-item.selected .nav-item-label {\n font-weight: 600;\n}\n.nav-item i {\n width: 18px;\n font-size: 14px;\n color: var(--mj-text-secondary);\n flex-shrink: 0;\n text-align: center;\n}\n\n.nav-item-content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.nav-item-label {\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.nav-item-meta {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.entity-search {\n position: relative;\n margin-bottom: 12px;\n flex-shrink: 0;\n}\n\n.search-icon {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.search-input {\n width: 100%;\n padding: 10px 36px 10px 36px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n background: var(--mj-bg-surface-card);\n transition: all 0.15s ease;\n}\n.search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n.search-input::placeholder {\n color: var(--mj-text-muted);\n}\n\n.clear-search {\n position: absolute;\n right: 6px;\n top: 50%;\n transform: translateY(-50%);\n width: 24px;\n height: 24px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n}\n.clear-search:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n}\n\n.entity-list {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n padding-right: 4px;\n}\n.entity-list::-webkit-scrollbar {\n width: 6px;\n}\n.entity-list::-webkit-scrollbar-track {\n background: transparent;\n}\n.entity-list::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 3px;\n}\n.entity-list::-webkit-scrollbar-thumb:hover {\n background: var(--mj-border-strong);\n}\n\n.entity-list-inner {\n /* Inner container grows naturally based on content */\n /* Does not scroll - parent .entity-list handles scrolling */\n}\n\n.entity-item .nav-item-label {\n flex: 1;\n}\n\n/* ============================================\n NAV PANEL APPLICATION GROUPS\n ============================================ */\n\n.nav-app-group {\n margin-bottom: 2px;\n}\n\n.nav-app-group-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n cursor: pointer;\n border-radius: 6px;\n transition: background 0.12s;\n user-select: none;\n}\n\n.nav-app-group-header:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.nav-app-group-icon {\n font-size: 12px;\n color: var(--mj-text-secondary);\n width: 16px;\n text-align: center;\n flex-shrink: 0;\n}\n\n.nav-app-group-name {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-secondary);\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.nav-app-group-count {\n font-size: 10px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n padding: 1px 6px;\n border-radius: 8px;\n}\n\n.nav-app-group-chevron {\n font-size: 9px;\n color: var(--mj-text-muted);\n transition: transform 0.15s;\n}\n\n.nav-app-group-chevron.expanded {\n transform: rotate(90deg);\n}\n\n.nav-app-group-entities {\n padding-left: 8px;\n}\n\n.nav-app-group-entities .nav-item {\n padding: 8px 10px 8px 16px;\n}\n\n.collapsed-icons {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding-top: 16px;\n}\n\n.icon-btn {\n width: 36px;\n height: 36px;\n border: none;\n background: transparent;\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n position: relative;\n}\n.icon-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n.icon-btn i {\n font-size: 16px;\n}\n\n.collapsed-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 4px;\n}\n"] }]
589
- }], null, { entities: [{
628
+ args: [{ standalone: false, selector: 'mj-explorer-navigation-panel', template: "<div class=\"navigation-panel-container\" [class.collapsed]=\"collapsed\">\n <!-- Collapse Toggle -->\n <button class=\"collapse-toggle\" (click)=\"onToggleCollapse()\" [title]=\"collapsed ? 'Expand' : 'Collapse'\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"collapsed\" [class.fa-chevron-left]=\"!collapsed\"></i>\n </button>\n\n @if (!collapsed) {\n <div class=\"panel-content\">\n <!-- Favorites Section -->\n <div class=\"section favorites-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('favorites')\">\n <i class=\"fa-solid fa-star section-icon\"></i>\n <span class=\"section-title\">Favorites</span>\n @if (favoriteRecords.length + favoriteEntities.length > 0) {\n <span class=\"section-count\">({{ favoriteRecords.length + favoriteEntities.length }})</span>\n }\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"favoritesSectionExpanded\" [class.fa-chevron-right]=\"!favoritesSectionExpanded\"></i>\n </div>\n\n @if (favoritesSectionExpanded) {\n <div class=\"section-content scrollable-section\">\n @if (favoriteRecords.length + favoriteEntities.length === 0) {\n <div class=\"empty-section\">\n <span>No favorites yet</span>\n </div>\n } @else {\n <div class=\"scrollable-list\">\n <div class=\"scrollable-list-inner\">\n @for (favorite of favoriteEntities; track favorite.entityName) {\n <div class=\"nav-item\" (click)=\"onFavoriteClick(favorite)\" [title]=\"favorite.entityName ? favorite.entityName + ' - ' + favorite.displayName : favorite.displayName\">\n <i [class]=\"getFavoriteIcon(favorite)\"></i>\n <span class=\"nav-item-label\">{{ favorite.displayName }}</span>\n </div>\n }\n @for (favorite of favoriteRecords; track favorite.entityName + '|' + favorite.compositeKeyString) {\n <div class=\"nav-item\" (click)=\"onFavoriteClick(favorite)\" [title]=\"favorite.entityName ? favorite.entityName + ' - ' + favorite.displayName : favorite.displayName\">\n <i [class]=\"getFavoriteIcon(favorite)\"></i>\n <span class=\"nav-item-label\">{{ favorite.displayName }}</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Recent Items Section -->\n <div class=\"section recent-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('recent')\">\n <i class=\"fa-solid fa-clock section-icon\"></i>\n <span class=\"section-title\">Recent</span>\n @if (filteredRecentItems.length > 0) {\n <span class=\"section-count\">({{ filteredRecentItems.length }})</span>\n }\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"recentSectionExpanded\" [class.fa-chevron-right]=\"!recentSectionExpanded\"></i>\n </div>\n\n @if (recentSectionExpanded) {\n <div class=\"section-content scrollable-section\">\n @if (filteredRecentItems.length === 0) {\n <div class=\"empty-section\">\n <span>No recent items</span>\n </div>\n } @else {\n <div class=\"scrollable-list\">\n <div class=\"scrollable-list-inner\">\n @for (item of filteredRecentItems; track item.entityName + '|' + item.compositeKeyString) {\n <div class=\"nav-item\" (click)=\"onRecentClick(item)\" [title]=\"item.entityName + ' - ' + item.displayName\">\n <i [class]=\"getRecentItemIcon(item)\"></i>\n <div class=\"nav-item-content\">\n <span class=\"nav-item-label\">{{ item.displayName }}</span>\n <span class=\"nav-item-meta\">{{ formatTimestamp(item.timestamp) }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Entities Section (ng-tree) -->\n <div class=\"section entities-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('entities')\">\n <i class=\"fa-solid fa-database section-icon\"></i>\n <span class=\"section-title\">Entities</span>\n <span class=\"section-count\">({{ entities.length }})</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"entitiesSectionExpanded\" [class.fa-chevron-right]=\"!entitiesSectionExpanded\"></i>\n </div>\n\n @if (entitiesSectionExpanded) {\n <div class=\"section-content entity-tree-container\">\n <!-- Entity Search -->\n <div class=\"entity-search\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search entities...\"\n [(ngModel)]=\"entitySearchTerm\"\n (ngModelChange)=\"onEntitySearchChanged()\"\n />\n @if (entitySearchTerm) {\n <button class=\"clear-search\" (click)=\"clearEntitySearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n\n <!-- Entity Tree -->\n <mj-tree\n #entityTree\n [BranchConfig]=\"treeBranchConfig\"\n [LeafConfig]=\"treeLeafConfig\"\n [SelectionMode]=\"'single'\"\n [SelectableTypes]=\"'leaf'\"\n [SelectedIDs]=\"selectedEntityIds\"\n [ShowIcons]=\"true\"\n [ShowExpandCollapseAll]=\"false\"\n [AnimateExpandCollapse]=\"true\"\n [EmptyMessage]=\"entitySearchTerm ? 'No matches for: ' + entitySearchTerm : 'No entities available'\"\n [EmptyIcon]=\"'fa-solid fa-database'\"\n (SelectionChange)=\"onTreeEntitySelected($event)\">\n </mj-tree>\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- Collapsed State - Show Icons Only -->\n <div class=\"collapsed-icons\">\n <button class=\"icon-btn\" title=\"Favorites\" (click)=\"onCollapsedIconClick('favorites')\">\n <i class=\"fa-solid fa-star\"></i>\n @if (favoriteRecords.length + favoriteEntities.length > 0) {\n <span class=\"collapsed-badge\">{{ favoriteRecords.length + favoriteEntities.length }}</span>\n }\n </button>\n <button class=\"icon-btn\" title=\"Recent\" (click)=\"onCollapsedIconClick('recent')\">\n <i class=\"fa-solid fa-clock\"></i>\n @if (filteredRecentItems.length > 0) {\n <span class=\"collapsed-badge\">{{ filteredRecentItems.length }}</span>\n }\n </button>\n <button class=\"icon-btn\" title=\"Entities\" (click)=\"onCollapsedIconClick('entities')\">\n <i class=\"fa-solid fa-database\"></i>\n <span class=\"collapsed-badge\">{{ entities.length }}</span>\n </button>\n </div>\n }\n</div>\n", styles: [".navigation-panel-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0; /* Critical for nested flex scrolling */\n position: relative;\n background: var(--mj-bg-surface);\n box-shadow: 1px 0 3px rgba(0, 0, 0, 0.05);\n}\n.navigation-panel-container.collapsed {\n align-items: center;\n padding-top: 48px;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.panel-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.collapse-toggle {\n position: absolute;\n top: 12px;\n right: 12px;\n width: 28px;\n height: 28px;\n border: none;\n background: var(--mj-bg-surface-card);\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n z-index: 10;\n}\n.collapse-toggle:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n.collapsed .collapse-toggle {\n right: auto;\n left: 50%;\n transform: translateX(-50%);\n background: transparent;\n}\n.collapsed .collapse-toggle:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.panel-content {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n padding-top: 48px;\n min-height: 0; /* Allow flex children to shrink below content size */\n}\n\n.section {\n flex-shrink: 0;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n/* Scrollable sections (Favorites, Recent) - allow them to shrink and scroll */\n.section.favorites-section,\n.section.recent-section {\n display: flex;\n flex-direction: column;\n min-height: 0;\n max-height: 200px; /* Limit height so entities section has room */\n}\n\n.section.entities-section {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n border-bottom: none;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n padding: 14px 16px;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s ease;\n background: var(--mj-bg-surface-card);\n}\n.section-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.section-icon {\n width: 20px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin-right: 10px;\n}\n\n.section-title {\n flex: 1;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n color: var(--mj-text-muted);\n}\n\n.section-count {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-right: 8px;\n font-weight: 500;\n}\n\n.expand-icon {\n font-size: 10px;\n color: var(--mj-text-muted);\n transition: transform 0.15s ease;\n}\n\n.section-content {\n padding: 8px 12px 12px 12px;\n background: var(--mj-bg-surface);\n}\n\n/* Scrollable section content for Favorites and Recent */\n.section-content.scrollable-section {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n}\n\n.scrollable-list {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n padding-right: 4px;\n}\n.scrollable-list::-webkit-scrollbar {\n width: 6px;\n}\n.scrollable-list::-webkit-scrollbar-track {\n background: transparent;\n}\n.scrollable-list::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 3px;\n}\n.scrollable-list::-webkit-scrollbar-thumb:hover {\n background: var(--mj-border-strong);\n}\n\n.scrollable-list-inner {\n /* Inner container grows naturally based on content */\n}\n\n.entities-section .section-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0; /* Allow content to shrink */\n overflow: hidden;\n}\n\n.entity-tree-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n}\n\n.entity-tree-container mj-tree {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n}\n\n.empty-section {\n padding: 20px 16px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n font-style: italic;\n}\n\n.nav-item {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n gap: 10px;\n margin-bottom: 2px;\n}\n.nav-item:hover {\n background: var(--mj-bg-surface-card);\n}\n.nav-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n.nav-item.selected i {\n color: var(--mj-brand-primary);\n}\n.nav-item.selected .nav-item-label {\n font-weight: 600;\n}\n.nav-item i {\n width: 18px;\n font-size: 14px;\n color: var(--mj-text-secondary);\n flex-shrink: 0;\n text-align: center;\n}\n\n.nav-item-content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.nav-item-label {\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.nav-item-meta {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.entity-search {\n position: relative;\n margin-bottom: 12px;\n flex-shrink: 0;\n}\n\n.search-icon {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.search-input {\n width: 100%;\n padding: 10px 36px 10px 36px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n background: var(--mj-bg-surface-card);\n transition: all 0.15s ease;\n}\n.search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n.search-input::placeholder {\n color: var(--mj-text-muted);\n}\n\n.clear-search {\n position: absolute;\n right: 6px;\n top: 50%;\n transform: translateY(-50%);\n width: 24px;\n height: 24px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n}\n.clear-search:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n}\n\n.entity-list {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n padding-right: 4px;\n}\n.entity-list::-webkit-scrollbar {\n width: 6px;\n}\n.entity-list::-webkit-scrollbar-track {\n background: transparent;\n}\n.entity-list::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 3px;\n}\n.entity-list::-webkit-scrollbar-thumb:hover {\n background: var(--mj-border-strong);\n}\n\n.entity-list-inner {\n /* Inner container grows naturally based on content */\n /* Does not scroll - parent .entity-list handles scrolling */\n}\n\n.entity-item .nav-item-label {\n flex: 1;\n}\n\n/* ============================================\n NAV PANEL APPLICATION GROUPS\n ============================================ */\n\n.nav-app-group {\n margin-bottom: 2px;\n}\n\n.nav-app-group-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n cursor: pointer;\n border-radius: 6px;\n transition: background 0.12s;\n user-select: none;\n}\n\n.nav-app-group-header:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.nav-app-group-icon {\n font-size: 12px;\n color: var(--mj-text-secondary);\n width: 16px;\n text-align: center;\n flex-shrink: 0;\n}\n\n.nav-app-group-name {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-secondary);\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.nav-app-group-count {\n font-size: 10px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n padding: 1px 6px;\n border-radius: 8px;\n}\n\n.nav-app-group-chevron {\n font-size: 9px;\n color: var(--mj-text-muted);\n transition: transform 0.15s;\n}\n\n.nav-app-group-chevron.expanded {\n transform: rotate(90deg);\n}\n\n.nav-app-group-entities {\n padding-left: 8px;\n}\n\n.nav-app-group-entities .nav-item {\n padding: 8px 10px 8px 16px;\n}\n\n.collapsed-icons {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding-top: 16px;\n}\n\n.icon-btn {\n width: 36px;\n height: 36px;\n border: none;\n background: transparent;\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n position: relative;\n}\n.icon-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n.icon-btn i {\n font-size: 16px;\n}\n\n.collapsed-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 4px;\n}\n"] }]
629
+ }], () => [{ type: i0.ChangeDetectorRef }], { entities: [{
590
630
  type: Input
591
631
  }], selectedEntityName: [{
592
632
  type: Input
@@ -1 +1 @@
1
- {"version":3,"file":"navigation-panel.component.js","sourceRoot":"","sources":["../../../../src/DataExplorer/components/navigation-panel/navigation-panel.component.ts","../../../../src/DataExplorer/components/navigation-panel/navigation-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges, ViewChild } from '@angular/core';\nimport { EntityInfo, CompositeKey } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { TreeBranchConfig, TreeLeafConfig, TreeNode, TreeComponent } from '@memberjunction/ng-trees';\nimport { RecentItem, FavoriteItem, AppEntityGroup } from '../../models/explorer-state.interface';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\n/**\n * Event emitted when a record should be opened in a full tab\n */\nexport interface OpenRecordEvent {\n entityName: string;\n compositeKey: CompositeKey;\n}\n\n/**\n * Event emitted when a record should be selected within Data Explorer (not full tab)\n */\nexport interface SelectRecordEvent {\n entityName: string;\n recordId: string;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-explorer-navigation-panel',\n templateUrl: './navigation-panel.component.html',\n styleUrls: ['./navigation-panel.component.css']\n})\nexport class NavigationPanelComponent extends BaseAngularComponent implements OnChanges {\n @Input() entities: EntityInfo[] = [];\n @Input() selectedEntityName: string | null = null;\n @Input() favorites: FavoriteItem[] = [];\n @Input() recentItems: RecentItem[] = [];\n @Input() collapsed = false;\n /**\n * Optional set of allowed entity names for filtering favorites/recents.\n * If provided, only items matching these entities will be shown.\n */\n @Input() allowedEntityNames: Set<string> | null = null;\n /** Application-based entity groups from the parent dashboard */\n @Input() appEntityGroups: AppEntityGroup[] = [];\n /** Optional application ID filter for the tree */\n @Input() applicationIdFilter: string | null = null;\n\n // Section expansion states\n @Input() favoritesSectionExpanded = true;\n @Input() recentSectionExpanded = true;\n @Input() entitiesSectionExpanded = true;\n @Input() viewsSectionExpanded = true;\n\n @Output() entitySelected = new EventEmitter<EntityInfo>();\n @Output() toggleCollapse = new EventEmitter<void>();\n @Output() sectionToggled = new EventEmitter<'favorites' | 'recent' | 'entities' | 'views'>();\n @Output() openRecord = new EventEmitter<OpenRecordEvent>();\n /** Emitted when a record should be selected within Data Explorer (navigate to entity + select record) */\n @Output() selectRecord = new EventEmitter<SelectRecordEvent>();\n /** Emitted when a collapsed icon is clicked - expands panel and focuses section */\n @Output() expandAndFocus = new EventEmitter<'favorites' | 'recent' | 'entities'>();\n /** Emitted when a nav panel app group is toggled */\n @Output() appGroupToggled = new EventEmitter<string>();\n\n private get metadata() { return this.ProviderToUse; }\n\n // Tree configuration for entity list\n public treeBranchConfig: TreeBranchConfig = {\n EntityName: 'MJ: Applications',\n DisplayField: 'Name',\n IDField: 'ID',\n IconField: 'Icon',\n OrderBy: 'Name'\n };\n\n public treeLeafConfig: TreeLeafConfig = {\n EntityName: 'MJ: Entities',\n ParentField: '', // Using JunctionConfig for M2M relationship\n DisplayField: 'Name',\n IDField: 'ID',\n IconField: 'Icon',\n JunctionConfig: {\n EntityName: 'MJ: Application Entities',\n BranchForeignKey: 'ApplicationID',\n LeafForeignKey: 'EntityID'\n },\n OrderBy: 'Name'\n };\n\n @ViewChild('entityTree') entityTree?: TreeComponent;\n\n /** Selected entity ID for tree highlighting */\n public selectedEntityIds: string[] = [];\n\n /** Search term for filtering the entity tree */\n public entitySearchTerm = '';\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['selectedEntityName']) {\n this.updateSelectedEntityKey();\n }\n if (changes['applicationIdFilter']) {\n this.updateTreeBranchFilter();\n }\n }\n\n /**\n * Update the selected entity IDs for tree highlighting when selected entity changes\n */\n private updateSelectedEntityKey(): void {\n if (this.selectedEntityName) {\n const entity = this.metadata.Entities.find(e => e.Name === this.selectedEntityName);\n if (entity) {\n this.selectedEntityIds = [entity.ID];\n return;\n }\n }\n this.selectedEntityIds = [];\n }\n\n /**\n * Update the tree's branch filter when application filter changes\n */\n private updateTreeBranchFilter(): void {\n if (this.applicationIdFilter) {\n this.treeBranchConfig = {\n ...this.treeBranchConfig,\n ExtraFilter: `ID='${this.applicationIdFilter}'`\n };\n } else {\n this.treeBranchConfig = {\n ...this.treeBranchConfig,\n ExtraFilter: undefined\n };\n }\n }\n\n /**\n * Filter the entity tree when search term changes\n */\n onEntitySearchChanged(): void {\n if (this.entityTree) {\n this.entityTree.FilterNodes(this.entitySearchTerm, {\n searchBranches: true,\n searchLeaves: true,\n caseSensitive: false\n });\n }\n }\n\n /**\n * Clear the entity search\n */\n clearEntitySearch(): void {\n this.entitySearchTerm = '';\n this.onEntitySearchChanged();\n }\n\n /**\n * Handle tree selection change - map TreeNode to EntityInfo and emit\n */\n onTreeEntitySelected(nodes: TreeNode[]): void {\n if (!nodes || nodes.length === 0) return;\n const node = nodes[0];\n if (node.Type !== 'leaf') return;\n\n // Find the EntityInfo by ID from the node\n const entity = this.metadata.Entities.find(e => UUIDsEqual(e.ID, node.ID));\n if (entity) {\n this.entitySelected.emit(entity);\n }\n }\n\n /**\n * Get recent items filtered by allowed entities (if filter is active)\n */\n get filteredRecentItems(): RecentItem[] {\n if (!this.allowedEntityNames) {\n return this.recentItems;\n }\n return this.recentItems.filter(r => this.allowedEntityNames!.has(r.entityName));\n }\n\n /**\n * Get favorites filtered to records only (respecting entity filter)\n */\n get favoriteRecords(): FavoriteItem[] {\n const records = this.favorites.filter(f => f.type === 'record');\n if (!this.allowedEntityNames) {\n return records;\n }\n return records.filter(f => f.entityName && this.allowedEntityNames!.has(f.entityName));\n }\n\n /**\n * Get favorites filtered to entities only (respecting entity filter)\n */\n get favoriteEntities(): FavoriteItem[] {\n const entities = this.favorites.filter(f => f.type === 'entity');\n if (!this.allowedEntityNames) {\n return entities;\n }\n return entities.filter(f => f.entityName && this.allowedEntityNames!.has(f.entityName));\n }\n\n /**\n * Handle entity click\n */\n onEntityClick(entity: EntityInfo): void {\n this.entitySelected.emit(entity);\n }\n\n /**\n * Handle favorite click - navigates to entity and selects record within Data Explorer\n */\n onFavoriteClick(favorite: FavoriteItem): void {\n if (favorite.type === 'entity' && favorite.entityName) {\n const entity = this.entities.find(e => e.Name === favorite.entityName);\n if (entity) {\n this.entitySelected.emit(entity);\n }\n } else if (favorite.type === 'record' && favorite.entityName && favorite.compositeKeyString) {\n // Extract record ID from the composite key string\n // Format is \"FieldName|Value\" or \"FieldName|Value||FieldName2|Value2\"\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromConcatenatedString(favorite.compositeKeyString);\n const recordId = compositeKey.KeyValuePairs[0]?.Value?.toString() || '';\n\n // Navigate to entity and select record within Data Explorer (not full tab)\n this.selectRecord.emit({\n entityName: favorite.entityName,\n recordId\n });\n }\n }\n\n /**\n * Handle recent item click - navigates to entity and selects record within Data Explorer\n */\n onRecentClick(item: RecentItem): void {\n // Extract record ID from the composite key string\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromConcatenatedString(item.compositeKeyString);\n const recordId = compositeKey.KeyValuePairs[0]?.Value?.toString() || '';\n\n // Navigate to entity and select record within Data Explorer (not full tab)\n this.selectRecord.emit({\n entityName: item.entityName,\n recordId\n });\n }\n\n /**\n * Handle section header click\n */\n onSectionToggle(section: 'favorites' | 'recent' | 'entities' | 'views'): void {\n this.sectionToggled.emit(section);\n }\n\n /**\n * Handle collapse toggle\n */\n onToggleCollapse(): void {\n this.toggleCollapse.emit();\n }\n\n /**\n * Handle collapsed icon click - expands panel and focuses section\n */\n onCollapsedIconClick(section: 'favorites' | 'recent' | 'entities'): void {\n this.expandAndFocus.emit(section);\n }\n\n /**\n * Check if entity is selected\n */\n isEntitySelected(entity: EntityInfo): boolean {\n return entity.Name === this.selectedEntityName;\n }\n\n /**\n * Get icon for entity\n */\n getEntityIcon(entity: EntityInfo): string {\n const icon = entity.Icon;\n if (!icon) {\n return 'fa-solid fa-table';\n }\n // If icon already has fa- prefix, use it as-is\n if (icon.startsWith('fa-') || icon.startsWith('fa ')) {\n // Ensure it has a style prefix (fa-solid, fa-regular, etc.)\n if (icon.startsWith('fa-solid') || icon.startsWith('fa-regular') ||\n icon.startsWith('fa-light') || icon.startsWith('fa-brands') ||\n icon.startsWith('fa ')) {\n return icon;\n }\n // It's just \"fa-something\", add fa-solid prefix\n return `fa-solid ${icon}`;\n }\n // Check if it's just an icon name like \"table\" or \"users\"\n return `fa-solid fa-${icon}`;\n }\n\n /**\n * Format recent item timestamp\n */\n formatTimestamp(timestamp: Date): string {\n const date = new Date(timestamp);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n\n if (diffMins < 1) return 'Just now';\n if (diffMins < 60) return `${diffMins}m ago`;\n\n const diffHours = Math.floor(diffMins / 60);\n if (diffHours < 24) return `${diffHours}h ago`;\n\n const diffDays = Math.floor(diffHours / 24);\n if (diffDays < 7) return `${diffDays}d ago`;\n\n return date.toLocaleDateString();\n }\n\n /**\n * Get icon for a recent item based on its entity\n */\n getRecentItemIcon(item: RecentItem): string {\n const entityInfo = this.metadata.Entities.find(e => e.Name === item.entityName);\n if (entityInfo) {\n return this.getEntityIcon(entityInfo);\n }\n return 'fa-solid fa-file-alt';\n }\n\n /**\n * Get icon for a favorite item based on its type and entity\n */\n getFavoriteIcon(favorite: FavoriteItem): string {\n if (favorite.type === 'view') {\n return 'fa-solid fa-filter';\n }\n\n // For entity and record types, look up the entity icon\n if (favorite.entityName) {\n const entityInfo = this.metadata.Entities.find(e => e.Name === favorite.entityName);\n if (entityInfo) {\n return this.getEntityIcon(entityInfo);\n }\n }\n\n // Fallback icons\n if (favorite.type === 'entity') {\n return 'fa-solid fa-table';\n }\n return 'fa-solid fa-file-alt';\n }\n}\n","<div class=\"navigation-panel-container\" [class.collapsed]=\"collapsed\">\n <!-- Collapse Toggle -->\n <button class=\"collapse-toggle\" (click)=\"onToggleCollapse()\" [title]=\"collapsed ? 'Expand' : 'Collapse'\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"collapsed\" [class.fa-chevron-left]=\"!collapsed\"></i>\n </button>\n\n @if (!collapsed) {\n <div class=\"panel-content\">\n <!-- Favorites Section -->\n <div class=\"section favorites-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('favorites')\">\n <i class=\"fa-solid fa-star section-icon\"></i>\n <span class=\"section-title\">Favorites</span>\n @if (favoriteRecords.length + favoriteEntities.length > 0) {\n <span class=\"section-count\">({{ favoriteRecords.length + favoriteEntities.length }})</span>\n }\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"favoritesSectionExpanded\" [class.fa-chevron-right]=\"!favoritesSectionExpanded\"></i>\n </div>\n\n @if (favoritesSectionExpanded) {\n <div class=\"section-content scrollable-section\">\n @if (favoriteRecords.length + favoriteEntities.length === 0) {\n <div class=\"empty-section\">\n <span>No favorites yet</span>\n </div>\n } @else {\n <div class=\"scrollable-list\">\n <div class=\"scrollable-list-inner\">\n @for (favorite of favoriteEntities; track favorite.displayName) {\n <div class=\"nav-item\" (click)=\"onFavoriteClick(favorite)\" [title]=\"favorite.entityName ? favorite.entityName + ' - ' + favorite.displayName : favorite.displayName\">\n <i [class]=\"getFavoriteIcon(favorite)\"></i>\n <span class=\"nav-item-label\">{{ favorite.displayName }}</span>\n </div>\n }\n @for (favorite of favoriteRecords; track favorite.displayName) {\n <div class=\"nav-item\" (click)=\"onFavoriteClick(favorite)\" [title]=\"favorite.entityName ? favorite.entityName + ' - ' + favorite.displayName : favorite.displayName\">\n <i [class]=\"getFavoriteIcon(favorite)\"></i>\n <span class=\"nav-item-label\">{{ favorite.displayName }}</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Recent Items Section -->\n <div class=\"section recent-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('recent')\">\n <i class=\"fa-solid fa-clock section-icon\"></i>\n <span class=\"section-title\">Recent</span>\n @if (filteredRecentItems.length > 0) {\n <span class=\"section-count\">({{ filteredRecentItems.length }})</span>\n }\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"recentSectionExpanded\" [class.fa-chevron-right]=\"!recentSectionExpanded\"></i>\n </div>\n\n @if (recentSectionExpanded) {\n <div class=\"section-content scrollable-section\">\n @if (filteredRecentItems.length === 0) {\n <div class=\"empty-section\">\n <span>No recent items</span>\n </div>\n } @else {\n <div class=\"scrollable-list\">\n <div class=\"scrollable-list-inner\">\n @for (item of filteredRecentItems; track item.compositeKeyString) {\n <div class=\"nav-item\" (click)=\"onRecentClick(item)\" [title]=\"item.entityName + ' - ' + item.displayName\">\n <i [class]=\"getRecentItemIcon(item)\"></i>\n <div class=\"nav-item-content\">\n <span class=\"nav-item-label\">{{ item.displayName }}</span>\n <span class=\"nav-item-meta\">{{ formatTimestamp(item.timestamp) }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Entities Section (ng-tree) -->\n <div class=\"section entities-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('entities')\">\n <i class=\"fa-solid fa-database section-icon\"></i>\n <span class=\"section-title\">Entities</span>\n <span class=\"section-count\">({{ entities.length }})</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"entitiesSectionExpanded\" [class.fa-chevron-right]=\"!entitiesSectionExpanded\"></i>\n </div>\n\n @if (entitiesSectionExpanded) {\n <div class=\"section-content entity-tree-container\">\n <!-- Entity Search -->\n <div class=\"entity-search\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search entities...\"\n [(ngModel)]=\"entitySearchTerm\"\n (ngModelChange)=\"onEntitySearchChanged()\"\n />\n @if (entitySearchTerm) {\n <button class=\"clear-search\" (click)=\"clearEntitySearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n\n <!-- Entity Tree -->\n <mj-tree\n #entityTree\n [BranchConfig]=\"treeBranchConfig\"\n [LeafConfig]=\"treeLeafConfig\"\n [SelectionMode]=\"'single'\"\n [SelectableTypes]=\"'leaf'\"\n [SelectedIDs]=\"selectedEntityIds\"\n [ShowIcons]=\"true\"\n [ShowExpandCollapseAll]=\"false\"\n [AnimateExpandCollapse]=\"true\"\n [EmptyMessage]=\"entitySearchTerm ? 'No matches for: ' + entitySearchTerm : 'No entities available'\"\n [EmptyIcon]=\"'fa-solid fa-database'\"\n (SelectionChange)=\"onTreeEntitySelected($event)\">\n </mj-tree>\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- Collapsed State - Show Icons Only -->\n <div class=\"collapsed-icons\">\n <button class=\"icon-btn\" title=\"Favorites\" (click)=\"onCollapsedIconClick('favorites')\">\n <i class=\"fa-solid fa-star\"></i>\n @if (favoriteRecords.length + favoriteEntities.length > 0) {\n <span class=\"collapsed-badge\">{{ favoriteRecords.length + favoriteEntities.length }}</span>\n }\n </button>\n <button class=\"icon-btn\" title=\"Recent\" (click)=\"onCollapsedIconClick('recent')\">\n <i class=\"fa-solid fa-clock\"></i>\n @if (filteredRecentItems.length > 0) {\n <span class=\"collapsed-badge\">{{ filteredRecentItems.length }}</span>\n }\n </button>\n <button class=\"icon-btn\" title=\"Entities\" (click)=\"onCollapsedIconClick('entities')\">\n <i class=\"fa-solid fa-database\"></i>\n <span class=\"collapsed-badge\">{{ entities.length }}</span>\n </button>\n </div>\n }\n</div>\n"]}
1
+ {"version":3,"file":"navigation-panel.component.js","sourceRoot":"","sources":["../../../../src/DataExplorer/components/navigation-panel/navigation-panel.component.ts","../../../../src/DataExplorer/components/navigation-panel/navigation-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, Input, Output, EventEmitter, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChild } from '@angular/core';\nimport { EntityInfo, CompositeKey } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { TreeBranchConfig, TreeLeafConfig, TreeNode, TreeComponent } from '@memberjunction/ng-trees';\nimport { RecentItem, FavoriteItem, AppEntityGroup } from '../../models/explorer-state.interface';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\n/**\n * Event emitted when a record should be opened in a full tab\n */\nexport interface OpenRecordEvent {\n entityName: string;\n compositeKey: CompositeKey;\n}\n\n/**\n * Event emitted when a record should be selected within Data Explorer (not full tab)\n */\nexport interface SelectRecordEvent {\n entityName: string;\n recordId: string;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-explorer-navigation-panel',\n templateUrl: './navigation-panel.component.html',\n styleUrls: ['./navigation-panel.component.css']\n})\nexport class NavigationPanelComponent extends BaseAngularComponent implements OnChanges, OnInit, OnDestroy {\n constructor(private cdr: ChangeDetectorRef) {\n super();\n }\n\n @Input() entities: EntityInfo[] = [];\n @Input() selectedEntityName: string | null = null;\n @Input() favorites: FavoriteItem[] = [];\n @Input() recentItems: RecentItem[] = [];\n @Input() collapsed = false;\n /**\n * Optional set of allowed entity names for filtering favorites/recents.\n * If provided, only items matching these entities will be shown.\n */\n @Input() allowedEntityNames: Set<string> | null = null;\n /** Application-based entity groups from the parent dashboard */\n @Input() appEntityGroups: AppEntityGroup[] = [];\n /** Optional application ID filter for the tree */\n @Input() applicationIdFilter: string | null = null;\n\n // Section expansion states\n @Input() favoritesSectionExpanded = true;\n @Input() recentSectionExpanded = true;\n @Input() entitiesSectionExpanded = true;\n @Input() viewsSectionExpanded = true;\n\n @Output() entitySelected = new EventEmitter<EntityInfo>();\n @Output() toggleCollapse = new EventEmitter<void>();\n @Output() sectionToggled = new EventEmitter<'favorites' | 'recent' | 'entities' | 'views'>();\n @Output() openRecord = new EventEmitter<OpenRecordEvent>();\n /** Emitted when a record should be selected within Data Explorer (navigate to entity + select record) */\n @Output() selectRecord = new EventEmitter<SelectRecordEvent>();\n /** Emitted when a collapsed icon is clicked - expands panel and focuses section */\n @Output() expandAndFocus = new EventEmitter<'favorites' | 'recent' | 'entities'>();\n /** Emitted when a nav panel app group is toggled */\n @Output() appGroupToggled = new EventEmitter<string>();\n\n private get metadata() { return this.ProviderToUse; }\n\n // Tree configuration for entity list\n public treeBranchConfig: TreeBranchConfig = {\n EntityName: 'MJ: Applications',\n DisplayField: 'Name',\n IDField: 'ID',\n IconField: 'Icon',\n OrderBy: 'Name'\n };\n\n public treeLeafConfig: TreeLeafConfig = {\n EntityName: 'MJ: Entities',\n ParentField: '', // Using JunctionConfig for M2M relationship\n DisplayField: 'Name',\n IDField: 'ID',\n IconField: 'Icon',\n JunctionConfig: {\n EntityName: 'MJ: Application Entities',\n BranchForeignKey: 'ApplicationID',\n LeafForeignKey: 'EntityID'\n },\n OrderBy: 'Name'\n };\n\n @ViewChild('entityTree') entityTree?: TreeComponent;\n\n /** Selected entity ID for tree highlighting */\n public selectedEntityIds: string[] = [];\n\n /** Search term for filtering the entity tree */\n public entitySearchTerm = '';\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['selectedEntityName']) {\n this.updateSelectedEntityKey();\n }\n if (changes['applicationIdFilter']) {\n this.updateTreeBranchFilter();\n }\n if (changes['recentItems']) {\n this.timestampLabelCache.clear();\n }\n }\n\n ngOnInit(): void {\n this.timestampRefreshHandle = setInterval(() => {\n if (this.timestampLabelCache.size === 0) return;\n this.timestampLabelCache.clear();\n this.cdr.markForCheck();\n }, 30000);\n }\n\n ngOnDestroy(): void {\n if (this.timestampRefreshHandle !== undefined) {\n clearInterval(this.timestampRefreshHandle);\n this.timestampRefreshHandle = undefined;\n }\n }\n\n /**\n * Update the selected entity IDs for tree highlighting when selected entity changes\n */\n private updateSelectedEntityKey(): void {\n if (this.selectedEntityName) {\n const entity = this.metadata.Entities.find(e => e.Name === this.selectedEntityName);\n if (entity) {\n this.selectedEntityIds = [entity.ID];\n return;\n }\n }\n this.selectedEntityIds = [];\n }\n\n /**\n * Update the tree's branch filter when application filter changes\n */\n private updateTreeBranchFilter(): void {\n if (this.applicationIdFilter) {\n this.treeBranchConfig = {\n ...this.treeBranchConfig,\n ExtraFilter: `ID='${this.applicationIdFilter}'`\n };\n } else {\n this.treeBranchConfig = {\n ...this.treeBranchConfig,\n ExtraFilter: undefined\n };\n }\n }\n\n /**\n * Filter the entity tree when search term changes\n */\n onEntitySearchChanged(): void {\n if (this.entityTree) {\n this.entityTree.FilterNodes(this.entitySearchTerm, {\n searchBranches: true,\n searchLeaves: true,\n caseSensitive: false\n });\n }\n }\n\n /**\n * Clear the entity search\n */\n clearEntitySearch(): void {\n this.entitySearchTerm = '';\n this.onEntitySearchChanged();\n }\n\n /**\n * Handle tree selection change - map TreeNode to EntityInfo and emit\n */\n onTreeEntitySelected(nodes: TreeNode[]): void {\n if (!nodes || nodes.length === 0) return;\n const node = nodes[0];\n if (node.Type !== 'leaf') return;\n\n // Find the EntityInfo by ID from the node\n const entity = this.metadata.Entities.find(e => UUIDsEqual(e.ID, node.ID));\n if (entity) {\n this.entitySelected.emit(entity);\n }\n }\n\n /**\n * Get recent items filtered by allowed entities (if filter is active)\n */\n get filteredRecentItems(): RecentItem[] {\n if (!this.allowedEntityNames) {\n return this.recentItems;\n }\n return this.recentItems.filter(r => this.allowedEntityNames!.has(r.entityName));\n }\n\n /**\n * Get favorites filtered to records only (respecting entity filter)\n */\n get favoriteRecords(): FavoriteItem[] {\n const records = this.favorites.filter(f => f.type === 'record');\n if (!this.allowedEntityNames) {\n return records;\n }\n return records.filter(f => f.entityName && this.allowedEntityNames!.has(f.entityName));\n }\n\n /**\n * Get favorites filtered to entities only (respecting entity filter)\n */\n get favoriteEntities(): FavoriteItem[] {\n const entities = this.favorites.filter(f => f.type === 'entity');\n if (!this.allowedEntityNames) {\n return entities;\n }\n return entities.filter(f => f.entityName && this.allowedEntityNames!.has(f.entityName));\n }\n\n /**\n * Handle entity click\n */\n onEntityClick(entity: EntityInfo): void {\n this.entitySelected.emit(entity);\n }\n\n /**\n * Handle favorite click - navigates to entity and selects record within Data Explorer\n */\n onFavoriteClick(favorite: FavoriteItem): void {\n if (favorite.type === 'entity' && favorite.entityName) {\n const entity = this.entities.find(e => e.Name === favorite.entityName);\n if (entity) {\n this.entitySelected.emit(entity);\n }\n } else if (favorite.type === 'record' && favorite.entityName && favorite.compositeKeyString) {\n // Extract record ID from the composite key string\n // Format is \"FieldName|Value\" or \"FieldName|Value||FieldName2|Value2\"\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromConcatenatedString(favorite.compositeKeyString);\n const recordId = compositeKey.KeyValuePairs[0]?.Value?.toString() || '';\n\n // Navigate to entity and select record within Data Explorer (not full tab)\n this.selectRecord.emit({\n entityName: favorite.entityName,\n recordId\n });\n }\n }\n\n /**\n * Handle recent item click - navigates to entity and selects record within Data Explorer\n */\n onRecentClick(item: RecentItem): void {\n // Extract record ID from the composite key string\n const compositeKey = new CompositeKey();\n compositeKey.LoadFromConcatenatedString(item.compositeKeyString);\n const recordId = compositeKey.KeyValuePairs[0]?.Value?.toString() || '';\n\n // Navigate to entity and select record within Data Explorer (not full tab)\n this.selectRecord.emit({\n entityName: item.entityName,\n recordId\n });\n }\n\n /**\n * Handle section header click\n */\n onSectionToggle(section: 'favorites' | 'recent' | 'entities' | 'views'): void {\n this.sectionToggled.emit(section);\n }\n\n /**\n * Handle collapse toggle\n */\n onToggleCollapse(): void {\n this.toggleCollapse.emit();\n }\n\n /**\n * Handle collapsed icon click - expands panel and focuses section\n */\n onCollapsedIconClick(section: 'favorites' | 'recent' | 'entities'): void {\n this.expandAndFocus.emit(section);\n }\n\n /**\n * Check if entity is selected\n */\n isEntitySelected(entity: EntityInfo): boolean {\n return entity.Name === this.selectedEntityName;\n }\n\n /**\n * Get icon for entity\n */\n getEntityIcon(entity: EntityInfo): string {\n const icon = entity.Icon;\n if (!icon) {\n return 'fa-solid fa-table';\n }\n // If icon already has fa- prefix, use it as-is\n if (icon.startsWith('fa-') || icon.startsWith('fa ')) {\n // Ensure it has a style prefix (fa-solid, fa-regular, etc.)\n if (icon.startsWith('fa-solid') || icon.startsWith('fa-regular') ||\n icon.startsWith('fa-light') || icon.startsWith('fa-brands') ||\n icon.startsWith('fa ')) {\n return icon;\n }\n // It's just \"fa-something\", add fa-solid prefix\n return `fa-solid ${icon}`;\n }\n // Check if it's just an icon name like \"table\" or \"users\"\n return `fa-solid fa-${icon}`;\n }\n\n /**\n * Cache of formatted relative-time labels keyed by timestamp epoch ms.\n * Stable within a change-detection cycle (avoids NG0100 from `now`-dependent\n * values shifting between dirty-check and verify passes). Cleared on a coarse\n * interval so the displayed label still updates over time.\n */\n private timestampLabelCache = new Map<number, string>();\n private timestampRefreshHandle?: ReturnType<typeof setInterval>;\n\n /**\n * Format recent item timestamp. Cached per-timestamp so the same value is\n * returned across change-detection passes within a single tick — recomputed\n * on a 30-second interval (see `ngOnInit`).\n */\n formatTimestamp(timestamp: Date): string {\n const epoch = new Date(timestamp).getTime();\n const cached = this.timestampLabelCache.get(epoch);\n if (cached !== undefined) {\n return cached;\n }\n const label = this.computeRelativeLabel(epoch);\n this.timestampLabelCache.set(epoch, label);\n return label;\n }\n\n private computeRelativeLabel(epoch: number): string {\n const diffMs = Date.now() - epoch;\n const diffMins = Math.floor(diffMs / 60000);\n\n if (diffMins < 1) return 'Just now';\n if (diffMins < 60) return `${diffMins}m ago`;\n\n const diffHours = Math.floor(diffMins / 60);\n if (diffHours < 24) return `${diffHours}h ago`;\n\n const diffDays = Math.floor(diffHours / 24);\n if (diffDays < 7) return `${diffDays}d ago`;\n\n return new Date(epoch).toLocaleDateString();\n }\n\n /**\n * Get icon for a recent item based on its entity\n */\n getRecentItemIcon(item: RecentItem): string {\n const entityInfo = this.metadata.Entities.find(e => e.Name === item.entityName);\n if (entityInfo) {\n return this.getEntityIcon(entityInfo);\n }\n return 'fa-solid fa-file-alt';\n }\n\n /**\n * Get icon for a favorite item based on its type and entity\n */\n getFavoriteIcon(favorite: FavoriteItem): string {\n if (favorite.type === 'view') {\n return 'fa-solid fa-filter';\n }\n\n // For entity and record types, look up the entity icon\n if (favorite.entityName) {\n const entityInfo = this.metadata.Entities.find(e => e.Name === favorite.entityName);\n if (entityInfo) {\n return this.getEntityIcon(entityInfo);\n }\n }\n\n // Fallback icons\n if (favorite.type === 'entity') {\n return 'fa-solid fa-table';\n }\n return 'fa-solid fa-file-alt';\n }\n}\n","<div class=\"navigation-panel-container\" [class.collapsed]=\"collapsed\">\n <!-- Collapse Toggle -->\n <button class=\"collapse-toggle\" (click)=\"onToggleCollapse()\" [title]=\"collapsed ? 'Expand' : 'Collapse'\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"collapsed\" [class.fa-chevron-left]=\"!collapsed\"></i>\n </button>\n\n @if (!collapsed) {\n <div class=\"panel-content\">\n <!-- Favorites Section -->\n <div class=\"section favorites-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('favorites')\">\n <i class=\"fa-solid fa-star section-icon\"></i>\n <span class=\"section-title\">Favorites</span>\n @if (favoriteRecords.length + favoriteEntities.length > 0) {\n <span class=\"section-count\">({{ favoriteRecords.length + favoriteEntities.length }})</span>\n }\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"favoritesSectionExpanded\" [class.fa-chevron-right]=\"!favoritesSectionExpanded\"></i>\n </div>\n\n @if (favoritesSectionExpanded) {\n <div class=\"section-content scrollable-section\">\n @if (favoriteRecords.length + favoriteEntities.length === 0) {\n <div class=\"empty-section\">\n <span>No favorites yet</span>\n </div>\n } @else {\n <div class=\"scrollable-list\">\n <div class=\"scrollable-list-inner\">\n @for (favorite of favoriteEntities; track favorite.entityName) {\n <div class=\"nav-item\" (click)=\"onFavoriteClick(favorite)\" [title]=\"favorite.entityName ? favorite.entityName + ' - ' + favorite.displayName : favorite.displayName\">\n <i [class]=\"getFavoriteIcon(favorite)\"></i>\n <span class=\"nav-item-label\">{{ favorite.displayName }}</span>\n </div>\n }\n @for (favorite of favoriteRecords; track favorite.entityName + '|' + favorite.compositeKeyString) {\n <div class=\"nav-item\" (click)=\"onFavoriteClick(favorite)\" [title]=\"favorite.entityName ? favorite.entityName + ' - ' + favorite.displayName : favorite.displayName\">\n <i [class]=\"getFavoriteIcon(favorite)\"></i>\n <span class=\"nav-item-label\">{{ favorite.displayName }}</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Recent Items Section -->\n <div class=\"section recent-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('recent')\">\n <i class=\"fa-solid fa-clock section-icon\"></i>\n <span class=\"section-title\">Recent</span>\n @if (filteredRecentItems.length > 0) {\n <span class=\"section-count\">({{ filteredRecentItems.length }})</span>\n }\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"recentSectionExpanded\" [class.fa-chevron-right]=\"!recentSectionExpanded\"></i>\n </div>\n\n @if (recentSectionExpanded) {\n <div class=\"section-content scrollable-section\">\n @if (filteredRecentItems.length === 0) {\n <div class=\"empty-section\">\n <span>No recent items</span>\n </div>\n } @else {\n <div class=\"scrollable-list\">\n <div class=\"scrollable-list-inner\">\n @for (item of filteredRecentItems; track item.entityName + '|' + item.compositeKeyString) {\n <div class=\"nav-item\" (click)=\"onRecentClick(item)\" [title]=\"item.entityName + ' - ' + item.displayName\">\n <i [class]=\"getRecentItemIcon(item)\"></i>\n <div class=\"nav-item-content\">\n <span class=\"nav-item-label\">{{ item.displayName }}</span>\n <span class=\"nav-item-meta\">{{ formatTimestamp(item.timestamp) }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Entities Section (ng-tree) -->\n <div class=\"section entities-section\">\n <div class=\"section-header\" (click)=\"onSectionToggle('entities')\">\n <i class=\"fa-solid fa-database section-icon\"></i>\n <span class=\"section-title\">Entities</span>\n <span class=\"section-count\">({{ entities.length }})</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"entitiesSectionExpanded\" [class.fa-chevron-right]=\"!entitiesSectionExpanded\"></i>\n </div>\n\n @if (entitiesSectionExpanded) {\n <div class=\"section-content entity-tree-container\">\n <!-- Entity Search -->\n <div class=\"entity-search\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search entities...\"\n [(ngModel)]=\"entitySearchTerm\"\n (ngModelChange)=\"onEntitySearchChanged()\"\n />\n @if (entitySearchTerm) {\n <button class=\"clear-search\" (click)=\"clearEntitySearch()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n\n <!-- Entity Tree -->\n <mj-tree\n #entityTree\n [BranchConfig]=\"treeBranchConfig\"\n [LeafConfig]=\"treeLeafConfig\"\n [SelectionMode]=\"'single'\"\n [SelectableTypes]=\"'leaf'\"\n [SelectedIDs]=\"selectedEntityIds\"\n [ShowIcons]=\"true\"\n [ShowExpandCollapseAll]=\"false\"\n [AnimateExpandCollapse]=\"true\"\n [EmptyMessage]=\"entitySearchTerm ? 'No matches for: ' + entitySearchTerm : 'No entities available'\"\n [EmptyIcon]=\"'fa-solid fa-database'\"\n (SelectionChange)=\"onTreeEntitySelected($event)\">\n </mj-tree>\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- Collapsed State - Show Icons Only -->\n <div class=\"collapsed-icons\">\n <button class=\"icon-btn\" title=\"Favorites\" (click)=\"onCollapsedIconClick('favorites')\">\n <i class=\"fa-solid fa-star\"></i>\n @if (favoriteRecords.length + favoriteEntities.length > 0) {\n <span class=\"collapsed-badge\">{{ favoriteRecords.length + favoriteEntities.length }}</span>\n }\n </button>\n <button class=\"icon-btn\" title=\"Recent\" (click)=\"onCollapsedIconClick('recent')\">\n <i class=\"fa-solid fa-clock\"></i>\n @if (filteredRecentItems.length > 0) {\n <span class=\"collapsed-badge\">{{ filteredRecentItems.length }}</span>\n }\n </button>\n <button class=\"icon-btn\" title=\"Entities\" (click)=\"onCollapsedIconClick('entities')\">\n <i class=\"fa-solid fa-database\"></i>\n <span class=\"collapsed-badge\">{{ entities.length }}</span>\n </button>\n </div>\n }\n</div>\n"]}