@memberjunction/ng-search 6.2.0-edge.3 → 6.2.0-edge.5
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/lib/search-overlay.component.d.ts +3 -3
- package/dist/lib/search-overlay.component.d.ts.map +1 -1
- package/dist/lib/search-overlay.component.js +6 -15
- package/dist/lib/search-overlay.component.js.map +1 -1
- package/dist/lib/search-suggest.component.d.ts.map +1 -1
- package/dist/lib/search-suggest.component.js +2 -1
- package/dist/lib/search-suggest.component.js.map +1 -1
- package/dist/lib/search-types.d.ts +15 -0
- package/dist/lib/search-types.d.ts.map +1 -1
- package/dist/lib/search-types.js +24 -1
- package/dist/lib/search-types.js.map +1 -1
- package/dist/lib/search.service.d.ts +7 -4
- package/dist/lib/search.service.d.ts.map +1 -1
- package/dist/lib/search.service.js +7 -9
- package/dist/lib/search.service.js.map +1 -1
- package/package.json +9 -9
|
@@ -189,9 +189,9 @@ export declare class SearchOverlayComponent implements OnInit, OnDestroy {
|
|
|
189
189
|
private subscribeToSearchState;
|
|
190
190
|
private executeSearch;
|
|
191
191
|
/**
|
|
192
|
-
* Streaming variant of executeSearch — subscribes to `SearchService.StreamSearch
|
|
193
|
-
*
|
|
194
|
-
* event carries
|
|
192
|
+
* Streaming variant of executeSearch — subscribes to `SearchService.StreamSearch`, shows each
|
|
193
|
+
* provider's count in the chip strip as it reports back, and renders the result list from the
|
|
194
|
+
* 'final' event. A 'provider' event carries no rows: they arrive before the server's permission pass.
|
|
195
195
|
*
|
|
196
196
|
* Cancellation: a new search invocation tears down the in-flight stream via
|
|
197
197
|
* `searchVersion` and `currentStream.unsubscribe()`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-overlay.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-overlay.component.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"search-overlay.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-overlay.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -824,9 +824,9 @@ export class SearchOverlayComponent {
|
|
|
824
824
|
this.cdr.detectChanges();
|
|
825
825
|
}
|
|
826
826
|
/**
|
|
827
|
-
* Streaming variant of executeSearch — subscribes to `SearchService.StreamSearch
|
|
828
|
-
*
|
|
829
|
-
* event carries
|
|
827
|
+
* Streaming variant of executeSearch — subscribes to `SearchService.StreamSearch`, shows each
|
|
828
|
+
* provider's count in the chip strip as it reports back, and renders the result list from the
|
|
829
|
+
* 'final' event. A 'provider' event carries no rows: they arrive before the server's permission pass.
|
|
830
830
|
*
|
|
831
831
|
* Cancellation: a new search invocation tears down the in-flight stream via
|
|
832
832
|
* `searchVersion` and `currentStream.unsubscribe()`.
|
|
@@ -849,28 +849,19 @@ export class SearchOverlayComponent {
|
|
|
849
849
|
if (version !== this.searchVersion)
|
|
850
850
|
return;
|
|
851
851
|
if (event.Phase === 'provider' && event.ProviderName) {
|
|
852
|
-
|
|
852
|
+
// Progress only: the count, never the rows (they precede the permission pass).
|
|
853
853
|
this.StreamingProviders = [
|
|
854
854
|
...this.StreamingProviders,
|
|
855
855
|
{
|
|
856
856
|
Name: event.ProviderName,
|
|
857
|
-
Count:
|
|
857
|
+
Count: event.ResultCount ?? 0,
|
|
858
858
|
ElapsedMs: event.ElapsedMs ?? 0,
|
|
859
859
|
State: 'Completed',
|
|
860
860
|
},
|
|
861
861
|
];
|
|
862
|
-
if (event.Results && event.Results.length > 0) {
|
|
863
|
-
// Append partials so the user sees the list grow as providers return.
|
|
864
|
-
this.AllResults = [...this.AllResults, ...event.Results];
|
|
865
|
-
this.ResultGroups = this.searchService.GroupResults(this.AllResults);
|
|
866
|
-
this.TotalCount = this.AllResults.length;
|
|
867
|
-
if (this.HighlightedIndex < 0) {
|
|
868
|
-
this.HighlightedIndex = 0;
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
862
|
}
|
|
872
863
|
else if (event.Phase === 'final' && event.Results) {
|
|
873
|
-
//
|
|
864
|
+
// The permission-filtered fused/reranked list.
|
|
874
865
|
this.AllResults = event.Results;
|
|
875
866
|
this.ResultGroups = this.searchService.GroupResults(this.AllResults);
|
|
876
867
|
this.Filters = this.searchService.BuildFilters(this.AllResults);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-overlay.component.js","sourceRoot":"","sources":["../../src/lib/search-overlay.component.ts","../../src/lib/search-overlay.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search Overlay Component\n *\n * A floating search overlay inspired by command palette / Spotlight style.\n * Triggered by Cmd+K (Mac) or Ctrl+K (Windows), appears as a centered\n * floating panel with backdrop blur, search input, and grouped results.\n *\n * Supports keyboard navigation (up/down/enter/escape), filter facets,\n * and responsive mobile layout.\n */\n\nimport {\n Component,\n EventEmitter,\n HostListener,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ChangeDetectorRef,\n ElementRef,\n ViewChild,\n inject\n} from '@angular/core';\nimport { Subject, Subscription } from 'rxjs';\nimport { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';\nimport { SearchService } from './search.service';\nimport {\n SearchResultItem,\n SearchResultGroup,\n SearchFilter,\n SearchRequest,\n SearchResultSelectedEvent,\n SearchFilterChangeEvent,\n SearchExecutedEvent,\n} from './search-types';\n\n/**\n * Per-provider streaming status displayed above the results list while a streaming\n * search is in flight. One entry per provider that has reported back. Populated\n * progressively as `streamScopedSearch` emits 'provider' events.\n */\nexport interface StreamingProviderStatus {\n /** Provider name from the SearchEngine (e.g. 'Vector', 'FullText') */\n Name: string;\n /** Result count contributed by this provider */\n Count: number;\n /** Wall-clock latency for this provider's leg, in milliseconds */\n ElapsedMs: number;\n /** Reported state for this provider */\n State: 'Completed' | 'Error';\n /** Last error message if State is 'Error' */\n ErrorMessage?: string;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-search-overlay',\n templateUrl: './search-overlay.component.html',\n styleUrls: ['./search-overlay.component.css']\n})\nexport class SearchOverlayComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n protected searchService = inject(SearchService);\n private destroy$ = new Subject<void>();\n private searchInput$ = new Subject<string>();\n\n @ViewChild('searchInput') SearchInputRef!: ElementRef<HTMLInputElement>;\n\n /** @deprecated Use {@link SearchInputRef}. */\n get searchInputRef(): ElementRef<HTMLInputElement> {\n return this.SearchInputRef;\n }\n /** @deprecated Use {@link SearchInputRef}. */\n set searchInputRef(value: ElementRef<HTMLInputElement>) {\n this.SearchInputRef = value;\n }\n\n // --- Configuration Inputs ---\n\n /** Placeholder text for the search input */\n @Input() Placeholder = 'Search across all your knowledge...';\n\n /**\n * Maximum number of results to fetch and display. Deliberately small — the\n * overlay is a quick-jump surface; \"See all results\" hands off to the full\n * Search Results workspace for anything deeper. 8 matches the omnibar\n * palette's RESULT count (it fetches 9 rows = 8 results + its see-all row;\n * this overlay's see-all is a footer button, not a row).\n */\n @Input() MaxResults = 8;\n\n /** Whether the overlay is currently visible */\n private _isOpen = false;\n\n @Input()\n set IsOpen(value: boolean) {\n const prev = this._isOpen;\n this._isOpen = value;\n if (value && !prev) {\n this.onOverlayOpened();\n }\n if (!value && prev) {\n this.onOverlayClosed();\n }\n }\n get IsOpen(): boolean {\n return this._isOpen;\n }\n\n /** Debounce time in ms before search fires */\n @Input() DebounceMs = 400;\n\n /** Which search sources to include */\n @Input() IncludeSources: ('vector' | 'fulltext' | 'entity')[] = ['vector', 'fulltext', 'entity'];\n\n /** Whether to show filter facets */\n @Input() ShowFilters = true;\n\n /** Text for the agent CTA button */\n @Input() AgentCtaText = 'Ask Knowledge Agent';\n\n /** Whether to show the agent CTA */\n @Input() ShowAgentCta = true;\n\n /**\n * When true, the overlay subscribes to `SearchService.StreamSearch` instead of awaiting\n * `ExecuteSearch`. Results render progressively as each provider reports back. The\n * per-provider status chip strip becomes visible while the stream is in flight.\n * Defaults to false to preserve the request-response UX that shipped in Phase 1.\n */\n @Input() EnableStreaming = false;\n\n /**\n * When false, the overlay does NOT claim the global Ctrl/Cmd+K chord. For hosts\n * (e.g. the Explorer shell) that own that shortcut themselves and open the\n * overlay programmatically — two listeners on the same chord would double-toggle.\n * Escape/arrow handling while open is unaffected.\n */\n @Input() EnableGlobalShortcut = true;\n\n /**\n * Optional promo strip pinned to the overlay's bottom edge — a host-supplied\n * nudge (e.g. Explorer advertising its command palette). The component is\n * deliberately ignorant of WHAT is being promoted; the host provides the\n * copy and handles both outcomes.\n */\n @Input() ShowPromo = false;\n\n /** Promo copy (one sentence). Required when ShowPromo is true. */\n @Input() PromoText = '';\n\n /** Label for the promo's accept action. */\n @Input() PromoActionLabel = 'Turn on';\n\n // --- Outputs ---\n\n @Output() IsOpenChange = new EventEmitter<boolean>();\n @Output() ResultSelected = new EventEmitter<SearchResultSelectedEvent>();\n @Output() FilterChanged = new EventEmitter<SearchFilterChangeEvent>();\n @Output() SearchExecuted = new EventEmitter<SearchExecutedEvent>();\n @Output() AgentCtaClicked = new EventEmitter<string>();\n /**\n * Emitted when the user clicks \"See all results\" — carries the current query.\n * Hosts (e.g. the Explorer shell) open the full Search Results workspace,\n * which has scopes, relevance controls, and richer result actions than this\n * capped quick-jump overlay. The overlay closes itself after emitting.\n */\n @Output() SeeAllRequested = new EventEmitter<string>();\n /** Promo accept — carries the current query so the host can hand it off. */\n @Output() PromoAccepted = new EventEmitter<string>();\n /** Promo dismissed — the host should persist this and stop showing it. */\n @Output() PromoDismissed = new EventEmitter<void>();\n\n // --- Component State ---\n\n public Query = '';\n public IsSearching = false;\n public ResultGroups: SearchResultGroup[] = [];\n public AllResults: SearchResultItem[] = [];\n public Filters: SearchFilter[] = [];\n public ActiveFilters: Record<string, string[]> = {};\n public TotalCount = 0;\n public ElapsedMs = 0;\n public HighlightedIndex = -1;\n public HasSearched = false;\n private searchVersion = 0;\n\n /**\n * Per-provider status entries shown above the results list while a streaming search\n * is in flight. One entry per provider that has reported back. Empty when the user\n * is not running a streaming search (or when `EnableStreaming` is false).\n */\n public 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 /** Element focused before the overlay opened — restored on close (a11y). */\n private previousFocus: HTMLElement | null = null;\n\n /** All results flattened for keyboard navigation */\n public get FlatResults(): SearchResultItem[] {\n return this.AllResults;\n }\n\n /** id of the highlighted option, announced via aria-activedescendant. */\n public get ActiveDescendantId(): string | null {\n return this.HighlightedIndex >= 0 && this.HighlightedIndex < this.FlatResults.length\n ? `so-opt-${this.HighlightedIndex}`\n : null;\n }\n\n ngOnInit(): void {\n this.setupSearchDebounce();\n this.subscribeToSearchState();\n }\n\n ngOnDestroy(): void {\n this.currentStream?.unsubscribe();\n this.currentStream = null;\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // --- Keyboard shortcuts ---\n\n @HostListener('document:keydown', ['$event'])\n HandleGlobalKeydown(event: KeyboardEvent): void {\n if (this.EnableGlobalShortcut && this.isToggleShortcut(event)) {\n event.preventDefault();\n this.ToggleOverlay();\n return;\n }\n if (this._isOpen) {\n this.handleOverlayKeydown(event);\n }\n }\n\n /** Toggle the overlay open/closed */\n public ToggleOverlay(): void {\n this.IsOpen = !this._isOpen;\n this.IsOpenChange.emit(this._isOpen);\n }\n\n /** Open the overlay */\n public Open(): void {\n if (!this._isOpen) {\n this.IsOpen = true;\n this.IsOpenChange.emit(true);\n }\n }\n\n /** Close the overlay */\n public Close(): void {\n if (this._isOpen) {\n this.IsOpen = false;\n this.IsOpenChange.emit(false);\n }\n }\n\n /** Handle query input changes */\n public OnQueryInput(value: string): void {\n this.Query = value;\n this.searchInput$.next(value);\n }\n\n /** Handle clicking a result */\n public OnResultClick(result: SearchResultItem, event: MouseEvent): void {\n this.ResultSelected.emit({\n Result: result,\n OpenInNewTab: event.metaKey || event.ctrlKey\n });\n this.Close();\n }\n\n /** Handle selecting the highlighted result */\n public SelectHighlighted(): void {\n if (this.HighlightedIndex >= 0 && this.HighlightedIndex < this.FlatResults.length) {\n this.ResultSelected.emit({\n Result: this.FlatResults[this.HighlightedIndex],\n OpenInNewTab: false\n });\n this.Close();\n }\n }\n\n /** Handle filter option toggle */\n public OnFilterToggle(category: string, value: string): void {\n const current = this.ActiveFilters[category] ?? [];\n const index = current.indexOf(value);\n if (index >= 0) {\n current.splice(index, 1);\n } else {\n current.push(value);\n }\n this.ActiveFilters[category] = current;\n this.FilterChanged.emit({ Category: category, SelectedValues: current });\n this.executeSearch();\n }\n\n /** Clear all active filters */\n public ClearAllFilters(): void {\n this.ActiveFilters = {};\n this.executeSearch();\n }\n\n /** Handle clicking the agent CTA */\n public OnAgentCtaClick(): void {\n this.AgentCtaClicked.emit(this.Query);\n this.Close();\n }\n\n /** Promo accept: emit the current query and close — the host takes over. */\n public OnPromoAccept(): void {\n this.PromoAccepted.emit(this.Query.trim());\n this.Close();\n }\n\n /** Promo dismiss: the host persists the dismissal; hide it immediately. */\n public OnPromoDismiss(): void {\n this.ShowPromo = false;\n this.PromoDismissed.emit();\n }\n\n /** Handle clicking \"See all results\" — hand off to the full Search workspace */\n public OnSeeAllClick(): void {\n const query = this.Query.trim();\n if (query.length > 0) {\n this.SeeAllRequested.emit(query);\n }\n this.Close();\n }\n\n /** Handle clicking the backdrop to close */\n public OnBackdropClick(): void {\n this.Close();\n }\n\n /** Check if a filter option is active */\n public IsFilterActive(category: string, value: string): boolean {\n return (this.ActiveFilters[category] ?? []).includes(value);\n }\n\n /** Get a score display value (percentage) */\n public FormatScore(score: number): string {\n return `${Math.round(score * 100)}%`;\n }\n\n /** Format elapsed time display */\n public FormatElapsedTime(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n return `${(ms / 1000).toFixed(1)}s`;\n }\n\n // --- Private Methods ---\n\n private isToggleShortcut(event: KeyboardEvent): boolean {\n return (event.metaKey || event.ctrlKey) && event.key === 'k';\n }\n\n private handleOverlayKeydown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'Escape':\n event.preventDefault();\n this.Close();\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.moveHighlight(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.moveHighlight(-1);\n break;\n case 'Enter': {\n // Only claim Enter when it belongs to the combobox model (typing in\n // the input / a focused result row). A focused BUTTON (close,\n // see-all, filter chip, promo) must keep its native Enter\n // activation — preventDefault here at document level would\n // silently swallow it, or worse, open the highlighted result.\n const active = document.activeElement as HTMLElement | null;\n const inCombobox = active === this.SearchInputRef?.nativeElement\n || (active?.classList.contains('result-item') ?? false);\n if (!inCombobox) {\n return;\n }\n event.preventDefault();\n this.SelectHighlighted();\n break;\n }\n }\n }\n\n private moveHighlight(direction: number): void {\n const maxIndex = this.FlatResults.length - 1;\n if (maxIndex < 0) return;\n\n // If a result row currently holds DOM focus (roving tabindex), keep focus\n // travelling with the highlight; from the input, only the highlight moves.\n const rowHadFocus = document.activeElement instanceof HTMLElement\n && document.activeElement.classList.contains('result-item');\n\n this.HighlightedIndex += direction;\n if (this.HighlightedIndex < 0) {\n this.HighlightedIndex = maxIndex;\n } else if (this.HighlightedIndex > maxIndex) {\n this.HighlightedIndex = 0;\n }\n this.cdr.detectChanges();\n\n // Keyboard-driven moves keep the highlighted row visible. Mouse hover sets\n // HighlightedIndex directly in the template and deliberately does NOT\n // scroll — auto-scrolling under the pointer fights the user's hand.\n const row = document.getElementById(`so-opt-${this.HighlightedIndex}`);\n row?.scrollIntoView({ block: 'nearest' });\n if (rowHadFocus) {\n row?.focus();\n }\n }\n\n /**\n * Tab behavior inside the dialog:\n * - On a result row, Tab / Shift+Tab step through the RESULTS themselves\n * (mirrors ArrowDown/Up) until walking off either end of the list — then\n * focus continues to the footer actions / back to the earlier controls.\n * - Everywhere else, Tab wraps within the dialog (focus trap): input → close\n * → filter chips → results → footer actions → back to the input.\n * Escape is handled by the document-level keydown.\n */\n public OnSpotlightKeydown(event: KeyboardEvent): void {\n if (event.key !== 'Tab') {\n return;\n }\n const activeEl = document.activeElement as HTMLElement | null;\n if (activeEl?.classList.contains('result-item')) {\n const last = this.FlatResults.length - 1;\n if (!event.shiftKey && this.HighlightedIndex < last) {\n event.preventDefault();\n this.moveHighlight(1); // row has focus, so focus travels with it\n return;\n }\n if (event.shiftKey && this.HighlightedIndex > 0) {\n event.preventDefault();\n this.moveHighlight(-1);\n return;\n }\n // At either end: fall through so Tab leaves the list naturally.\n }\n const root = (event.currentTarget as HTMLElement) ?? null;\n if (!root) {\n return;\n }\n const focusables = Array.from(\n root.querySelectorAll<HTMLElement>('input, button, .result-item[tabindex=\"0\"], .search-recent-item[tabindex=\"0\"]')\n ).filter((el) => el.offsetParent !== null);\n if (focusables.length === 0) {\n return;\n }\n const active = document.activeElement as HTMLElement | null;\n if (!event.shiftKey && active === focusables[focusables.length - 1]) {\n event.preventDefault();\n focusables[0].focus();\n } else if (event.shiftKey && active === focusables[0]) {\n event.preventDefault();\n focusables[focusables.length - 1].focus();\n }\n }\n\n /**\n * Recent-search row activated (click or Enter/Space). Re-runs the search AND\n * refocuses the input — the activated row leaves the DOM when recents are\n * replaced by results, which would otherwise drop focus to <body>.\n */\n public OnRecentSelect(query: string): void {\n this.OnQueryInput(query);\n this.SearchInputRef?.nativeElement?.focus();\n }\n\n /** Recent-search rows are keyboard-activatable (Enter/Space = click). */\n public OnRecentKeydown(event: KeyboardEvent, query: string): void {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.OnRecentSelect(query);\n }\n }\n\n private setupSearchDebounce(): void {\n this.searchInput$\n .pipe(\n debounceTime(this.DebounceMs),\n distinctUntilChanged(),\n takeUntil(this.destroy$)\n )\n .subscribe(() => this.executeSearch());\n }\n\n private subscribeToSearchState(): void {\n this.searchService.IsSearching$\n .pipe(takeUntil(this.destroy$))\n .subscribe(val => {\n this.IsSearching = val;\n this.cdr.detectChanges();\n });\n }\n\n private async executeSearch(): Promise<void> {\n const query = this.Query.trim();\n if (!query) {\n this.clearResults();\n return;\n }\n\n const version = ++this.searchVersion;\n\n const request: SearchRequest = {\n Query: query,\n MaxResults: this.MaxResults,\n ActiveFilters: this.ActiveFilters,\n IncludeSources: this.IncludeSources,\n };\n\n if (this.EnableStreaming) {\n this.executeStreamingSearch(query, request, version);\n return;\n }\n\n const response = await this.searchService.ExecuteSearch(request);\n\n // Discard results if a newer search was triggered while this one was in-flight\n if (version !== this.searchVersion) {\n return;\n }\n\n this.AllResults = response.Results;\n this.ResultGroups = response.Groups;\n this.Filters = response.Filters;\n this.TotalCount = response.TotalCount;\n this.ElapsedMs = response.ElapsedMs;\n this.HasSearched = true;\n this.HighlightedIndex = response.Results.length > 0 ? 0 : -1;\n\n this.SearchExecuted.emit({\n Query: query,\n Filters: this.ActiveFilters,\n ResultCount: response.TotalCount,\n ElapsedMs: response.ElapsedMs,\n });\n\n this.cdr.detectChanges();\n }\n\n /**\n * Streaming variant of executeSearch — subscribes to `SearchService.StreamSearch` and\n * progressively updates the result list as each provider reports back. The 'final'\n * event carries the canonical fused/reranked list, which replaces the partials.\n *\n * Cancellation: a new search invocation tears down the in-flight stream via\n * `searchVersion` and `currentStream.unsubscribe()`.\n */\n private executeStreamingSearch(query: string, request: SearchRequest, version: number): void {\n // Tear down any prior stream so we don't get cross-talk between consecutive queries.\n this.currentStream?.unsubscribe();\n this.currentStream = null;\n\n // Reset visible state for a fresh stream.\n this.StreamingProviders = [];\n this.AllResults = [];\n this.ResultGroups = [];\n this.TotalCount = 0;\n this.ElapsedMs = 0;\n this.HasSearched = true;\n this.HighlightedIndex = -1;\n this.cdr.detectChanges();\n\n this.currentStream = this.searchService.StreamSearch(request).subscribe({\n next: (event) => {\n if (version !== this.searchVersion) return;\n\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 // Append partials so the user sees the list grow as providers return.\n this.AllResults = [...this.AllResults, ...event.Results];\n this.ResultGroups = this.searchService.GroupResults(this.AllResults);\n this.TotalCount = this.AllResults.length;\n if (this.HighlightedIndex < 0) {\n this.HighlightedIndex = 0;\n }\n }\n } else if (event.Phase === 'final' && event.Results) {\n // Replace the appended partials with the canonical fused/reranked list.\n this.AllResults = event.Results;\n this.ResultGroups = this.searchService.GroupResults(this.AllResults);\n this.Filters = this.searchService.BuildFilters(this.AllResults);\n this.TotalCount = event.Results.length;\n this.ElapsedMs = event.ElapsedMs ?? this.ElapsedMs;\n this.HighlightedIndex = event.Results.length > 0 ? 0 : -1;\n }\n\n this.cdr.detectChanges();\n },\n error: (err: Error) => {\n if (version !== this.searchVersion) return;\n this.StreamingProviders = [\n ...this.StreamingProviders,\n { Name: 'stream', Count: 0, ElapsedMs: 0, State: 'Error', ErrorMessage: err.message },\n ];\n this.cdr.detectChanges();\n },\n complete: () => {\n if (version !== this.searchVersion) return;\n this.SearchExecuted.emit({\n Query: query,\n Filters: this.ActiveFilters,\n ResultCount: this.TotalCount,\n ElapsedMs: this.ElapsedMs,\n });\n this.cdr.detectChanges();\n },\n });\n }\n\n private clearResults(): void {\n this.AllResults = [];\n this.ResultGroups = [];\n this.Filters = [];\n this.TotalCount = 0;\n this.ElapsedMs = 0;\n this.HasSearched = false;\n this.HighlightedIndex = -1;\n this.cdr.detectChanges();\n }\n\n private onOverlayOpened(): void {\n // Remember what had focus so Close() can hand it back (a11y: the overlay\n // is a modal dialog — focus must return to the summoning control).\n this.previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n // Focus input after view updates\n Promise.resolve().then(() => {\n this.SearchInputRef?.nativeElement?.focus();\n this.cdr.detectChanges();\n });\n }\n\n private onOverlayClosed(): void {\n this.HighlightedIndex = -1;\n if (this.previousFocus?.isConnected) {\n this.previousFocus.focus();\n }\n this.previousFocus = null;\n }\n\n /** Check if any filters are active (used by template) */\n public HasActiveFilters(): boolean {\n return Object.values(this.ActiveFilters).some(v => v.length > 0);\n }\n\n /** @deprecated Use {@link HasActiveFilters}. */\n public hasActiveFilters(): boolean {\n return this.HasActiveFilters();\n }\n\n /** Check if a result is currently keyboard-highlighted */\n public IsResultHighlighted(result: SearchResultItem): boolean {\n const flatIndex = this.GetFlatIndex(result);\n return flatIndex === this.HighlightedIndex;\n }\n\n /** @deprecated Use {@link IsResultHighlighted}. */\n public isResultHighlighted(result: SearchResultItem): boolean {\n return this.IsResultHighlighted(result);\n }\n\n /** Get the flat index of a result for keyboard navigation */\n public GetFlatIndex(result: SearchResultItem): number {\n return this.FlatResults.indexOf(result);\n }\n\n /** @deprecated Use {@link GetFlatIndex}. */\n public getFlatIndex(result: SearchResultItem): number {\n return this.GetFlatIndex(result);\n }\n}\n","@if (IsOpen) {\n <!-- Backdrop -->\n <div class=\"search-backdrop\" (click)=\"OnBackdropClick()\"></div>\n\n <!-- Spotlight container -->\n <div class=\"search-spotlight\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Search\"\n (click)=\"$event.stopPropagation()\" (keydown)=\"OnSpotlightKeydown($event)\">\n <!-- Search input area -->\n <div class=\"search-input-wrap\">\n <i class=\"fa-solid fa-magnifying-glass search-icon\"></i>\n <input\n #searchInput\n type=\"text\"\n class=\"search-input\"\n role=\"combobox\"\n aria-controls=\"search-overlay-listbox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"AllResults.length > 0\"\n [attr.aria-activedescendant]=\"ActiveDescendantId\"\n [placeholder]=\"Placeholder\"\n [value]=\"Query\"\n (input)=\"OnQueryInput($any($event.target).value)\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (IsSearching) {\n <div class=\"search-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n </div>\n }\n <div class=\"search-shortcut-hint\">\n <kbd>ESC</kbd>\n </div>\n <button type=\"button\" class=\"search-close-btn\" aria-label=\"Close\" title=\"Close\" (click)=\"Close()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <!-- Results area -->\n <div class=\"search-results-area\">\n @if (EnableStreaming && (IsSearching || StreamingProviders.length > 0)) {\n <!-- Streaming status strip — one chip per provider that has reported -->\n <div class=\"streaming-status-strip\" aria-live=\"polite\">\n @if (StreamingProviders.length === 0 && IsSearching) {\n <span class=\"streaming-chip streaming-chip-pending\">\n <i class=\"fa-solid fa-circle-notch fa-spin\"></i>\n <span>Searching…</span>\n </span>\n }\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\">{{ FormatElapsedTime(p.ElapsedMs) }}</span>\n } @else if (p.ErrorMessage) {\n <span class=\"streaming-chip-time\">{{ p.ErrorMessage }}</span>\n }\n </span>\n }\n </div>\n }\n @if (ShowFilters && Filters.length > 0) {\n <!-- Filter chips -->\n <div class=\"search-filter-bar\">\n @for (filter of Filters; track filter.Category) {\n @for (option of filter.Options; track option.Value) {\n <button\n class=\"filter-chip\"\n [class.filter-chip-active]=\"IsFilterActive(filter.Category, option.Value)\"\n (click)=\"OnFilterToggle(filter.Category, option.Value)\"\n >\n @if (option.Icon) {\n <i [class]=\"option.Icon\"></i>\n }\n <span>{{ option.Label }}</span>\n <span class=\"filter-chip-count\">{{ option.Count }}</span>\n </button>\n }\n }\n @if (hasActiveFilters()) {\n <button class=\"filter-clear-btn\" (click)=\"ClearAllFilters()\">\n <i class=\"fa-solid fa-times\"></i> Clear\n </button>\n }\n </div>\n }\n\n @if (HasSearched && AllResults.length === 0 && !IsSearching) {\n <!-- No results -->\n <mj-empty-state\n Variant=\"no-results\"\n Title=\"No results found\"\n Message=\"Try different keywords or remove some filters\">\n @if (ShowAgentCta) {\n <button ngProjectAs=\"[actions]\" class=\"agent-cta-btn\" (click)=\"OnAgentCtaClick()\">\n <i class=\"fa-solid fa-robot\"></i>\n {{ AgentCtaText }}\n </button>\n }\n </mj-empty-state>\n }\n\n @if (!HasSearched && !IsSearching) {\n <!-- Recent searches -->\n <div class=\"search-recent\">\n @if (searchService.RecentSearches$.value.length > 0) {\n <div class=\"search-recent-header\">\n <span class=\"search-recent-title\">Recent Searches</span>\n </div>\n @for (recent of searchService.RecentSearches$.value; track recent.Query; let i = $index) {\n @if (i < 5) {\n <div class=\"search-recent-item\" role=\"button\" tabindex=\"0\"\n (click)=\"OnRecentSelect(recent.Query)\"\n (keydown)=\"OnRecentKeydown($event, recent.Query)\">\n <i class=\"fa-solid fa-clock search-recent-icon\"></i>\n <span>{{ recent.Query }}</span>\n <span class=\"search-recent-count\">{{ recent.ResultCount }} results</span>\n </div>\n }\n }\n } @else {\n <mj-empty-state\n Variant=\"no-results\"\n Title=\"Start typing to search across all your knowledge\"\n Size=\"compact\" />\n }\n </div>\n }\n\n @if (AllResults.length > 0) {\n <!-- Grouped results -->\n <div id=\"search-overlay-listbox\" role=\"listbox\" aria-label=\"Search results\">\n @for (group of ResultGroups; track group.SourceType) {\n <div class=\"result-group\" role=\"presentation\">\n <div class=\"result-group-header\" role=\"presentation\">\n <i [class]=\"group.Icon\"></i>\n <span class=\"result-group-label\">{{ group.Label }}</span>\n <span class=\"result-group-count\">{{ group.TotalCount }}</span>\n </div>\n @for (result of group.Results; track result.ID; let ri = $index) {\n <div\n class=\"result-item\"\n role=\"option\"\n [attr.id]=\"'so-opt-' + getFlatIndex(result)\"\n [attr.tabindex]=\"isResultHighlighted(result) ? 0 : -1\"\n [attr.aria-selected]=\"isResultHighlighted(result)\"\n [class.result-item-highlighted]=\"isResultHighlighted(result)\"\n (click)=\"OnResultClick(result, $event)\"\n (focus)=\"HighlightedIndex = getFlatIndex(result)\"\n (mouseenter)=\"HighlightedIndex = getFlatIndex(result)\"\n >\n <div class=\"result-item-icon\">\n <i [class]=\"result.SourceIcon\"></i>\n </div>\n <div class=\"result-item-content\">\n <div class=\"result-item-title\">{{ result.Title }}</div>\n <div class=\"result-item-snippet\">{{ result.Snippet }}</div>\n @if (result.Tags.length > 0) {\n <div class=\"result-item-tags\">\n @for (tag of result.Tags; track tag; let ti = $index) {\n @if (ti < 3) {\n <span class=\"result-tag\">{{ tag }}</span>\n }\n }\n </div>\n }\n </div>\n <div class=\"result-item-score\">\n <span class=\"score-badge\">{{ FormatScore(result.Score) }}</span>\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"search-footer\">\n <span class=\"search-footer-count\">\n {{ TotalCount }} results in {{ FormatElapsedTime(ElapsedMs) }}\n </span>\n <div class=\"search-footer-actions\">\n <button type=\"button\" class=\"see-all-btn\" (click)=\"OnSeeAllClick()\">\n See all results\n <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n @if (ShowAgentCta) {\n <button class=\"agent-cta-btn agent-cta-btn-small\" (click)=\"OnAgentCtaClick()\">\n <i class=\"fa-solid fa-robot\"></i>\n {{ AgentCtaText }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Host-supplied promo strip (e.g. command palette nudge) -->\n @if (ShowPromo && PromoText) {\n <div class=\"search-promo\">\n <i class=\"fa-solid fa-wand-magic-sparkles search-promo-icon\"></i>\n <span class=\"search-promo-text\">{{ PromoText }}</span>\n <button type=\"button\" class=\"search-promo-action\" (click)=\"OnPromoAccept()\">{{ PromoActionLabel }}</button>\n <button type=\"button\" class=\"search-promo-dismiss\" aria-label=\"Dismiss\" title=\"Dismiss\" (click)=\"OnPromoDismiss()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"search-overlay.component.js","sourceRoot":"","sources":["../../src/lib/search-overlay.component.ts","../../src/lib/search-overlay.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search Overlay Component\n *\n * A floating search overlay inspired by command palette / Spotlight style.\n * Triggered by Cmd+K (Mac) or Ctrl+K (Windows), appears as a centered\n * floating panel with backdrop blur, search input, and grouped results.\n *\n * Supports keyboard navigation (up/down/enter/escape), filter facets,\n * and responsive mobile layout.\n */\n\nimport {\n Component,\n EventEmitter,\n HostListener,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ChangeDetectorRef,\n ElementRef,\n ViewChild,\n inject\n} from '@angular/core';\nimport { Subject, Subscription } from 'rxjs';\nimport { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';\nimport { SearchService } from './search.service';\nimport {\n SearchResultItem,\n SearchResultGroup,\n SearchFilter,\n SearchRequest,\n SearchResultSelectedEvent,\n SearchFilterChangeEvent,\n SearchExecutedEvent,\n} from './search-types';\n\n/**\n * Per-provider streaming status displayed above the results list while a streaming\n * search is in flight. One entry per provider that has reported back. Populated\n * progressively as `streamScopedSearch` emits 'provider' events.\n */\nexport interface StreamingProviderStatus {\n /** Provider name from the SearchEngine (e.g. 'Vector', 'FullText') */\n Name: string;\n /** Result count contributed by this provider */\n Count: number;\n /** Wall-clock latency for this provider's leg, in milliseconds */\n ElapsedMs: number;\n /** Reported state for this provider */\n State: 'Completed' | 'Error';\n /** Last error message if State is 'Error' */\n ErrorMessage?: string;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-search-overlay',\n templateUrl: './search-overlay.component.html',\n styleUrls: ['./search-overlay.component.css']\n})\nexport class SearchOverlayComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n protected searchService = inject(SearchService);\n private destroy$ = new Subject<void>();\n private searchInput$ = new Subject<string>();\n\n @ViewChild('searchInput') SearchInputRef!: ElementRef<HTMLInputElement>;\n\n /** @deprecated Use {@link SearchInputRef}. */\n get searchInputRef(): ElementRef<HTMLInputElement> {\n return this.SearchInputRef;\n }\n /** @deprecated Use {@link SearchInputRef}. */\n set searchInputRef(value: ElementRef<HTMLInputElement>) {\n this.SearchInputRef = value;\n }\n\n // --- Configuration Inputs ---\n\n /** Placeholder text for the search input */\n @Input() Placeholder = 'Search across all your knowledge...';\n\n /**\n * Maximum number of results to fetch and display. Deliberately small — the\n * overlay is a quick-jump surface; \"See all results\" hands off to the full\n * Search Results workspace for anything deeper. 8 matches the omnibar\n * palette's RESULT count (it fetches 9 rows = 8 results + its see-all row;\n * this overlay's see-all is a footer button, not a row).\n */\n @Input() MaxResults = 8;\n\n /** Whether the overlay is currently visible */\n private _isOpen = false;\n\n @Input()\n set IsOpen(value: boolean) {\n const prev = this._isOpen;\n this._isOpen = value;\n if (value && !prev) {\n this.onOverlayOpened();\n }\n if (!value && prev) {\n this.onOverlayClosed();\n }\n }\n get IsOpen(): boolean {\n return this._isOpen;\n }\n\n /** Debounce time in ms before search fires */\n @Input() DebounceMs = 400;\n\n /** Which search sources to include */\n @Input() IncludeSources: ('vector' | 'fulltext' | 'entity')[] = ['vector', 'fulltext', 'entity'];\n\n /** Whether to show filter facets */\n @Input() ShowFilters = true;\n\n /** Text for the agent CTA button */\n @Input() AgentCtaText = 'Ask Knowledge Agent';\n\n /** Whether to show the agent CTA */\n @Input() ShowAgentCta = true;\n\n /**\n * When true, the overlay subscribes to `SearchService.StreamSearch` instead of awaiting\n * `ExecuteSearch`. Results render progressively as each provider reports back. The\n * per-provider status chip strip becomes visible while the stream is in flight.\n * Defaults to false to preserve the request-response UX that shipped in Phase 1.\n */\n @Input() EnableStreaming = false;\n\n /**\n * When false, the overlay does NOT claim the global Ctrl/Cmd+K chord. For hosts\n * (e.g. the Explorer shell) that own that shortcut themselves and open the\n * overlay programmatically — two listeners on the same chord would double-toggle.\n * Escape/arrow handling while open is unaffected.\n */\n @Input() EnableGlobalShortcut = true;\n\n /**\n * Optional promo strip pinned to the overlay's bottom edge — a host-supplied\n * nudge (e.g. Explorer advertising its command palette). The component is\n * deliberately ignorant of WHAT is being promoted; the host provides the\n * copy and handles both outcomes.\n */\n @Input() ShowPromo = false;\n\n /** Promo copy (one sentence). Required when ShowPromo is true. */\n @Input() PromoText = '';\n\n /** Label for the promo's accept action. */\n @Input() PromoActionLabel = 'Turn on';\n\n // --- Outputs ---\n\n @Output() IsOpenChange = new EventEmitter<boolean>();\n @Output() ResultSelected = new EventEmitter<SearchResultSelectedEvent>();\n @Output() FilterChanged = new EventEmitter<SearchFilterChangeEvent>();\n @Output() SearchExecuted = new EventEmitter<SearchExecutedEvent>();\n @Output() AgentCtaClicked = new EventEmitter<string>();\n /**\n * Emitted when the user clicks \"See all results\" — carries the current query.\n * Hosts (e.g. the Explorer shell) open the full Search Results workspace,\n * which has scopes, relevance controls, and richer result actions than this\n * capped quick-jump overlay. The overlay closes itself after emitting.\n */\n @Output() SeeAllRequested = new EventEmitter<string>();\n /** Promo accept — carries the current query so the host can hand it off. */\n @Output() PromoAccepted = new EventEmitter<string>();\n /** Promo dismissed — the host should persist this and stop showing it. */\n @Output() PromoDismissed = new EventEmitter<void>();\n\n // --- Component State ---\n\n public Query = '';\n public IsSearching = false;\n public ResultGroups: SearchResultGroup[] = [];\n public AllResults: SearchResultItem[] = [];\n public Filters: SearchFilter[] = [];\n public ActiveFilters: Record<string, string[]> = {};\n public TotalCount = 0;\n public ElapsedMs = 0;\n public HighlightedIndex = -1;\n public HasSearched = false;\n private searchVersion = 0;\n\n /**\n * Per-provider status entries shown above the results list while a streaming search\n * is in flight. One entry per provider that has reported back. Empty when the user\n * is not running a streaming search (or when `EnableStreaming` is false).\n */\n public 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 /** Element focused before the overlay opened — restored on close (a11y). */\n private previousFocus: HTMLElement | null = null;\n\n /** All results flattened for keyboard navigation */\n public get FlatResults(): SearchResultItem[] {\n return this.AllResults;\n }\n\n /** id of the highlighted option, announced via aria-activedescendant. */\n public get ActiveDescendantId(): string | null {\n return this.HighlightedIndex >= 0 && this.HighlightedIndex < this.FlatResults.length\n ? `so-opt-${this.HighlightedIndex}`\n : null;\n }\n\n ngOnInit(): void {\n this.setupSearchDebounce();\n this.subscribeToSearchState();\n }\n\n ngOnDestroy(): void {\n this.currentStream?.unsubscribe();\n this.currentStream = null;\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // --- Keyboard shortcuts ---\n\n @HostListener('document:keydown', ['$event'])\n HandleGlobalKeydown(event: KeyboardEvent): void {\n if (this.EnableGlobalShortcut && this.isToggleShortcut(event)) {\n event.preventDefault();\n this.ToggleOverlay();\n return;\n }\n if (this._isOpen) {\n this.handleOverlayKeydown(event);\n }\n }\n\n /** Toggle the overlay open/closed */\n public ToggleOverlay(): void {\n this.IsOpen = !this._isOpen;\n this.IsOpenChange.emit(this._isOpen);\n }\n\n /** Open the overlay */\n public Open(): void {\n if (!this._isOpen) {\n this.IsOpen = true;\n this.IsOpenChange.emit(true);\n }\n }\n\n /** Close the overlay */\n public Close(): void {\n if (this._isOpen) {\n this.IsOpen = false;\n this.IsOpenChange.emit(false);\n }\n }\n\n /** Handle query input changes */\n public OnQueryInput(value: string): void {\n this.Query = value;\n this.searchInput$.next(value);\n }\n\n /** Handle clicking a result */\n public OnResultClick(result: SearchResultItem, event: MouseEvent): void {\n this.ResultSelected.emit({\n Result: result,\n OpenInNewTab: event.metaKey || event.ctrlKey\n });\n this.Close();\n }\n\n /** Handle selecting the highlighted result */\n public SelectHighlighted(): void {\n if (this.HighlightedIndex >= 0 && this.HighlightedIndex < this.FlatResults.length) {\n this.ResultSelected.emit({\n Result: this.FlatResults[this.HighlightedIndex],\n OpenInNewTab: false\n });\n this.Close();\n }\n }\n\n /** Handle filter option toggle */\n public OnFilterToggle(category: string, value: string): void {\n const current = this.ActiveFilters[category] ?? [];\n const index = current.indexOf(value);\n if (index >= 0) {\n current.splice(index, 1);\n } else {\n current.push(value);\n }\n this.ActiveFilters[category] = current;\n this.FilterChanged.emit({ Category: category, SelectedValues: current });\n this.executeSearch();\n }\n\n /** Clear all active filters */\n public ClearAllFilters(): void {\n this.ActiveFilters = {};\n this.executeSearch();\n }\n\n /** Handle clicking the agent CTA */\n public OnAgentCtaClick(): void {\n this.AgentCtaClicked.emit(this.Query);\n this.Close();\n }\n\n /** Promo accept: emit the current query and close — the host takes over. */\n public OnPromoAccept(): void {\n this.PromoAccepted.emit(this.Query.trim());\n this.Close();\n }\n\n /** Promo dismiss: the host persists the dismissal; hide it immediately. */\n public OnPromoDismiss(): void {\n this.ShowPromo = false;\n this.PromoDismissed.emit();\n }\n\n /** Handle clicking \"See all results\" — hand off to the full Search workspace */\n public OnSeeAllClick(): void {\n const query = this.Query.trim();\n if (query.length > 0) {\n this.SeeAllRequested.emit(query);\n }\n this.Close();\n }\n\n /** Handle clicking the backdrop to close */\n public OnBackdropClick(): void {\n this.Close();\n }\n\n /** Check if a filter option is active */\n public IsFilterActive(category: string, value: string): boolean {\n return (this.ActiveFilters[category] ?? []).includes(value);\n }\n\n /** Get a score display value (percentage) */\n public FormatScore(score: number): string {\n return `${Math.round(score * 100)}%`;\n }\n\n /** Format elapsed time display */\n public FormatElapsedTime(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n return `${(ms / 1000).toFixed(1)}s`;\n }\n\n // --- Private Methods ---\n\n private isToggleShortcut(event: KeyboardEvent): boolean {\n return (event.metaKey || event.ctrlKey) && event.key === 'k';\n }\n\n private handleOverlayKeydown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'Escape':\n event.preventDefault();\n this.Close();\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.moveHighlight(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.moveHighlight(-1);\n break;\n case 'Enter': {\n // Only claim Enter when it belongs to the combobox model (typing in\n // the input / a focused result row). A focused BUTTON (close,\n // see-all, filter chip, promo) must keep its native Enter\n // activation — preventDefault here at document level would\n // silently swallow it, or worse, open the highlighted result.\n const active = document.activeElement as HTMLElement | null;\n const inCombobox = active === this.SearchInputRef?.nativeElement\n || (active?.classList.contains('result-item') ?? false);\n if (!inCombobox) {\n return;\n }\n event.preventDefault();\n this.SelectHighlighted();\n break;\n }\n }\n }\n\n private moveHighlight(direction: number): void {\n const maxIndex = this.FlatResults.length - 1;\n if (maxIndex < 0) return;\n\n // If a result row currently holds DOM focus (roving tabindex), keep focus\n // travelling with the highlight; from the input, only the highlight moves.\n const rowHadFocus = document.activeElement instanceof HTMLElement\n && document.activeElement.classList.contains('result-item');\n\n this.HighlightedIndex += direction;\n if (this.HighlightedIndex < 0) {\n this.HighlightedIndex = maxIndex;\n } else if (this.HighlightedIndex > maxIndex) {\n this.HighlightedIndex = 0;\n }\n this.cdr.detectChanges();\n\n // Keyboard-driven moves keep the highlighted row visible. Mouse hover sets\n // HighlightedIndex directly in the template and deliberately does NOT\n // scroll — auto-scrolling under the pointer fights the user's hand.\n const row = document.getElementById(`so-opt-${this.HighlightedIndex}`);\n row?.scrollIntoView({ block: 'nearest' });\n if (rowHadFocus) {\n row?.focus();\n }\n }\n\n /**\n * Tab behavior inside the dialog:\n * - On a result row, Tab / Shift+Tab step through the RESULTS themselves\n * (mirrors ArrowDown/Up) until walking off either end of the list — then\n * focus continues to the footer actions / back to the earlier controls.\n * - Everywhere else, Tab wraps within the dialog (focus trap): input → close\n * → filter chips → results → footer actions → back to the input.\n * Escape is handled by the document-level keydown.\n */\n public OnSpotlightKeydown(event: KeyboardEvent): void {\n if (event.key !== 'Tab') {\n return;\n }\n const activeEl = document.activeElement as HTMLElement | null;\n if (activeEl?.classList.contains('result-item')) {\n const last = this.FlatResults.length - 1;\n if (!event.shiftKey && this.HighlightedIndex < last) {\n event.preventDefault();\n this.moveHighlight(1); // row has focus, so focus travels with it\n return;\n }\n if (event.shiftKey && this.HighlightedIndex > 0) {\n event.preventDefault();\n this.moveHighlight(-1);\n return;\n }\n // At either end: fall through so Tab leaves the list naturally.\n }\n const root = (event.currentTarget as HTMLElement) ?? null;\n if (!root) {\n return;\n }\n const focusables = Array.from(\n root.querySelectorAll<HTMLElement>('input, button, .result-item[tabindex=\"0\"], .search-recent-item[tabindex=\"0\"]')\n ).filter((el) => el.offsetParent !== null);\n if (focusables.length === 0) {\n return;\n }\n const active = document.activeElement as HTMLElement | null;\n if (!event.shiftKey && active === focusables[focusables.length - 1]) {\n event.preventDefault();\n focusables[0].focus();\n } else if (event.shiftKey && active === focusables[0]) {\n event.preventDefault();\n focusables[focusables.length - 1].focus();\n }\n }\n\n /**\n * Recent-search row activated (click or Enter/Space). Re-runs the search AND\n * refocuses the input — the activated row leaves the DOM when recents are\n * replaced by results, which would otherwise drop focus to <body>.\n */\n public OnRecentSelect(query: string): void {\n this.OnQueryInput(query);\n this.SearchInputRef?.nativeElement?.focus();\n }\n\n /** Recent-search rows are keyboard-activatable (Enter/Space = click). */\n public OnRecentKeydown(event: KeyboardEvent, query: string): void {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.OnRecentSelect(query);\n }\n }\n\n private setupSearchDebounce(): void {\n this.searchInput$\n .pipe(\n debounceTime(this.DebounceMs),\n distinctUntilChanged(),\n takeUntil(this.destroy$)\n )\n .subscribe(() => this.executeSearch());\n }\n\n private subscribeToSearchState(): void {\n this.searchService.IsSearching$\n .pipe(takeUntil(this.destroy$))\n .subscribe(val => {\n this.IsSearching = val;\n this.cdr.detectChanges();\n });\n }\n\n private async executeSearch(): Promise<void> {\n const query = this.Query.trim();\n if (!query) {\n this.clearResults();\n return;\n }\n\n const version = ++this.searchVersion;\n\n const request: SearchRequest = {\n Query: query,\n MaxResults: this.MaxResults,\n ActiveFilters: this.ActiveFilters,\n IncludeSources: this.IncludeSources,\n };\n\n if (this.EnableStreaming) {\n this.executeStreamingSearch(query, request, version);\n return;\n }\n\n const response = await this.searchService.ExecuteSearch(request);\n\n // Discard results if a newer search was triggered while this one was in-flight\n if (version !== this.searchVersion) {\n return;\n }\n\n this.AllResults = response.Results;\n this.ResultGroups = response.Groups;\n this.Filters = response.Filters;\n this.TotalCount = response.TotalCount;\n this.ElapsedMs = response.ElapsedMs;\n this.HasSearched = true;\n this.HighlightedIndex = response.Results.length > 0 ? 0 : -1;\n\n this.SearchExecuted.emit({\n Query: query,\n Filters: this.ActiveFilters,\n ResultCount: response.TotalCount,\n ElapsedMs: response.ElapsedMs,\n });\n\n this.cdr.detectChanges();\n }\n\n /**\n * Streaming variant of executeSearch — subscribes to `SearchService.StreamSearch`, shows each\n * provider's count in the chip strip as it reports back, and renders the result list from the\n * 'final' event. A 'provider' event carries no rows: they arrive before the server's permission pass.\n *\n * Cancellation: a new search invocation tears down the in-flight stream via\n * `searchVersion` and `currentStream.unsubscribe()`.\n */\n private executeStreamingSearch(query: string, request: SearchRequest, version: number): void {\n // Tear down any prior stream so we don't get cross-talk between consecutive queries.\n this.currentStream?.unsubscribe();\n this.currentStream = null;\n\n // Reset visible state for a fresh stream.\n this.StreamingProviders = [];\n this.AllResults = [];\n this.ResultGroups = [];\n this.TotalCount = 0;\n this.ElapsedMs = 0;\n this.HasSearched = true;\n this.HighlightedIndex = -1;\n this.cdr.detectChanges();\n\n this.currentStream = this.searchService.StreamSearch(request).subscribe({\n next: (event) => {\n if (version !== this.searchVersion) return;\n\n if (event.Phase === 'provider' && event.ProviderName) {\n // Progress only: the count, never the rows (they precede the permission pass).\n this.StreamingProviders = [\n ...this.StreamingProviders,\n {\n Name: event.ProviderName,\n Count: event.ResultCount ?? 0,\n ElapsedMs: event.ElapsedMs ?? 0,\n State: 'Completed',\n },\n ];\n } else if (event.Phase === 'final' && event.Results) {\n // The permission-filtered fused/reranked list.\n this.AllResults = event.Results;\n this.ResultGroups = this.searchService.GroupResults(this.AllResults);\n this.Filters = this.searchService.BuildFilters(this.AllResults);\n this.TotalCount = event.Results.length;\n this.ElapsedMs = event.ElapsedMs ?? this.ElapsedMs;\n this.HighlightedIndex = event.Results.length > 0 ? 0 : -1;\n }\n\n this.cdr.detectChanges();\n },\n error: (err: Error) => {\n if (version !== this.searchVersion) return;\n this.StreamingProviders = [\n ...this.StreamingProviders,\n { Name: 'stream', Count: 0, ElapsedMs: 0, State: 'Error', ErrorMessage: err.message },\n ];\n this.cdr.detectChanges();\n },\n complete: () => {\n if (version !== this.searchVersion) return;\n this.SearchExecuted.emit({\n Query: query,\n Filters: this.ActiveFilters,\n ResultCount: this.TotalCount,\n ElapsedMs: this.ElapsedMs,\n });\n this.cdr.detectChanges();\n },\n });\n }\n\n private clearResults(): void {\n this.AllResults = [];\n this.ResultGroups = [];\n this.Filters = [];\n this.TotalCount = 0;\n this.ElapsedMs = 0;\n this.HasSearched = false;\n this.HighlightedIndex = -1;\n this.cdr.detectChanges();\n }\n\n private onOverlayOpened(): void {\n // Remember what had focus so Close() can hand it back (a11y: the overlay\n // is a modal dialog — focus must return to the summoning control).\n this.previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n // Focus input after view updates\n Promise.resolve().then(() => {\n this.SearchInputRef?.nativeElement?.focus();\n this.cdr.detectChanges();\n });\n }\n\n private onOverlayClosed(): void {\n this.HighlightedIndex = -1;\n if (this.previousFocus?.isConnected) {\n this.previousFocus.focus();\n }\n this.previousFocus = null;\n }\n\n /** Check if any filters are active (used by template) */\n public HasActiveFilters(): boolean {\n return Object.values(this.ActiveFilters).some(v => v.length > 0);\n }\n\n /** @deprecated Use {@link HasActiveFilters}. */\n public hasActiveFilters(): boolean {\n return this.HasActiveFilters();\n }\n\n /** Check if a result is currently keyboard-highlighted */\n public IsResultHighlighted(result: SearchResultItem): boolean {\n const flatIndex = this.GetFlatIndex(result);\n return flatIndex === this.HighlightedIndex;\n }\n\n /** @deprecated Use {@link IsResultHighlighted}. */\n public isResultHighlighted(result: SearchResultItem): boolean {\n return this.IsResultHighlighted(result);\n }\n\n /** Get the flat index of a result for keyboard navigation */\n public GetFlatIndex(result: SearchResultItem): number {\n return this.FlatResults.indexOf(result);\n }\n\n /** @deprecated Use {@link GetFlatIndex}. */\n public getFlatIndex(result: SearchResultItem): number {\n return this.GetFlatIndex(result);\n }\n}\n","@if (IsOpen) {\n <!-- Backdrop -->\n <div class=\"search-backdrop\" (click)=\"OnBackdropClick()\"></div>\n\n <!-- Spotlight container -->\n <div class=\"search-spotlight\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Search\"\n (click)=\"$event.stopPropagation()\" (keydown)=\"OnSpotlightKeydown($event)\">\n <!-- Search input area -->\n <div class=\"search-input-wrap\">\n <i class=\"fa-solid fa-magnifying-glass search-icon\"></i>\n <input\n #searchInput\n type=\"text\"\n class=\"search-input\"\n role=\"combobox\"\n aria-controls=\"search-overlay-listbox\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"AllResults.length > 0\"\n [attr.aria-activedescendant]=\"ActiveDescendantId\"\n [placeholder]=\"Placeholder\"\n [value]=\"Query\"\n (input)=\"OnQueryInput($any($event.target).value)\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (IsSearching) {\n <div class=\"search-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n </div>\n }\n <div class=\"search-shortcut-hint\">\n <kbd>ESC</kbd>\n </div>\n <button type=\"button\" class=\"search-close-btn\" aria-label=\"Close\" title=\"Close\" (click)=\"Close()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <!-- Results area -->\n <div class=\"search-results-area\">\n @if (EnableStreaming && (IsSearching || StreamingProviders.length > 0)) {\n <!-- Streaming status strip — one chip per provider that has reported -->\n <div class=\"streaming-status-strip\" aria-live=\"polite\">\n @if (StreamingProviders.length === 0 && IsSearching) {\n <span class=\"streaming-chip streaming-chip-pending\">\n <i class=\"fa-solid fa-circle-notch fa-spin\"></i>\n <span>Searching…</span>\n </span>\n }\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\">{{ FormatElapsedTime(p.ElapsedMs) }}</span>\n } @else if (p.ErrorMessage) {\n <span class=\"streaming-chip-time\">{{ p.ErrorMessage }}</span>\n }\n </span>\n }\n </div>\n }\n @if (ShowFilters && Filters.length > 0) {\n <!-- Filter chips -->\n <div class=\"search-filter-bar\">\n @for (filter of Filters; track filter.Category) {\n @for (option of filter.Options; track option.Value) {\n <button\n class=\"filter-chip\"\n [class.filter-chip-active]=\"IsFilterActive(filter.Category, option.Value)\"\n (click)=\"OnFilterToggle(filter.Category, option.Value)\"\n >\n @if (option.Icon) {\n <i [class]=\"option.Icon\"></i>\n }\n <span>{{ option.Label }}</span>\n <span class=\"filter-chip-count\">{{ option.Count }}</span>\n </button>\n }\n }\n @if (hasActiveFilters()) {\n <button class=\"filter-clear-btn\" (click)=\"ClearAllFilters()\">\n <i class=\"fa-solid fa-times\"></i> Clear\n </button>\n }\n </div>\n }\n\n @if (HasSearched && AllResults.length === 0 && !IsSearching) {\n <!-- No results -->\n <mj-empty-state\n Variant=\"no-results\"\n Title=\"No results found\"\n Message=\"Try different keywords or remove some filters\">\n @if (ShowAgentCta) {\n <button ngProjectAs=\"[actions]\" class=\"agent-cta-btn\" (click)=\"OnAgentCtaClick()\">\n <i class=\"fa-solid fa-robot\"></i>\n {{ AgentCtaText }}\n </button>\n }\n </mj-empty-state>\n }\n\n @if (!HasSearched && !IsSearching) {\n <!-- Recent searches -->\n <div class=\"search-recent\">\n @if (searchService.RecentSearches$.value.length > 0) {\n <div class=\"search-recent-header\">\n <span class=\"search-recent-title\">Recent Searches</span>\n </div>\n @for (recent of searchService.RecentSearches$.value; track recent.Query; let i = $index) {\n @if (i < 5) {\n <div class=\"search-recent-item\" role=\"button\" tabindex=\"0\"\n (click)=\"OnRecentSelect(recent.Query)\"\n (keydown)=\"OnRecentKeydown($event, recent.Query)\">\n <i class=\"fa-solid fa-clock search-recent-icon\"></i>\n <span>{{ recent.Query }}</span>\n <span class=\"search-recent-count\">{{ recent.ResultCount }} results</span>\n </div>\n }\n }\n } @else {\n <mj-empty-state\n Variant=\"no-results\"\n Title=\"Start typing to search across all your knowledge\"\n Size=\"compact\" />\n }\n </div>\n }\n\n @if (AllResults.length > 0) {\n <!-- Grouped results -->\n <div id=\"search-overlay-listbox\" role=\"listbox\" aria-label=\"Search results\">\n @for (group of ResultGroups; track group.SourceType) {\n <div class=\"result-group\" role=\"presentation\">\n <div class=\"result-group-header\" role=\"presentation\">\n <i [class]=\"group.Icon\"></i>\n <span class=\"result-group-label\">{{ group.Label }}</span>\n <span class=\"result-group-count\">{{ group.TotalCount }}</span>\n </div>\n @for (result of group.Results; track result.ID; let ri = $index) {\n <div\n class=\"result-item\"\n role=\"option\"\n [attr.id]=\"'so-opt-' + getFlatIndex(result)\"\n [attr.tabindex]=\"isResultHighlighted(result) ? 0 : -1\"\n [attr.aria-selected]=\"isResultHighlighted(result)\"\n [class.result-item-highlighted]=\"isResultHighlighted(result)\"\n (click)=\"OnResultClick(result, $event)\"\n (focus)=\"HighlightedIndex = getFlatIndex(result)\"\n (mouseenter)=\"HighlightedIndex = getFlatIndex(result)\"\n >\n <div class=\"result-item-icon\">\n <i [class]=\"result.SourceIcon\"></i>\n </div>\n <div class=\"result-item-content\">\n <div class=\"result-item-title\">{{ result.Title }}</div>\n <div class=\"result-item-snippet\">{{ result.Snippet }}</div>\n @if (result.Tags.length > 0) {\n <div class=\"result-item-tags\">\n @for (tag of result.Tags; track tag; let ti = $index) {\n @if (ti < 3) {\n <span class=\"result-tag\">{{ tag }}</span>\n }\n }\n </div>\n }\n </div>\n <div class=\"result-item-score\">\n <span class=\"score-badge\">{{ FormatScore(result.Score) }}</span>\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"search-footer\">\n <span class=\"search-footer-count\">\n {{ TotalCount }} results in {{ FormatElapsedTime(ElapsedMs) }}\n </span>\n <div class=\"search-footer-actions\">\n <button type=\"button\" class=\"see-all-btn\" (click)=\"OnSeeAllClick()\">\n See all results\n <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n @if (ShowAgentCta) {\n <button class=\"agent-cta-btn agent-cta-btn-small\" (click)=\"OnAgentCtaClick()\">\n <i class=\"fa-solid fa-robot\"></i>\n {{ AgentCtaText }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Host-supplied promo strip (e.g. command palette nudge) -->\n @if (ShowPromo && PromoText) {\n <div class=\"search-promo\">\n <i class=\"fa-solid fa-wand-magic-sparkles search-promo-icon\"></i>\n <span class=\"search-promo-text\">{{ PromoText }}</span>\n <button type=\"button\" class=\"search-promo-action\" (click)=\"OnPromoAccept()\">{{ PromoActionLabel }}</button>\n <button type=\"button\" class=\"search-promo-dismiss\" aria-label=\"Dismiss\" title=\"Dismiss\" (click)=\"OnPromoDismiss()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-suggest.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-suggest.component.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAEH,YAAY,EAEZ,MAAM,EAIT,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"search-suggest.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-suggest.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { Component, EventEmitter, Input, Output, ChangeDetectorRef, inject } from '@angular/core';
|
|
9
9
|
import { StartupManager } from '@memberjunction/core';
|
|
10
10
|
import { UserInfoEngine } from '@memberjunction/core-entities';
|
|
11
|
+
import { PassesSemanticFloor } from './search-types';
|
|
11
12
|
import { MJEventType, MJGlobal } from '@memberjunction/global';
|
|
12
13
|
import * as i0 from "@angular/core";
|
|
13
14
|
const _forTrack0 = ($index, $item) => $item.Query;
|
|
@@ -468,7 +469,7 @@ export class SearchSuggestComponent {
|
|
|
468
469
|
get VisiblePreviewResults() {
|
|
469
470
|
const minScore = this.MinRelevancePercent / 100;
|
|
470
471
|
return [...this.PreviewResults]
|
|
471
|
-
.filter(r => r
|
|
472
|
+
.filter(r => PassesSemanticFloor(r, minScore))
|
|
472
473
|
.sort((a, b) => b.Score - a.Score)
|
|
473
474
|
.slice(0, this.MaxPreviewResults);
|
|
474
475
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-suggest.component.js","sourceRoot":"","sources":["../../src/lib/search-suggest.component.ts","../../src/lib/search-suggest.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search Suggest Component\n *\n * Autocomplete dropdown showing preview results and recent searches.\n * Supports keyboard navigation (up/down/enter) for accessibility.\n * Designed to be paired with SearchInputComponent via SearchCompositeComponent.\n */\n\nimport {\n Component,\n EventEmitter,\n Input,\n OnInit,\n Output,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport { StartupManager } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { SearchResultItem, RecentRecordItem } from './search-types';\nimport { RecentSearch } from './search.service';\nimport { MJEventType, MJGlobal } from '@memberjunction/global';\n\n/** User setting key for persisting the preview min relevance threshold */\nconst PREVIEW_MIN_RELEVANCE_KEY = 'search.previewMinRelevance';\n\n/** Preset options for the min relevance filter */\nconst MIN_RELEVANCE_OPTIONS = [0, 15, 30, 50, 70];\n\n@Component({\n standalone: false,\n selector: 'mj-search-suggest',\n templateUrl: './search-suggest.component.html',\n styleUrls: ['./search-suggest.component.css']\n})\nexport class SearchSuggestComponent implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n\n // --- Configuration Inputs ---\n\n /** Whether the suggest dropdown is visible */\n @Input() IsOpen = false;\n\n /** Preview search results to display */\n @Input() PreviewResults: SearchResultItem[] = [];\n\n /** Recent search entries to show when query is empty/short */\n @Input() RecentSearches: RecentSearch[] = [];\n\n /** Total count of results for the current query (may exceed PreviewResults.length) */\n @Input() TotalCount = 0;\n\n /** Whether a search is currently loading */\n @Input() IsLoading = false;\n\n /** Current query text — used to determine whether to show recent vs preview */\n @Input() Query = '';\n\n /** Minimum query length before preview results are shown */\n @Input() MinQueryLength = 2;\n\n /** Maximum number of preview results to display */\n @Input() MaxPreviewResults = 8;\n\n /** Whether to show the recent searches section */\n @Input() ShowRecent = true;\n\n /**\n * Recently opened records (host-loaded, e.g. from SearchService\n * .GetRecentlyOpenedRecords). Rendered as a \"Recently Opened\" section in\n * the idle/empty state so users can jump straight back to a record they\n * just had open — the complement to Recent Searches (queries).\n */\n @Input() RecentRecords: RecentRecordItem[] = [];\n\n /**\n * Optional promo row pinned to the dropdown's bottom edge — a host-supplied\n * nudge (e.g. Explorer advertising its command palette). The component is\n * deliberately ignorant of WHAT is being promoted; the host provides the\n * copy and handles both outcomes.\n */\n @Input() ShowPromo = false;\n\n /** Promo copy (one sentence). Required when ShowPromo is true. */\n @Input() PromoText = '';\n\n /** Label for the promo's accept action. */\n @Input() PromoActionLabel = 'Turn on';\n\n // --- Outputs ---\n\n /** Emitted when the user selects a preview result */\n @Output() ResultSelected = new EventEmitter<SearchResultItem>();\n\n /** Emitted when the user selects a recent search */\n @Output() RecentSelected = new EventEmitter<string>();\n\n /** Emitted when the user clicks \"See all N results\" */\n @Output() SeeAllRequested = new EventEmitter<string>();\n\n /** Emitted when the user clicks \"Clear\" on recent searches */\n @Output() ClearRecentRequested = new EventEmitter<void>();\n\n /** Emitted when the user selects a recently opened record */\n @Output() RecentRecordSelected = new EventEmitter<RecentRecordItem>();\n\n /** Promo accept — carries the current query so the host can hand it off. */\n @Output() PromoAccepted = new EventEmitter<string>();\n\n /** Promo dismissed — the host should persist this and stop showing it. */\n @Output() PromoDismissed = new EventEmitter<void>();\n\n // --- Internal state ---\n\n /** Currently keyboard-highlighted index (-1 for none) */\n public HighlightedIndex = -1;\n\n /** Min relevance percentage (0-100) for filtering preview results */\n public MinRelevancePercent = 0;\n\n /** Whether the filter popover is open */\n public IsFilterOpen = false;\n\n /** Available min relevance presets */\n public readonly MinRelevanceOptions = MIN_RELEVANCE_OPTIONS;\n\n // --- Lifecycle ---\n\n async ngOnInit(): Promise<void> {\n await this.loadMinRelevanceSetting();\n }\n\n // --- Public Methods ---\n\n /** Move keyboard highlight up */\n public NavigateUp(): void {\n const maxIndex = this.getNavigableItemCount() - 1;\n if (maxIndex < 0) return;\n\n this.HighlightedIndex--;\n if (this.HighlightedIndex < 0) {\n this.HighlightedIndex = maxIndex;\n }\n this.cdr.detectChanges();\n }\n\n /** Move keyboard highlight down */\n public NavigateDown(): void {\n const maxIndex = this.getNavigableItemCount() - 1;\n if (maxIndex < 0) return;\n\n this.HighlightedIndex++;\n if (this.HighlightedIndex > maxIndex) {\n this.HighlightedIndex = 0;\n }\n this.cdr.detectChanges();\n }\n\n /** Select the currently highlighted item */\n public SelectHighlighted(): void {\n if (this.HighlightedIndex < 0) return;\n\n if (this.ShowRecentSection) {\n // Navigating recent searches\n const visibleRecent = this.VisibleRecentSearches;\n if (this.HighlightedIndex < visibleRecent.length) {\n this.OnRecentClick(visibleRecent[this.HighlightedIndex]);\n return;\n }\n }\n\n if (this.ShowRecentRecordsSection) {\n // Navigating recently opened records (indexes continue after recents)\n const offset = this.ShowRecentSection ? this.VisibleRecentSearches.length : 0;\n const recordIndex = this.HighlightedIndex - offset;\n const visibleRecords = this.VisibleRecentRecords;\n if (recordIndex >= 0 && recordIndex < visibleRecords.length) {\n this.OnRecentRecordClick(visibleRecords[recordIndex]);\n return;\n }\n }\n\n if (this.ShowPreviewSection) {\n // Navigating preview results\n const offset = this.ShowRecentSection ? this.VisibleRecentSearches.length : 0;\n const resultIndex = this.HighlightedIndex - offset;\n const visibleResults = this.VisiblePreviewResults;\n if (resultIndex >= 0 && resultIndex < visibleResults.length) {\n this.OnResultClick(visibleResults[resultIndex]);\n return;\n }\n\n // \"See all\" footer\n if (resultIndex === visibleResults.length && this.ShowSeeAllFooter) {\n this.OnSeeAllClick();\n }\n }\n }\n\n /** Reset the highlighted index */\n public ResetHighlight(): void {\n this.HighlightedIndex = -1;\n }\n\n /** Number of keyboard-navigable rows currently visible (recents + recently\n opened + preview results + see-all). Public so the composite's Tab\n handling knows when the highlight has walked off the end of the list. */\n public get NavigableItemCount(): number {\n return this.getNavigableItemCount();\n }\n\n // --- Template getters ---\n\n /** Whether to show recent searches section */\n public get ShowRecentSection(): boolean {\n return this.ShowRecent && this.Query.length < this.MinQueryLength && this.RecentSearches.length > 0;\n }\n\n /** @deprecated Use {@link ShowRecentSection}. */\n public get showRecentSection(): boolean {\n return this.ShowRecentSection;\n }\n\n /** Whether to show preview results section */\n public get ShowPreviewSection(): boolean {\n return this.Query.length >= this.MinQueryLength;\n }\n\n /** @deprecated Use {@link ShowPreviewSection}. */\n public get showPreviewSection(): boolean {\n return this.ShowPreviewSection;\n }\n\n /** Whether to show the recently-opened-records section (idle state only) */\n public get ShowRecentRecordsSection(): boolean {\n return this.Query.length < this.MinQueryLength && this.RecentRecords.length > 0;\n }\n\n /** @deprecated Use {@link ShowRecentRecordsSection}. */\n public get showRecentRecordsSection(): boolean {\n return this.ShowRecentRecordsSection;\n }\n\n /** Visible recently opened records (capped at 3) */\n public get VisibleRecentRecords(): RecentRecordItem[] {\n return this.RecentRecords.slice(0, 3);\n }\n\n /** Whether to show the \"See all N results\" footer */\n public get ShowSeeAllFooter(): boolean {\n return this.ShowPreviewSection && this.TotalCount > 0;\n }\n\n /** @deprecated Use {@link ShowSeeAllFooter}. */\n public get showSeeAllFooter(): boolean {\n return this.ShowSeeAllFooter;\n }\n\n /** Visible recent searches (capped at 5) */\n public get VisibleRecentSearches(): RecentSearch[] {\n return this.RecentSearches.slice(0, 5);\n }\n\n /** Visible preview results filtered by min relevance, sorted by score descending, capped at MaxPreviewResults */\n public get VisiblePreviewResults(): SearchResultItem[] {\n const minScore = this.MinRelevancePercent / 100;\n return [...this.PreviewResults]\n .filter(r => r.Score >= minScore)\n .sort((a, b) => b.Score - a.Score)\n .slice(0, this.MaxPreviewResults);\n }\n\n // --- Template event handlers ---\n\n /** Handle clicking a preview result */\n public OnResultClick(result: SearchResultItem): void {\n this.ResultSelected.emit(result);\n }\n\n /** Handle clicking a recent search */\n public OnRecentClick(recent: RecentSearch): void {\n this.RecentSelected.emit(recent.Query);\n }\n\n /** Handle clicking a recently opened record */\n public OnRecentRecordClick(record: RecentRecordItem): void {\n this.RecentRecordSelected.emit(record);\n }\n\n /** Handle clicking \"See all\" */\n public OnSeeAllClick(): void {\n this.SeeAllRequested.emit(this.Query);\n }\n\n /** Promo accept — fired on click so keyboard Enter/Space work too; the\n template's mousedown-preventDefault keeps the input from blurring first. */\n public OnPromoAccept(): void {\n this.PromoAccepted.emit(this.Query);\n }\n\n /** Promo dismiss. */\n public OnPromoDismiss(): void {\n this.PromoDismissed.emit();\n }\n\n /** \"Clear\" on recent searches — click-driven so keyboard Enter/Space work;\n the template's mousedown-preventDefault keeps the input from blurring. */\n public OnClearRecentClick(event: MouseEvent): void {\n event.stopPropagation();\n this.ClearRecentRequested.emit();\n }\n\n /** Check if an item at the given index is highlighted */\n public IsHighlighted(index: number): boolean {\n return this.HighlightedIndex === index;\n }\n\n /** Format a score value as a percentage */\n public FormatScore(score: number): string {\n return `${Math.round(score * 100)}%`;\n }\n\n /** Get the CSS class for a score value: high (green), medium (amber), low (gray) */\n public GetScoreClass(score: number): string {\n if (score >= 0.40) return 'suggest-score-high';\n if (score >= 0.15) return 'suggest-score-medium';\n return 'suggest-score-low';\n }\n\n /** Toggle the filter popover */\n public ToggleFilter(event: MouseEvent): void {\n event.stopPropagation();\n event.preventDefault();\n this.IsFilterOpen = !this.IsFilterOpen;\n this.cdr.detectChanges();\n }\n\n /** Set the min relevance and persist */\n public SetMinRelevance(percent: number, event: MouseEvent): void {\n event.stopPropagation();\n event.preventDefault();\n this.MinRelevancePercent = percent;\n this.IsFilterOpen = false;\n this.persistMinRelevanceSetting(percent);\n this.cdr.detectChanges();\n }\n\n /** Whether a given option is the currently selected min relevance */\n public IsSelectedRelevance(percent: number): boolean {\n return this.MinRelevancePercent === percent;\n }\n\n /** Format a relevance option for display */\n public FormatRelevanceOption(percent: number): string {\n return percent === 0 ? 'Show all' : `≥ ${percent}%`;\n }\n\n // --- Private ---\n\n private getNavigableItemCount(): number {\n let count = 0;\n if (this.ShowRecentSection) {\n count += this.VisibleRecentSearches.length;\n }\n if (this.ShowRecentRecordsSection) {\n count += this.VisibleRecentRecords.length;\n }\n if (this.ShowPreviewSection) {\n count += this.VisiblePreviewResults.length;\n if (this.ShowSeeAllFooter) {\n count += 1; // \"See all\" item\n }\n }\n return count;\n }\n\n private async loadMinRelevanceSetting(): Promise<void> {\n try {\n // Wait for all startup engines (including UserInfoEngine) to finish loading\n MJGlobal.Instance.GetEventListener(true).subscribe( async (event) => {\n switch (event.event) {\n case MJEventType.LoggedIn:\n // Wait for StartupManager to complete before refreshing \n await StartupManager.Instance.Startup();\n\n const engine = UserInfoEngine.Instance;\n const saved = engine.GetSetting(PREVIEW_MIN_RELEVANCE_KEY);\n\n if (saved != null) {\n const parsed = parseInt(saved, 10);\n if (!isNaN(parsed) && parsed >= 0 && parsed <= 100) {\n this.MinRelevancePercent = parsed;\n this.cdr.detectChanges();\n }\n }\n }\n });\n } catch (err) {\n console.error('[SearchSuggest] loadMinRelevanceSetting error:', err);\n }\n }\n\n private persistMinRelevanceSetting(percent: number): void {\n try {\n UserInfoEngine.Instance.SetSettingDebounced(PREVIEW_MIN_RELEVANCE_KEY, String(percent));\n } catch {\n // Silently fail if UserInfoEngine not available\n }\n }\n}\n","@if (IsOpen) {\n <div class=\"suggest-dropdown\">\n @if (IsLoading && showPreviewSection) {\n <div class=\"suggest-loading\">\n <i class=\"fa-solid fa-spinner fa-spin suggest-loading-icon\"></i>\n <span>Searching...</span>\n </div>\n }\n\n <!-- Recent searches section -->\n @if (showRecentSection) {\n <div class=\"suggest-section\">\n <div class=\"suggest-section-header\">\n <i class=\"fa-solid fa-clock suggest-section-icon\"></i>\n <span>Recent Searches</span>\n <button type=\"button\" class=\"suggest-clear-link\" aria-label=\"Clear recent searches\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"OnClearRecentClick($event)\">Clear</button>\n </div>\n @for (recent of VisibleRecentSearches; track recent.Query; let i = $index) {\n <div\n class=\"suggest-item suggest-recent-item\"\n [class.suggest-item-highlighted]=\"IsHighlighted(i)\"\n (mousedown)=\"OnRecentClick(recent); $event.preventDefault()\"\n (mouseenter)=\"HighlightedIndex = i\"\n >\n <i class=\"fa-solid fa-clock suggest-item-icon\"></i>\n <span class=\"suggest-item-text\">{{ recent.Query }}</span>\n <span class=\"suggest-item-meta\">{{ recent.ResultCount }} results</span>\n </div>\n }\n </div>\n }\n\n <!-- Recently opened records section (idle state) -->\n @if (showRecentRecordsSection) {\n <div class=\"suggest-section\">\n <div class=\"suggest-section-header\">\n <i class=\"fa-solid fa-clock-rotate-left suggest-section-icon\"></i>\n <span>Recently Opened</span>\n </div>\n @for (record of VisibleRecentRecords; track record.EntityName + record.RecordID; let i = $index) {\n <div\n class=\"suggest-item suggest-recent-item\"\n [class.suggest-item-highlighted]=\"IsHighlighted((showRecentSection ? VisibleRecentSearches.length : 0) + i)\"\n (mousedown)=\"OnRecentRecordClick(record); $event.preventDefault()\"\n (mouseenter)=\"HighlightedIndex = (showRecentSection ? VisibleRecentSearches.length : 0) + i\"\n >\n <i class=\"fa-solid fa-file-lines suggest-item-icon\"></i>\n <span class=\"suggest-item-text\">{{ record.RecordName }}</span>\n <span class=\"suggest-item-meta\">{{ record.EntityDisplayName || record.EntityName }}</span>\n </div>\n }\n </div>\n }\n\n <!-- Preview results section -->\n @if (showPreviewSection && !IsLoading) {\n @if (VisiblePreviewResults.length > 0) {\n <div class=\"suggest-section\">\n @for (result of VisiblePreviewResults; track result.ID; let i = $index) {\n <div\n class=\"suggest-item suggest-result-item\"\n [class.suggest-item-highlighted]=\"IsHighlighted((showRecentSection ? VisibleRecentSearches.length : 0) + i)\"\n (mousedown)=\"OnResultClick(result); $event.preventDefault()\"\n (mouseenter)=\"HighlightedIndex = (showRecentSection ? VisibleRecentSearches.length : 0) + i\"\n >\n <div class=\"suggest-result-icon\">\n <i [class]=\"result.EntityIcon || result.SourceIcon || 'fa-solid fa-database'\"></i>\n </div>\n <div class=\"suggest-result-body\">\n <div class=\"suggest-result-title\">{{ result.RecordName || result.Title }}</div>\n <div class=\"suggest-result-entity\">{{ result.EntityDisplayName || result.EntityName }}</div>\n </div>\n <span class=\"suggest-result-score\" [class]=\"'suggest-result-score ' + GetScoreClass(result.Score)\">{{ FormatScore(result.Score) }}</span>\n </div>\n }\n </div>\n } @else if (!IsLoading) {\n <div class=\"suggest-empty\">\n <span>No results found</span>\n </div>\n }\n\n <!-- See all footer -->\n @if (showSeeAllFooter) {\n <div\n class=\"suggest-see-all\"\n [class.suggest-item-highlighted]=\"IsHighlighted((showRecentSection ? VisibleRecentSearches.length : 0) + VisiblePreviewResults.length)\"\n (mousedown)=\"OnSeeAllClick(); $event.preventDefault()\"\n (mouseenter)=\"HighlightedIndex = (showRecentSection ? VisibleRecentSearches.length : 0) + VisiblePreviewResults.length\"\n >\n <i class=\"fa-solid fa-arrow-right suggest-see-all-icon\"></i>\n <span>See all {{ TotalCount }} results</span>\n </div>\n }\n }\n\n <!-- Min relevance filter bar -->\n @if (showPreviewSection) {\n <div class=\"suggest-filter-bar\">\n <div class=\"suggest-filter-toggle\" (mousedown)=\"ToggleFilter($event)\">\n <i class=\"fa-solid fa-sliders suggest-filter-icon\"></i>\n <span class=\"suggest-filter-label\">\n @if (MinRelevancePercent > 0) {\n Min relevance: {{ MinRelevancePercent }}%\n } @else {\n Showing all results\n }\n </span>\n <i class=\"fa-solid fa-chevron-down suggest-filter-chevron\" [class.suggest-filter-chevron-open]=\"IsFilterOpen\"></i>\n </div>\n\n @if (IsFilterOpen) {\n <div class=\"suggest-filter-popover\">\n <div class=\"suggest-filter-popover-header\">Min Relevance</div>\n @for (option of MinRelevanceOptions; track option) {\n <div\n class=\"suggest-filter-option\"\n [class.suggest-filter-option-active]=\"IsSelectedRelevance(option)\"\n (mousedown)=\"SetMinRelevance(option, $event)\"\n >\n <span>{{ FormatRelevanceOption(option) }}</span>\n @if (IsSelectedRelevance(option)) {\n <i class=\"fa-solid fa-check suggest-filter-check\"></i>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Empty state when no recents of either kind and query too short -->\n @if (!showRecentSection && !showRecentRecordsSection && !showPreviewSection) {\n <div class=\"suggest-empty\">\n <span>Type at least {{ MinQueryLength }} characters to search</span>\n </div>\n }\n\n <!-- Host-supplied promo row (e.g. command palette nudge) -->\n @if (ShowPromo && PromoText) {\n <div class=\"suggest-promo\">\n <i class=\"fa-solid fa-wand-magic-sparkles suggest-promo-icon\"></i>\n <span class=\"suggest-promo-text\">{{ PromoText }}</span>\n <button type=\"button\" class=\"suggest-promo-action\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"OnPromoAccept()\">{{ PromoActionLabel }}</button>\n <button type=\"button\" class=\"suggest-promo-dismiss\" aria-label=\"Dismiss\" title=\"Dismiss\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"OnPromoDismiss(); $event.stopPropagation()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"search-suggest.component.js","sourceRoot":"","sources":["../../src/lib/search-suggest.component.ts","../../src/lib/search-suggest.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search Suggest Component\n *\n * Autocomplete dropdown showing preview results and recent searches.\n * Supports keyboard navigation (up/down/enter) for accessibility.\n * Designed to be paired with SearchInputComponent via SearchCompositeComponent.\n */\n\nimport {\n Component,\n EventEmitter,\n Input,\n OnInit,\n Output,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport { StartupManager } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { SearchResultItem, RecentRecordItem, PassesSemanticFloor } from './search-types';\nimport { RecentSearch } from './search.service';\nimport { MJEventType, MJGlobal } from '@memberjunction/global';\n\n/** User setting key for persisting the preview min relevance threshold */\nconst PREVIEW_MIN_RELEVANCE_KEY = 'search.previewMinRelevance';\n\n/** Preset options for the min relevance filter */\nconst MIN_RELEVANCE_OPTIONS = [0, 15, 30, 50, 70];\n\n@Component({\n standalone: false,\n selector: 'mj-search-suggest',\n templateUrl: './search-suggest.component.html',\n styleUrls: ['./search-suggest.component.css']\n})\nexport class SearchSuggestComponent implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n\n // --- Configuration Inputs ---\n\n /** Whether the suggest dropdown is visible */\n @Input() IsOpen = false;\n\n /** Preview search results to display */\n @Input() PreviewResults: SearchResultItem[] = [];\n\n /** Recent search entries to show when query is empty/short */\n @Input() RecentSearches: RecentSearch[] = [];\n\n /** Total count of results for the current query (may exceed PreviewResults.length) */\n @Input() TotalCount = 0;\n\n /** Whether a search is currently loading */\n @Input() IsLoading = false;\n\n /** Current query text — used to determine whether to show recent vs preview */\n @Input() Query = '';\n\n /** Minimum query length before preview results are shown */\n @Input() MinQueryLength = 2;\n\n /** Maximum number of preview results to display */\n @Input() MaxPreviewResults = 8;\n\n /** Whether to show the recent searches section */\n @Input() ShowRecent = true;\n\n /**\n * Recently opened records (host-loaded, e.g. from SearchService\n * .GetRecentlyOpenedRecords). Rendered as a \"Recently Opened\" section in\n * the idle/empty state so users can jump straight back to a record they\n * just had open — the complement to Recent Searches (queries).\n */\n @Input() RecentRecords: RecentRecordItem[] = [];\n\n /**\n * Optional promo row pinned to the dropdown's bottom edge — a host-supplied\n * nudge (e.g. Explorer advertising its command palette). The component is\n * deliberately ignorant of WHAT is being promoted; the host provides the\n * copy and handles both outcomes.\n */\n @Input() ShowPromo = false;\n\n /** Promo copy (one sentence). Required when ShowPromo is true. */\n @Input() PromoText = '';\n\n /** Label for the promo's accept action. */\n @Input() PromoActionLabel = 'Turn on';\n\n // --- Outputs ---\n\n /** Emitted when the user selects a preview result */\n @Output() ResultSelected = new EventEmitter<SearchResultItem>();\n\n /** Emitted when the user selects a recent search */\n @Output() RecentSelected = new EventEmitter<string>();\n\n /** Emitted when the user clicks \"See all N results\" */\n @Output() SeeAllRequested = new EventEmitter<string>();\n\n /** Emitted when the user clicks \"Clear\" on recent searches */\n @Output() ClearRecentRequested = new EventEmitter<void>();\n\n /** Emitted when the user selects a recently opened record */\n @Output() RecentRecordSelected = new EventEmitter<RecentRecordItem>();\n\n /** Promo accept — carries the current query so the host can hand it off. */\n @Output() PromoAccepted = new EventEmitter<string>();\n\n /** Promo dismissed — the host should persist this and stop showing it. */\n @Output() PromoDismissed = new EventEmitter<void>();\n\n // --- Internal state ---\n\n /** Currently keyboard-highlighted index (-1 for none) */\n public HighlightedIndex = -1;\n\n /** Min relevance percentage (0-100) for filtering preview results */\n public MinRelevancePercent = 0;\n\n /** Whether the filter popover is open */\n public IsFilterOpen = false;\n\n /** Available min relevance presets */\n public readonly MinRelevanceOptions = MIN_RELEVANCE_OPTIONS;\n\n // --- Lifecycle ---\n\n async ngOnInit(): Promise<void> {\n await this.loadMinRelevanceSetting();\n }\n\n // --- Public Methods ---\n\n /** Move keyboard highlight up */\n public NavigateUp(): void {\n const maxIndex = this.getNavigableItemCount() - 1;\n if (maxIndex < 0) return;\n\n this.HighlightedIndex--;\n if (this.HighlightedIndex < 0) {\n this.HighlightedIndex = maxIndex;\n }\n this.cdr.detectChanges();\n }\n\n /** Move keyboard highlight down */\n public NavigateDown(): void {\n const maxIndex = this.getNavigableItemCount() - 1;\n if (maxIndex < 0) return;\n\n this.HighlightedIndex++;\n if (this.HighlightedIndex > maxIndex) {\n this.HighlightedIndex = 0;\n }\n this.cdr.detectChanges();\n }\n\n /** Select the currently highlighted item */\n public SelectHighlighted(): void {\n if (this.HighlightedIndex < 0) return;\n\n if (this.ShowRecentSection) {\n // Navigating recent searches\n const visibleRecent = this.VisibleRecentSearches;\n if (this.HighlightedIndex < visibleRecent.length) {\n this.OnRecentClick(visibleRecent[this.HighlightedIndex]);\n return;\n }\n }\n\n if (this.ShowRecentRecordsSection) {\n // Navigating recently opened records (indexes continue after recents)\n const offset = this.ShowRecentSection ? this.VisibleRecentSearches.length : 0;\n const recordIndex = this.HighlightedIndex - offset;\n const visibleRecords = this.VisibleRecentRecords;\n if (recordIndex >= 0 && recordIndex < visibleRecords.length) {\n this.OnRecentRecordClick(visibleRecords[recordIndex]);\n return;\n }\n }\n\n if (this.ShowPreviewSection) {\n // Navigating preview results\n const offset = this.ShowRecentSection ? this.VisibleRecentSearches.length : 0;\n const resultIndex = this.HighlightedIndex - offset;\n const visibleResults = this.VisiblePreviewResults;\n if (resultIndex >= 0 && resultIndex < visibleResults.length) {\n this.OnResultClick(visibleResults[resultIndex]);\n return;\n }\n\n // \"See all\" footer\n if (resultIndex === visibleResults.length && this.ShowSeeAllFooter) {\n this.OnSeeAllClick();\n }\n }\n }\n\n /** Reset the highlighted index */\n public ResetHighlight(): void {\n this.HighlightedIndex = -1;\n }\n\n /** Number of keyboard-navigable rows currently visible (recents + recently\n opened + preview results + see-all). Public so the composite's Tab\n handling knows when the highlight has walked off the end of the list. */\n public get NavigableItemCount(): number {\n return this.getNavigableItemCount();\n }\n\n // --- Template getters ---\n\n /** Whether to show recent searches section */\n public get ShowRecentSection(): boolean {\n return this.ShowRecent && this.Query.length < this.MinQueryLength && this.RecentSearches.length > 0;\n }\n\n /** @deprecated Use {@link ShowRecentSection}. */\n public get showRecentSection(): boolean {\n return this.ShowRecentSection;\n }\n\n /** Whether to show preview results section */\n public get ShowPreviewSection(): boolean {\n return this.Query.length >= this.MinQueryLength;\n }\n\n /** @deprecated Use {@link ShowPreviewSection}. */\n public get showPreviewSection(): boolean {\n return this.ShowPreviewSection;\n }\n\n /** Whether to show the recently-opened-records section (idle state only) */\n public get ShowRecentRecordsSection(): boolean {\n return this.Query.length < this.MinQueryLength && this.RecentRecords.length > 0;\n }\n\n /** @deprecated Use {@link ShowRecentRecordsSection}. */\n public get showRecentRecordsSection(): boolean {\n return this.ShowRecentRecordsSection;\n }\n\n /** Visible recently opened records (capped at 3) */\n public get VisibleRecentRecords(): RecentRecordItem[] {\n return this.RecentRecords.slice(0, 3);\n }\n\n /** Whether to show the \"See all N results\" footer */\n public get ShowSeeAllFooter(): boolean {\n return this.ShowPreviewSection && this.TotalCount > 0;\n }\n\n /** @deprecated Use {@link ShowSeeAllFooter}. */\n public get showSeeAllFooter(): boolean {\n return this.ShowSeeAllFooter;\n }\n\n /** Visible recent searches (capped at 5) */\n public get VisibleRecentSearches(): RecentSearch[] {\n return this.RecentSearches.slice(0, 5);\n }\n\n /** Visible preview results filtered by min relevance, sorted by score descending, capped at MaxPreviewResults */\n public get VisiblePreviewResults(): SearchResultItem[] {\n const minScore = this.MinRelevancePercent / 100;\n return [...this.PreviewResults]\n .filter(r => PassesSemanticFloor(r, minScore))\n .sort((a, b) => b.Score - a.Score)\n .slice(0, this.MaxPreviewResults);\n }\n\n // --- Template event handlers ---\n\n /** Handle clicking a preview result */\n public OnResultClick(result: SearchResultItem): void {\n this.ResultSelected.emit(result);\n }\n\n /** Handle clicking a recent search */\n public OnRecentClick(recent: RecentSearch): void {\n this.RecentSelected.emit(recent.Query);\n }\n\n /** Handle clicking a recently opened record */\n public OnRecentRecordClick(record: RecentRecordItem): void {\n this.RecentRecordSelected.emit(record);\n }\n\n /** Handle clicking \"See all\" */\n public OnSeeAllClick(): void {\n this.SeeAllRequested.emit(this.Query);\n }\n\n /** Promo accept — fired on click so keyboard Enter/Space work too; the\n template's mousedown-preventDefault keeps the input from blurring first. */\n public OnPromoAccept(): void {\n this.PromoAccepted.emit(this.Query);\n }\n\n /** Promo dismiss. */\n public OnPromoDismiss(): void {\n this.PromoDismissed.emit();\n }\n\n /** \"Clear\" on recent searches — click-driven so keyboard Enter/Space work;\n the template's mousedown-preventDefault keeps the input from blurring. */\n public OnClearRecentClick(event: MouseEvent): void {\n event.stopPropagation();\n this.ClearRecentRequested.emit();\n }\n\n /** Check if an item at the given index is highlighted */\n public IsHighlighted(index: number): boolean {\n return this.HighlightedIndex === index;\n }\n\n /** Format a score value as a percentage */\n public FormatScore(score: number): string {\n return `${Math.round(score * 100)}%`;\n }\n\n /** Get the CSS class for a score value: high (green), medium (amber), low (gray) */\n public GetScoreClass(score: number): string {\n if (score >= 0.40) return 'suggest-score-high';\n if (score >= 0.15) return 'suggest-score-medium';\n return 'suggest-score-low';\n }\n\n /** Toggle the filter popover */\n public ToggleFilter(event: MouseEvent): void {\n event.stopPropagation();\n event.preventDefault();\n this.IsFilterOpen = !this.IsFilterOpen;\n this.cdr.detectChanges();\n }\n\n /** Set the min relevance and persist */\n public SetMinRelevance(percent: number, event: MouseEvent): void {\n event.stopPropagation();\n event.preventDefault();\n this.MinRelevancePercent = percent;\n this.IsFilterOpen = false;\n this.persistMinRelevanceSetting(percent);\n this.cdr.detectChanges();\n }\n\n /** Whether a given option is the currently selected min relevance */\n public IsSelectedRelevance(percent: number): boolean {\n return this.MinRelevancePercent === percent;\n }\n\n /** Format a relevance option for display */\n public FormatRelevanceOption(percent: number): string {\n return percent === 0 ? 'Show all' : `≥ ${percent}%`;\n }\n\n // --- Private ---\n\n private getNavigableItemCount(): number {\n let count = 0;\n if (this.ShowRecentSection) {\n count += this.VisibleRecentSearches.length;\n }\n if (this.ShowRecentRecordsSection) {\n count += this.VisibleRecentRecords.length;\n }\n if (this.ShowPreviewSection) {\n count += this.VisiblePreviewResults.length;\n if (this.ShowSeeAllFooter) {\n count += 1; // \"See all\" item\n }\n }\n return count;\n }\n\n private async loadMinRelevanceSetting(): Promise<void> {\n try {\n // Wait for all startup engines (including UserInfoEngine) to finish loading\n MJGlobal.Instance.GetEventListener(true).subscribe( async (event) => {\n switch (event.event) {\n case MJEventType.LoggedIn:\n // Wait for StartupManager to complete before refreshing \n await StartupManager.Instance.Startup();\n\n const engine = UserInfoEngine.Instance;\n const saved = engine.GetSetting(PREVIEW_MIN_RELEVANCE_KEY);\n\n if (saved != null) {\n const parsed = parseInt(saved, 10);\n if (!isNaN(parsed) && parsed >= 0 && parsed <= 100) {\n this.MinRelevancePercent = parsed;\n this.cdr.detectChanges();\n }\n }\n }\n });\n } catch (err) {\n console.error('[SearchSuggest] loadMinRelevanceSetting error:', err);\n }\n }\n\n private persistMinRelevanceSetting(percent: number): void {\n try {\n UserInfoEngine.Instance.SetSettingDebounced(PREVIEW_MIN_RELEVANCE_KEY, String(percent));\n } catch {\n // Silently fail if UserInfoEngine not available\n }\n }\n}\n","@if (IsOpen) {\n <div class=\"suggest-dropdown\">\n @if (IsLoading && showPreviewSection) {\n <div class=\"suggest-loading\">\n <i class=\"fa-solid fa-spinner fa-spin suggest-loading-icon\"></i>\n <span>Searching...</span>\n </div>\n }\n\n <!-- Recent searches section -->\n @if (showRecentSection) {\n <div class=\"suggest-section\">\n <div class=\"suggest-section-header\">\n <i class=\"fa-solid fa-clock suggest-section-icon\"></i>\n <span>Recent Searches</span>\n <button type=\"button\" class=\"suggest-clear-link\" aria-label=\"Clear recent searches\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"OnClearRecentClick($event)\">Clear</button>\n </div>\n @for (recent of VisibleRecentSearches; track recent.Query; let i = $index) {\n <div\n class=\"suggest-item suggest-recent-item\"\n [class.suggest-item-highlighted]=\"IsHighlighted(i)\"\n (mousedown)=\"OnRecentClick(recent); $event.preventDefault()\"\n (mouseenter)=\"HighlightedIndex = i\"\n >\n <i class=\"fa-solid fa-clock suggest-item-icon\"></i>\n <span class=\"suggest-item-text\">{{ recent.Query }}</span>\n <span class=\"suggest-item-meta\">{{ recent.ResultCount }} results</span>\n </div>\n }\n </div>\n }\n\n <!-- Recently opened records section (idle state) -->\n @if (showRecentRecordsSection) {\n <div class=\"suggest-section\">\n <div class=\"suggest-section-header\">\n <i class=\"fa-solid fa-clock-rotate-left suggest-section-icon\"></i>\n <span>Recently Opened</span>\n </div>\n @for (record of VisibleRecentRecords; track record.EntityName + record.RecordID; let i = $index) {\n <div\n class=\"suggest-item suggest-recent-item\"\n [class.suggest-item-highlighted]=\"IsHighlighted((showRecentSection ? VisibleRecentSearches.length : 0) + i)\"\n (mousedown)=\"OnRecentRecordClick(record); $event.preventDefault()\"\n (mouseenter)=\"HighlightedIndex = (showRecentSection ? VisibleRecentSearches.length : 0) + i\"\n >\n <i class=\"fa-solid fa-file-lines suggest-item-icon\"></i>\n <span class=\"suggest-item-text\">{{ record.RecordName }}</span>\n <span class=\"suggest-item-meta\">{{ record.EntityDisplayName || record.EntityName }}</span>\n </div>\n }\n </div>\n }\n\n <!-- Preview results section -->\n @if (showPreviewSection && !IsLoading) {\n @if (VisiblePreviewResults.length > 0) {\n <div class=\"suggest-section\">\n @for (result of VisiblePreviewResults; track result.ID; let i = $index) {\n <div\n class=\"suggest-item suggest-result-item\"\n [class.suggest-item-highlighted]=\"IsHighlighted((showRecentSection ? VisibleRecentSearches.length : 0) + i)\"\n (mousedown)=\"OnResultClick(result); $event.preventDefault()\"\n (mouseenter)=\"HighlightedIndex = (showRecentSection ? VisibleRecentSearches.length : 0) + i\"\n >\n <div class=\"suggest-result-icon\">\n <i [class]=\"result.EntityIcon || result.SourceIcon || 'fa-solid fa-database'\"></i>\n </div>\n <div class=\"suggest-result-body\">\n <div class=\"suggest-result-title\">{{ result.RecordName || result.Title }}</div>\n <div class=\"suggest-result-entity\">{{ result.EntityDisplayName || result.EntityName }}</div>\n </div>\n <span class=\"suggest-result-score\" [class]=\"'suggest-result-score ' + GetScoreClass(result.Score)\">{{ FormatScore(result.Score) }}</span>\n </div>\n }\n </div>\n } @else if (!IsLoading) {\n <div class=\"suggest-empty\">\n <span>No results found</span>\n </div>\n }\n\n <!-- See all footer -->\n @if (showSeeAllFooter) {\n <div\n class=\"suggest-see-all\"\n [class.suggest-item-highlighted]=\"IsHighlighted((showRecentSection ? VisibleRecentSearches.length : 0) + VisiblePreviewResults.length)\"\n (mousedown)=\"OnSeeAllClick(); $event.preventDefault()\"\n (mouseenter)=\"HighlightedIndex = (showRecentSection ? VisibleRecentSearches.length : 0) + VisiblePreviewResults.length\"\n >\n <i class=\"fa-solid fa-arrow-right suggest-see-all-icon\"></i>\n <span>See all {{ TotalCount }} results</span>\n </div>\n }\n }\n\n <!-- Min relevance filter bar -->\n @if (showPreviewSection) {\n <div class=\"suggest-filter-bar\">\n <div class=\"suggest-filter-toggle\" (mousedown)=\"ToggleFilter($event)\">\n <i class=\"fa-solid fa-sliders suggest-filter-icon\"></i>\n <span class=\"suggest-filter-label\">\n @if (MinRelevancePercent > 0) {\n Min relevance: {{ MinRelevancePercent }}%\n } @else {\n Showing all results\n }\n </span>\n <i class=\"fa-solid fa-chevron-down suggest-filter-chevron\" [class.suggest-filter-chevron-open]=\"IsFilterOpen\"></i>\n </div>\n\n @if (IsFilterOpen) {\n <div class=\"suggest-filter-popover\">\n <div class=\"suggest-filter-popover-header\">Min Relevance</div>\n @for (option of MinRelevanceOptions; track option) {\n <div\n class=\"suggest-filter-option\"\n [class.suggest-filter-option-active]=\"IsSelectedRelevance(option)\"\n (mousedown)=\"SetMinRelevance(option, $event)\"\n >\n <span>{{ FormatRelevanceOption(option) }}</span>\n @if (IsSelectedRelevance(option)) {\n <i class=\"fa-solid fa-check suggest-filter-check\"></i>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Empty state when no recents of either kind and query too short -->\n @if (!showRecentSection && !showRecentRecordsSection && !showPreviewSection) {\n <div class=\"suggest-empty\">\n <span>Type at least {{ MinQueryLength }} characters to search</span>\n </div>\n }\n\n <!-- Host-supplied promo row (e.g. command palette nudge) -->\n @if (ShowPromo && PromoText) {\n <div class=\"suggest-promo\">\n <i class=\"fa-solid fa-wand-magic-sparkles suggest-promo-icon\"></i>\n <span class=\"suggest-promo-text\">{{ PromoText }}</span>\n <button type=\"button\" class=\"suggest-promo-action\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"OnPromoAccept()\">{{ PromoActionLabel }}</button>\n <button type=\"button\" class=\"suggest-promo-dismiss\" aria-label=\"Dismiss\" title=\"Dismiss\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"OnPromoDismiss(); $event.stopPropagation()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n </div>\n}\n"]}
|
|
@@ -47,10 +47,25 @@ export interface SearchResultItem {
|
|
|
47
47
|
}
|
|
48
48
|
/** Breakdown of score contribution from each search source */
|
|
49
49
|
export interface ScoreBreakdown {
|
|
50
|
+
/** Semantic (vector) similarity, on the embedding model's own scale. */
|
|
50
51
|
Vector?: number;
|
|
51
52
|
FullText?: number;
|
|
53
|
+
/** Keyword (LIKE) match on searchable entity fields. */
|
|
52
54
|
Entity?: number;
|
|
55
|
+
Storage?: number;
|
|
56
|
+
Tag?: number;
|
|
57
|
+
ReRank?: number;
|
|
53
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Whether a result passes the "similar-meaning cutoff" (the relevance slider), 0–1.
|
|
61
|
+
*
|
|
62
|
+
* The cutoff applies to SEMANTIC similarity only, matching the server, which applies `MinScore`
|
|
63
|
+
* to the vector lane before fusion. A result found by any text lane (keyword, full-text, storage,
|
|
64
|
+
* tag) always passes: a hit there already means the text matched. The fused `Score` is never
|
|
65
|
+
* compared: it is rank-based (RRF ÷ max), so a hit found by one of N lanes tops out at 1/N and
|
|
66
|
+
* filtering on it would hide most results when three or more lanes return hits.
|
|
67
|
+
*/
|
|
68
|
+
export declare function PassesSemanticFloor(result: SearchResultItem, minScore: number): boolean;
|
|
54
69
|
/** Grouped search results by source type */
|
|
55
70
|
export interface SearchResultGroup {
|
|
56
71
|
/** The source type label */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-types.d.ts","sourceRoot":"","sources":["../../src/lib/search-types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"search-types.d.ts","sourceRoot":"","sources":["../../src/lib/search-types.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/search-types.js
CHANGED
|
@@ -4,5 +4,28 @@
|
|
|
4
4
|
* Defines the data contracts for search results, filters,
|
|
5
5
|
* and events used across all search components.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Whether a result passes the "similar-meaning cutoff" (the relevance slider), 0–1.
|
|
9
|
+
*
|
|
10
|
+
* The cutoff applies to SEMANTIC similarity only, matching the server, which applies `MinScore`
|
|
11
|
+
* to the vector lane before fusion. A result found by any text lane (keyword, full-text, storage,
|
|
12
|
+
* tag) always passes: a hit there already means the text matched. The fused `Score` is never
|
|
13
|
+
* compared: it is rank-based (RRF ÷ max), so a hit found by one of N lanes tops out at 1/N and
|
|
14
|
+
* filtering on it would hide most results when three or more lanes return hits.
|
|
15
|
+
*/
|
|
16
|
+
export function PassesSemanticFloor(result, minScore) {
|
|
17
|
+
if (!minScore || minScore <= 0)
|
|
18
|
+
return true;
|
|
19
|
+
const b = result.ScoreBreakdown ?? {};
|
|
20
|
+
const hasTextEvidence = b.Entity != null || b.FullText != null || b.Storage != null || b.Tag != null;
|
|
21
|
+
if (hasTextEvidence)
|
|
22
|
+
return true;
|
|
23
|
+
// No semantic evidence: nothing to judge, so it passes. Unlike the server's
|
|
24
|
+
// ApplySemanticFloor (which runs before fusion, on raw provider scores), this must NOT fall
|
|
25
|
+
// back to `Score`: here `Score` is fused and rank-based, and comparing it to the cutoff is
|
|
26
|
+
// the bug this function exists to avoid.
|
|
27
|
+
if (b.Vector == null)
|
|
28
|
+
return true;
|
|
29
|
+
return b.Vector >= minScore;
|
|
30
|
+
}
|
|
8
31
|
//# sourceMappingURL=search-types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-types.js","sourceRoot":"","sources":["../../src/lib/search-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG","sourcesContent":["/**\n * @fileoverview Shared types for the ng-search package.\n *\n * Defines the data contracts for search results, filters,\n * and events used across all search components.\n */\n\n/** Represents a single search result item */\nexport interface SearchResultItem {\n /** Unique identifier */\n ID: string;\n /** Display title */\n Title: string;\n /** Short text snippet showing match context */\n Snippet: string;\n /** The entity name this result belongs to */\n EntityName: string;\n /** Human-readable display name for the entity (e.g., \"People\" instead of \"MJ_BizApps_Common: People\") */\n EntityDisplayName?: string;\n /** The primary key of the source record */\n RecordID: string;\n /** Classification of the result source */\n SourceType: 'entity' | 'content-item' | 'file' | 'web-page';\n /** Discriminator for UI rendering: 'entity-record', 'storage-file', or 'content-item' */\n ResultType?: string;\n /** Relevance score between 0 and 1 */\n Score: number;\n /** Breakdown of how the score was computed */\n ScoreBreakdown: ScoreBreakdown;\n /** Human-readable tags */\n Tags: string[];\n /** Font Awesome icon class for the source type */\n SourceIcon: string;\n /** Entity-specific icon from EntityInfo.Icon (e.g., \"fa-solid fa-robot\") */\n EntityIcon?: string;\n /** Human-readable record name resolved from EntityRecordName */\n RecordName?: string;\n /** When this result was matched */\n MatchedAt: Date;\n /** Raw vector metadata JSON — contains all entity fields stored in the vector DB */\n RawMetadata?: string;\n /** ID of the SearchProvider metadata record that produced this result */\n ProviderId?: string;\n /** Display label from the SearchProvider metadata (e.g., \"Database\", \"Semantic Search\") */\n ProviderLabel?: string;\n /** Font Awesome icon class from the SearchProvider metadata */\n ProviderIcon?: string;\n}\n\n/** Breakdown of score contribution from each search source */\nexport interface ScoreBreakdown {\n Vector?: number;\n FullText?: number;\n Entity?: number;\n}\n\n/** Grouped search results by source type */\nexport interface SearchResultGroup {\n /** The source type label */\n Label: string;\n /** Font Awesome icon class */\n Icon: string;\n /** The source type key */\n SourceType: string;\n /** Results in this group */\n Results: SearchResultItem[];\n /** Total count for this source (may exceed Results.length if paginated) */\n TotalCount: number;\n}\n\n/** Faceted filter configuration */\nexport interface SearchFilter {\n /** Filter category name */\n Category: string;\n /** Filter options within this category */\n Options: SearchFilterOption[];\n /** Whether multiple options can be selected */\n MultiSelect: boolean;\n}\n\n/** Single filter option within a category */\nexport interface SearchFilterOption {\n /** Display label */\n Label: string;\n /** Value to filter by */\n Value: string;\n /** Count of results matching this option */\n Count: number;\n /** Whether this option is currently selected */\n IsSelected: boolean;\n /** Font Awesome icon class */\n Icon?: string;\n}\n\n/** Search request parameters */\nexport interface SearchRequest {\n /** The search query string */\n Query: string;\n /** Maximum number of results to return */\n MaxResults: number;\n /** Active filter selections */\n ActiveFilters: Record<string, string[]>;\n /** Which search sources to include */\n IncludeSources: ('vector' | 'fulltext' | 'entity' | 'storage')[];\n /**\n * Minimum relevance score (0-1) to include in results.\n * Results below this threshold are filtered out.\n * Default: 0.35 (35%).\n */\n MinScore?: number;\n /**\n * Optional array of `MJ: Search Scopes` record IDs selected in the UI scope selector.\n * When provided, the server resolves each scope and runs only those constrained providers.\n * When omitted (or all selected scopes are `IsGlobal`), behavior is equivalent to the\n * pre-scope unconstrained search.\n */\n ScopeIDs?: string[];\n}\n\n/** Lightweight scope metadata returned by the `SearchScopes` GraphQL query. */\nexport interface SearchScopeInfo {\n ID: string;\n Name: string;\n Description?: string;\n Icon?: string;\n IsGlobal: boolean;\n IsDefault: boolean;\n /** True when the scope has an OwnerUserID — renders as a personal scope in the UI. */\n IsPersonal: boolean;\n}\n\n/** Metadata about an active search provider from the server */\nexport interface SearchProviderInfo {\n /** SearchProvider record ID */\n ID: string;\n /** Provider name */\n Name: string;\n /** UI display label */\n DisplayName: string;\n /** Font Awesome icon class */\n Icon: string;\n /** The SourceType key this provider uses */\n SourceType: string;\n /** Priority (lower = higher) */\n Priority: number;\n}\n\n/** Search response from the service */\nexport interface SearchResponse {\n /** Whether the search succeeded */\n Success: boolean;\n /** The search results */\n Results: SearchResultItem[];\n /** Grouped results by source type */\n Groups: SearchResultGroup[];\n /** Available filters based on results */\n Filters: SearchFilter[];\n /** Total result count across all sources */\n TotalCount: number;\n /** Time taken in milliseconds */\n ElapsedMs: number;\n /** Count of results from each source */\n SourceCounts: { Vector: number; FullText: number; Entity: number; Storage: number };\n /** Active search providers metadata (for UI labels and icons) */\n Providers: SearchProviderInfo[];\n /** Error message if Success is false */\n ErrorMessage?: string;\n}\n\n/** Event emitted when a search result is selected */\nexport interface SearchResultSelectedEvent {\n /** The selected result item */\n Result: SearchResultItem;\n /** Whether to open in a new tab */\n OpenInNewTab: boolean;\n}\n\n/** Event emitted when filters change */\nexport interface SearchFilterChangeEvent {\n /** The filter category that changed */\n Category: string;\n /** The new selected values */\n SelectedValues: string[];\n}\n\n/** Event emitted when search is executed */\nexport interface SearchExecutedEvent {\n /** The search query */\n Query: string;\n /** Active filters */\n Filters: Record<string, string[]>;\n /** Number of results returned */\n ResultCount: number;\n /** Time taken in ms */\n ElapsedMs: number;\n}\n\n/** A recently opened record (from MJ: User Record Logs) surfaced in search empty states */\nexport interface RecentRecordItem {\n /** Entity name (e.g. 'MJ: AI Prompt Runs') */\n EntityName: string;\n /** Human-readable display name for the entity (e.g., 'AI Prompt Runs') */\n EntityDisplayName?: string;\n /** Record primary key value */\n RecordID: string;\n /** Resolved display name (falls back to the ID when resolution fails) */\n RecordName: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"search-types.js","sourceRoot":"","sources":["../../src/lib/search-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwDH;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAwB,EAAE,QAAgB;IAC1E,IAAI,CAAC,QAAQ,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,MAAM,CAAC,GAAG,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;IACtC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,IAAI,IAAI,IAAI,CAAC,CAAC,QAAQ,IAAI,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC;IACrG,IAAI,eAAe;QAAE,OAAO,IAAI,CAAC;IACjC,4EAA4E;IAC5E,4FAA4F;IAC5F,2FAA2F;IAC3F,yCAAyC;IACzC,IAAI,CAAC,CAAC,MAAM,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAClC,OAAO,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC;AAChC,CAAC","sourcesContent":["/**\n * @fileoverview Shared types for the ng-search package.\n *\n * Defines the data contracts for search results, filters,\n * and events used across all search components.\n */\n\n/** Represents a single search result item */\nexport interface SearchResultItem {\n /** Unique identifier */\n ID: string;\n /** Display title */\n Title: string;\n /** Short text snippet showing match context */\n Snippet: string;\n /** The entity name this result belongs to */\n EntityName: string;\n /** Human-readable display name for the entity (e.g., \"People\" instead of \"MJ_BizApps_Common: People\") */\n EntityDisplayName?: string;\n /** The primary key of the source record */\n RecordID: string;\n /** Classification of the result source */\n SourceType: 'entity' | 'content-item' | 'file' | 'web-page';\n /** Discriminator for UI rendering: 'entity-record', 'storage-file', or 'content-item' */\n ResultType?: string;\n /** Relevance score between 0 and 1 */\n Score: number;\n /** Breakdown of how the score was computed */\n ScoreBreakdown: ScoreBreakdown;\n /** Human-readable tags */\n Tags: string[];\n /** Font Awesome icon class for the source type */\n SourceIcon: string;\n /** Entity-specific icon from EntityInfo.Icon (e.g., \"fa-solid fa-robot\") */\n EntityIcon?: string;\n /** Human-readable record name resolved from EntityRecordName */\n RecordName?: string;\n /** When this result was matched */\n MatchedAt: Date;\n /** Raw vector metadata JSON — contains all entity fields stored in the vector DB */\n RawMetadata?: string;\n /** ID of the SearchProvider metadata record that produced this result */\n ProviderId?: string;\n /** Display label from the SearchProvider metadata (e.g., \"Database\", \"Semantic Search\") */\n ProviderLabel?: string;\n /** Font Awesome icon class from the SearchProvider metadata */\n ProviderIcon?: string;\n}\n\n/** Breakdown of score contribution from each search source */\nexport interface ScoreBreakdown {\n /** Semantic (vector) similarity, on the embedding model's own scale. */\n Vector?: number;\n FullText?: number;\n /** Keyword (LIKE) match on searchable entity fields. */\n Entity?: number;\n Storage?: number;\n Tag?: number;\n ReRank?: number;\n}\n\n/**\n * Whether a result passes the \"similar-meaning cutoff\" (the relevance slider), 0–1.\n *\n * The cutoff applies to SEMANTIC similarity only, matching the server, which applies `MinScore`\n * to the vector lane before fusion. A result found by any text lane (keyword, full-text, storage,\n * tag) always passes: a hit there already means the text matched. The fused `Score` is never\n * compared: it is rank-based (RRF ÷ max), so a hit found by one of N lanes tops out at 1/N and\n * filtering on it would hide most results when three or more lanes return hits.\n */\nexport function PassesSemanticFloor(result: SearchResultItem, minScore: number): boolean {\n if (!minScore || minScore <= 0) return true;\n const b = result.ScoreBreakdown ?? {};\n const hasTextEvidence = b.Entity != null || b.FullText != null || b.Storage != null || b.Tag != null;\n if (hasTextEvidence) return true;\n // No semantic evidence: nothing to judge, so it passes. Unlike the server's\n // ApplySemanticFloor (which runs before fusion, on raw provider scores), this must NOT fall\n // back to `Score`: here `Score` is fused and rank-based, and comparing it to the cutoff is\n // the bug this function exists to avoid.\n if (b.Vector == null) return true;\n return b.Vector >= minScore;\n}\n\n/** Grouped search results by source type */\nexport interface SearchResultGroup {\n /** The source type label */\n Label: string;\n /** Font Awesome icon class */\n Icon: string;\n /** The source type key */\n SourceType: string;\n /** Results in this group */\n Results: SearchResultItem[];\n /** Total count for this source (may exceed Results.length if paginated) */\n TotalCount: number;\n}\n\n/** Faceted filter configuration */\nexport interface SearchFilter {\n /** Filter category name */\n Category: string;\n /** Filter options within this category */\n Options: SearchFilterOption[];\n /** Whether multiple options can be selected */\n MultiSelect: boolean;\n}\n\n/** Single filter option within a category */\nexport interface SearchFilterOption {\n /** Display label */\n Label: string;\n /** Value to filter by */\n Value: string;\n /** Count of results matching this option */\n Count: number;\n /** Whether this option is currently selected */\n IsSelected: boolean;\n /** Font Awesome icon class */\n Icon?: string;\n}\n\n/** Search request parameters */\nexport interface SearchRequest {\n /** The search query string */\n Query: string;\n /** Maximum number of results to return */\n MaxResults: number;\n /** Active filter selections */\n ActiveFilters: Record<string, string[]>;\n /** Which search sources to include */\n IncludeSources: ('vector' | 'fulltext' | 'entity' | 'storage')[];\n /**\n * Minimum relevance score (0-1) to include in results.\n * Results below this threshold are filtered out.\n * Default: 0.35 (35%).\n */\n MinScore?: number;\n /**\n * Optional array of `MJ: Search Scopes` record IDs selected in the UI scope selector.\n * When provided, the server resolves each scope and runs only those constrained providers.\n * When omitted (or all selected scopes are `IsGlobal`), behavior is equivalent to the\n * pre-scope unconstrained search.\n */\n ScopeIDs?: string[];\n}\n\n/** Lightweight scope metadata returned by the `SearchScopes` GraphQL query. */\nexport interface SearchScopeInfo {\n ID: string;\n Name: string;\n Description?: string;\n Icon?: string;\n IsGlobal: boolean;\n IsDefault: boolean;\n /** True when the scope has an OwnerUserID — renders as a personal scope in the UI. */\n IsPersonal: boolean;\n}\n\n/** Metadata about an active search provider from the server */\nexport interface SearchProviderInfo {\n /** SearchProvider record ID */\n ID: string;\n /** Provider name */\n Name: string;\n /** UI display label */\n DisplayName: string;\n /** Font Awesome icon class */\n Icon: string;\n /** The SourceType key this provider uses */\n SourceType: string;\n /** Priority (lower = higher) */\n Priority: number;\n}\n\n/** Search response from the service */\nexport interface SearchResponse {\n /** Whether the search succeeded */\n Success: boolean;\n /** The search results */\n Results: SearchResultItem[];\n /** Grouped results by source type */\n Groups: SearchResultGroup[];\n /** Available filters based on results */\n Filters: SearchFilter[];\n /** Total result count across all sources */\n TotalCount: number;\n /** Time taken in milliseconds */\n ElapsedMs: number;\n /** Count of results from each source */\n SourceCounts: { Vector: number; FullText: number; Entity: number; Storage: number };\n /** Active search providers metadata (for UI labels and icons) */\n Providers: SearchProviderInfo[];\n /** Error message if Success is false */\n ErrorMessage?: string;\n}\n\n/** Event emitted when a search result is selected */\nexport interface SearchResultSelectedEvent {\n /** The selected result item */\n Result: SearchResultItem;\n /** Whether to open in a new tab */\n OpenInNewTab: boolean;\n}\n\n/** Event emitted when filters change */\nexport interface SearchFilterChangeEvent {\n /** The filter category that changed */\n Category: string;\n /** The new selected values */\n SelectedValues: string[];\n}\n\n/** Event emitted when search is executed */\nexport interface SearchExecutedEvent {\n /** The search query */\n Query: string;\n /** Active filters */\n Filters: Record<string, string[]>;\n /** Number of results returned */\n ResultCount: number;\n /** Time taken in ms */\n ElapsedMs: number;\n}\n\n/** A recently opened record (from MJ: User Record Logs) surfaced in search empty states */\nexport interface RecentRecordItem {\n /** Entity name (e.g. 'MJ: AI Prompt Runs') */\n EntityName: string;\n /** Human-readable display name for the entity (e.g., 'AI Prompt Runs') */\n EntityDisplayName?: string;\n /** Record primary key value */\n RecordID: string;\n /** Resolved display name (falls back to the ID when resolution fails) */\n RecordName: string;\n}\n"]}
|
|
@@ -44,8 +44,9 @@ export declare class SearchService {
|
|
|
44
44
|
*
|
|
45
45
|
* Consumers (typically the search composite component) should:
|
|
46
46
|
* - render skeleton rows immediately when the Observable is created
|
|
47
|
-
* - on each 'provider' event:
|
|
48
|
-
*
|
|
47
|
+
* - on each 'provider' event: show progress — `ProviderName` and `ResultCount`. A 'provider'
|
|
48
|
+
* event never carries rows: they arrive before the server's permission pass.
|
|
49
|
+
* - on 'final': render the result list
|
|
49
50
|
* - on error: show the failure message + clear the skeleton
|
|
50
51
|
*
|
|
51
52
|
* Returns rxjs Observable rather than awaiting a Promise — callers
|
|
@@ -57,6 +58,8 @@ export declare class SearchService {
|
|
|
57
58
|
StreamSearch(request: SearchRequest): Observable<{
|
|
58
59
|
Phase: string;
|
|
59
60
|
ProviderName?: string;
|
|
61
|
+
/** Set on 'provider' events: how many hits that provider returned, capped at `MaxResults`. */
|
|
62
|
+
ResultCount?: number;
|
|
60
63
|
Results?: SearchResultItem[];
|
|
61
64
|
ElapsedMs?: number;
|
|
62
65
|
ErrorMessage?: string;
|
|
@@ -102,8 +105,8 @@ export declare class SearchService {
|
|
|
102
105
|
private recentRecordNameCache;
|
|
103
106
|
/**
|
|
104
107
|
* Recently opened records for search empty states, newest first — same
|
|
105
|
-
* source as the omnibar's '#' empty state (MJ: User Record Logs
|
|
106
|
-
* UserInfoEngine). Fail-soft: any error yields [] rather than blocking
|
|
108
|
+
* source as the omnibar's '#' empty state (MJ: User Record Logs, queried
|
|
109
|
+
* through UserInfoEngine.LoadRecentRecordLogs). Fail-soft: any error yields [] rather than blocking
|
|
107
110
|
* the surface. Display names resolve via GetEntityRecordNames with the
|
|
108
111
|
* record ID as fallback.
|
|
109
112
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.service.d.ts","sourceRoot":"","sources":["../../src/lib/search.service.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,OAAO,EAAc,MAAM,MAAM,CAAC;AAExE,OAAO,EAAgB,iBAAiB,EAA4B,MAAM,sBAAsB,CAAC;AASjG,OAAO,EACH,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EAGZ,eAAe,EACf,gBAAgB,EACnB,MAAM,gBAAgB,CAAC;;AA8BxB,sCAAsC;AACtC,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACvB;AASD;;;GAGG;AACH,qBACa,aAAa;IACtB,OAAO,CAAC,SAAS,CAAkC;IACnD,IAAW,QAAQ,IAAI,iBAAiB,CAEvC;IACD,IAAW,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,EAElD;IAED,8BAA8B;IACvB,cAAc,yCAAoD;IAEzE,sCAAsC;IAC/B,YAAY,2BAAuC;IAE1D,2EAA2E;IACpE,eAAe,kCAA2C;IAEjE,mBAAmB;IACZ,OAAO,kBAAyB;IAEvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAM;IACxC,OAAO,CAAC,oBAAoB,CAAS;IAErC,oFAAoF;IACpF,OAAO,CAAC,qBAAqB,CAAyC;IAEtE,0FAA0F;IACnF,OAAO,qCAA8C;IAC5D,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,kBAAkB,CAA2C;IAErE;;OAEG;IACU,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAuB3E
|
|
1
|
+
{"version":3,"file":"search.service.d.ts","sourceRoot":"","sources":["../../src/lib/search.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -96,8 +96,9 @@ export class SearchService {
|
|
|
96
96
|
*
|
|
97
97
|
* Consumers (typically the search composite component) should:
|
|
98
98
|
* - render skeleton rows immediately when the Observable is created
|
|
99
|
-
* - on each 'provider' event:
|
|
100
|
-
*
|
|
99
|
+
* - on each 'provider' event: show progress — `ProviderName` and `ResultCount`. A 'provider'
|
|
100
|
+
* event never carries rows: they arrive before the server's permission pass.
|
|
101
|
+
* - on 'final': render the result list
|
|
101
102
|
* - on error: show the failure message + clear the skeleton
|
|
102
103
|
*
|
|
103
104
|
* Returns rxjs Observable rather than awaiting a Promise — callers
|
|
@@ -123,6 +124,7 @@ export class SearchService {
|
|
|
123
124
|
}).pipe(map((ev) => ({
|
|
124
125
|
Phase: ev.Phase,
|
|
125
126
|
ProviderName: ev.ProviderName,
|
|
127
|
+
ResultCount: ev.ResultCount,
|
|
126
128
|
Results: ev.Results ? ev.Results.map(r => this.mapClientResultItem(r)) : undefined,
|
|
127
129
|
ElapsedMs: ev.ElapsedMs,
|
|
128
130
|
ErrorMessage: ev.ErrorMessage,
|
|
@@ -340,18 +342,14 @@ export class SearchService {
|
|
|
340
342
|
recentRecordNameCache = new Map();
|
|
341
343
|
/**
|
|
342
344
|
* Recently opened records for search empty states, newest first — same
|
|
343
|
-
* source as the omnibar's '#' empty state (MJ: User Record Logs
|
|
344
|
-
* UserInfoEngine). Fail-soft: any error yields [] rather than blocking
|
|
345
|
+
* source as the omnibar's '#' empty state (MJ: User Record Logs, queried
|
|
346
|
+
* through UserInfoEngine.LoadRecentRecordLogs). Fail-soft: any error yields [] rather than blocking
|
|
345
347
|
* the surface. Display names resolve via GetEntityRecordNames with the
|
|
346
348
|
* record ID as fallback.
|
|
347
349
|
*/
|
|
348
350
|
async GetRecentlyOpenedRecords(max = 3) {
|
|
349
351
|
try {
|
|
350
|
-
const
|
|
351
|
-
await engine.Config(false, this.Provider.CurrentUser ?? undefined); // no-op when loaded
|
|
352
|
-
const logs = [...engine.UserRecordLogs]
|
|
353
|
-
.sort((a, b) => new Date(b.LatestAt).getTime() - new Date(a.LatestAt).getTime())
|
|
354
|
-
.slice(0, max);
|
|
352
|
+
const logs = await UserInfoEngine.Instance.LoadRecentRecordLogs(max, this.Provider.CurrentUser ?? undefined, this.Provider);
|
|
355
353
|
if (logs.length === 0) {
|
|
356
354
|
return [];
|
|
357
355
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.service.js","sourceRoot":"","sources":["../../src/lib/search.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search service that connects to the UnifiedSearchService via GraphQL.\n *\n * Provides a reactive interface for executing searches, managing search history,\n * and transforming raw search responses into display-ready grouped results.\n */\n\nimport { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable, Subject, throwError } from 'rxjs';\nimport { map } from 'rxjs/operators';\nimport { CompositeKey, IMetadataProvider, Metadata, StartupManager } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { MJEventType, MJGlobal } from '@memberjunction/global';\nimport {\n GraphQLSearchClient,\n GraphQLDataProvider,\n SearchClientResponse,\n SearchClientResultItem\n} from '@memberjunction/graphql-dataprovider';\nimport {\n SearchRequest,\n SearchResponse,\n SearchResultItem,\n SearchResultGroup,\n SearchFilter,\n SearchFilterOption,\n SearchProviderInfo,\n SearchScopeInfo,\n RecentRecordItem\n} from './search-types';\n\n/** Default minimum relevance score threshold (0-1). Results below this are filtered out. */\nconst DEFAULT_MIN_SCORE = 0.35;\n\n/** Fallback icon mapping for source types (used when provider metadata is not available) */\nconst FALLBACK_SOURCE_ICONS: Record<string, string> = {\n 'entity': 'fa-solid fa-database',\n 'vector': 'fa-solid fa-brain',\n 'fulltext': 'fa-solid fa-magnifying-glass',\n 'content-item': 'fa-solid fa-file-lines',\n 'file': 'fa-solid fa-file',\n 'web-page': 'fa-solid fa-globe',\n 'storage': 'fa-solid fa-folder-open',\n};\n\n/** Fallback labels for source types (used when provider metadata is not available) */\nconst FALLBACK_SOURCE_LABELS: Record<string, string> = {\n 'entity': 'Database',\n 'vector': 'Semantic Search',\n 'fulltext': 'Full-Text Search',\n 'content-item': 'Content Items',\n 'file': 'Documents',\n 'web-page': 'Web Pages',\n 'storage': 'File Storage',\n};\n\n/** User setting key for persisting recent searches */\nconst RECENT_SEARCHES_KEY = 'search.recentSearches';\n\n/** Recent search entry for history */\nexport interface RecentSearch {\n Query: string;\n Timestamp: Date;\n ResultCount: number;\n}\n\n/** JSON-safe shape for persistence (Date → ISO string) */\ninterface RecentSearchJson {\n Query: string;\n Timestamp: string;\n ResultCount: number;\n}\n\n/**\n * Multi-provider note: callers under a non-default provider should set\n * `service.Provider = component.ProviderToUse` before invoking any methods.\n */\n@Injectable({ providedIn: 'root' })\nexport class SearchService {\n private _provider: IMetadataProvider | null = null;\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n }\n\n /** Current search response */\n public SearchResults$ = new BehaviorSubject<SearchResponse | null>(null);\n\n /** Whether a search is in progress */\n public IsSearching$ = new BehaviorSubject<boolean>(false);\n\n /** Recent search history (persisted via UserInfoEngine, max 20 entries) */\n public RecentSearches$ = new BehaviorSubject<RecentSearch[]>([]);\n\n /** Error stream */\n public Errors$ = new Subject<string>();\n\n private readonly maxRecentSearches = 20;\n private recentSearchesLoaded = false;\n\n /** Cached provider metadata keyed by SourceType, populated from search responses */\n private providersBySourceType = new Map<string, SearchProviderInfo>();\n\n /** Cached list of scopes the current user can see. Populated lazily by `LoadScopes()`. */\n public Scopes$ = new BehaviorSubject<SearchScopeInfo[]>([]);\n private scopesLoaded = false;\n private scopesLoadInFlight: Promise<SearchScopeInfo[]> | null = null;\n\n /**\n * Execute a search request via the SearchKnowledge GraphQL mutation.\n */\n public async ExecuteSearch(request: SearchRequest): Promise<SearchResponse> {\n this.IsSearching$.next(true);\n const startTime = Date.now();\n\n try {\n const response = await this.executeGraphQLSearch(request);\n response.ElapsedMs = Date.now() - startTime;\n\n this.SearchResults$.next(response);\n this.addToRecentSearches(request.Query, response.TotalCount);\n\n return response;\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Search failed';\n this.Errors$.next(errorMessage);\n const errorResponse = this.createEmptyResponse(errorMessage);\n this.SearchResults$.next(errorResponse);\n return errorResponse;\n } finally {\n this.IsSearching$.next(false);\n }\n }\n\n /**\n * Phase 2C streaming search. Returns an Observable that emits one\n * notification per provider as it returns, plus a 'fused' / 'reranked'\n * / 'final' terminal event. Same auth + permission behavior as\n * ExecuteSearch — denials surface as an error on the Observable.\n *\n * Consumers (typically the search composite component) should:\n * - render skeleton rows immediately when the Observable is created\n * - on each 'provider' event: append the rows for that source\n * - on 'final': replace the partials with the canonical fused list\n * - on error: show the failure message + clear the skeleton\n *\n * Returns rxjs Observable rather than awaiting a Promise — callers\n * decide whether to subscribe + populate state, or unsubscribe on\n * navigation. The service does NOT update its own SearchResults$\n * subject for streaming calls; the caller owns the partial-render\n * state model.\n */\n public StreamSearch(request: SearchRequest): Observable<{\n Phase: string;\n ProviderName?: string;\n Results?: SearchResultItem[];\n ElapsedMs?: number;\n ErrorMessage?: string;\n }> {\n const provider = Metadata.Provider; // global-provider-ok: streaming search service consumes the GraphQL channel of the global default provider\n if (!(provider instanceof GraphQLDataProvider)) {\n return throwError(() => new Error('GraphQL provider not available'));\n }\n const client = new GraphQLSearchClient(provider);\n const filters = this.buildClientFilters(request);\n const minScore = request.MinScore ?? DEFAULT_MIN_SCORE;\n return client.StreamSearch({\n Query: request.Query,\n MaxResults: request.MaxResults || 20,\n MinScore: minScore > 0 ? minScore : undefined,\n Filters: filters,\n ScopeIDs: request.ScopeIDs && request.ScopeIDs.length > 0 ? request.ScopeIDs : undefined,\n }).pipe(map((ev) => ({\n Phase: ev.Phase,\n ProviderName: ev.ProviderName,\n Results: ev.Results ? ev.Results.map(r => this.mapClientResultItem(r)) : undefined,\n ElapsedMs: ev.ElapsedMs,\n ErrorMessage: ev.ErrorMessage,\n })));\n }\n\n /**\n * Lightweight preview search for autocomplete/typeahead.\n * Does NOT update SearchResults$ or IsSearching$ observables,\n * and does NOT add to recent search history.\n */\n public async PreviewSearch(query: string, maxResults: number = 8): Promise<SearchResponse> {\n try {\n if (!query.trim()) {\n return this.createEmptyResponse();\n }\n\n const provider = this.Provider;\n if (!(provider instanceof GraphQLDataProvider)) {\n return this.createEmptyResponse('GraphQL provider not available');\n }\n\n const client = new GraphQLSearchClient(provider);\n const clientResponse = await client.PreviewSearch(query, maxResults);\n return this.mapClientResponseToSearchResponse(clientResponse);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Preview search failed';\n return this.createEmptyResponse(errorMessage);\n }\n }\n\n /** Clear the current search results */\n public ClearResults(): void {\n this.SearchResults$.next(null);\n }\n\n /** Clear recent search history (memory and persisted) */\n public ClearRecentSearches(): void {\n this.RecentSearches$.next([]);\n this.persistRecentSearches([]);\n }\n\n /**\n * Group flat results by source type for display.\n */\n public GroupResults(results: SearchResultItem[]): SearchResultGroup[] {\n const groupMap = new Map<string, SearchResultItem[]>();\n\n for (const result of results) {\n const key = result.SourceType;\n const existing = groupMap.get(key);\n if (existing) {\n existing.push(result);\n } else {\n groupMap.set(key, [result]);\n }\n }\n\n return Array.from(groupMap.entries()).map(([sourceType, items]) => {\n // Priority: cached provider metadata > per-result metadata > fallback maps\n const cached = this.providersBySourceType.get(sourceType);\n return {\n Label: cached?.DisplayName ?? items[0]?.ProviderLabel ?? FALLBACK_SOURCE_LABELS[sourceType] ?? sourceType,\n Icon: cached?.Icon ?? items[0]?.ProviderIcon ?? FALLBACK_SOURCE_ICONS[sourceType] ?? 'fa-solid fa-circle',\n SourceType: sourceType,\n Results: items,\n TotalCount: items.length\n };\n });\n }\n\n /**\n * Build filter facets from a set of results.\n */\n public BuildFilters(results: SearchResultItem[]): SearchFilter[] {\n return [\n this.buildSourceTypeFilter(results),\n this.buildEntityNameFilter(results),\n this.buildFileTypeFilter(results),\n this.buildTagFilter(results)\n ].filter(f => f.Options.length > 0); // Hide categories with no options\n }\n\n /** Get the icon for a given source type */\n public GetSourceIcon(sourceType: string): string {\n return this.providersBySourceType.get(sourceType)?.Icon ?? FALLBACK_SOURCE_ICONS[sourceType] ?? 'fa-solid fa-circle';\n }\n\n private buildSourceTypeFilter(results: SearchResultItem[]): SearchFilter {\n const counts = new Map<string, number>();\n for (const r of results) {\n counts.set(r.SourceType, (counts.get(r.SourceType) ?? 0) + 1);\n }\n const options: SearchFilterOption[] = Array.from(counts.entries()).map(([type, count]) => {\n const cached = this.providersBySourceType.get(type);\n return {\n Label: cached?.DisplayName ?? FALLBACK_SOURCE_LABELS[type] ?? type,\n Value: type,\n Count: count,\n IsSelected: false,\n Icon: cached?.Icon ?? FALLBACK_SOURCE_ICONS[type]\n };\n });\n return { Category: 'Source', Options: options, MultiSelect: true };\n }\n\n private buildEntityNameFilter(results: SearchResultItem[]): SearchFilter {\n const counts = new Map<string, { count: number; displayName: string; icon?: string }>();\n let fileCount = 0;\n for (const r of results) {\n if (r.ResultType === 'storage-file') {\n fileCount++;\n } else {\n const existing = counts.get(r.EntityName);\n const displayName = r.EntityDisplayName || r.EntityName;\n if (existing) {\n existing.count++;\n } else {\n counts.set(r.EntityName, { count: 1, displayName, icon: r.EntityIcon });\n }\n }\n }\n const options: SearchFilterOption[] = Array.from(counts.entries())\n .sort((a, b) => b[1].count - a[1].count)\n .map(([name, data]) => ({\n Label: data.displayName,\n Value: name,\n Count: data.count,\n IsSelected: false,\n Icon: data.icon ?? 'fa-solid fa-table'\n }));\n\n // Add a single \"Files\" entry for all storage file results\n if (fileCount > 0) {\n options.push({\n Label: 'Files',\n Value: '__storage-files__',\n Count: fileCount,\n IsSelected: false,\n Icon: 'fa-solid fa-file'\n });\n }\n\n return { Category: 'Entity', Options: options, MultiSelect: true };\n }\n\n private buildFileTypeFilter(results: SearchResultItem[]): SearchFilter {\n const counts = new Map<string, number>();\n for (const r of results) {\n if (r.ResultType !== 'storage-file') continue;\n const ext = r.Title?.split('.').pop()?.toUpperCase();\n if (ext && ext.length <= 6) {\n counts.set(ext, (counts.get(ext) ?? 0) + 1);\n }\n }\n const options: SearchFilterOption[] = Array.from(counts.entries())\n .sort((a, b) => b[1] - a[1])\n .map(([ext, count]) => ({\n Label: ext,\n Value: ext,\n Count: count,\n IsSelected: false,\n Icon: 'fa-solid fa-file'\n }));\n return { Category: 'File Type', Options: options, MultiSelect: true };\n }\n\n private buildTagFilter(results: SearchResultItem[]): SearchFilter {\n const counts = new Map<string, number>();\n for (const r of results) {\n for (const tag of r.Tags) {\n counts.set(tag, (counts.get(tag) ?? 0) + 1);\n }\n }\n const options: SearchFilterOption[] = Array.from(counts.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, 15)\n .map(([tag, count]) => ({\n Label: tag,\n Value: tag,\n Count: count,\n IsSelected: false,\n Icon: 'fa-solid fa-tag'\n }));\n return { Category: 'Tags', Options: options, MultiSelect: true };\n }\n\n /**\n * Load persisted recent searches from UserInfoEngine.\n * Safe to call multiple times — only loads once.\n */\n public async LoadRecentSearches(): Promise<void> {\n if (this.recentSearchesLoaded) return;\n\n try {\n MJGlobal.Instance.GetEventListener(true).subscribe(async (event) => {\n if (event.event === MJEventType.LoggedIn) {\n await StartupManager.Instance.Startup();\n\n const engine = UserInfoEngine.Instance;\n\n const json = engine.GetSetting(RECENT_SEARCHES_KEY);\n\n if (json) {\n const parsed = JSON.parse(json) as RecentSearchJson[];\n const searches: RecentSearch[] = parsed.map(s => ({\n Query: s.Query,\n Timestamp: new Date(s.Timestamp),\n ResultCount: s.ResultCount\n }));\n this.RecentSearches$.next(searches);\n }\n }\n });\n } catch (err) {\n console.error('[SearchService] LoadRecentSearches error:', err);\n }\n this.recentSearchesLoaded = true;\n }\n\n /**\n * Record a query into recent searches WITHOUT running a search. For surfaces\n * (e.g. the omnibar palette) where the user types a query but executes a\n * suggestion that navigates directly — no full ExecuteSearch ever runs, so\n * the automatic recording inside ExecuteSearch never fires for that query.\n * Deduplicates by query text and persists via UserInfoEngine like all recents.\n */\n /** Resolved record-name memo — GetEntityRecordNames round-trips are cosmetic\n and stable, so resolve each entity/record pair once per session. */\n private recentRecordNameCache = new Map<string, string>();\n\n /**\n * Recently opened records for search empty states, newest first — same\n * source as the omnibar's '#' empty state (MJ: User Record Logs via\n * UserInfoEngine). Fail-soft: any error yields [] rather than blocking\n * the surface. Display names resolve via GetEntityRecordNames with the\n * record ID as fallback.\n */\n public async GetRecentlyOpenedRecords(max = 3): Promise<RecentRecordItem[]> {\n try {\n const engine = UserInfoEngine.Instance;\n await engine.Config(false, this.Provider.CurrentUser ?? undefined); // no-op when loaded\n const logs = [...engine.UserRecordLogs]\n .sort((a, b) => new Date(b.LatestAt).getTime() - new Date(a.LatestAt).getTime())\n .slice(0, max);\n if (logs.length === 0) {\n return [];\n }\n const unresolved = logs.filter((l) => !this.recentRecordNameCache.has(`${l.Entity}||${l.RecordID}`));\n if (unresolved.length > 0) {\n try {\n // Recents span arbitrary entities whose key column can have any name; `FromID`\n // assumed `ID` and left those records showing a raw id instead of a name.\n const results = await this.Provider.GetEntityRecordNames(\n unresolved.map((l) => ({\n EntityName: l.Entity,\n CompositeKey: CompositeKey.FromURLSegment(this.Provider.EntityByName(l.Entity), l.RecordID),\n })),\n this.Provider.CurrentUser ?? undefined,\n );\n for (const r of results ?? []) {\n if (r.Success && r.RecordName) {\n this.recentRecordNameCache.set(`${r.EntityName}||${r.CompositeKey.GetValueByIndex(0)}`, r.RecordName);\n }\n }\n } catch {\n // name lookup is cosmetic — IDs are an acceptable fallback\n }\n }\n return logs.map((log) => {\n let entityInfo;\n try {\n entityInfo = this.Provider?.EntityByName ? this.Provider.EntityByName(log.Entity) : undefined;\n } catch {\n // Non-fatal if metadata cache is uninitialized\n }\n return {\n EntityName: log.Entity,\n EntityDisplayName: entityInfo?.DisplayName || log.Entity,\n RecordID: log.RecordID,\n RecordName: this.recentRecordNameCache.get(`${log.Entity}||${log.RecordID}`) ?? log.RecordID,\n };\n });\n } catch {\n return [];\n }\n }\n\n public RecordRecentSearch(query: string, resultCount = 0): void {\n const trimmed = query.trim();\n if (trimmed.length > 0) {\n this.addToRecentSearches(trimmed, resultCount);\n }\n }\n\n private addToRecentSearches(query: string, resultCount: number): void {\n const current = this.RecentSearches$.value;\n const filtered = current.filter(s => s.Query !== query);\n const updated = [\n { Query: query, Timestamp: new Date(), ResultCount: resultCount },\n ...filtered\n ].slice(0, this.maxRecentSearches);\n this.RecentSearches$.next(updated);\n this.persistRecentSearches(updated);\n }\n\n private persistRecentSearches(searches: RecentSearch[]): void {\n try {\n const json: RecentSearchJson[] = searches.map(s => ({\n Query: s.Query,\n Timestamp: s.Timestamp.toISOString(),\n ResultCount: s.ResultCount\n }));\n UserInfoEngine.Instance.SetSettingDebounced(RECENT_SEARCHES_KEY, JSON.stringify(json));\n } catch {\n // Silently fail if UserInfoEngine not available\n }\n }\n\n /** Cache provider metadata by SourceType for use in GroupResults/BuildFilters */\n private cacheProviders(providers: SearchProviderInfo[]): void {\n for (const p of providers) {\n this.providersBySourceType.set(p.SourceType, p);\n }\n }\n\n private createEmptyResponse(errorMessage?: string): SearchResponse {\n return {\n Success: !errorMessage,\n Results: [],\n Groups: [],\n Filters: [],\n TotalCount: 0,\n ElapsedMs: 0,\n SourceCounts: { Vector: 0, FullText: 0, Entity: 0, Storage: 0 },\n Providers: [],\n ErrorMessage: errorMessage\n };\n }\n\n /**\n * Execute search via the GraphQLSearchClient.\n */\n private async executeGraphQLSearch(request: SearchRequest): Promise<SearchResponse> {\n if (!request.Query.trim()) {\n return this.createEmptyResponse();\n }\n\n const provider = this.Provider;\n if (!(provider instanceof GraphQLDataProvider)) {\n return this.createEmptyResponse('GraphQL provider not available');\n }\n\n const client = new GraphQLSearchClient(provider);\n const filters = this.buildClientFilters(request);\n const minScore = request.MinScore ?? DEFAULT_MIN_SCORE;\n\n const clientResponse = await client.ExecuteSearch({\n Query: request.Query,\n MaxResults: request.MaxResults || 20,\n MinScore: minScore > 0 ? minScore : undefined,\n Filters: filters,\n ScopeIDs: request.ScopeIDs && request.ScopeIDs.length > 0 ? request.ScopeIDs : undefined\n });\n\n return this.mapClientResponseToSearchResponse(clientResponse);\n }\n\n /** Convert a SearchClientResponse into the SearchResponse shape used by this service */\n private mapClientResponseToSearchResponse(clientResponse: SearchClientResponse): SearchResponse {\n if (!clientResponse.Success) {\n return this.createEmptyResponse(clientResponse.ErrorMessage ?? 'Search failed');\n }\n\n // Cache provider metadata for use in GroupResults/BuildFilters\n const providers: SearchProviderInfo[] = (clientResponse.Providers ?? []).map(p => ({\n ID: p.ID,\n Name: p.Name,\n DisplayName: p.DisplayName,\n Icon: p.Icon,\n SourceType: p.SourceType,\n Priority: p.Priority,\n }));\n this.cacheProviders(providers);\n\n const results: SearchResultItem[] = (clientResponse.Results ?? []).map(r => this.mapClientResultItem(r));\n\n const groups = this.GroupResults(results);\n const filters = this.BuildFilters(results);\n\n return {\n Success: true,\n Results: results,\n Groups: groups,\n Filters: filters,\n TotalCount: clientResponse.TotalCount,\n ElapsedMs: clientResponse.ElapsedMs,\n SourceCounts: {\n Vector: clientResponse.SourceCounts.Vector,\n FullText: clientResponse.SourceCounts.FullText,\n Entity: clientResponse.SourceCounts.Entity,\n Storage: clientResponse.SourceCounts.Storage\n },\n Providers: providers,\n };\n }\n\n /** Map a single SearchClientResultItem to a SearchResultItem */\n private mapClientResultItem(r: SearchClientResultItem): SearchResultItem {\n let entityDisplayName = r.EntityDisplayName;\n let entityIcon = r.EntityIcon;\n try {\n const entity = this.Provider?.EntityByName?.(r.EntityName);\n if (!entityDisplayName && entity) {\n entityDisplayName = entity.DisplayName || entity.Name;\n }\n if (!entityIcon && entity?.Icon) {\n entityIcon = entity.Icon;\n }\n } catch {\n // Non-fatal if metadata cache is uninitialized (e.g. in unit tests)\n }\n if (!entityDisplayName) {\n entityDisplayName = r.EntityName;\n }\n\n return {\n ID: r.ID,\n Title: r.RecordName || r.Title,\n Snippet: r.Snippet,\n EntityName: r.EntityName,\n EntityDisplayName: entityDisplayName,\n RecordID: r.RecordID,\n SourceType: (r.SourceType as SearchResultItem['SourceType']) || 'entity',\n ResultType: r.ResultType,\n Score: r.Score,\n ScoreBreakdown: r.ScoreBreakdown ?? {},\n Tags: r.Tags ?? [],\n SourceIcon: entityIcon || r.ProviderIcon || FALLBACK_SOURCE_ICONS[r.SourceType] || 'fa-solid fa-database',\n EntityIcon: entityIcon,\n RecordName: r.RecordName,\n MatchedAt: new Date(r.MatchedAt),\n RawMetadata: r.RawMetadata,\n ProviderId: r.ProviderId,\n ProviderLabel: r.ProviderLabel,\n ProviderIcon: r.ProviderIcon,\n };\n }\n\n /**\n * Load the list of search scopes available to the current user.\n * Cached after the first successful call; pass `force=true` to reload.\n */\n public async LoadScopes(force: boolean = false): Promise<SearchScopeInfo[]> {\n if (this.scopesLoaded && !force) return this.Scopes$.value;\n if (this.scopesLoadInFlight && !force) return this.scopesLoadInFlight;\n\n const load = (async (): Promise<SearchScopeInfo[]> => {\n try {\n const provider = Metadata.Provider; // global-provider-ok: scope discovery consumes the GraphQL channel of the global default provider\n if (!(provider instanceof GraphQLDataProvider)) {\n this.Scopes$.next([]);\n return [];\n }\n const client = new GraphQLSearchClient(provider);\n const scopes = await client.GetSearchScopes();\n this.Scopes$.next(scopes);\n this.scopesLoaded = true;\n return scopes;\n } catch {\n this.Scopes$.next([]);\n return [];\n } finally {\n this.scopesLoadInFlight = null;\n }\n })();\n\n this.scopesLoadInFlight = load;\n return load;\n }\n\n /** Build the client filters from active filter selections */\n private buildClientFilters(request: SearchRequest): { EntityNames?: string[]; SourceTypes?: string[]; Tags?: string[] } | undefined {\n if (!request.ActiveFilters || Object.keys(request.ActiveFilters).length === 0) {\n return undefined;\n }\n\n const result: { EntityNames?: string[]; SourceTypes?: string[]; Tags?: string[] } = {};\n\n const entityFilters = request.ActiveFilters['Entity'];\n if (entityFilters?.length) {\n result.EntityNames = entityFilters;\n }\n\n const sourceFilters = request.ActiveFilters['Source'];\n if (sourceFilters?.length) {\n result.SourceTypes = sourceFilters;\n }\n\n const tagFilters = request.ActiveFilters['Tags'];\n if (tagFilters?.length) {\n result.Tags = tagFilters;\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"search.service.js","sourceRoot":"","sources":["../../src/lib/search.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search service that connects to the UnifiedSearchService via GraphQL.\n *\n * Provides a reactive interface for executing searches, managing search history,\n * and transforming raw search responses into display-ready grouped results.\n */\n\nimport { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable, Subject, throwError } from 'rxjs';\nimport { map } from 'rxjs/operators';\nimport { CompositeKey, IMetadataProvider, Metadata, StartupManager } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { MJEventType, MJGlobal } from '@memberjunction/global';\nimport {\n GraphQLSearchClient,\n GraphQLDataProvider,\n SearchClientResponse,\n SearchClientResultItem\n} from '@memberjunction/graphql-dataprovider';\nimport {\n SearchRequest,\n SearchResponse,\n SearchResultItem,\n SearchResultGroup,\n SearchFilter,\n SearchFilterOption,\n SearchProviderInfo,\n SearchScopeInfo,\n RecentRecordItem\n} from './search-types';\n\n/** Default minimum relevance score threshold (0-1). Results below this are filtered out. */\nconst DEFAULT_MIN_SCORE = 0.35;\n\n/** Fallback icon mapping for source types (used when provider metadata is not available) */\nconst FALLBACK_SOURCE_ICONS: Record<string, string> = {\n 'entity': 'fa-solid fa-database',\n 'vector': 'fa-solid fa-brain',\n 'fulltext': 'fa-solid fa-magnifying-glass',\n 'content-item': 'fa-solid fa-file-lines',\n 'file': 'fa-solid fa-file',\n 'web-page': 'fa-solid fa-globe',\n 'storage': 'fa-solid fa-folder-open',\n};\n\n/** Fallback labels for source types (used when provider metadata is not available) */\nconst FALLBACK_SOURCE_LABELS: Record<string, string> = {\n 'entity': 'Database',\n 'vector': 'Semantic Search',\n 'fulltext': 'Full-Text Search',\n 'content-item': 'Content Items',\n 'file': 'Documents',\n 'web-page': 'Web Pages',\n 'storage': 'File Storage',\n};\n\n/** User setting key for persisting recent searches */\nconst RECENT_SEARCHES_KEY = 'search.recentSearches';\n\n/** Recent search entry for history */\nexport interface RecentSearch {\n Query: string;\n Timestamp: Date;\n ResultCount: number;\n}\n\n/** JSON-safe shape for persistence (Date → ISO string) */\ninterface RecentSearchJson {\n Query: string;\n Timestamp: string;\n ResultCount: number;\n}\n\n/**\n * Multi-provider note: callers under a non-default provider should set\n * `service.Provider = component.ProviderToUse` before invoking any methods.\n */\n@Injectable({ providedIn: 'root' })\nexport class SearchService {\n private _provider: IMetadataProvider | null = null;\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n }\n\n /** Current search response */\n public SearchResults$ = new BehaviorSubject<SearchResponse | null>(null);\n\n /** Whether a search is in progress */\n public IsSearching$ = new BehaviorSubject<boolean>(false);\n\n /** Recent search history (persisted via UserInfoEngine, max 20 entries) */\n public RecentSearches$ = new BehaviorSubject<RecentSearch[]>([]);\n\n /** Error stream */\n public Errors$ = new Subject<string>();\n\n private readonly maxRecentSearches = 20;\n private recentSearchesLoaded = false;\n\n /** Cached provider metadata keyed by SourceType, populated from search responses */\n private providersBySourceType = new Map<string, SearchProviderInfo>();\n\n /** Cached list of scopes the current user can see. Populated lazily by `LoadScopes()`. */\n public Scopes$ = new BehaviorSubject<SearchScopeInfo[]>([]);\n private scopesLoaded = false;\n private scopesLoadInFlight: Promise<SearchScopeInfo[]> | null = null;\n\n /**\n * Execute a search request via the SearchKnowledge GraphQL mutation.\n */\n public async ExecuteSearch(request: SearchRequest): Promise<SearchResponse> {\n this.IsSearching$.next(true);\n const startTime = Date.now();\n\n try {\n const response = await this.executeGraphQLSearch(request);\n response.ElapsedMs = Date.now() - startTime;\n\n this.SearchResults$.next(response);\n this.addToRecentSearches(request.Query, response.TotalCount);\n\n return response;\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Search failed';\n this.Errors$.next(errorMessage);\n const errorResponse = this.createEmptyResponse(errorMessage);\n this.SearchResults$.next(errorResponse);\n return errorResponse;\n } finally {\n this.IsSearching$.next(false);\n }\n }\n\n /**\n * Phase 2C streaming search. Returns an Observable that emits one\n * notification per provider as it returns, plus a 'fused' / 'reranked'\n * / 'final' terminal event. Same auth + permission behavior as\n * ExecuteSearch — denials surface as an error on the Observable.\n *\n * Consumers (typically the search composite component) should:\n * - render skeleton rows immediately when the Observable is created\n * - on each 'provider' event: show progress — `ProviderName` and `ResultCount`. A 'provider'\n * event never carries rows: they arrive before the server's permission pass.\n * - on 'final': render the result list\n * - on error: show the failure message + clear the skeleton\n *\n * Returns rxjs Observable rather than awaiting a Promise — callers\n * decide whether to subscribe + populate state, or unsubscribe on\n * navigation. The service does NOT update its own SearchResults$\n * subject for streaming calls; the caller owns the partial-render\n * state model.\n */\n public StreamSearch(request: SearchRequest): Observable<{\n Phase: string;\n ProviderName?: string;\n /** Set on 'provider' events: how many hits that provider returned, capped at `MaxResults`. */\n ResultCount?: number;\n Results?: SearchResultItem[];\n ElapsedMs?: number;\n ErrorMessage?: string;\n }> {\n const provider = Metadata.Provider; // global-provider-ok: streaming search service consumes the GraphQL channel of the global default provider\n if (!(provider instanceof GraphQLDataProvider)) {\n return throwError(() => new Error('GraphQL provider not available'));\n }\n const client = new GraphQLSearchClient(provider);\n const filters = this.buildClientFilters(request);\n const minScore = request.MinScore ?? DEFAULT_MIN_SCORE;\n return client.StreamSearch({\n Query: request.Query,\n MaxResults: request.MaxResults || 20,\n MinScore: minScore > 0 ? minScore : undefined,\n Filters: filters,\n ScopeIDs: request.ScopeIDs && request.ScopeIDs.length > 0 ? request.ScopeIDs : undefined,\n }).pipe(map((ev) => ({\n Phase: ev.Phase,\n ProviderName: ev.ProviderName,\n ResultCount: ev.ResultCount,\n Results: ev.Results ? ev.Results.map(r => this.mapClientResultItem(r)) : undefined,\n ElapsedMs: ev.ElapsedMs,\n ErrorMessage: ev.ErrorMessage,\n })));\n }\n\n /**\n * Lightweight preview search for autocomplete/typeahead.\n * Does NOT update SearchResults$ or IsSearching$ observables,\n * and does NOT add to recent search history.\n */\n public async PreviewSearch(query: string, maxResults: number = 8): Promise<SearchResponse> {\n try {\n if (!query.trim()) {\n return this.createEmptyResponse();\n }\n\n const provider = this.Provider;\n if (!(provider instanceof GraphQLDataProvider)) {\n return this.createEmptyResponse('GraphQL provider not available');\n }\n\n const client = new GraphQLSearchClient(provider);\n const clientResponse = await client.PreviewSearch(query, maxResults);\n return this.mapClientResponseToSearchResponse(clientResponse);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Preview search failed';\n return this.createEmptyResponse(errorMessage);\n }\n }\n\n /** Clear the current search results */\n public ClearResults(): void {\n this.SearchResults$.next(null);\n }\n\n /** Clear recent search history (memory and persisted) */\n public ClearRecentSearches(): void {\n this.RecentSearches$.next([]);\n this.persistRecentSearches([]);\n }\n\n /**\n * Group flat results by source type for display.\n */\n public GroupResults(results: SearchResultItem[]): SearchResultGroup[] {\n const groupMap = new Map<string, SearchResultItem[]>();\n\n for (const result of results) {\n const key = result.SourceType;\n const existing = groupMap.get(key);\n if (existing) {\n existing.push(result);\n } else {\n groupMap.set(key, [result]);\n }\n }\n\n return Array.from(groupMap.entries()).map(([sourceType, items]) => {\n // Priority: cached provider metadata > per-result metadata > fallback maps\n const cached = this.providersBySourceType.get(sourceType);\n return {\n Label: cached?.DisplayName ?? items[0]?.ProviderLabel ?? FALLBACK_SOURCE_LABELS[sourceType] ?? sourceType,\n Icon: cached?.Icon ?? items[0]?.ProviderIcon ?? FALLBACK_SOURCE_ICONS[sourceType] ?? 'fa-solid fa-circle',\n SourceType: sourceType,\n Results: items,\n TotalCount: items.length\n };\n });\n }\n\n /**\n * Build filter facets from a set of results.\n */\n public BuildFilters(results: SearchResultItem[]): SearchFilter[] {\n return [\n this.buildSourceTypeFilter(results),\n this.buildEntityNameFilter(results),\n this.buildFileTypeFilter(results),\n this.buildTagFilter(results)\n ].filter(f => f.Options.length > 0); // Hide categories with no options\n }\n\n /** Get the icon for a given source type */\n public GetSourceIcon(sourceType: string): string {\n return this.providersBySourceType.get(sourceType)?.Icon ?? FALLBACK_SOURCE_ICONS[sourceType] ?? 'fa-solid fa-circle';\n }\n\n private buildSourceTypeFilter(results: SearchResultItem[]): SearchFilter {\n const counts = new Map<string, number>();\n for (const r of results) {\n counts.set(r.SourceType, (counts.get(r.SourceType) ?? 0) + 1);\n }\n const options: SearchFilterOption[] = Array.from(counts.entries()).map(([type, count]) => {\n const cached = this.providersBySourceType.get(type);\n return {\n Label: cached?.DisplayName ?? FALLBACK_SOURCE_LABELS[type] ?? type,\n Value: type,\n Count: count,\n IsSelected: false,\n Icon: cached?.Icon ?? FALLBACK_SOURCE_ICONS[type]\n };\n });\n return { Category: 'Source', Options: options, MultiSelect: true };\n }\n\n private buildEntityNameFilter(results: SearchResultItem[]): SearchFilter {\n const counts = new Map<string, { count: number; displayName: string; icon?: string }>();\n let fileCount = 0;\n for (const r of results) {\n if (r.ResultType === 'storage-file') {\n fileCount++;\n } else {\n const existing = counts.get(r.EntityName);\n const displayName = r.EntityDisplayName || r.EntityName;\n if (existing) {\n existing.count++;\n } else {\n counts.set(r.EntityName, { count: 1, displayName, icon: r.EntityIcon });\n }\n }\n }\n const options: SearchFilterOption[] = Array.from(counts.entries())\n .sort((a, b) => b[1].count - a[1].count)\n .map(([name, data]) => ({\n Label: data.displayName,\n Value: name,\n Count: data.count,\n IsSelected: false,\n Icon: data.icon ?? 'fa-solid fa-table'\n }));\n\n // Add a single \"Files\" entry for all storage file results\n if (fileCount > 0) {\n options.push({\n Label: 'Files',\n Value: '__storage-files__',\n Count: fileCount,\n IsSelected: false,\n Icon: 'fa-solid fa-file'\n });\n }\n\n return { Category: 'Entity', Options: options, MultiSelect: true };\n }\n\n private buildFileTypeFilter(results: SearchResultItem[]): SearchFilter {\n const counts = new Map<string, number>();\n for (const r of results) {\n if (r.ResultType !== 'storage-file') continue;\n const ext = r.Title?.split('.').pop()?.toUpperCase();\n if (ext && ext.length <= 6) {\n counts.set(ext, (counts.get(ext) ?? 0) + 1);\n }\n }\n const options: SearchFilterOption[] = Array.from(counts.entries())\n .sort((a, b) => b[1] - a[1])\n .map(([ext, count]) => ({\n Label: ext,\n Value: ext,\n Count: count,\n IsSelected: false,\n Icon: 'fa-solid fa-file'\n }));\n return { Category: 'File Type', Options: options, MultiSelect: true };\n }\n\n private buildTagFilter(results: SearchResultItem[]): SearchFilter {\n const counts = new Map<string, number>();\n for (const r of results) {\n for (const tag of r.Tags) {\n counts.set(tag, (counts.get(tag) ?? 0) + 1);\n }\n }\n const options: SearchFilterOption[] = Array.from(counts.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, 15)\n .map(([tag, count]) => ({\n Label: tag,\n Value: tag,\n Count: count,\n IsSelected: false,\n Icon: 'fa-solid fa-tag'\n }));\n return { Category: 'Tags', Options: options, MultiSelect: true };\n }\n\n /**\n * Load persisted recent searches from UserInfoEngine.\n * Safe to call multiple times — only loads once.\n */\n public async LoadRecentSearches(): Promise<void> {\n if (this.recentSearchesLoaded) return;\n\n try {\n MJGlobal.Instance.GetEventListener(true).subscribe(async (event) => {\n if (event.event === MJEventType.LoggedIn) {\n await StartupManager.Instance.Startup();\n\n const engine = UserInfoEngine.Instance;\n\n const json = engine.GetSetting(RECENT_SEARCHES_KEY);\n\n if (json) {\n const parsed = JSON.parse(json) as RecentSearchJson[];\n const searches: RecentSearch[] = parsed.map(s => ({\n Query: s.Query,\n Timestamp: new Date(s.Timestamp),\n ResultCount: s.ResultCount\n }));\n this.RecentSearches$.next(searches);\n }\n }\n });\n } catch (err) {\n console.error('[SearchService] LoadRecentSearches error:', err);\n }\n this.recentSearchesLoaded = true;\n }\n\n /**\n * Record a query into recent searches WITHOUT running a search. For surfaces\n * (e.g. the omnibar palette) where the user types a query but executes a\n * suggestion that navigates directly — no full ExecuteSearch ever runs, so\n * the automatic recording inside ExecuteSearch never fires for that query.\n * Deduplicates by query text and persists via UserInfoEngine like all recents.\n */\n /** Resolved record-name memo — GetEntityRecordNames round-trips are cosmetic\n and stable, so resolve each entity/record pair once per session. */\n private recentRecordNameCache = new Map<string, string>();\n\n /**\n * Recently opened records for search empty states, newest first — same\n * source as the omnibar's '#' empty state (MJ: User Record Logs, queried\n * through UserInfoEngine.LoadRecentRecordLogs). Fail-soft: any error yields [] rather than blocking\n * the surface. Display names resolve via GetEntityRecordNames with the\n * record ID as fallback.\n */\n public async GetRecentlyOpenedRecords(max = 3): Promise<RecentRecordItem[]> {\n try {\n const logs = await UserInfoEngine.Instance.LoadRecentRecordLogs(max, this.Provider.CurrentUser ?? undefined, this.Provider);\n if (logs.length === 0) {\n return [];\n }\n const unresolved = logs.filter((l) => !this.recentRecordNameCache.has(`${l.Entity}||${l.RecordID}`));\n if (unresolved.length > 0) {\n try {\n // Recents span arbitrary entities whose key column can have any name; `FromID`\n // assumed `ID` and left those records showing a raw id instead of a name.\n const results = await this.Provider.GetEntityRecordNames(\n unresolved.map((l) => ({\n EntityName: l.Entity,\n CompositeKey: CompositeKey.FromURLSegment(this.Provider.EntityByName(l.Entity), l.RecordID),\n })),\n this.Provider.CurrentUser ?? undefined,\n );\n for (const r of results ?? []) {\n if (r.Success && r.RecordName) {\n this.recentRecordNameCache.set(`${r.EntityName}||${r.CompositeKey.GetValueByIndex(0)}`, r.RecordName);\n }\n }\n } catch {\n // name lookup is cosmetic — IDs are an acceptable fallback\n }\n }\n return logs.map((log) => {\n let entityInfo;\n try {\n entityInfo = this.Provider?.EntityByName ? this.Provider.EntityByName(log.Entity) : undefined;\n } catch {\n // Non-fatal if metadata cache is uninitialized\n }\n return {\n EntityName: log.Entity,\n EntityDisplayName: entityInfo?.DisplayName || log.Entity,\n RecordID: log.RecordID,\n RecordName: this.recentRecordNameCache.get(`${log.Entity}||${log.RecordID}`) ?? log.RecordID,\n };\n });\n } catch {\n return [];\n }\n }\n\n public RecordRecentSearch(query: string, resultCount = 0): void {\n const trimmed = query.trim();\n if (trimmed.length > 0) {\n this.addToRecentSearches(trimmed, resultCount);\n }\n }\n\n private addToRecentSearches(query: string, resultCount: number): void {\n const current = this.RecentSearches$.value;\n const filtered = current.filter(s => s.Query !== query);\n const updated = [\n { Query: query, Timestamp: new Date(), ResultCount: resultCount },\n ...filtered\n ].slice(0, this.maxRecentSearches);\n this.RecentSearches$.next(updated);\n this.persistRecentSearches(updated);\n }\n\n private persistRecentSearches(searches: RecentSearch[]): void {\n try {\n const json: RecentSearchJson[] = searches.map(s => ({\n Query: s.Query,\n Timestamp: s.Timestamp.toISOString(),\n ResultCount: s.ResultCount\n }));\n UserInfoEngine.Instance.SetSettingDebounced(RECENT_SEARCHES_KEY, JSON.stringify(json));\n } catch {\n // Silently fail if UserInfoEngine not available\n }\n }\n\n /** Cache provider metadata by SourceType for use in GroupResults/BuildFilters */\n private cacheProviders(providers: SearchProviderInfo[]): void {\n for (const p of providers) {\n this.providersBySourceType.set(p.SourceType, p);\n }\n }\n\n private createEmptyResponse(errorMessage?: string): SearchResponse {\n return {\n Success: !errorMessage,\n Results: [],\n Groups: [],\n Filters: [],\n TotalCount: 0,\n ElapsedMs: 0,\n SourceCounts: { Vector: 0, FullText: 0, Entity: 0, Storage: 0 },\n Providers: [],\n ErrorMessage: errorMessage\n };\n }\n\n /**\n * Execute search via the GraphQLSearchClient.\n */\n private async executeGraphQLSearch(request: SearchRequest): Promise<SearchResponse> {\n if (!request.Query.trim()) {\n return this.createEmptyResponse();\n }\n\n const provider = this.Provider;\n if (!(provider instanceof GraphQLDataProvider)) {\n return this.createEmptyResponse('GraphQL provider not available');\n }\n\n const client = new GraphQLSearchClient(provider);\n const filters = this.buildClientFilters(request);\n const minScore = request.MinScore ?? DEFAULT_MIN_SCORE;\n\n const clientResponse = await client.ExecuteSearch({\n Query: request.Query,\n MaxResults: request.MaxResults || 20,\n MinScore: minScore > 0 ? minScore : undefined,\n Filters: filters,\n ScopeIDs: request.ScopeIDs && request.ScopeIDs.length > 0 ? request.ScopeIDs : undefined\n });\n\n return this.mapClientResponseToSearchResponse(clientResponse);\n }\n\n /** Convert a SearchClientResponse into the SearchResponse shape used by this service */\n private mapClientResponseToSearchResponse(clientResponse: SearchClientResponse): SearchResponse {\n if (!clientResponse.Success) {\n return this.createEmptyResponse(clientResponse.ErrorMessage ?? 'Search failed');\n }\n\n // Cache provider metadata for use in GroupResults/BuildFilters\n const providers: SearchProviderInfo[] = (clientResponse.Providers ?? []).map(p => ({\n ID: p.ID,\n Name: p.Name,\n DisplayName: p.DisplayName,\n Icon: p.Icon,\n SourceType: p.SourceType,\n Priority: p.Priority,\n }));\n this.cacheProviders(providers);\n\n const results: SearchResultItem[] = (clientResponse.Results ?? []).map(r => this.mapClientResultItem(r));\n\n const groups = this.GroupResults(results);\n const filters = this.BuildFilters(results);\n\n return {\n Success: true,\n Results: results,\n Groups: groups,\n Filters: filters,\n TotalCount: clientResponse.TotalCount,\n ElapsedMs: clientResponse.ElapsedMs,\n SourceCounts: {\n Vector: clientResponse.SourceCounts.Vector,\n FullText: clientResponse.SourceCounts.FullText,\n Entity: clientResponse.SourceCounts.Entity,\n Storage: clientResponse.SourceCounts.Storage\n },\n Providers: providers,\n };\n }\n\n /** Map a single SearchClientResultItem to a SearchResultItem */\n private mapClientResultItem(r: SearchClientResultItem): SearchResultItem {\n let entityDisplayName = r.EntityDisplayName;\n let entityIcon = r.EntityIcon;\n try {\n const entity = this.Provider?.EntityByName?.(r.EntityName);\n if (!entityDisplayName && entity) {\n entityDisplayName = entity.DisplayName || entity.Name;\n }\n if (!entityIcon && entity?.Icon) {\n entityIcon = entity.Icon;\n }\n } catch {\n // Non-fatal if metadata cache is uninitialized (e.g. in unit tests)\n }\n if (!entityDisplayName) {\n entityDisplayName = r.EntityName;\n }\n\n return {\n ID: r.ID,\n Title: r.RecordName || r.Title,\n Snippet: r.Snippet,\n EntityName: r.EntityName,\n EntityDisplayName: entityDisplayName,\n RecordID: r.RecordID,\n SourceType: (r.SourceType as SearchResultItem['SourceType']) || 'entity',\n ResultType: r.ResultType,\n Score: r.Score,\n ScoreBreakdown: r.ScoreBreakdown ?? {},\n Tags: r.Tags ?? [],\n SourceIcon: entityIcon || r.ProviderIcon || FALLBACK_SOURCE_ICONS[r.SourceType] || 'fa-solid fa-database',\n EntityIcon: entityIcon,\n RecordName: r.RecordName,\n MatchedAt: new Date(r.MatchedAt),\n RawMetadata: r.RawMetadata,\n ProviderId: r.ProviderId,\n ProviderLabel: r.ProviderLabel,\n ProviderIcon: r.ProviderIcon,\n };\n }\n\n /**\n * Load the list of search scopes available to the current user.\n * Cached after the first successful call; pass `force=true` to reload.\n */\n public async LoadScopes(force: boolean = false): Promise<SearchScopeInfo[]> {\n if (this.scopesLoaded && !force) return this.Scopes$.value;\n if (this.scopesLoadInFlight && !force) return this.scopesLoadInFlight;\n\n const load = (async (): Promise<SearchScopeInfo[]> => {\n try {\n const provider = Metadata.Provider; // global-provider-ok: scope discovery consumes the GraphQL channel of the global default provider\n if (!(provider instanceof GraphQLDataProvider)) {\n this.Scopes$.next([]);\n return [];\n }\n const client = new GraphQLSearchClient(provider);\n const scopes = await client.GetSearchScopes();\n this.Scopes$.next(scopes);\n this.scopesLoaded = true;\n return scopes;\n } catch {\n this.Scopes$.next([]);\n return [];\n } finally {\n this.scopesLoadInFlight = null;\n }\n })();\n\n this.scopesLoadInFlight = load;\n return load;\n }\n\n /** Build the client filters from active filter selections */\n private buildClientFilters(request: SearchRequest): { EntityNames?: string[]; SourceTypes?: string[]; Tags?: string[] } | undefined {\n if (!request.ActiveFilters || Object.keys(request.ActiveFilters).length === 0) {\n return undefined;\n }\n\n const result: { EntityNames?: string[]; SourceTypes?: string[]; Tags?: string[] } = {};\n\n const entityFilters = request.ActiveFilters['Entity'];\n if (entityFilters?.length) {\n result.EntityNames = entityFilters;\n }\n\n const sourceFilters = request.ActiveFilters['Source'];\n if (sourceFilters?.length) {\n result.SourceTypes = sourceFilters;\n }\n\n const tagFilters = request.ActiveFilters['Tags'];\n if (tagFilters?.length) {\n result.Tags = tagFilters;\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-search",
|
|
3
|
-
"version": "6.2.0-edge.
|
|
3
|
+
"version": "6.2.0-edge.5",
|
|
4
4
|
"description": "MemberJunction: Reusable search overlay and results components - command palette / Spotlight style search",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@angular/compiler": "21.2.22",
|
|
15
15
|
"@angular/compiler-cli": "21.2.22",
|
|
16
|
-
"@memberjunction/ng-test-utils": "6.2.0-edge.
|
|
16
|
+
"@memberjunction/ng-test-utils": "6.2.0-edge.5",
|
|
17
17
|
"vitest": "^4.0.18"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
"@angular/forms": "^21.2.22"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@memberjunction/ng-ui-components": "6.2.0-edge.
|
|
26
|
-
"@memberjunction/core": "6.2.0-edge.
|
|
27
|
-
"@memberjunction/ng-base-types": "6.2.0-edge.
|
|
28
|
-
"@memberjunction/global": "6.2.0-edge.
|
|
29
|
-
"@memberjunction/graphql-dataprovider": "6.2.0-edge.
|
|
30
|
-
"@memberjunction/core-entities": "6.2.0-edge.
|
|
31
|
-
"@memberjunction/ng-shared-generic": "6.2.0-edge.
|
|
25
|
+
"@memberjunction/ng-ui-components": "6.2.0-edge.5",
|
|
26
|
+
"@memberjunction/core": "6.2.0-edge.5",
|
|
27
|
+
"@memberjunction/ng-base-types": "6.2.0-edge.5",
|
|
28
|
+
"@memberjunction/global": "6.2.0-edge.5",
|
|
29
|
+
"@memberjunction/graphql-dataprovider": "6.2.0-edge.5",
|
|
30
|
+
"@memberjunction/core-entities": "6.2.0-edge.5",
|
|
31
|
+
"@memberjunction/ng-shared-generic": "6.2.0-edge.5",
|
|
32
32
|
"rxjs": "^7.8.2",
|
|
33
33
|
"tslib": "^2.8.1"
|
|
34
34
|
},
|