Skip to content

Commit 3d720ac

Browse files
authored
Merge pull request #423 from adiologydev/chore/korrektly-improvements
chore: improve korrektly search
2 parents 134c787 + 6bf577d commit 3d720ac

File tree

1 file changed

+63
-19
lines changed

1 file changed

+63
-19
lines changed

docs/.vitepress/theme/components/KorrektlySearch.vue

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
<script setup lang="ts">
2-
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
3-
import { useData } from 'vitepress'
2+
import { ref, watch, onMounted } from 'vue'
43
import { onKeyStroke } from '@vueuse/core'
54
6-
const { isDark } = useData()
7-
85
interface SearchResult {
96
id: string
107
title: string
@@ -57,12 +54,27 @@ defineExpose({
5754
openSearch
5855
})
5956
60-
const closeSearch = () => {
61-
isOpen.value = false
57+
const clearSearch = () => {
58+
// Cancel any ongoing search operations
59+
if (searchTimeout) {
60+
clearTimeout(searchTimeout)
61+
searchTimeout = null
62+
}
63+
if (abortController) {
64+
abortController.abort()
65+
abortController = null
66+
}
67+
6268
searchQuery.value = ''
6369
searchResults.value = []
6470
selectedIndex.value = 0
6571
searchError.value = null
72+
isLoading.value = false
73+
}
74+
75+
const closeSearch = () => {
76+
clearSearch()
77+
isOpen.value = false
6678
}
6779
6880
// Keyboard shortcuts (only for modal interactions)
@@ -94,15 +106,23 @@ onKeyStroke('Enter', () => {
94106
95107
// Debounced search
96108
let searchTimeout: NodeJS.Timeout | null = null
109+
let abortController: AbortController | null = null
97110
98111
watch(searchQuery, async (newQuery) => {
112+
// Cancel previous timeout and abort any ongoing request
99113
if (searchTimeout) {
100114
clearTimeout(searchTimeout)
115+
searchTimeout = null
116+
}
117+
if (abortController) {
118+
abortController.abort()
119+
abortController = null
101120
}
102121
103122
if (!newQuery.trim()) {
104123
searchResults.value = []
105124
searchError.value = null
125+
isLoading.value = false
106126
return
107127
}
108128
@@ -118,6 +138,16 @@ const performSearch = async (query: string) => {
118138
return
119139
}
120140
141+
if (!korrektlyConfig.datasetId || !korrektlyConfig.apiToken) {
142+
console.error('Korrektly dataset ID not configured')
143+
searchError.value = 'Search is not properly configured. Please check the environment variables.'
144+
return
145+
}
146+
147+
// Create new abort controller for this search
148+
abortController = new AbortController()
149+
const currentAbortController = abortController
150+
121151
isLoading.value = true
122152
searchError.value = null
123153
try {
@@ -127,6 +157,11 @@ const performSearch = async (query: string) => {
127157
search_type: 'hybrid',
128158
})
129159
160+
// Check if this request was aborted
161+
if (currentAbortController.signal.aborted) {
162+
return
163+
}
164+
130165
// Check if response contains an error
131166
if (response?.error || response?.message) {
132167
const errorMessage = response.message || response.error || 'An unknown error occurred'
@@ -148,7 +183,10 @@ const performSearch = async (query: string) => {
148183
149184
const title = getMetadata('title') || getMetadata('heading') || extractTitle(chunk.content_html) || 'Untitled'
150185
const description = getMetadata('description') || ''
151-
const hierarchy = getMetadata('hierarchy') || ''
186+
187+
// Handle hierarchy as array
188+
const hierarchyMeta = chunk.metadata?.find((m: any) => m.key === 'hierarchy')
189+
const hierarchy = hierarchyMeta?.value || []
152190
153191
// Build URL from source_url or group tracking_id
154192
let url = chunk.source_url || ''
@@ -161,17 +199,15 @@ const performSearch = async (query: string) => {
161199
url = url.replace('.md', '')
162200
}
163201
164-
// Create breadcrumb from hierarchy or URL (excluding 'docs' prefix)
202+
// Create breadcrumb from hierarchy array or URL (excluding 'docs' prefix)
165203
let breadcrumb = ''
166-
if (hierarchy) {
167-
// Convert "home > aditya > workspace > coollabs > coolify-docs > docs > services > n8n"
168-
// to "services / n8n"
169-
const parts = hierarchy.split(' > ')
170-
const docsIndex = parts.indexOf('docs')
171-
if (docsIndex !== -1 && docsIndex < parts.length - 1) {
172-
breadcrumb = parts.slice(docsIndex + 1).join(' / ')
204+
if (Array.isArray(hierarchy) && hierarchy.length > 0) {
205+
// Find 'docs' in the hierarchy array and take everything after it
206+
const docsIndex = hierarchy.indexOf('docs')
207+
if (docsIndex !== -1 && docsIndex < hierarchy.length - 1) {
208+
breadcrumb = hierarchy.slice(docsIndex + 1).join(' / ')
173209
} else {
174-
breadcrumb = hierarchy.replace(/ > /g, ' / ')
210+
breadcrumb = hierarchy.join(' / ')
175211
}
176212
} else if (url) {
177213
// Extract from URL: /docs/services/n8n -> services / n8n
@@ -191,6 +227,11 @@ const performSearch = async (query: string) => {
191227
192228
selectedIndex.value = 0
193229
} catch (error: any) {
230+
// Don't show error if the request was aborted
231+
if (currentAbortController.signal.aborted) {
232+
return
233+
}
234+
194235
console.error('Search error:', error)
195236
196237
// Try to extract error message from the error object
@@ -207,7 +248,10 @@ const performSearch = async (query: string) => {
207248
searchError.value = errorMessage
208249
searchResults.value = []
209250
} finally {
210-
isLoading.value = false
251+
// Only reset loading if not aborted
252+
if (!currentAbortController.signal.aborted) {
253+
isLoading.value = false
254+
}
211255
}
212256
}
213257
@@ -283,7 +327,8 @@ const truncate = (text: string, length: number) => {
283327
<button
284328
v-if="searchQuery"
285329
class="absolute right-3 w-6 h-6 flex items-center justify-center rounded bg-[var(--vp-c-bg-soft)] text-[var(--vp-c-text-2)] hover:bg-[var(--vp-c-bg-elv)] hover:text-[var(--vp-c-text-1)] transition-all text-xl leading-none"
286-
@click="searchQuery = ''"
330+
@click="clearSearch"
331+
title="Clear search"
287332
>
288333
×
289334
</button>
@@ -353,7 +398,6 @@ const truncate = (text: string, length: number) => {
353398

354399
<!-- Initial State -->
355400
<div v-else class="py-12 px-6 text-center text-[var(--vp-c-text-2)]">
356-
<p class="text-sm mb-6">Start typing to search...</p>
357401
<div class="mt-6">
358402
<p class="text-xs font-semibold text-[var(--vp-c-text-2)] mb-3 uppercase tracking-wide">Popular searches:</p>
359403
<div class="flex flex-wrap gap-2 justify-center">

0 commit comments

Comments
 (0)