feat(Index.tsx): add functionality to include tags in search queries and persist setting
This commit is contained in:
@@ -238,22 +238,40 @@ Keep tags concise, use lowercase, and separate words with hyphens if needed.`);
|
|||||||
// Check Ollama status
|
// Check Ollama status
|
||||||
const checkOllamaStatus = async () => {
|
const checkOllamaStatus = async () => {
|
||||||
try {
|
try {
|
||||||
|
// Add timeout to prevent hanging
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeoutId = setTimeout(() => controller.abort(), 500);
|
||||||
|
|
||||||
const response = await fetch(`${OLLAMA_ENDPOINT}/api/tags`, {
|
const response = await fetch(`${OLLAMA_ENDPOINT}/api/tags`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
|
signal: controller.signal,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
setOllamaStatus('online');
|
setOllamaStatus('online');
|
||||||
|
addDebugInfo('Ollama connection successful');
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
setOllamaStatus('offline');
|
setOllamaStatus('offline');
|
||||||
|
addDebugInfo(`Ollama responded with status: ${response.status}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setOllamaStatus('offline');
|
setOllamaStatus('offline');
|
||||||
|
if (error instanceof Error) {
|
||||||
|
if (error.name === 'AbortError') {
|
||||||
|
addDebugInfo('Ollama connection timed out after 5 seconds');
|
||||||
|
} else if (error.message.includes('fetch')) {
|
||||||
|
addDebugInfo('Ollama network error - check if Ollama is running and accessible');
|
||||||
|
} else {
|
||||||
|
addDebugInfo(`Ollama connection error: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -845,6 +863,7 @@ ${content}${context}`;
|
|||||||
q: query,
|
q: query,
|
||||||
matchingStrategy: 'all',
|
matchingStrategy: 'all',
|
||||||
limit: 50,
|
limit: 50,
|
||||||
|
attributesToSearchOn: includeTagsInSearch ? ['content', 'tags'] : ['content'],
|
||||||
attributesToHighlight: includeTagsInSearch ? ['content', 'tags'] : ['content'],
|
attributesToHighlight: includeTagsInSearch ? ['content', 'tags'] : ['content'],
|
||||||
showRankingScore: true,
|
showRankingScore: true,
|
||||||
highlightPreTag: '<mark class="bg-yellow-200">',
|
highlightPreTag: '<mark class="bg-yellow-200">',
|
||||||
@@ -896,7 +915,7 @@ ${content}${context}`;
|
|||||||
clearTimeout(searchTimeoutRef.current);
|
clearTimeout(searchTimeoutRef.current);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [searchQuery]);
|
}, [searchQuery, includeTagsInSearch]);
|
||||||
|
|
||||||
// Go to closest note by ISO8601 date
|
// Go to closest note by ISO8601 date
|
||||||
const goToClosestNoteToDate = async (iso8601: string) => {
|
const goToClosestNoteToDate = async (iso8601: string) => {
|
||||||
@@ -1522,8 +1541,17 @@ ${content}${context}`;
|
|||||||
await loadAutoGenerateTagsSetting();
|
await loadAutoGenerateTagsSetting();
|
||||||
await loadSystemPromptSetting();
|
await loadSystemPromptSetting();
|
||||||
await loadContextSizeSetting();
|
await loadContextSizeSetting();
|
||||||
|
await loadIncludeTagsSetting();
|
||||||
await checkOllamaStatus();
|
await checkOllamaStatus();
|
||||||
|
|
||||||
|
// Retry Ollama connection after a delay if it failed
|
||||||
|
setTimeout(async () => {
|
||||||
|
if (ollamaStatus === 'offline') {
|
||||||
|
addDebugInfo('Retrying Ollama connection...');
|
||||||
|
await checkOllamaStatus();
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
const totalTime = Date.now() - dataLoadStartTime;
|
const totalTime = Date.now() - dataLoadStartTime;
|
||||||
debugTiming('Total Data Loading', dataLoadStartTime);
|
debugTiming('Total Data Loading', dataLoadStartTime);
|
||||||
addDebugInfo(`Total Data Loading: ${totalTime}ms`);
|
addDebugInfo(`Total Data Loading: ${totalTime}ms`);
|
||||||
@@ -1659,6 +1687,33 @@ ${content}${context}`;
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Load include tags in search setting
|
||||||
|
const loadIncludeTagsSetting = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetchWithTiming(`${MEILISEARCH_ENDPOINT}/indexes/${SETTINGS_INDEX}/search`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${MEILISEARCH_API_KEY}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
q: 'includeTagsInSearch',
|
||||||
|
filter: 'key = "includeTagsInSearch"',
|
||||||
|
limit: 1,
|
||||||
|
}),
|
||||||
|
}, 'Load Include Tags Setting');
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.hits.length > 0) {
|
||||||
|
setIncludeTagsInSearch(data.hits[0].value === 'true');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading include tags setting:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Save font size setting
|
// Save font size setting
|
||||||
const saveFontSizeSetting = async (newFontSize: string) => {
|
const saveFontSizeSetting = async (newFontSize: string) => {
|
||||||
try {
|
try {
|
||||||
@@ -1807,6 +1862,43 @@ ${content}${context}`;
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Save include tags in search setting
|
||||||
|
const saveIncludeTagsSetting = async (enabled: boolean) => {
|
||||||
|
try {
|
||||||
|
const document = {
|
||||||
|
key: 'includeTagsInSearch',
|
||||||
|
value: enabled.toString(),
|
||||||
|
updatedAt: new Date().getTime(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await fetchWithTiming(`${MEILISEARCH_ENDPOINT}/indexes/${SETTINGS_INDEX}/documents`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${MEILISEARCH_API_KEY}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify(document),
|
||||||
|
}, 'Save Include Tags Setting');
|
||||||
|
|
||||||
|
if (response.status !== 202) {
|
||||||
|
throw new Error('Failed to save include tags setting');
|
||||||
|
}
|
||||||
|
|
||||||
|
setIncludeTagsInSearch(enabled);
|
||||||
|
toast({
|
||||||
|
title: "Search setting updated",
|
||||||
|
description: `Tag search ${enabled ? 'enabled' : 'disabled'}.`,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error saving include tags setting:', error);
|
||||||
|
toast({
|
||||||
|
title: "Error",
|
||||||
|
description: "Failed to save include tags setting.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`min-h-screen bg-background text-foreground flex flex-col ${getTextClass('base')}`}>
|
<div className={`min-h-screen bg-background text-foreground flex flex-col ${getTextClass('base')}`}>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
@@ -2066,7 +2158,10 @@ ${content}${context}`;
|
|||||||
<span className={`${getTextClass('base')} text-muted-foreground`}>Include tags</span>
|
<span className={`${getTextClass('base')} text-muted-foreground`}>Include tags</span>
|
||||||
<Switch
|
<Switch
|
||||||
checked={includeTagsInSearch}
|
checked={includeTagsInSearch}
|
||||||
onCheckedChange={setIncludeTagsInSearch}
|
onCheckedChange={async (enabled) => {
|
||||||
|
await saveIncludeTagsSetting(enabled);
|
||||||
|
// The search effect will automatically re-run due to includeTagsInSearch dependency
|
||||||
|
}}
|
||||||
aria-label="Toggle tag search"
|
aria-label="Toggle tag search"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -2303,24 +2398,7 @@ ${content}${context}`;
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Search Settings */}
|
|
||||||
<div className="space-y-6">
|
|
||||||
<h3 className={`${getTextClass('2xl')} font-semibold`}>Search</h3>
|
|
||||||
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div>
|
|
||||||
<label className={`${getTextClass('xl')} font-medium`}>Include Tags in Search</label>
|
|
||||||
<p className={`${getTextClass('base')} text-muted-foreground`}>
|
|
||||||
Search both content and tags when enabled
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<Switch
|
|
||||||
checked={includeTagsInSearch}
|
|
||||||
onCheckedChange={setIncludeTagsInSearch}
|
|
||||||
aria-label="Toggle tag search"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Display Settings */}
|
{/* Display Settings */}
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
Reference in New Issue
Block a user