@memberjunction/ng-explorer-core 5.42.0 → 5.44.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.
- package/dist/generated/lazy-feature-config.d.ts +1 -1
- package/dist/generated/lazy-feature-config.d.ts.map +1 -1
- package/dist/generated/lazy-feature-config.js +14 -3
- package/dist/generated/lazy-feature-config.js.map +1 -1
- package/dist/lib/about/about-dialog.component.d.ts +0 -1
- package/dist/lib/about/about-dialog.component.d.ts.map +1 -1
- package/dist/lib/about/about-dialog.component.js +217 -218
- package/dist/lib/about/about-dialog.component.js.map +1 -1
- package/dist/lib/command-palette/command-palette.component.js +8 -14
- package/dist/lib/command-palette/command-palette.component.js.map +1 -1
- package/dist/lib/conversation-feedback/conversation-feedback.js +66 -73
- package/dist/lib/conversation-feedback/conversation-feedback.js.map +1 -1
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +35 -45
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +2 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +14 -8
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js +9 -8
- package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts +62 -2
- package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/livekit-room-resource.component.js +604 -105
- package/dist/lib/resource-wrappers/livekit-room-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.js +35 -43
- package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts +10 -2
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.js +19 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts +1 -0
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.js +3 -2
- package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
- package/dist/lib/shell/shell.module.d.ts +1 -1
- package/dist/lib/shell/shell.module.d.ts.map +1 -1
- package/dist/lib/shell/shell.module.js +4 -1
- package/dist/lib/shell/shell.module.js.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +5 -7
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js +17 -27
- package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts +6 -2
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.js +48 -57
- package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
- package/dist/lib/single-search-result/single-search-result.component.js +17 -22
- package/dist/lib/single-search-result/single-search-result.component.js.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.js +60 -75
- package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +12 -5
- package/dist/module.js.map +1 -1
- package/package.json +47 -47
- package/dist/lib/__tests__/explorer-core.test.d.ts +0 -2
- package/dist/lib/__tests__/explorer-core.test.d.ts.map +0 -1
- package/dist/lib/__tests__/explorer-core.test.js +0 -229
- package/dist/lib/__tests__/explorer-core.test.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-results-resource.component.js","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/search-results-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, inject } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { CompositeKey, Metadata, RunView } from '@memberjunction/core';\nimport { ResourceData } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport { FileOpenService } from '@memberjunction/ng-file-storage';\nimport {\n SearchService,\n SearchResultItem,\n SearchFilter,\n SearchFilterChangeEvent,\n SearchRequest,\n SearchResponse,\n SearchResultSelectedEvent,\n StreamingProviderStatus,\n} from '@memberjunction/ng-search';\nimport { WordCloudItem, WordCloudItemEvent } from '@memberjunction/ng-word-cloud';\n\n@RegisterClass(BaseResourceComponent, 'SearchResultsResource')\n@Component({\n standalone: false,\n selector: 'mj-search-results-resource',\n template: `\n <div class=\"search-results-page\">\n <!-- Streaming status strip — visible while streamScopedSearch is in flight -->\n @if (EnableStreaming && (IsSearching || StreamingProviders.length > 0)) {\n <div class=\"streaming-status-strip\" aria-live=\"polite\">\n @for (p of StreamingProviders; track p.Name) {\n <span class=\"streaming-chip\"\n [class.streaming-chip-error]=\"p.State === 'Error'\"\n [class.streaming-chip-completed]=\"p.State === 'Completed'\">\n @if (p.State === 'Completed') {\n <i class=\"fa-solid fa-check\"></i>\n } @else {\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n }\n <span class=\"streaming-chip-name\">{{ p.Name }}</span>\n @if (p.State === 'Completed') {\n <span class=\"streaming-chip-count\">{{ p.Count }}</span>\n <span class=\"streaming-chip-time\">{{ p.ElapsedMs }}ms</span>\n } @else if (p.ErrorMessage) {\n <span class=\"streaming-chip-time\">{{ p.ErrorMessage }}</span>\n }\n </span>\n }\n @if (IsSearching) {\n <span class=\"streaming-chip streaming-chip-pending\">\n <i class=\"fa-solid fa-circle-notch fa-spin\"></i>\n <span>Streaming…</span>\n </span>\n }\n </div>\n }\n\n <!-- Header bar (always visible when we have server results) -->\n @if (HasSearched && ServerResultCount > 0) {\n <div class=\"search-header\">\n <div class=\"search-header-left\">\n @if (!ShowFilterPanel) {\n <button class=\"sr-icon-btn\" title=\"Show filters\" (click)=\"ToggleFilterPanel()\">\n <i class=\"fa-solid fa-filter\"></i>\n </button>\n }\n <span class=\"search-meta\">\n {{ FilteredResults.length }} of {{ ServerResultCount }} result{{ ServerResultCount !== 1 ? 's' : '' }}\n for \"{{ CurrentQuery }}\" in {{ ElapsedMs }}ms\n </span>\n </div>\n <div class=\"search-header-right\">\n <!-- Search within results -->\n <div class=\"sr-refine-wrapper\">\n <i class=\"fa-solid fa-filter-list sr-refine-icon\"></i>\n <input class=\"mj-input sr-refine-input\"\n placeholder=\"Filter within results...\"\n [value]=\"ClientFilterText\"\n (input)=\"OnClientFilterTextChange($any($event.target).value)\" />\n @if (ClientFilterText) {\n <button class=\"sr-refine-clear\" (click)=\"OnClientFilterTextChange('')\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n }\n </div>\n <!-- Sort -->\n <select class=\"mj-input sr-sort-select\" [value]=\"SortField\" (change)=\"OnSortChange($any($event.target).value)\">\n <option value=\"score\">Sort: Relevance</option>\n <option value=\"title\">Sort: Name</option>\n <option value=\"entity\">Sort: Entity</option>\n </select>\n <!-- View mode toggle -->\n <div class=\"sr-view-toggle\">\n <button class=\"sr-icon-btn\"\n [class.sr-view-active]=\"ViewMode === 'list'\"\n title=\"List view\"\n (click)=\"SetViewMode('list')\">\n <i class=\"fa-solid fa-list\"></i>\n </button>\n <button class=\"sr-icon-btn\"\n [class.sr-view-active]=\"ViewMode === 'cloud'\"\n title=\"Tag cloud view\"\n (click)=\"SetViewMode('cloud')\">\n <i class=\"fa-solid fa-cloud\"></i>\n </button>\n </div>\n <!-- Refresh -->\n <button class=\"sr-icon-btn\" title=\"Refresh search\" (click)=\"OnRefresh()\" [disabled]=\"IsSearching\">\n <i class=\"fa-solid fa-arrows-rotate\" [class.fa-spin]=\"IsSearching\"></i>\n </button>\n </div>\n </div>\n }\n\n <!-- Initial loading (first search) -->\n @if (IsSearching && ServerResultCount === 0) {\n <div class=\"search-loading\">\n <mj-loading text=\"Searching...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- No server results -->\n @if (!IsSearching && ServerResultCount === 0 && HasSearched) {\n <div class=\"search-no-results\">\n <i class=\"fa-solid fa-magnifying-glass-minus\"></i>\n <h3>No results found</h3>\n <p>Try different keywords or broaden your search.</p>\n </div>\n }\n <!-- Results body (visible when server returned results) -->\n @if (ServerResultCount > 0) {\n <div class=\"search-results-body-wrapper\">\n <!-- Semi-opaque loading overlay for re-queries (slider lowered, etc.) -->\n @if (IsSearching) {\n <div class=\"search-requery-overlay\">\n <mj-loading text=\"Updating results...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n @if (ViewMode === 'cloud') {\n <div class=\"search-cloud-wrapper\">\n @if (IsLoadingCloud) {\n <mj-loading text=\"Loading tag cloud...\" size=\"medium\"></mj-loading>\n } @else {\n <mj-word-cloud\n [Items]=\"CloudItems\"\n [MaxItems]=\"80\"\n ColorMode=\"weight-gradient\"\n [Interactive]=\"true\"\n (ItemClick)=\"OnCloudItemClick($event)\">\n </mj-word-cloud>\n }\n </div>\n } @else {\n <div class=\"search-body\">\n @if (ShowFilterPanel) {\n <mj-search-filter\n [Filters]=\"Filters\"\n [ActiveFilters]=\"ActiveFilters\"\n [ShowRelevanceSlider]=\"true\"\n [MinScorePercent]=\"MinScorePercent\"\n [ServerMinScorePercent]=\"serverMinScorePercent\"\n (FilterChanged)=\"OnFilterChanged($event)\"\n (FiltersCleared)=\"OnFiltersCleared()\"\n (CloseRequested)=\"ToggleFilterPanel()\"\n (MinScoreChanged)=\"OnMinScoreChanged($any($event))\">\n </mj-search-filter>\n }\n @if (FilteredResults.length > 0) {\n <mj-search-results\n [FlatResults]=\"FilteredResults\"\n [HighlightText]=\"ClientFilterText\"\n [ShowScores]=\"true\"\n [ShowTags]=\"true\"\n [ShowSummary]=\"false\"\n [PageSize]=\"20\"\n (ResultSelected)=\"OnResultSelected($event)\"\n (OpenRecordRequested)=\"OnOpenRecord($event)\">\n </mj-search-results>\n } @else {\n <div class=\"search-no-results-inline\">\n <i class=\"fa-solid fa-filter-circle-xmark\"></i>\n <p>No results match current filters. Try lowering the minimum relevance.</p>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [`\n .search-results-page {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n overflow: hidden;\n }\n .search-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 8px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n }\n .search-header-left {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .search-header-right {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .search-meta {\n color: var(--mj-text-muted);\n font-size: 13px;\n white-space: nowrap;\n }\n .sr-icon-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s;\n font-size: 13px;\n flex-shrink: 0;\n }\n .sr-icon-btn:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n .sr-icon-btn:disabled { opacity: 0.4; cursor: default; }\n .sr-refine-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n }\n .sr-refine-icon {\n position: absolute;\n left: 8px;\n color: var(--mj-text-muted);\n font-size: 12px;\n pointer-events: none;\n }\n .sr-refine-input {\n padding: 5px 28px 5px 26px;\n font-size: 12px;\n width: 180px;\n border-radius: 6px;\n }\n .sr-refine-clear {\n position: absolute;\n right: 6px;\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 11px;\n padding: 2px;\n }\n .sr-refine-clear:hover { color: var(--mj-text-primary); }\n .sr-sort-select {\n padding: 5px 24px 5px 8px;\n font-size: 12px;\n border-radius: 6px;\n min-width: 130px;\n }\n .search-loading {\n display: flex;\n justify-content: center;\n padding: 60px 0;\n }\n .search-body {\n flex: 1;\n display: flex;\n gap: 16px;\n padding: 16px 24px;\n overflow: hidden;\n }\n .search-body mj-search-filter {\n flex-shrink: 0;\n width: 240px;\n overflow-y: auto;\n }\n .search-body mj-search-results {\n flex: 1;\n min-width: 0;\n overflow-y: auto;\n }\n .search-no-results {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-muted);\n }\n .search-no-results i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.4;\n }\n .search-no-results h3 {\n font-size: 18px;\n color: var(--mj-text-primary);\n margin: 0 0 8px;\n }\n .search-no-results p {\n font-size: 14px;\n margin: 0;\n }\n .search-results-body-wrapper {\n position: relative;\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n .search-requery-overlay {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-bg-page) 75%, transparent);\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .search-no-results-inline {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n color: var(--mj-text-muted);\n padding: 40px 20px;\n }\n .search-no-results-inline i {\n font-size: 32px;\n opacity: 0.4;\n }\n .search-no-results-inline p {\n font-size: 13px;\n margin: 0;\n }\n .sr-view-toggle {\n display: flex;\n gap: 2px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n padding: 2px;\n background: var(--mj-bg-surface-sunken);\n }\n .sr-view-toggle .sr-icon-btn {\n border: none;\n border-radius: 4px;\n width: 28px;\n height: 26px;\n font-size: 12px;\n background: transparent;\n }\n .sr-view-toggle .sr-icon-btn.sr-view-active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n }\n .search-cloud-wrapper {\n flex: 1;\n padding: 24px;\n overflow: hidden;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .search-cloud-wrapper mj-word-cloud {\n width: 100%;\n height: 100%;\n max-height: 600px;\n }\n .streaming-status-strip {\n display: flex;\n flex-wrap: wrap;\n gap: 0.4rem;\n padding: 0.5rem 1rem;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n .streaming-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.2rem 0.55rem;\n border-radius: 9999px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 0.74rem;\n }\n .streaming-chip-pending {\n color: var(--mj-text-muted);\n }\n .streaming-chip-completed {\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n border-color: var(--mj-status-success-border);\n color: var(--mj-status-success-text);\n }\n .streaming-chip-error {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n border-color: var(--mj-status-error-border);\n color: var(--mj-status-error-text);\n }\n .streaming-chip-name { font-weight: 500; }\n .streaming-chip-count { opacity: 0.7; }\n .streaming-chip-time { opacity: 0.6; font-size: 0.7rem; }\n `]\n})\nexport class SearchResultsResource extends BaseResourceComponent {\n private cdr = inject(ChangeDetectorRef);\n private searchService = inject(SearchService);\n private fileOpenService = inject(FileOpenService);\n\n CurrentQuery = '';\n IsSearching = false;\n HasSearched = false;\n TotalCount = 0;\n ElapsedMs = 0;\n Filters: SearchFilter[] = [];\n ActiveFilters: Record<string, string[]> = {};\n FilteredResults: SearchResultItem[] = [];\n MinScorePercent = 30;\n /** The MinScore that was sent to the server on the last search. If the user\n * slides below this, we need to re-query the server to get more results. */\n serverMinScorePercent = 30;\n /** How many results the server returned (before client-side filtering) */\n ServerResultCount = 0;\n ShowFilterPanel = true;\n SortField: 'score' | 'title' | 'entity' = 'score';\n ClientFilterText = '';\n ViewMode: 'list' | 'cloud' = 'list';\n CloudItems: WordCloudItem[] = [];\n IsLoadingCloud = false;\n\n /** All results from the last search (before client-side filtering) */\n private allResults: SearchResultItem[] = [];\n\n /** Selected scope IDs from the search bar (empty = unscoped/global). */\n private ScopeIDs: string[] = [];\n\n /**\n * Phase 2C streaming opt-in. Off by default to preserve Phase 1 request-response UX.\n * Enable per-resource via `Data.Configuration.EnableStreaming` or per-tab via the\n * `?stream=1` query param (mostly for engineering verification before flipping the\n * default).\n */\n EnableStreaming = false;\n\n /** Per-provider stream status displayed above results while a stream is in flight. */\n StreamingProviders: StreamingProviderStatus[] = [];\n\n /** Active stream subscription so we can cancel on a new search or destroy. */\n private currentStream: Subscription | null = null;\n\n private dataLoaded = false;\n\n // Override Data setter to trigger search when tab container provides the data\n // (ngOnInit fires before Data is set, so we can't rely on it)\n override set Data(value: ResourceData) {\n super.Data = value;\n if (!this.dataLoaded) {\n this.dataLoaded = true;\n this.loadFromData();\n }\n }\n override get Data(): ResourceData {\n return super.Data;\n }\n\n private async loadFromData(): Promise<void> {\n this.registerAgentTools();\n\n // Load filter panel preference\n try {\n const { UserInfoEngine } = require('@memberjunction/core-entities');\n const pref = UserInfoEngine.Instance.GetSetting('search.showFilterPanel');\n if (pref === 'false') this.ShowFilterPanel = false;\n } catch { /* ignore */ }\n\n const config = this.Data?.Configuration;\n if (config?.Query) {\n this.CurrentQuery = config.Query as string;\n } else if (config?.SearchInput) {\n this.CurrentQuery = config.SearchInput as string;\n }\n\n // Apply min relevance from the search bar dropdown if provided\n if (config?.MinRelevance != null) {\n const mr = Number(config.MinRelevance);\n if (!isNaN(mr) && mr >= 0 && mr <= 100) {\n this.MinScorePercent = mr;\n }\n }\n\n // Carry scope selection from the search bar through into the initial query.\n if (Array.isArray(config?.ScopeIDs)) {\n this.ScopeIDs = (config.ScopeIDs as unknown[]).filter((x): x is string => typeof x === 'string');\n }\n\n // Streaming opt-in: resource config wins; URL query param `?stream=1` is the\n // engineering-verification override (cleared once the default flips). Read the\n // URL directly because the resource's tab config doesn't always mirror URL params\n // into `Configuration.queryParams` at the moment loadFromData() runs.\n if (config?.EnableStreaming === true) {\n this.EnableStreaming = true;\n }\n try {\n const streamParam = new URL(window.location.href).searchParams.get('stream');\n if (streamParam === '1' || streamParam === 'true') {\n this.EnableStreaming = true;\n }\n } catch { /* ignore — server-side render or odd URL */ }\n\n // Sync min relevance to URL query param\n this.navigationService.UpdateActiveTabQueryParams({ minRelevance: String(this.MinScorePercent) });\n\n if (this.CurrentQuery) {\n await this.ExecuteSearch(this.CurrentQuery);\n }\n\n this.NotifyLoadComplete();\n }\n\n override ngOnDestroy(): void {\n this.currentStream?.unsubscribe();\n this.currentStream = null;\n super.ngOnDestroy();\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n const query = (data.Configuration?.Query ?? data.Configuration?.SearchInput ?? 'Search') as string;\n return `Search: ${query}`;\n }\n\n async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-magnifying-glass';\n }\n\n async OnRefineSearch(query: string): Promise<void> {\n const trimmed = query?.trim();\n if (trimmed && trimmed.length >= 2) {\n this.CurrentQuery = trimmed;\n this.ActiveFilters = {};\n await this.ExecuteSearch(trimmed);\n }\n }\n\n OnFilterChanged(event: SearchFilterChangeEvent): void {\n this.ActiveFilters = {\n ...this.ActiveFilters,\n [event.Category]: event.SelectedValues\n };\n this.applyClientFilters();\n }\n\n OnFiltersCleared(): void {\n this.ActiveFilters = {};\n this.MinScorePercent = 30;\n this.navigationService.UpdateActiveTabQueryParams({ minRelevance: '30' });\n this.applyClientFilters();\n }\n\n OnMinScoreChanged(percent: number): void {\n this.MinScorePercent = percent;\n this.navigationService.UpdateActiveTabQueryParams({ minRelevance: String(percent) });\n if (percent < this.serverMinScorePercent && this.CurrentQuery) {\n // User lowered below what server filtered — need to re-query with lower threshold\n this.ExecuteSearch(this.CurrentQuery);\n } else {\n // User raised or stayed at/above server threshold — client-side filter is sufficient\n this.applyClientFilters();\n }\n }\n\n /**\n * React to ?minRelevance= changes that arrive after initial load — e.g. a Home pin or\n * deep link to a specific relevance threshold, or browser back/forward — when this tab\n * is re-focused rather than freshly loaded (so loadFromData() does not run again).\n */\n protected override OnQueryParamsChanged(params: Record<string, string>, _source: 'popstate' | 'deeplink'): void {\n const minRelevance = params['minRelevance'];\n if (minRelevance == null) return;\n const mr = Number(minRelevance);\n if (isNaN(mr) || mr < 0 || mr > 100 || mr === this.MinScorePercent) return;\n\n this.MinScorePercent = mr;\n if (mr < this.serverMinScorePercent && this.CurrentQuery) {\n // Below what the server filtered — re-query with the lower threshold.\n void this.ExecuteSearch(this.CurrentQuery);\n } else {\n this.applyClientFilters();\n }\n }\n\n OnResultSelected(event: SearchResultSelectedEvent): void {\n this.navigateToResult(event.Result);\n }\n\n OnOpenRecord(result: SearchResultItem): void {\n this.navigateToResult(result);\n }\n\n async OnRefresh(): Promise<void> {\n if (this.CurrentQuery) {\n this.ActiveFilters = {};\n this.MinScorePercent = 30;\n this.ClientFilterText = '';\n await this.ExecuteSearch(this.CurrentQuery);\n }\n }\n\n ToggleFilterPanel(): void {\n this.ShowFilterPanel = !this.ShowFilterPanel;\n // Persist preference\n try {\n const { UserInfoEngine } = require('@memberjunction/core-entities');\n UserInfoEngine.Instance.SetSettingDebounced(\n 'search.showFilterPanel',\n this.ShowFilterPanel ? 'true' : 'false'\n );\n } catch { /* ignore if UserInfoEngine not available */ }\n this.cdr.detectChanges();\n }\n\n OnSortChange(field: string): void {\n this.SortField = field as 'score' | 'title' | 'entity';\n this.applyClientFilters();\n }\n\n OnClientFilterTextChange(text: string): void {\n this.ClientFilterText = text;\n this.applyClientFilters();\n }\n\n SetViewMode(mode: 'list' | 'cloud'): void {\n this.ViewMode = mode;\n if (mode === 'cloud') {\n this.buildCloudItems();\n }\n this.emitAgentContext();\n this.cdr.detectChanges();\n }\n\n OnCloudItemClick(_event: WordCloudItemEvent): void {\n // No-op for now — tag filtering in the filter panel is not yet implemented.\n // Future: clicking a tag could filter results to only those with that tag.\n }\n\n /**\n * Navigate to a search result based on its ResultType discriminator.\n * - entity-record: opens the MJ entity record viewer\n * - storage-file: opens the file via pre-authenticated URL in new tab\n * - content-item: opens the MJ entity record viewer (content items are entity records)\n */\n private navigateToResult(result: SearchResultItem): void {\n if (result.ResultType === 'storage-file') {\n // Try preview first (opens in provider's web viewer), fall back to download\n if (!this.fileOpenService.OpenPreviewFromSearchResult(result.RawMetadata)) {\n this.fileOpenService.OpenFileFromSearchResult(result.RawMetadata);\n }\n return;\n }\n\n if (!result.EntityName || !result.RecordID) return;\n\n // entity-record, content-item, or unset — navigate to entity record\n const pkey = new CompositeKey([{ FieldName: 'ID', Value: result.RecordID }]);\n this.navigationService.OpenEntityRecord(result.EntityName, pkey);\n }\n\n private async ExecuteSearch(query: string): Promise<void> {\n this.IsSearching = true;\n this.HasSearched = false;\n this.cdr.detectChanges();\n\n this.serverMinScorePercent = this.MinScorePercent;\n const request: SearchRequest = {\n Query: query,\n MaxResults: 50,\n ActiveFilters: {},\n IncludeSources: ['vector', 'fulltext', 'entity', 'storage'],\n MinScore: this.MinScorePercent / 100\n };\n if (this.ScopeIDs.length > 0) {\n request.ScopeIDs = [...this.ScopeIDs];\n }\n\n if (this.EnableStreaming) {\n this.executeStreamingSearch(query, request);\n return;\n }\n\n const response: SearchResponse = await this.searchService.ExecuteSearch(request);\n\n this.allResults = [...response.Results].sort((a, b) => b.Score - a.Score);\n this.ServerResultCount = this.allResults.length;\n this.TotalCount = response.TotalCount;\n this.ElapsedMs = response.ElapsedMs;\n this.Filters = response.Filters;\n this.FilteredResults = [...this.allResults];\n\n this.IsSearching = false;\n this.HasSearched = true;\n this.emitAgentContext();\n this.cdr.detectChanges();\n }\n\n /**\n * Phase 2C streaming variant. Subscribes to `streamScopedSearch` and progressively\n * populates the result list as each provider reports back. The 'final' event carries\n * the canonical fused/reranked list, which replaces any partials the user already saw.\n *\n * Cancellation: a new query starts by tearing down the in-flight stream so events\n * from a stale search do not bleed into the current view.\n */\n private executeStreamingSearch(query: string, request: SearchRequest): void {\n // Cancel any prior stream so events from a stale query don't leak in.\n this.currentStream?.unsubscribe();\n this.currentStream = null;\n\n // Reset visible streaming state.\n this.StreamingProviders = [];\n this.allResults = [];\n this.FilteredResults = [];\n this.ServerResultCount = 0;\n this.TotalCount = 0;\n this.ElapsedMs = 0;\n this.cdr.detectChanges();\n\n this.currentStream = this.searchService.StreamSearch(request).subscribe({\n next: (event) => {\n if (event.Phase === 'provider' && event.ProviderName) {\n const count = event.Results?.length ?? 0;\n this.StreamingProviders = [\n ...this.StreamingProviders,\n {\n Name: event.ProviderName,\n Count: count,\n ElapsedMs: event.ElapsedMs ?? 0,\n State: 'Completed',\n },\n ];\n if (event.Results && event.Results.length > 0) {\n this.allResults = [...this.allResults, ...event.Results].sort((a, b) => b.Score - a.Score);\n this.ServerResultCount = this.allResults.length;\n this.applyClientFilters();\n }\n } else if (event.Phase === 'final' && event.Results) {\n this.allResults = [...event.Results].sort((a, b) => b.Score - a.Score);\n this.ServerResultCount = this.allResults.length;\n this.TotalCount = event.Results.length;\n this.ElapsedMs = event.ElapsedMs ?? this.ElapsedMs;\n this.Filters = this.searchService.BuildFilters(this.allResults);\n this.applyClientFilters();\n this.HasSearched = true;\n }\n this.cdr.detectChanges();\n },\n error: (err: Error) => {\n this.StreamingProviders = [\n ...this.StreamingProviders,\n { Name: 'stream', Count: 0, ElapsedMs: 0, State: 'Error', ErrorMessage: err.message },\n ];\n this.IsSearching = false;\n this.HasSearched = true;\n this.cdr.detectChanges();\n },\n complete: () => {\n this.IsSearching = false;\n this.HasSearched = true;\n this.emitAgentContext();\n this.cdr.detectChanges();\n },\n });\n }\n\n /**\n * Apply active filter selections to the full result set.\n */\n private applyClientFilters(): void {\n let results = this.allResults;\n\n // Apply min score filter FIRST (this determines what's \"available\")\n if (this.MinScorePercent > 0) {\n const minScore = this.MinScorePercent / 100;\n results = results.filter(r => r.Score >= minScore);\n }\n\n // Rebuild filters from score-filtered results so counts are accurate\n this.Filters = this.searchService.BuildFilters(results);\n this.TotalCount = results.length;\n\n // Apply facet filters\n if (this.hasActiveFilters()) {\n results = results.filter(r => this.matchesActiveFilters(r));\n }\n\n // Apply client text filter (search within results)\n if (this.ClientFilterText.trim()) {\n const term = this.ClientFilterText.trim().toLowerCase();\n results = results.filter(r =>\n (r.Title?.toLowerCase().includes(term)) ||\n (r.Snippet?.toLowerCase().includes(term)) ||\n (r.EntityName?.toLowerCase().includes(term)) ||\n (r.RecordName?.toLowerCase().includes(term)) ||\n (r.Tags?.some(t => t.toLowerCase().includes(term)))\n );\n }\n\n // Sort\n switch (this.SortField) {\n case 'title':\n results = [...results].sort((a, b) => (a.Title || '').localeCompare(b.Title || ''));\n break;\n case 'entity':\n results = [...results].sort((a, b) => a.EntityName.localeCompare(b.EntityName) || b.Score - a.Score);\n break;\n case 'score':\n default:\n results = [...results].sort((a, b) => b.Score - a.Score);\n break;\n }\n\n this.FilteredResults = results;\n this.emitAgentContext();\n this.cdr.detectChanges();\n }\n\n private hasActiveFilters(): boolean {\n return Object.values(this.ActiveFilters).some(v => v.length > 0);\n }\n\n private matchesActiveFilters(result: SearchResultItem): boolean {\n const entityFilter = this.ActiveFilters['Entity'];\n if (entityFilter?.length) {\n const matchesEntity = entityFilter.includes(result.EntityName);\n const matchesFiles = entityFilter.includes('__storage-files__') && result.ResultType === 'storage-file';\n if (!matchesEntity && !matchesFiles) return false;\n }\n\n const sourceFilter = this.ActiveFilters['Source'];\n if (sourceFilter?.length && !sourceFilter.includes(result.SourceType)) {\n return false;\n }\n\n const tagFilter = this.ActiveFilters['Tags'];\n if (tagFilter?.length && !tagFilter.some(t => result.Tags.includes(t))) {\n return false;\n }\n\n const fileTypeFilter = this.ActiveFilters['File Type'];\n if (fileTypeFilter?.length) {\n if (result.ResultType !== 'storage-file') return false;\n const ext = result.Title?.split('.').pop()?.toUpperCase() ?? '';\n if (!fileTypeFilter.includes(ext)) return false;\n }\n\n return true;\n }\n\n /**\n * Build WordCloudItem[] from search results by extracting entity names and tags,\n * weighted by their frequency across all results.\n */\n /**\n * Build word cloud items from MJ: Tagged Items linked to the search results.\n * Queries the TaggedItem entity for all records in the result set, aggregates\n * tag names by count and weight, and builds WordCloudItem[] for the cloud.\n */\n private async buildCloudItems(): Promise<void> {\n this.IsLoadingCloud = true;\n this.cdr.detectChanges();\n\n try {\n // Group results by entity to build efficient queries\n const byEntity = new Map<string, string[]>();\n for (const result of this.allResults) {\n const md = this.ProviderToUse;\n const entity = md.Entities.find(e => e.Name === result.EntityName);\n if (!entity) continue;\n const list = byEntity.get(entity.ID) || [];\n list.push(result.RecordID);\n byEntity.set(entity.ID, list);\n }\n\n // Query Tagged Items for all record IDs across all entities\n const tagAggregates = new Map<string, { count: number; totalWeight: number }>();\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n\n for (const [entityID, recordIDs] of byEntity) {\n if (recordIDs.length === 0) continue;\n\n // Build IN clause (batch in groups of 50 to avoid huge queries)\n for (let i = 0; i < recordIDs.length; i += 50) {\n const batch = recordIDs.slice(i, i + 50);\n const inClause = batch.map(id => `'${id.replace(/'/g, \"''\")}'`).join(',');\n\n const result = await rv.RunView<{ Tag: string; Weight: number }>({\n EntityName: 'MJ: Tagged Items',\n ExtraFilter: `EntityID = '${entityID}' AND RecordID IN (${inClause})`,\n Fields: ['Tag', 'Weight'],\n ResultType: 'simple'\n });\n\n if (result.Success && result.Results) {\n for (const row of result.Results) {\n const tagName = row.Tag;\n if (!tagName) continue;\n const existing = tagAggregates.get(tagName) || { count: 0, totalWeight: 0 };\n existing.count++;\n existing.totalWeight += (row.Weight ?? 1);\n tagAggregates.set(tagName, existing);\n }\n }\n }\n }\n\n // Build cloud items from aggregated tags\n if (tagAggregates.size === 0) {\n this.CloudItems = [{ Text: 'No tags found', Weight: 1, Category: 'empty' }];\n } else {\n const maxWeight = Math.max(...Array.from(tagAggregates.values()).map(v => v.totalWeight), 1);\n this.CloudItems = Array.from(tagAggregates.entries())\n .sort((a, b) => b[1].totalWeight - a[1].totalWeight)\n .map(([tagName, agg]) => ({\n Text: tagName,\n Weight: agg.totalWeight / maxWeight,\n Category: 'tag',\n Metadata: { type: 'tag', count: agg.count, totalWeight: agg.totalWeight }\n }));\n }\n } catch (err) {\n this.CloudItems = [{ Text: 'Error loading tags', Weight: 1, Category: 'error' }];\n }\n\n this.IsLoadingCloud = false;\n this.cdr.detectChanges();\n }\n\n /** Report current search state to the AI agent */\n private emitAgentContext(): void {\n this.navigationService.SetAgentContext(this, {\n CurrentQuery: this.CurrentQuery || null,\n ResultCount: this.TotalCount,\n FilteredCount: this.FilteredResults.length,\n ElapsedMs: this.ElapsedMs,\n HasSearched: this.HasSearched,\n ShowFilterPanel: this.ShowFilterPanel,\n ViewMode: this.ViewMode,\n SortField: this.SortField,\n MinScorePercent: this.MinScorePercent,\n ClientFilterText: this.ClientFilterText,\n ActiveFilterCount: Object.values(this.ActiveFilters).filter(v => v.length > 0).length,\n TopResults: this.FilteredResults.slice(0, 50).map(r => ({\n Title: r.Title || r.RecordName,\n EntityName: r.EntityName,\n RecordID: r.RecordID,\n Score: Math.round(r.Score * 100),\n SourceType: r.SourceType,\n Snippet: r.Snippet?.substring(0, 100)\n })),\n });\n }\n\n /** Register client tools the agent can invoke on the search results */\n private registerAgentTools(): void {\n this.navigationService.SetAgentClientTools(this, [\n {\n Name: 'RunSearch',\n Description: 'Execute a search query and display results',\n ParameterSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'The search query text' }\n },\n required: ['query']\n },\n Handler: async (params: Record<string, unknown>) => {\n const query = String(params['query'] ?? '');\n this.CurrentQuery = query;\n await this.ExecuteSearch(query);\n return { Success: true, Data: { ResultCount: this.TotalCount, ElapsedMs: this.ElapsedMs } };\n }\n },\n {\n Name: 'SortResults',\n Description: 'Change the sort order of search results',\n ParameterSchema: {\n type: 'object',\n properties: {\n field: { type: 'string', enum: ['score', 'title', 'entity'], description: 'Sort field' }\n },\n required: ['field']\n },\n Handler: async (params: Record<string, unknown>) => {\n this.OnSortChange(String(params['field']));\n return { Success: true, Data: { SortField: this.SortField } };\n }\n },\n {\n Name: 'FilterWithinResults',\n Description: 'Filter the current results by a keyword (client-side text filter)',\n ParameterSchema: {\n type: 'object',\n properties: {\n text: { type: 'string', description: 'Filter text (empty string to clear)' }\n },\n required: ['text']\n },\n Handler: async (params: Record<string, unknown>) => {\n this.OnClientFilterTextChange(String(params['text'] ?? ''));\n return { Success: true, Data: { FilteredCount: this.FilteredResults.length } };\n }\n },\n {\n Name: 'SetViewMode',\n Description: 'Switch between list view and tag cloud visualization',\n ParameterSchema: {\n type: 'object',\n properties: {\n mode: { type: 'string', enum: ['list', 'cloud'], description: 'View mode' }\n },\n required: ['mode']\n },\n Handler: async (params: Record<string, unknown>) => {\n this.SetViewMode((params['mode'] as 'list' | 'cloud') ?? 'list');\n return { Success: true, Data: { ViewMode: this.ViewMode } };\n }\n },\n {\n Name: 'ToggleFilterPanel',\n Description: 'Show or hide the filter panel on the left',\n ParameterSchema: { type: 'object', properties: {} },\n Handler: async () => {\n this.ToggleFilterPanel();\n return { Success: true, Data: { ShowFilterPanel: this.ShowFilterPanel } };\n }\n },\n {\n Name: 'SetMinRelevance',\n Description: 'Set the minimum relevance score filter (0-100 percent)',\n ParameterSchema: {\n type: 'object',\n properties: {\n percent: { type: 'number', description: 'Minimum relevance percentage (0-100)' }\n },\n required: ['percent']\n },\n Handler: async (params: Record<string, unknown>) => {\n this.OnMinScoreChanged(Number(params['percent'] ?? 0));\n return { Success: true, Data: { MinScorePercent: this.MinScorePercent, FilteredCount: this.FilteredResults.length } };\n }\n },\n {\n Name: 'RefreshSearch',\n Description: 'Re-execute the current search query',\n ParameterSchema: { type: 'object', properties: {} },\n Handler: async () => {\n await this.OnRefresh();\n return { Success: true, Data: { ResultCount: this.TotalCount, ElapsedMs: this.ElapsedMs } };\n }\n }\n ]);\n }\n}\n\nexport function LoadSearchResultsResource() {\n // Tree-shaking prevention\n}\n"]}
|
|
1
|
+
{"version":3,"file":"search-results-resource.component.js","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/search-results-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, inject } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { CompositeKey, Metadata, RunView } from '@memberjunction/core';\nimport { ResourceData } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport { FileOpenService } from '@memberjunction/ng-file-storage';\nimport {\n SearchService,\n SearchResultItem,\n SearchFilter,\n SearchFilterChangeEvent,\n SearchRequest,\n SearchResponse,\n SearchResultSelectedEvent,\n StreamingProviderStatus,\n} from '@memberjunction/ng-search';\nimport { WordCloudItem, WordCloudItemEvent } from '@memberjunction/ng-word-cloud';\n\n@RegisterClass(BaseResourceComponent, 'SearchResultsResource')\n@Component({\n standalone: false,\n selector: 'mj-search-results-resource',\n template: `\n <div class=\"search-results-page\">\n <!-- Streaming status strip — visible while streamScopedSearch is in flight -->\n @if (EnableStreaming && (IsSearching || StreamingProviders.length > 0)) {\n <div class=\"streaming-status-strip\" aria-live=\"polite\">\n @for (p of StreamingProviders; track p.Name) {\n <span class=\"streaming-chip\"\n [class.streaming-chip-error]=\"p.State === 'Error'\"\n [class.streaming-chip-completed]=\"p.State === 'Completed'\">\n @if (p.State === 'Completed') {\n <i class=\"fa-solid fa-check\"></i>\n } @else {\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n }\n <span class=\"streaming-chip-name\">{{ p.Name }}</span>\n @if (p.State === 'Completed') {\n <span class=\"streaming-chip-count\">{{ p.Count }}</span>\n <span class=\"streaming-chip-time\">{{ p.ElapsedMs }}ms</span>\n } @else if (p.ErrorMessage) {\n <span class=\"streaming-chip-time\">{{ p.ErrorMessage }}</span>\n }\n </span>\n }\n @if (IsSearching) {\n <span class=\"streaming-chip streaming-chip-pending\">\n <i class=\"fa-solid fa-circle-notch fa-spin\"></i>\n <span>Streaming…</span>\n </span>\n }\n </div>\n }\n\n <!-- Header bar (always visible when we have server results) -->\n @if (HasSearched && ServerResultCount > 0) {\n <div class=\"search-header\">\n <div class=\"search-header-left\">\n @if (!ShowFilterPanel) {\n <button class=\"sr-icon-btn\" title=\"Show filters\" (click)=\"ToggleFilterPanel()\">\n <i class=\"fa-solid fa-filter\"></i>\n </button>\n }\n <span class=\"search-meta\">\n {{ FilteredResults.length }} of {{ ServerResultCount }} result{{ ServerResultCount !== 1 ? 's' : '' }}\n for \"{{ CurrentQuery }}\" in {{ ElapsedMs }}ms\n </span>\n </div>\n <div class=\"search-header-right\">\n <!-- Search within results -->\n <div class=\"sr-refine-wrapper\">\n <i class=\"fa-solid fa-filter-list sr-refine-icon\"></i>\n <input class=\"mj-input sr-refine-input\"\n placeholder=\"Filter within results...\"\n [value]=\"ClientFilterText\"\n (input)=\"OnClientFilterTextChange($any($event.target).value)\" />\n @if (ClientFilterText) {\n <button class=\"sr-refine-clear\" (click)=\"OnClientFilterTextChange('')\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n }\n </div>\n <!-- Sort -->\n <select class=\"mj-input sr-sort-select\" [value]=\"SortField\" (change)=\"OnSortChange($any($event.target).value)\">\n <option value=\"score\">Sort: Relevance</option>\n <option value=\"title\">Sort: Name</option>\n <option value=\"entity\">Sort: Entity</option>\n </select>\n <!-- View mode toggle -->\n <div class=\"sr-view-toggle\">\n <button class=\"sr-icon-btn\"\n [class.sr-view-active]=\"ViewMode === 'list'\"\n title=\"List view\"\n (click)=\"SetViewMode('list')\">\n <i class=\"fa-solid fa-list\"></i>\n </button>\n <button class=\"sr-icon-btn\"\n [class.sr-view-active]=\"ViewMode === 'cloud'\"\n title=\"Tag cloud view\"\n (click)=\"SetViewMode('cloud')\">\n <i class=\"fa-solid fa-cloud\"></i>\n </button>\n </div>\n <!-- Refresh -->\n <button class=\"sr-icon-btn\" title=\"Refresh search\" (click)=\"OnRefresh()\" [disabled]=\"IsSearching\">\n <i class=\"fa-solid fa-arrows-rotate\" [class.fa-spin]=\"IsSearching\"></i>\n </button>\n </div>\n </div>\n }\n\n <!-- Initial loading (first search) -->\n @if (IsSearching && ServerResultCount === 0) {\n <div class=\"search-loading\">\n <mj-loading text=\"Searching...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- No server results -->\n @if (!IsSearching && ServerResultCount === 0 && HasSearched) {\n <mj-empty-state\n class=\"search-no-results\"\n Variant=\"no-results\"\n Icon=\"fa-solid fa-magnifying-glass-minus\"\n Title=\"No results found\"\n Message=\"Try different keywords or broaden your search.\" />\n }\n <!-- Results body (visible when server returned results) -->\n @if (ServerResultCount > 0) {\n <div class=\"search-results-body-wrapper\">\n <!-- Semi-opaque loading overlay for re-queries (slider lowered, etc.) -->\n @if (IsSearching) {\n <div class=\"search-requery-overlay\">\n <mj-loading text=\"Updating results...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n @if (ViewMode === 'cloud') {\n <div class=\"search-cloud-wrapper\">\n @if (IsLoadingCloud) {\n <mj-loading text=\"Loading tag cloud...\" size=\"medium\"></mj-loading>\n } @else {\n <mj-word-cloud\n [Items]=\"CloudItems\"\n [MaxItems]=\"80\"\n ColorMode=\"weight-gradient\"\n [Interactive]=\"true\"\n (ItemClick)=\"OnCloudItemClick($event)\">\n </mj-word-cloud>\n }\n </div>\n } @else {\n <div class=\"search-body\">\n @if (ShowFilterPanel) {\n <mj-search-filter\n [Filters]=\"Filters\"\n [ActiveFilters]=\"ActiveFilters\"\n [ShowRelevanceSlider]=\"true\"\n [MinScorePercent]=\"MinScorePercent\"\n [ServerMinScorePercent]=\"serverMinScorePercent\"\n (FilterChanged)=\"OnFilterChanged($event)\"\n (FiltersCleared)=\"OnFiltersCleared()\"\n (CloseRequested)=\"ToggleFilterPanel()\"\n (MinScoreChanged)=\"OnMinScoreChanged($any($event))\">\n </mj-search-filter>\n }\n @if (FilteredResults.length > 0) {\n <mj-search-results\n [FlatResults]=\"FilteredResults\"\n [HighlightText]=\"ClientFilterText\"\n [ShowScores]=\"true\"\n [ShowTags]=\"true\"\n [ShowSummary]=\"false\"\n [PageSize]=\"20\"\n (ResultSelected)=\"OnResultSelected($event)\"\n (OpenRecordRequested)=\"OnOpenRecord($event)\">\n </mj-search-results>\n } @else {\n <mj-empty-state\n class=\"search-no-results-inline\"\n Variant=\"no-results\"\n Icon=\"fa-solid fa-filter-circle-xmark\"\n Title=\"No results match current filters. Try lowering the minimum relevance.\" />\n }\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [`\n .search-results-page {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n overflow: hidden;\n }\n .search-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 8px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n }\n .search-header-left {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .search-header-right {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .search-meta {\n color: var(--mj-text-muted);\n font-size: 13px;\n white-space: nowrap;\n }\n .sr-icon-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s;\n font-size: 13px;\n flex-shrink: 0;\n }\n .sr-icon-btn:hover { background: var(--mj-bg-surface-hover); color: var(--mj-text-primary); }\n .sr-icon-btn:disabled { opacity: 0.4; cursor: default; }\n .sr-refine-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n }\n .sr-refine-icon {\n position: absolute;\n left: 8px;\n color: var(--mj-text-muted);\n font-size: 12px;\n pointer-events: none;\n }\n .sr-refine-input {\n padding: 5px 28px 5px 26px;\n font-size: 12px;\n width: 180px;\n border-radius: 6px;\n }\n .sr-refine-clear {\n position: absolute;\n right: 6px;\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 11px;\n padding: 2px;\n }\n .sr-refine-clear:hover { color: var(--mj-text-primary); }\n .sr-sort-select {\n padding: 5px 24px 5px 8px;\n font-size: 12px;\n border-radius: 6px;\n min-width: 130px;\n }\n .search-loading {\n display: flex;\n justify-content: center;\n padding: 60px 0;\n }\n .search-body {\n flex: 1;\n display: flex;\n gap: 16px;\n padding: 16px 24px;\n overflow: hidden;\n }\n .search-body mj-search-filter {\n flex-shrink: 0;\n width: 240px;\n overflow-y: auto;\n }\n .search-body mj-search-results {\n flex: 1;\n min-width: 0;\n overflow-y: auto;\n }\n .search-results-body-wrapper {\n position: relative;\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n .search-requery-overlay {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-bg-page) 75%, transparent);\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .search-no-results-inline {\n flex: 1;\n }\n .sr-view-toggle {\n display: flex;\n gap: 2px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n padding: 2px;\n background: var(--mj-bg-surface-sunken);\n }\n .sr-view-toggle .sr-icon-btn {\n border: none;\n border-radius: 4px;\n width: 28px;\n height: 26px;\n font-size: 12px;\n background: transparent;\n }\n .sr-view-toggle .sr-icon-btn.sr-view-active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n }\n .search-cloud-wrapper {\n flex: 1;\n padding: 24px;\n overflow: hidden;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .search-cloud-wrapper mj-word-cloud {\n width: 100%;\n height: 100%;\n max-height: 600px;\n }\n .streaming-status-strip {\n display: flex;\n flex-wrap: wrap;\n gap: 0.4rem;\n padding: 0.5rem 1rem;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n .streaming-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.2rem 0.55rem;\n border-radius: 9999px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 0.74rem;\n }\n .streaming-chip-pending {\n color: var(--mj-text-muted);\n }\n .streaming-chip-completed {\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n border-color: var(--mj-status-success-border);\n color: var(--mj-status-success-text);\n }\n .streaming-chip-error {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n border-color: var(--mj-status-error-border);\n color: var(--mj-status-error-text);\n }\n .streaming-chip-name { font-weight: 500; }\n .streaming-chip-count { opacity: 0.7; }\n .streaming-chip-time { opacity: 0.6; font-size: 0.7rem; }\n `]\n})\nexport class SearchResultsResource extends BaseResourceComponent {\n private cdr = inject(ChangeDetectorRef);\n private searchService = inject(SearchService);\n private fileOpenService = inject(FileOpenService);\n\n CurrentQuery = '';\n IsSearching = false;\n HasSearched = false;\n TotalCount = 0;\n ElapsedMs = 0;\n Filters: SearchFilter[] = [];\n ActiveFilters: Record<string, string[]> = {};\n FilteredResults: SearchResultItem[] = [];\n MinScorePercent = 30;\n /** The MinScore that was sent to the server on the last search. If the user\n * slides below this, we need to re-query the server to get more results. */\n serverMinScorePercent = 30;\n /** How many results the server returned (before client-side filtering) */\n ServerResultCount = 0;\n ShowFilterPanel = true;\n SortField: 'score' | 'title' | 'entity' = 'score';\n ClientFilterText = '';\n ViewMode: 'list' | 'cloud' = 'list';\n CloudItems: WordCloudItem[] = [];\n IsLoadingCloud = false;\n\n /** All results from the last search (before client-side filtering) */\n private allResults: SearchResultItem[] = [];\n\n /** Selected scope IDs from the search bar (empty = unscoped/global). */\n private ScopeIDs: string[] = [];\n\n /**\n * Phase 2C streaming opt-in. Off by default to preserve Phase 1 request-response UX.\n * Enable per-resource via `Data.Configuration.EnableStreaming` or per-tab via the\n * `?stream=1` query param (mostly for engineering verification before flipping the\n * default).\n */\n EnableStreaming = false;\n\n /** Per-provider stream status displayed above results while a stream is in flight. */\n StreamingProviders: StreamingProviderStatus[] = [];\n\n /** Active stream subscription so we can cancel on a new search or destroy. */\n private currentStream: Subscription | null = null;\n\n private dataLoaded = false;\n\n // Override Data setter to trigger search when tab container provides the data\n // (ngOnInit fires before Data is set, so we can't rely on it)\n override set Data(value: ResourceData) {\n super.Data = value;\n if (!this.dataLoaded) {\n this.dataLoaded = true;\n this.loadFromData();\n }\n }\n override get Data(): ResourceData {\n return super.Data;\n }\n\n private async loadFromData(): Promise<void> {\n this.registerAgentTools();\n\n // Load filter panel preference\n try {\n const { UserInfoEngine } = require('@memberjunction/core-entities');\n const pref = UserInfoEngine.Instance.GetSetting('search.showFilterPanel');\n if (pref === 'false') this.ShowFilterPanel = false;\n } catch { /* ignore */ }\n\n const config = this.Data?.Configuration;\n if (config?.Query) {\n this.CurrentQuery = config.Query as string;\n } else if (config?.SearchInput) {\n this.CurrentQuery = config.SearchInput as string;\n }\n\n // Apply min relevance from the search bar dropdown if provided\n if (config?.MinRelevance != null) {\n const mr = Number(config.MinRelevance);\n if (!isNaN(mr) && mr >= 0 && mr <= 100) {\n this.MinScorePercent = mr;\n }\n }\n\n // Carry scope selection from the search bar through into the initial query.\n if (Array.isArray(config?.ScopeIDs)) {\n this.ScopeIDs = (config.ScopeIDs as unknown[]).filter((x): x is string => typeof x === 'string');\n }\n\n // Streaming opt-in: resource config wins; URL query param `?stream=1` is the\n // engineering-verification override (cleared once the default flips). Read the\n // URL directly because the resource's tab config doesn't always mirror URL params\n // into `Configuration.queryParams` at the moment loadFromData() runs.\n if (config?.EnableStreaming === true) {\n this.EnableStreaming = true;\n }\n try {\n const streamParam = new URL(window.location.href).searchParams.get('stream');\n if (streamParam === '1' || streamParam === 'true') {\n this.EnableStreaming = true;\n }\n } catch { /* ignore — server-side render or odd URL */ }\n\n // Sync min relevance to URL query param\n this.UpdateQueryParams({ minRelevance: String(this.MinScorePercent) });\n\n if (this.CurrentQuery) {\n await this.ExecuteSearch(this.CurrentQuery);\n }\n\n this.NotifyLoadComplete();\n }\n\n override ngOnDestroy(): void {\n this.currentStream?.unsubscribe();\n this.currentStream = null;\n super.ngOnDestroy();\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n const query = (data.Configuration?.Query ?? data.Configuration?.SearchInput ?? 'Search') as string;\n return `Search: ${query}`;\n }\n\n async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-magnifying-glass';\n }\n\n async OnRefineSearch(query: string): Promise<void> {\n const trimmed = query?.trim();\n if (trimmed && trimmed.length >= 2) {\n this.CurrentQuery = trimmed;\n this.ActiveFilters = {};\n await this.ExecuteSearch(trimmed);\n }\n }\n\n OnFilterChanged(event: SearchFilterChangeEvent): void {\n this.ActiveFilters = {\n ...this.ActiveFilters,\n [event.Category]: event.SelectedValues\n };\n this.applyClientFilters();\n }\n\n OnFiltersCleared(): void {\n this.ActiveFilters = {};\n this.MinScorePercent = 30;\n this.UpdateQueryParams({ minRelevance: '30' });\n this.applyClientFilters();\n }\n\n OnMinScoreChanged(percent: number): void {\n this.MinScorePercent = percent;\n this.UpdateQueryParams({ minRelevance: String(percent) });\n if (percent < this.serverMinScorePercent && this.CurrentQuery) {\n // User lowered below what server filtered — need to re-query with lower threshold\n this.ExecuteSearch(this.CurrentQuery);\n } else {\n // User raised or stayed at/above server threshold — client-side filter is sufficient\n this.applyClientFilters();\n }\n }\n\n /**\n * React to ?minRelevance= changes that arrive after initial load — e.g. a Home pin or\n * deep link to a specific relevance threshold, or browser back/forward — when this tab\n * is re-focused rather than freshly loaded (so loadFromData() does not run again).\n */\n protected override OnQueryParamsChanged(params: Record<string, string>, _source: 'popstate' | 'deeplink'): void {\n const minRelevance = params['minRelevance'];\n if (minRelevance == null) return;\n const mr = Number(minRelevance);\n if (isNaN(mr) || mr < 0 || mr > 100 || mr === this.MinScorePercent) return;\n\n this.MinScorePercent = mr;\n if (mr < this.serverMinScorePercent && this.CurrentQuery) {\n // Below what the server filtered — re-query with the lower threshold.\n void this.ExecuteSearch(this.CurrentQuery);\n } else {\n this.applyClientFilters();\n }\n }\n\n OnResultSelected(event: SearchResultSelectedEvent): void {\n this.navigateToResult(event.Result);\n }\n\n OnOpenRecord(result: SearchResultItem): void {\n this.navigateToResult(result);\n }\n\n async OnRefresh(): Promise<void> {\n if (this.CurrentQuery) {\n this.ActiveFilters = {};\n this.MinScorePercent = 30;\n this.ClientFilterText = '';\n await this.ExecuteSearch(this.CurrentQuery);\n }\n }\n\n ToggleFilterPanel(): void {\n this.ShowFilterPanel = !this.ShowFilterPanel;\n // Persist preference\n try {\n const { UserInfoEngine } = require('@memberjunction/core-entities');\n UserInfoEngine.Instance.SetSettingDebounced(\n 'search.showFilterPanel',\n this.ShowFilterPanel ? 'true' : 'false'\n );\n } catch { /* ignore if UserInfoEngine not available */ }\n this.cdr.detectChanges();\n }\n\n OnSortChange(field: string): void {\n this.SortField = field as 'score' | 'title' | 'entity';\n this.applyClientFilters();\n }\n\n OnClientFilterTextChange(text: string): void {\n this.ClientFilterText = text;\n this.applyClientFilters();\n }\n\n SetViewMode(mode: 'list' | 'cloud'): void {\n this.ViewMode = mode;\n if (mode === 'cloud') {\n this.buildCloudItems();\n }\n this.emitAgentContext();\n this.cdr.detectChanges();\n }\n\n OnCloudItemClick(_event: WordCloudItemEvent): void {\n // No-op for now — tag filtering in the filter panel is not yet implemented.\n // Future: clicking a tag could filter results to only those with that tag.\n }\n\n /**\n * Navigate to a search result based on its ResultType discriminator.\n * - entity-record: opens the MJ entity record viewer\n * - storage-file: opens the file via pre-authenticated URL in new tab\n * - content-item: opens the MJ entity record viewer (content items are entity records)\n */\n private navigateToResult(result: SearchResultItem): void {\n if (result.ResultType === 'storage-file') {\n // Try preview first (opens in provider's web viewer), fall back to download\n if (!this.fileOpenService.OpenPreviewFromSearchResult(result.RawMetadata)) {\n this.fileOpenService.OpenFileFromSearchResult(result.RawMetadata);\n }\n return;\n }\n\n if (!result.EntityName || !result.RecordID) return;\n\n // entity-record, content-item, or unset — navigate to entity record\n const pkey = new CompositeKey([{ FieldName: 'ID', Value: result.RecordID }]);\n this.navigationService.OpenEntityRecord(result.EntityName, pkey);\n }\n\n private async ExecuteSearch(query: string): Promise<void> {\n this.IsSearching = true;\n this.HasSearched = false;\n this.cdr.detectChanges();\n\n this.serverMinScorePercent = this.MinScorePercent;\n const request: SearchRequest = {\n Query: query,\n MaxResults: 50,\n ActiveFilters: {},\n IncludeSources: ['vector', 'fulltext', 'entity', 'storage'],\n MinScore: this.MinScorePercent / 100\n };\n if (this.ScopeIDs.length > 0) {\n request.ScopeIDs = [...this.ScopeIDs];\n }\n\n if (this.EnableStreaming) {\n this.executeStreamingSearch(query, request);\n return;\n }\n\n const response: SearchResponse = await this.searchService.ExecuteSearch(request);\n\n this.allResults = [...response.Results].sort((a, b) => b.Score - a.Score);\n this.ServerResultCount = this.allResults.length;\n this.TotalCount = response.TotalCount;\n this.ElapsedMs = response.ElapsedMs;\n this.Filters = response.Filters;\n this.FilteredResults = [...this.allResults];\n\n this.IsSearching = false;\n this.HasSearched = true;\n this.emitAgentContext();\n this.cdr.detectChanges();\n }\n\n /**\n * Phase 2C streaming variant. Subscribes to `streamScopedSearch` and progressively\n * populates the result list as each provider reports back. The 'final' event carries\n * the canonical fused/reranked list, which replaces any partials the user already saw.\n *\n * Cancellation: a new query starts by tearing down the in-flight stream so events\n * from a stale search do not bleed into the current view.\n */\n private executeStreamingSearch(query: string, request: SearchRequest): void {\n // Cancel any prior stream so events from a stale query don't leak in.\n this.currentStream?.unsubscribe();\n this.currentStream = null;\n\n // Reset visible streaming state.\n this.StreamingProviders = [];\n this.allResults = [];\n this.FilteredResults = [];\n this.ServerResultCount = 0;\n this.TotalCount = 0;\n this.ElapsedMs = 0;\n this.cdr.detectChanges();\n\n this.currentStream = this.searchService.StreamSearch(request).subscribe({\n next: (event) => {\n if (event.Phase === 'provider' && event.ProviderName) {\n const count = event.Results?.length ?? 0;\n this.StreamingProviders = [\n ...this.StreamingProviders,\n {\n Name: event.ProviderName,\n Count: count,\n ElapsedMs: event.ElapsedMs ?? 0,\n State: 'Completed',\n },\n ];\n if (event.Results && event.Results.length > 0) {\n this.allResults = [...this.allResults, ...event.Results].sort((a, b) => b.Score - a.Score);\n this.ServerResultCount = this.allResults.length;\n this.applyClientFilters();\n }\n } else if (event.Phase === 'final' && event.Results) {\n this.allResults = [...event.Results].sort((a, b) => b.Score - a.Score);\n this.ServerResultCount = this.allResults.length;\n this.TotalCount = event.Results.length;\n this.ElapsedMs = event.ElapsedMs ?? this.ElapsedMs;\n this.Filters = this.searchService.BuildFilters(this.allResults);\n this.applyClientFilters();\n this.HasSearched = true;\n }\n this.cdr.detectChanges();\n },\n error: (err: Error) => {\n this.StreamingProviders = [\n ...this.StreamingProviders,\n { Name: 'stream', Count: 0, ElapsedMs: 0, State: 'Error', ErrorMessage: err.message },\n ];\n this.IsSearching = false;\n this.HasSearched = true;\n this.cdr.detectChanges();\n },\n complete: () => {\n this.IsSearching = false;\n this.HasSearched = true;\n this.emitAgentContext();\n this.cdr.detectChanges();\n },\n });\n }\n\n /**\n * Apply active filter selections to the full result set.\n */\n private applyClientFilters(): void {\n let results = this.allResults;\n\n // Apply min score filter FIRST (this determines what's \"available\")\n if (this.MinScorePercent > 0) {\n const minScore = this.MinScorePercent / 100;\n results = results.filter(r => r.Score >= minScore);\n }\n\n // Rebuild filters from score-filtered results so counts are accurate\n this.Filters = this.searchService.BuildFilters(results);\n this.TotalCount = results.length;\n\n // Apply facet filters\n if (this.hasActiveFilters()) {\n results = results.filter(r => this.matchesActiveFilters(r));\n }\n\n // Apply client text filter (search within results)\n if (this.ClientFilterText.trim()) {\n const term = this.ClientFilterText.trim().toLowerCase();\n results = results.filter(r =>\n (r.Title?.toLowerCase().includes(term)) ||\n (r.Snippet?.toLowerCase().includes(term)) ||\n (r.EntityName?.toLowerCase().includes(term)) ||\n (r.RecordName?.toLowerCase().includes(term)) ||\n (r.Tags?.some(t => t.toLowerCase().includes(term)))\n );\n }\n\n // Sort\n switch (this.SortField) {\n case 'title':\n results = [...results].sort((a, b) => (a.Title || '').localeCompare(b.Title || ''));\n break;\n case 'entity':\n results = [...results].sort((a, b) => a.EntityName.localeCompare(b.EntityName) || b.Score - a.Score);\n break;\n case 'score':\n default:\n results = [...results].sort((a, b) => b.Score - a.Score);\n break;\n }\n\n this.FilteredResults = results;\n this.emitAgentContext();\n this.cdr.detectChanges();\n }\n\n private hasActiveFilters(): boolean {\n return Object.values(this.ActiveFilters).some(v => v.length > 0);\n }\n\n private matchesActiveFilters(result: SearchResultItem): boolean {\n const entityFilter = this.ActiveFilters['Entity'];\n if (entityFilter?.length) {\n const matchesEntity = entityFilter.includes(result.EntityName);\n const matchesFiles = entityFilter.includes('__storage-files__') && result.ResultType === 'storage-file';\n if (!matchesEntity && !matchesFiles) return false;\n }\n\n const sourceFilter = this.ActiveFilters['Source'];\n if (sourceFilter?.length && !sourceFilter.includes(result.SourceType)) {\n return false;\n }\n\n const tagFilter = this.ActiveFilters['Tags'];\n if (tagFilter?.length && !tagFilter.some(t => result.Tags.includes(t))) {\n return false;\n }\n\n const fileTypeFilter = this.ActiveFilters['File Type'];\n if (fileTypeFilter?.length) {\n if (result.ResultType !== 'storage-file') return false;\n const ext = result.Title?.split('.').pop()?.toUpperCase() ?? '';\n if (!fileTypeFilter.includes(ext)) return false;\n }\n\n return true;\n }\n\n /**\n * Build WordCloudItem[] from search results by extracting entity names and tags,\n * weighted by their frequency across all results.\n */\n /**\n * Build word cloud items from MJ: Tagged Items linked to the search results.\n * Queries the TaggedItem entity for all records in the result set, aggregates\n * tag names by count and weight, and builds WordCloudItem[] for the cloud.\n */\n private async buildCloudItems(): Promise<void> {\n this.IsLoadingCloud = true;\n this.cdr.detectChanges();\n\n try {\n // Group results by entity to build efficient queries\n const byEntity = new Map<string, string[]>();\n for (const result of this.allResults) {\n const md = this.ProviderToUse;\n const entity = md.Entities.find(e => e.Name === result.EntityName);\n if (!entity) continue;\n const list = byEntity.get(entity.ID) || [];\n list.push(result.RecordID);\n byEntity.set(entity.ID, list);\n }\n\n // Query Tagged Items for all record IDs across all entities\n const tagAggregates = new Map<string, { count: number; totalWeight: number }>();\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n\n for (const [entityID, recordIDs] of byEntity) {\n if (recordIDs.length === 0) continue;\n\n // Build IN clause (batch in groups of 50 to avoid huge queries)\n for (let i = 0; i < recordIDs.length; i += 50) {\n const batch = recordIDs.slice(i, i + 50);\n const inClause = batch.map(id => `'${id.replace(/'/g, \"''\")}'`).join(',');\n\n const result = await rv.RunView<{ Tag: string; Weight: number }>({\n EntityName: 'MJ: Tagged Items',\n ExtraFilter: `EntityID = '${entityID}' AND RecordID IN (${inClause})`,\n Fields: ['Tag', 'Weight'],\n ResultType: 'simple'\n });\n\n if (result.Success && result.Results) {\n for (const row of result.Results) {\n const tagName = row.Tag;\n if (!tagName) continue;\n const existing = tagAggregates.get(tagName) || { count: 0, totalWeight: 0 };\n existing.count++;\n existing.totalWeight += (row.Weight ?? 1);\n tagAggregates.set(tagName, existing);\n }\n }\n }\n }\n\n // Build cloud items from aggregated tags\n if (tagAggregates.size === 0) {\n this.CloudItems = [{ Text: 'No tags found', Weight: 1, Category: 'empty' }];\n } else {\n const maxWeight = Math.max(...Array.from(tagAggregates.values()).map(v => v.totalWeight), 1);\n this.CloudItems = Array.from(tagAggregates.entries())\n .sort((a, b) => b[1].totalWeight - a[1].totalWeight)\n .map(([tagName, agg]) => ({\n Text: tagName,\n Weight: agg.totalWeight / maxWeight,\n Category: 'tag',\n Metadata: { type: 'tag', count: agg.count, totalWeight: agg.totalWeight }\n }));\n }\n } catch (err) {\n this.CloudItems = [{ Text: 'Error loading tags', Weight: 1, Category: 'error' }];\n }\n\n this.IsLoadingCloud = false;\n this.cdr.detectChanges();\n }\n\n /** Report current search state to the AI agent */\n private emitAgentContext(): void {\n this.navigationService.SetAgentContext(this, {\n CurrentQuery: this.CurrentQuery || null,\n ResultCount: this.TotalCount,\n FilteredCount: this.FilteredResults.length,\n ElapsedMs: this.ElapsedMs,\n HasSearched: this.HasSearched,\n ShowFilterPanel: this.ShowFilterPanel,\n ViewMode: this.ViewMode,\n SortField: this.SortField,\n MinScorePercent: this.MinScorePercent,\n ClientFilterText: this.ClientFilterText,\n ActiveFilterCount: Object.values(this.ActiveFilters).filter(v => v.length > 0).length,\n TopResults: this.FilteredResults.slice(0, 50).map(r => ({\n Title: r.Title || r.RecordName,\n EntityName: r.EntityName,\n RecordID: r.RecordID,\n Score: Math.round(r.Score * 100),\n SourceType: r.SourceType,\n Snippet: r.Snippet?.substring(0, 100)\n })),\n });\n }\n\n /** Register client tools the agent can invoke on the search results */\n private registerAgentTools(): void {\n this.navigationService.SetAgentClientTools(this, [\n {\n Name: 'RunSearch',\n Description: 'Execute a search query and display results',\n ParameterSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'The search query text' }\n },\n required: ['query']\n },\n Handler: async (params: Record<string, unknown>) => {\n const query = String(params['query'] ?? '');\n this.CurrentQuery = query;\n await this.ExecuteSearch(query);\n return { Success: true, Data: { ResultCount: this.TotalCount, ElapsedMs: this.ElapsedMs } };\n }\n },\n {\n Name: 'SortResults',\n Description: 'Change the sort order of search results',\n ParameterSchema: {\n type: 'object',\n properties: {\n field: { type: 'string', enum: ['score', 'title', 'entity'], description: 'Sort field' }\n },\n required: ['field']\n },\n Handler: async (params: Record<string, unknown>) => {\n this.OnSortChange(String(params['field']));\n return { Success: true, Data: { SortField: this.SortField } };\n }\n },\n {\n Name: 'FilterWithinResults',\n Description: 'Filter the current results by a keyword (client-side text filter)',\n ParameterSchema: {\n type: 'object',\n properties: {\n text: { type: 'string', description: 'Filter text (empty string to clear)' }\n },\n required: ['text']\n },\n Handler: async (params: Record<string, unknown>) => {\n this.OnClientFilterTextChange(String(params['text'] ?? ''));\n return { Success: true, Data: { FilteredCount: this.FilteredResults.length } };\n }\n },\n {\n Name: 'SetViewMode',\n Description: 'Switch between list view and tag cloud visualization',\n ParameterSchema: {\n type: 'object',\n properties: {\n mode: { type: 'string', enum: ['list', 'cloud'], description: 'View mode' }\n },\n required: ['mode']\n },\n Handler: async (params: Record<string, unknown>) => {\n this.SetViewMode((params['mode'] as 'list' | 'cloud') ?? 'list');\n return { Success: true, Data: { ViewMode: this.ViewMode } };\n }\n },\n {\n Name: 'ToggleFilterPanel',\n Description: 'Show or hide the filter panel on the left',\n ParameterSchema: { type: 'object', properties: {} },\n Handler: async () => {\n this.ToggleFilterPanel();\n return { Success: true, Data: { ShowFilterPanel: this.ShowFilterPanel } };\n }\n },\n {\n Name: 'SetMinRelevance',\n Description: 'Set the minimum relevance score filter (0-100 percent)',\n ParameterSchema: {\n type: 'object',\n properties: {\n percent: { type: 'number', description: 'Minimum relevance percentage (0-100)' }\n },\n required: ['percent']\n },\n Handler: async (params: Record<string, unknown>) => {\n this.OnMinScoreChanged(Number(params['percent'] ?? 0));\n return { Success: true, Data: { MinScorePercent: this.MinScorePercent, FilteredCount: this.FilteredResults.length } };\n }\n },\n {\n Name: 'RefreshSearch',\n Description: 'Re-execute the current search query',\n ParameterSchema: { type: 'object', properties: {} },\n Handler: async () => {\n await this.OnRefresh();\n return { Success: true, Data: { ResultCount: this.TotalCount, ElapsedMs: this.ElapsedMs } };\n }\n }\n ]);\n }\n}\n\nexport function LoadSearchResultsResource() {\n // Tree-shaking prevention\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ComponentRef, ApplicationRef } from '@angular/core';
|
|
2
|
-
import { BaseResourceComponent } from '@memberjunction/ng-shared';
|
|
2
|
+
import { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';
|
|
3
3
|
import { ResourceData } from '@memberjunction/core-entities';
|
|
4
4
|
/**
|
|
5
5
|
* Metadata about a cached component
|
|
@@ -44,6 +44,7 @@ export interface CachedComponentInfo {
|
|
|
44
44
|
*/
|
|
45
45
|
export declare class ComponentCacheManager {
|
|
46
46
|
private appRef;
|
|
47
|
+
private navigationService?;
|
|
47
48
|
private cache;
|
|
48
49
|
/**
|
|
49
50
|
* Maximum number of detached (not currently visible) components to keep
|
|
@@ -51,7 +52,14 @@ export declare class ComponentCacheManager {
|
|
|
51
52
|
* evicted. Set to 0 to disable eviction (legacy behavior). Default: 20.
|
|
52
53
|
*/
|
|
53
54
|
static MaxDetachedComponents: number;
|
|
54
|
-
|
|
55
|
+
/**
|
|
56
|
+
* @param navigationService Optional — when provided, the cache manager keeps the AI agent's live
|
|
57
|
+
* client-tool set in sync with the attached surface: it replays a reattached component's tools
|
|
58
|
+
* ({@link NavigationService.NotifyResourceReattached}) and clears them on detach
|
|
59
|
+
* ({@link NavigationService.NotifyResourceDetached}), since cached components don't re-run
|
|
60
|
+
* `ngAfterViewInit`. Centralizing it here covers BOTH single-resource and Golden Layout paths.
|
|
61
|
+
*/
|
|
62
|
+
constructor(appRef: ApplicationRef, navigationService?: NavigationService | undefined);
|
|
55
63
|
/**
|
|
56
64
|
* Generate a unique cache key from resource identity.
|
|
57
65
|
* This is the ONE canonical key format used by ALL cache operations.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-cache-manager.d.ts","sourceRoot":"","sources":["../../../../../src/lib/shell/components/tabs/component-cache-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"component-cache-manager.d.ts","sourceRoot":"","sources":["../../../../../src/lib/shell/components/tabs/component-cache-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
export class ComponentCacheManager {
|
|
19
19
|
appRef;
|
|
20
|
+
navigationService;
|
|
20
21
|
cache = new Map();
|
|
21
22
|
/**
|
|
22
23
|
* Maximum number of detached (not currently visible) components to keep
|
|
@@ -24,8 +25,16 @@ export class ComponentCacheManager {
|
|
|
24
25
|
* evicted. Set to 0 to disable eviction (legacy behavior). Default: 20.
|
|
25
26
|
*/
|
|
26
27
|
static MaxDetachedComponents = 20;
|
|
27
|
-
|
|
28
|
+
/**
|
|
29
|
+
* @param navigationService Optional — when provided, the cache manager keeps the AI agent's live
|
|
30
|
+
* client-tool set in sync with the attached surface: it replays a reattached component's tools
|
|
31
|
+
* ({@link NavigationService.NotifyResourceReattached}) and clears them on detach
|
|
32
|
+
* ({@link NavigationService.NotifyResourceDetached}), since cached components don't re-run
|
|
33
|
+
* `ngAfterViewInit`. Centralizing it here covers BOTH single-resource and Golden Layout paths.
|
|
34
|
+
*/
|
|
35
|
+
constructor(appRef, navigationService) {
|
|
28
36
|
this.appRef = appRef;
|
|
37
|
+
this.navigationService = navigationService;
|
|
29
38
|
}
|
|
30
39
|
/**
|
|
31
40
|
* Generate a unique cache key from resource identity.
|
|
@@ -105,6 +114,9 @@ export class ComponentCacheManager {
|
|
|
105
114
|
info.isAttached = true;
|
|
106
115
|
info.attachedToTabId = tabId;
|
|
107
116
|
info.lastUsed = new Date();
|
|
117
|
+
// Replay this surface's agent client tools to the AI agent on reattach (cached components keep
|
|
118
|
+
// their instance but never re-run ngAfterViewInit, so they don't re-register on their own).
|
|
119
|
+
this.navigationService?.NotifyResourceReattached(info.componentRef.instance);
|
|
108
120
|
}
|
|
109
121
|
}
|
|
110
122
|
/**
|
|
@@ -121,6 +133,9 @@ export class ComponentCacheManager {
|
|
|
121
133
|
info.isAttached = false;
|
|
122
134
|
info.attachedToTabId = null;
|
|
123
135
|
info.lastUsed = new Date();
|
|
136
|
+
// Clear this surface's agent client tools on detach so the previous app's tools aren't offered to
|
|
137
|
+
// the AI agent on the next surface. NotifyResourceReattached replays them if the user returns.
|
|
138
|
+
this.navigationService?.NotifyResourceDetached(info.componentRef.instance);
|
|
124
139
|
this.EvictIfNeeded();
|
|
125
140
|
return info;
|
|
126
141
|
}
|
|
@@ -183,6 +198,8 @@ export class ComponentCacheManager {
|
|
|
183
198
|
.sort((a, b) => a[1].lastUsed.getTime() - b[1].lastUsed.getTime());
|
|
184
199
|
while (detached.length > ComponentCacheManager.MaxDetachedComponents) {
|
|
185
200
|
const [key, info] = detached.shift();
|
|
201
|
+
// Drop the destroyed component's cached agent tools so the registry doesn't retain a dead ref.
|
|
202
|
+
this.navigationService?.ForgetResource(info.componentRef.instance);
|
|
186
203
|
this.appRef.detachView(info.componentRef.hostView);
|
|
187
204
|
info.componentRef.destroy();
|
|
188
205
|
this.cache.delete(key);
|
|
@@ -205,6 +222,7 @@ export class ComponentCacheManager {
|
|
|
205
222
|
const info = this.cache.get(key);
|
|
206
223
|
if (!info)
|
|
207
224
|
return;
|
|
225
|
+
this.navigationService?.ForgetResource(info.componentRef.instance);
|
|
208
226
|
this.appRef.detachView(info.componentRef.hostView);
|
|
209
227
|
info.componentRef.destroy();
|
|
210
228
|
this.cache.delete(key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-cache-manager.js","sourceRoot":"","sources":["../../../../../src/lib/shell/components/tabs/component-cache-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { ComponentRef, ApplicationRef } from '@angular/core';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { ResourceData } from '@memberjunction/core-entities';\n\n/**\n * Metadata about a cached component\n */\nexport interface CachedComponentInfo {\n // The Angular component reference\n componentRef: ComponentRef<BaseResourceComponent>;\n\n // The wrapper DOM element (for detaching/reattaching)\n wrapperElement: HTMLElement;\n\n // Resource identity (the ONLY key used for cache operations)\n resourceType: string;\n resourceRecordId: string;\n applicationId: string;\n\n // Optional tiebreaker used when recordId is empty (e.g., \"new record\" tabs for\n // different entities all have recordId='' but must NOT share a cache entry).\n // For entity-record resources this is the entity name; null/undefined for\n // resource types that don't need disambiguation.\n keyDiscriminator?: string;\n\n // Usage tracking\n isAttached: boolean; // Currently attached to a tab/container?\n attachedToTabId: string | null; // Which tab is it attached to? (metadata only, NOT used for lookup)\n\n // Lifecycle tracking\n lastUsed: Date;\n createdAt: Date;\n\n // Resource data snapshot (for comparison)\n resourceData: ResourceData;\n\n // Saved query params from the tab config at detach time.\n // Restored to the tab config when the component is reattached,\n // so the URL reflects the component's preserved state.\n savedQueryParams?: Record<string, string>;\n\n // Agent context reported by this component via NavigationService.SetAgentContext()\n // Cached so it can be restored when the component becomes active again.\n AgentContext?: Record<string, unknown>;\n\n // Agent client tools registered by this component via NavigationService.SetAgentClientTools()\n // Cached so they can be re-registered when the component becomes active again.\n AgentClientTools?: { Name: string; Description: string; ParameterSchema: Record<string, unknown>; Handler: (params: Record<string, unknown>) => Promise<unknown> }[];\n}\n\n/**\n * Smart component cache manager that preserves component state across tab switches.\n *\n * ALL cache operations use a consistent identity key: `appId::resourceType::recordId`.\n * This key is the same regardless of whether the component is in Golden Layout (tabbed)\n * mode or Single Resource mode, ensuring components are reusable across both modes.\n *\n * The `attachedToTabId` field is metadata for debugging/display — it is NEVER used\n * as a lookup key. This prevents bugs where multiple resources sharing the same tab ID\n * (e.g., nav items within a single-resource app) interfere with each other's cache state.\n *\n * Features:\n * - Caches components by resource identity (appId + resourceType + recordId)\n * - Tracks component usage to prevent double-attachment\n * - Detaches/reattaches DOM elements without destroying Angular components\n * - LRU eviction when detached component count exceeds MaxDetachedComponents\n */\nexport class ComponentCacheManager {\n private cache = new Map<string, CachedComponentInfo>();\n\n /**\n * Maximum number of detached (not currently visible) components to keep\n * cached. When exceeded, least-recently-used detached components are\n * evicted. Set to 0 to disable eviction (legacy behavior). Default: 20.\n */\n public static MaxDetachedComponents: number = 20;\n\n constructor(private appRef: ApplicationRef) {}\n\n /**\n * Generate a unique cache key from resource identity.\n * This is the ONE canonical key format used by ALL cache operations.\n *\n * `discriminator` is appended into the recordId slot only when recordId is empty.\n * It exists to prevent collisions between distinct \"new record\" tabs that share\n * an empty recordId — e.g., a new MJ:Companies form and a new MJ:Employees form\n * would otherwise both cache at `appId::RecordResource::__no_record__` and clobber\n * each other. Passing the entity name as discriminator keeps them separate.\n */\n private getCacheKey(resourceType: string, recordId: string, appId: string, discriminator?: string): string {\n const normalizedRecordId = recordId\n || (discriminator ? `__new__::${discriminator}` : '__no_record__');\n return `${appId}::${resourceType}::${normalizedRecordId}`;\n }\n\n /**\n * Check if a component exists in cache and is available for reuse.\n */\n hasAvailableComponent(resourceType: string, recordId: string, appId: string, discriminator?: string): boolean {\n const key = this.getCacheKey(resourceType, recordId, appId, discriminator);\n const info = this.cache.get(key);\n return info !== undefined && !info.isAttached;\n }\n\n /**\n * Get a cached component if available (not currently attached).\n * Lookup is by resource identity, not tab ID.\n */\n getCachedComponent(resourceType: string, recordId: string, appId: string, discriminator?: string): CachedComponentInfo | null {\n const key = this.getCacheKey(resourceType, recordId, appId, discriminator);\n const info = this.cache.get(key);\n\n if (!info) {\n return null;\n }\n\n // Can only reuse if not currently attached elsewhere\n if (info.isAttached) {\n return null;\n }\n\n return info;\n }\n\n /**\n * Store a component in the cache and mark as attached.\n */\n cacheComponent(\n componentRef: ComponentRef<BaseResourceComponent>,\n wrapperElement: HTMLElement,\n resourceData: ResourceData,\n tabId: string\n ): void {\n // Use driverClass (the actual component class name) as the resourceType for the cache key,\n // NOT resourceData.ResourceType (which is often just \"Custom\" for dashboard resources).\n // This must match the lookup key used in getCachedComponent/markAsAttached/markAsDetached.\n const resolvedResourceType = resourceData.Configuration?.resourceTypeDriverClass\n || resourceData.Configuration?.driverClass\n || resourceData.ResourceType;\n // Entity name discriminates between distinct \"new record\" tabs (empty recordId).\n // For non-Records resource types this is undefined, leaving the key unchanged.\n const discriminator = resourceData.Configuration?.Entity as string | undefined;\n const key = this.getCacheKey(\n resolvedResourceType,\n resourceData.ResourceRecordID || '',\n resourceData.Configuration?.applicationId || '',\n discriminator\n );\n\n const info: CachedComponentInfo = {\n componentRef,\n wrapperElement,\n resourceType: resolvedResourceType,\n resourceRecordId: resourceData.ResourceRecordID || '',\n applicationId: resourceData.Configuration?.applicationId || '',\n keyDiscriminator: discriminator,\n isAttached: true,\n attachedToTabId: tabId,\n lastUsed: new Date(),\n createdAt: new Date(),\n resourceData\n };\n\n this.cache.set(key, info);\n }\n\n /**\n * Mark a component as attached. Lookup by resource identity.\n */\n markAsAttached(resourceType: string, recordId: string, appId: string, tabId: string, discriminator?: string): void {\n const key = this.getCacheKey(resourceType, recordId, appId, discriminator);\n const info = this.cache.get(key);\n\n if (info) {\n info.isAttached = true;\n info.attachedToTabId = tabId;\n info.lastUsed = new Date();\n }\n }\n\n /**\n * Mark a component as detached (available for reuse). Lookup by resource identity.\n *\n * This is the ONLY way to detach a component. Both single-resource mode and\n * Golden Layout mode use this same method to ensure consistent cache behavior.\n */\n markAsDetached(resourceType: string, recordId: string, appId: string, discriminator?: string): CachedComponentInfo | null {\n const key = this.getCacheKey(resourceType, recordId, appId, discriminator);\n const info = this.cache.get(key);\n if (!info) return null;\n\n info.isAttached = false;\n info.attachedToTabId = null;\n info.lastUsed = new Date();\n this.EvictIfNeeded();\n return info;\n }\n\n /**\n * Re-key a cached component when its underlying record identity changes.\n *\n * Used when a \"new record\" component (cached at `recordId = ''`) becomes a saved record\n * (now identified by its new PK). Without re-keying, the next \"new record\" request would\n * still resolve to this same cache entry, surfacing the previously-saved record on a form\n * the user expects to be blank.\n *\n * Preserves the live component instance — only the cache key + stored identity change.\n * Returns true if a matching entry was found and re-keyed, false otherwise.\n */\n rekeyComponent(\n resourceType: string,\n oldRecordId: string,\n newRecordId: string,\n appId: string,\n oldDiscriminator?: string,\n newDiscriminator?: string\n ): boolean {\n const oldKey = this.getCacheKey(resourceType, oldRecordId, appId, oldDiscriminator);\n const info = this.cache.get(oldKey);\n if (!info) {\n return false;\n }\n\n // Once a record has a real id, the discriminator no longer matters (the id is unique).\n // Default the new discriminator to undefined unless explicitly provided.\n const newKey = this.getCacheKey(resourceType, newRecordId, appId, newDiscriminator);\n if (oldKey === newKey) {\n return false;\n }\n\n info.resourceRecordId = newRecordId;\n info.keyDiscriminator = newDiscriminator;\n info.lastUsed = new Date();\n if (info.resourceData) {\n info.resourceData.ResourceRecordID = newRecordId;\n }\n\n this.cache.delete(oldKey);\n this.cache.set(newKey, info);\n return true;\n }\n\n /**\n * Find a cached component by tab ID and detach it.\n * This is a convenience wrapper for callers that only know the tab ID\n * (e.g., Golden Layout tab close events). It resolves the tab ID to\n * resource identity, then delegates to the identity-based markAsDetached.\n */\n findAndDetachByTabId(tabId: string): CachedComponentInfo | null {\n const entry = Array.from(this.cache.entries())\n .find(([_, info]) => info.attachedToTabId === tabId);\n\n if (!entry) return null;\n\n const [_, info] = entry;\n return this.markAsDetached(info.resourceType, info.resourceRecordId, info.applicationId, info.keyDiscriminator);\n }\n\n /**\n * Evict least-recently-used detached components when over the limit.\n * Only evicts components that are not currently attached.\n */\n private EvictIfNeeded(): void {\n if (ComponentCacheManager.MaxDetachedComponents <= 0) return;\n\n const detached = Array.from(this.cache.entries())\n .filter(([_, info]) => !info.isAttached)\n .sort((a, b) => a[1].lastUsed.getTime() - b[1].lastUsed.getTime());\n\n while (detached.length > ComponentCacheManager.MaxDetachedComponents) {\n const [key, info] = detached.shift()!;\n this.appRef.detachView(info.componentRef.hostView);\n info.componentRef.destroy();\n this.cache.delete(key);\n }\n }\n\n /**\n * Get component info by tab ID (for finding what's attached to a tab).\n * Uses linear scan since tabId is metadata, not a key.\n */\n getComponentByTabId(tabId: string): CachedComponentInfo | null {\n const entry = Array.from(this.cache.entries())\n .find(([_, info]) => info.attachedToTabId === tabId);\n\n return entry ? entry[1] : null;\n }\n\n /**\n * Remove and destroy a specific component from cache by resource identity.\n */\n destroyComponent(resourceType: string, recordId: string, appId: string, discriminator?: string): void {\n const key = this.getCacheKey(resourceType, recordId, appId, discriminator);\n const info = this.cache.get(key);\n\n if (!info) return;\n\n this.appRef.detachView(info.componentRef.hostView);\n info.componentRef.destroy();\n this.cache.delete(key);\n }\n\n /**\n * Remove and destroy component by tab ID (convenience for Golden Layout tab close).\n */\n destroyComponentByTabId(tabId: string): void {\n const entry = Array.from(this.cache.entries())\n .find(([_, info]) => info.attachedToTabId === tabId);\n\n if (!entry) return;\n\n const [key, info] = entry;\n this.appRef.detachView(info.componentRef.hostView);\n info.componentRef.destroy();\n this.cache.delete(key);\n }\n\n /**\n * Clear the entire cache, destroying all components.\n * Call this on user logout or app shutdown.\n */\n clearCache(): void {\n this.cache.forEach(info => {\n this.appRef.detachView(info.componentRef.hostView);\n info.componentRef.destroy();\n });\n this.cache.clear();\n }\n\n /**\n * Selectively clear cached components matching a predicate.\n * Components that match are destroyed; those that don't are kept.\n *\n * Use this for tenant switching: clear org-scoped components while\n * keeping system/global components alive.\n *\n * @param predicate Return true for components that should be destroyed.\n * @returns Number of components destroyed.\n */\n ClearCacheByPredicate(predicate: (info: CachedComponentInfo) => boolean): number {\n let destroyed = 0;\n const toRemove: string[] = [];\n\n this.cache.forEach((info, key) => {\n if (predicate(info)) {\n this.appRef.detachView(info.componentRef.hostView);\n info.componentRef.destroy();\n toRemove.push(key);\n destroyed++;\n }\n });\n\n for (const key of toRemove) {\n this.cache.delete(key);\n }\n\n return destroyed;\n }\n\n /**\n * Get cache statistics for debugging.\n */\n getCacheStats(): {\n total: number;\n attached: number;\n detached: number;\n byResourceType: Map<string, number>;\n } {\n const stats = {\n total: this.cache.size,\n attached: 0,\n detached: 0,\n byResourceType: new Map<string, number>()\n };\n\n this.cache.forEach(info => {\n if (info.isAttached) {\n stats.attached++;\n } else {\n stats.detached++;\n }\n\n const count = stats.byResourceType.get(info.resourceType) || 0;\n stats.byResourceType.set(info.resourceType, count + 1);\n });\n\n return stats;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"component-cache-manager.js","sourceRoot":"","sources":["../../../../../src/lib/shell/components/tabs/component-cache-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { ComponentRef, ApplicationRef } from '@angular/core';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { ResourceData } from '@memberjunction/core-entities';\n\n/**\n * Metadata about a cached component\n */\nexport interface CachedComponentInfo {\n // The Angular component reference\n componentRef: ComponentRef<BaseResourceComponent>;\n\n // The wrapper DOM element (for detaching/reattaching)\n wrapperElement: HTMLElement;\n\n // Resource identity (the ONLY key used for cache operations)\n resourceType: string;\n resourceRecordId: string;\n applicationId: string;\n\n // Optional tiebreaker used when recordId is empty (e.g., \"new record\" tabs for\n // different entities all have recordId='' but must NOT share a cache entry).\n // For entity-record resources this is the entity name; null/undefined for\n // resource types that don't need disambiguation.\n keyDiscriminator?: string;\n\n // Usage tracking\n isAttached: boolean; // Currently attached to a tab/container?\n attachedToTabId: string | null; // Which tab is it attached to? (metadata only, NOT used for lookup)\n\n // Lifecycle tracking\n lastUsed: Date;\n createdAt: Date;\n\n // Resource data snapshot (for comparison)\n resourceData: ResourceData;\n\n // Saved query params from the tab config at detach time.\n // Restored to the tab config when the component is reattached,\n // so the URL reflects the component's preserved state.\n savedQueryParams?: Record<string, string>;\n\n // Agent context reported by this component via NavigationService.SetAgentContext()\n // Cached so it can be restored when the component becomes active again.\n AgentContext?: Record<string, unknown>;\n\n // Agent client tools registered by this component via NavigationService.SetAgentClientTools()\n // Cached so they can be re-registered when the component becomes active again.\n AgentClientTools?: { Name: string; Description: string; ParameterSchema: Record<string, unknown>; Handler: (params: Record<string, unknown>) => Promise<unknown> }[];\n}\n\n/**\n * Smart component cache manager that preserves component state across tab switches.\n *\n * ALL cache operations use a consistent identity key: `appId::resourceType::recordId`.\n * This key is the same regardless of whether the component is in Golden Layout (tabbed)\n * mode or Single Resource mode, ensuring components are reusable across both modes.\n *\n * The `attachedToTabId` field is metadata for debugging/display — it is NEVER used\n * as a lookup key. This prevents bugs where multiple resources sharing the same tab ID\n * (e.g., nav items within a single-resource app) interfere with each other's cache state.\n *\n * Features:\n * - Caches components by resource identity (appId + resourceType + recordId)\n * - Tracks component usage to prevent double-attachment\n * - Detaches/reattaches DOM elements without destroying Angular components\n * - LRU eviction when detached component count exceeds MaxDetachedComponents\n */\nexport class ComponentCacheManager {\n private cache = new Map<string, CachedComponentInfo>();\n\n /**\n * Maximum number of detached (not currently visible) components to keep\n * cached. When exceeded, least-recently-used detached components are\n * evicted. Set to 0 to disable eviction (legacy behavior). Default: 20.\n */\n public static MaxDetachedComponents: number = 20;\n\n /**\n * @param navigationService Optional — when provided, the cache manager keeps the AI agent's live\n * client-tool set in sync with the attached surface: it replays a reattached component's tools\n * ({@link NavigationService.NotifyResourceReattached}) and clears them on detach\n * ({@link NavigationService.NotifyResourceDetached}), since cached components don't re-run\n * `ngAfterViewInit`. Centralizing it here covers BOTH single-resource and Golden Layout paths.\n */\n constructor(private appRef: ApplicationRef, private navigationService?: NavigationService) {}\n\n /**\n * Generate a unique cache key from resource identity.\n * This is the ONE canonical key format used by ALL cache operations.\n *\n * `discriminator` is appended into the recordId slot only when recordId is empty.\n * It exists to prevent collisions between distinct \"new record\" tabs that share\n * an empty recordId — e.g., a new MJ:Companies form and a new MJ:Employees form\n * would otherwise both cache at `appId::RecordResource::__no_record__` and clobber\n * each other. Passing the entity name as discriminator keeps them separate.\n */\n private getCacheKey(resourceType: string, recordId: string, appId: string, discriminator?: string): string {\n const normalizedRecordId = recordId\n || (discriminator ? `__new__::${discriminator}` : '__no_record__');\n return `${appId}::${resourceType}::${normalizedRecordId}`;\n }\n\n /**\n * Check if a component exists in cache and is available for reuse.\n */\n hasAvailableComponent(resourceType: string, recordId: string, appId: string, discriminator?: string): boolean {\n const key = this.getCacheKey(resourceType, recordId, appId, discriminator);\n const info = this.cache.get(key);\n return info !== undefined && !info.isAttached;\n }\n\n /**\n * Get a cached component if available (not currently attached).\n * Lookup is by resource identity, not tab ID.\n */\n getCachedComponent(resourceType: string, recordId: string, appId: string, discriminator?: string): CachedComponentInfo | null {\n const key = this.getCacheKey(resourceType, recordId, appId, discriminator);\n const info = this.cache.get(key);\n\n if (!info) {\n return null;\n }\n\n // Can only reuse if not currently attached elsewhere\n if (info.isAttached) {\n return null;\n }\n\n return info;\n }\n\n /**\n * Store a component in the cache and mark as attached.\n */\n cacheComponent(\n componentRef: ComponentRef<BaseResourceComponent>,\n wrapperElement: HTMLElement,\n resourceData: ResourceData,\n tabId: string\n ): void {\n // Use driverClass (the actual component class name) as the resourceType for the cache key,\n // NOT resourceData.ResourceType (which is often just \"Custom\" for dashboard resources).\n // This must match the lookup key used in getCachedComponent/markAsAttached/markAsDetached.\n const resolvedResourceType = resourceData.Configuration?.resourceTypeDriverClass\n || resourceData.Configuration?.driverClass\n || resourceData.ResourceType;\n // Entity name discriminates between distinct \"new record\" tabs (empty recordId).\n // For non-Records resource types this is undefined, leaving the key unchanged.\n const discriminator = resourceData.Configuration?.Entity as string | undefined;\n const key = this.getCacheKey(\n resolvedResourceType,\n resourceData.ResourceRecordID || '',\n resourceData.Configuration?.applicationId || '',\n discriminator\n );\n\n const info: CachedComponentInfo = {\n componentRef,\n wrapperElement,\n resourceType: resolvedResourceType,\n resourceRecordId: resourceData.ResourceRecordID || '',\n applicationId: resourceData.Configuration?.applicationId || '',\n keyDiscriminator: discriminator,\n isAttached: true,\n attachedToTabId: tabId,\n lastUsed: new Date(),\n createdAt: new Date(),\n resourceData\n };\n\n this.cache.set(key, info);\n }\n\n /**\n * Mark a component as attached. Lookup by resource identity.\n */\n markAsAttached(resourceType: string, recordId: string, appId: string, tabId: string, discriminator?: string): void {\n const key = this.getCacheKey(resourceType, recordId, appId, discriminator);\n const info = this.cache.get(key);\n\n if (info) {\n info.isAttached = true;\n info.attachedToTabId = tabId;\n info.lastUsed = new Date();\n // Replay this surface's agent client tools to the AI agent on reattach (cached components keep\n // their instance but never re-run ngAfterViewInit, so they don't re-register on their own).\n this.navigationService?.NotifyResourceReattached(info.componentRef.instance);\n }\n }\n\n /**\n * Mark a component as detached (available for reuse). Lookup by resource identity.\n *\n * This is the ONLY way to detach a component. Both single-resource mode and\n * Golden Layout mode use this same method to ensure consistent cache behavior.\n */\n markAsDetached(resourceType: string, recordId: string, appId: string, discriminator?: string): CachedComponentInfo | null {\n const key = this.getCacheKey(resourceType, recordId, appId, discriminator);\n const info = this.cache.get(key);\n if (!info) return null;\n\n info.isAttached = false;\n info.attachedToTabId = null;\n info.lastUsed = new Date();\n // Clear this surface's agent client tools on detach so the previous app's tools aren't offered to\n // the AI agent on the next surface. NotifyResourceReattached replays them if the user returns.\n this.navigationService?.NotifyResourceDetached(info.componentRef.instance);\n this.EvictIfNeeded();\n return info;\n }\n\n /**\n * Re-key a cached component when its underlying record identity changes.\n *\n * Used when a \"new record\" component (cached at `recordId = ''`) becomes a saved record\n * (now identified by its new PK). Without re-keying, the next \"new record\" request would\n * still resolve to this same cache entry, surfacing the previously-saved record on a form\n * the user expects to be blank.\n *\n * Preserves the live component instance — only the cache key + stored identity change.\n * Returns true if a matching entry was found and re-keyed, false otherwise.\n */\n rekeyComponent(\n resourceType: string,\n oldRecordId: string,\n newRecordId: string,\n appId: string,\n oldDiscriminator?: string,\n newDiscriminator?: string\n ): boolean {\n const oldKey = this.getCacheKey(resourceType, oldRecordId, appId, oldDiscriminator);\n const info = this.cache.get(oldKey);\n if (!info) {\n return false;\n }\n\n // Once a record has a real id, the discriminator no longer matters (the id is unique).\n // Default the new discriminator to undefined unless explicitly provided.\n const newKey = this.getCacheKey(resourceType, newRecordId, appId, newDiscriminator);\n if (oldKey === newKey) {\n return false;\n }\n\n info.resourceRecordId = newRecordId;\n info.keyDiscriminator = newDiscriminator;\n info.lastUsed = new Date();\n if (info.resourceData) {\n info.resourceData.ResourceRecordID = newRecordId;\n }\n\n this.cache.delete(oldKey);\n this.cache.set(newKey, info);\n return true;\n }\n\n /**\n * Find a cached component by tab ID and detach it.\n * This is a convenience wrapper for callers that only know the tab ID\n * (e.g., Golden Layout tab close events). It resolves the tab ID to\n * resource identity, then delegates to the identity-based markAsDetached.\n */\n findAndDetachByTabId(tabId: string): CachedComponentInfo | null {\n const entry = Array.from(this.cache.entries())\n .find(([_, info]) => info.attachedToTabId === tabId);\n\n if (!entry) return null;\n\n const [_, info] = entry;\n return this.markAsDetached(info.resourceType, info.resourceRecordId, info.applicationId, info.keyDiscriminator);\n }\n\n /**\n * Evict least-recently-used detached components when over the limit.\n * Only evicts components that are not currently attached.\n */\n private EvictIfNeeded(): void {\n if (ComponentCacheManager.MaxDetachedComponents <= 0) return;\n\n const detached = Array.from(this.cache.entries())\n .filter(([_, info]) => !info.isAttached)\n .sort((a, b) => a[1].lastUsed.getTime() - b[1].lastUsed.getTime());\n\n while (detached.length > ComponentCacheManager.MaxDetachedComponents) {\n const [key, info] = detached.shift()!;\n // Drop the destroyed component's cached agent tools so the registry doesn't retain a dead ref.\n this.navigationService?.ForgetResource(info.componentRef.instance);\n this.appRef.detachView(info.componentRef.hostView);\n info.componentRef.destroy();\n this.cache.delete(key);\n }\n }\n\n /**\n * Get component info by tab ID (for finding what's attached to a tab).\n * Uses linear scan since tabId is metadata, not a key.\n */\n getComponentByTabId(tabId: string): CachedComponentInfo | null {\n const entry = Array.from(this.cache.entries())\n .find(([_, info]) => info.attachedToTabId === tabId);\n\n return entry ? entry[1] : null;\n }\n\n /**\n * Remove and destroy a specific component from cache by resource identity.\n */\n destroyComponent(resourceType: string, recordId: string, appId: string, discriminator?: string): void {\n const key = this.getCacheKey(resourceType, recordId, appId, discriminator);\n const info = this.cache.get(key);\n\n if (!info) return;\n\n this.navigationService?.ForgetResource(info.componentRef.instance);\n this.appRef.detachView(info.componentRef.hostView);\n info.componentRef.destroy();\n this.cache.delete(key);\n }\n\n /**\n * Remove and destroy component by tab ID (convenience for Golden Layout tab close).\n */\n destroyComponentByTabId(tabId: string): void {\n const entry = Array.from(this.cache.entries())\n .find(([_, info]) => info.attachedToTabId === tabId);\n\n if (!entry) return;\n\n const [key, info] = entry;\n this.appRef.detachView(info.componentRef.hostView);\n info.componentRef.destroy();\n this.cache.delete(key);\n }\n\n /**\n * Clear the entire cache, destroying all components.\n * Call this on user logout or app shutdown.\n */\n clearCache(): void {\n this.cache.forEach(info => {\n this.appRef.detachView(info.componentRef.hostView);\n info.componentRef.destroy();\n });\n this.cache.clear();\n }\n\n /**\n * Selectively clear cached components matching a predicate.\n * Components that match are destroyed; those that don't are kept.\n *\n * Use this for tenant switching: clear org-scoped components while\n * keeping system/global components alive.\n *\n * @param predicate Return true for components that should be destroyed.\n * @returns Number of components destroyed.\n */\n ClearCacheByPredicate(predicate: (info: CachedComponentInfo) => boolean): number {\n let destroyed = 0;\n const toRemove: string[] = [];\n\n this.cache.forEach((info, key) => {\n if (predicate(info)) {\n this.appRef.detachView(info.componentRef.hostView);\n info.componentRef.destroy();\n toRemove.push(key);\n destroyed++;\n }\n });\n\n for (const key of toRemove) {\n this.cache.delete(key);\n }\n\n return destroyed;\n }\n\n /**\n * Get cache statistics for debugging.\n */\n getCacheStats(): {\n total: number;\n attached: number;\n detached: number;\n byResourceType: Map<string, number>;\n } {\n const stats = {\n total: this.cache.size,\n attached: 0,\n detached: 0,\n byResourceType: new Map<string, number>()\n };\n\n this.cache.forEach(info => {\n if (info.isAttached) {\n stats.attached++;\n } else {\n stats.detached++;\n }\n\n const count = stats.byResourceType.get(info.resourceType) || 0;\n stats.byResourceType.set(info.resourceType, count + 1);\n });\n\n return stats;\n }\n}\n"]}
|
|
@@ -34,6 +34,7 @@ export declare class TabContainerComponent extends BaseAngularComponent implemen
|
|
|
34
34
|
*/
|
|
35
35
|
layoutInitError: EventEmitter<void>;
|
|
36
36
|
private pinService;
|
|
37
|
+
private navigationService;
|
|
37
38
|
private subscriptions;
|
|
38
39
|
private layoutInitRetryCount;
|
|
39
40
|
private readonly MAX_LAYOUT_INIT_RETRIES;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tab-container.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/shell/components/tabs/tab-container.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EACN,SAAS,EACT,aAAa,EAEb,UAAU,EACV,cAAc,EACd,mBAAmB,EAKnB,iBAAiB,EAGjB,YAAY,EAEb,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAKnB,MAAM,qCAAqC,CAAC;AAM7C,OAAO,EAAyB,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEvF,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;AACrE;;;;;;;;;GASG;AACH,qBAOa,qBAAsB,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS,EAAE,aAAa;
|
|
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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"}
|