mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-02 21:19:12 +00:00
Enhance Search Modal, Error State Handling in Khoj Obsidian Plugin
### Search Modal Enhancements -b52cd85Allow Reranking results using Keybinding from Khoj Search Modal -580f4acAdd hints to Modal for available Keybindings -da49ea2Add placeholder text to modal in Khoj Obsidian plugin ### Handle Failure to Connect to Khoj Backend Load plugin but warn on failure to connect to Khoj backend -f046a95Track connectedToBackend as a setting. Use it across obsidian plugin to: - Disable command if not connected to backend - Trigger warning notice on clicking Khoj ribbon if not connected to backend - Show warning at top of Khoj Obsidian plugin settings pane -768e874Load obsidian plugin even if fail to connect to backend but show warning - Allows user to see reason for failure to try resolve it - Allows user to update Khoj URL settings to point to URL of Khoj server ### Miscellaneous -7991ab7Add button in Obsidian plugin settings to force re-indexing your vault - Useful if index gets corrupted
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Plugin } from 'obsidian';
|
||||
import { Notice, Plugin } from 'obsidian';
|
||||
import { KhojSetting, KhojSettingTab, DEFAULT_SETTINGS } from 'src/settings'
|
||||
import { KhojModal } from 'src/modal'
|
||||
import { configureKhojBackend } from './utils';
|
||||
@@ -14,18 +14,22 @@ export default class Khoj extends Plugin {
|
||||
this.addCommand({
|
||||
id: 'search',
|
||||
name: 'Search',
|
||||
callback: () => {
|
||||
new KhojModal(this.app, this.settings).open();
|
||||
checkCallback: (checking) => {
|
||||
if (!checking && this.settings.connectedToBackend)
|
||||
new KhojModal(this.app, this.settings).open();
|
||||
return this.settings.connectedToBackend;
|
||||
}
|
||||
});
|
||||
|
||||
// Create an icon in the left ribbon.
|
||||
this.addRibbonIcon('search', 'Khoj', (_: MouseEvent) => {
|
||||
// Called when the user clicks the icon.
|
||||
new KhojModal(this.app, this.settings).open();
|
||||
this.settings.connectedToBackend
|
||||
? new KhojModal(this.app, this.settings).open()
|
||||
: new Notice(`❗️Ensure Khoj backend is running and Khoj URL is pointing to it in the plugin settings`);
|
||||
});
|
||||
|
||||
// Add a settings tab so the user can configure various aspects of the plugin
|
||||
// Add a settings tab so the user can configure khoj
|
||||
this.addSettingTab(new KhojSettingTab(this.app, this));
|
||||
}
|
||||
|
||||
@@ -41,7 +45,7 @@ export default class Khoj extends Plugin {
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings)
|
||||
.then(() => configureKhojBackend(this.settings));
|
||||
await configureKhojBackend(this.settings)
|
||||
.then(() => this.saveData(this.settings));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { App, SuggestModal, Notice, request, MarkdownRenderer } from 'obsidian';
|
||||
import { App, SuggestModal, Notice, request, MarkdownRenderer, Instruction, Platform } from 'obsidian';
|
||||
import { KhojSetting } from 'src/settings';
|
||||
import { getVaultAbsolutePath } from 'src/utils';
|
||||
|
||||
@@ -9,16 +9,54 @@ export interface SearchResult {
|
||||
|
||||
export class KhojModal extends SuggestModal<SearchResult> {
|
||||
setting: KhojSetting;
|
||||
rerank: boolean;
|
||||
|
||||
constructor(app: App, setting: KhojSetting) {
|
||||
super(app);
|
||||
this.setting = setting;
|
||||
this.rerank = false;
|
||||
|
||||
// Register Modal Keybindings to Rerank Results
|
||||
this.scope.register(['Mod'], 'Enter', async () => {
|
||||
this.rerank = true
|
||||
let results = await this.getSuggestions(this.inputEl.value);
|
||||
|
||||
this.resultContainerEl.empty();
|
||||
results.forEach((result) => {
|
||||
this.renderSuggestion(result, this.resultContainerEl);
|
||||
});
|
||||
this.rerank = false
|
||||
});
|
||||
|
||||
// Add Hints to Modal for available Keybindings
|
||||
const modalInstructions: Instruction[] = [
|
||||
{
|
||||
command: '↑↓',
|
||||
purpose: 'to navigate',
|
||||
},
|
||||
{
|
||||
command: '↵',
|
||||
purpose: 'to open',
|
||||
},
|
||||
{
|
||||
command: Platform.isMacOS ? 'cmd ↵': 'ctrl ↵',
|
||||
purpose: 'to rerank',
|
||||
},
|
||||
{
|
||||
command: 'esc',
|
||||
purpose: 'to dismiss',
|
||||
},
|
||||
]
|
||||
this.setInstructions(modalInstructions);
|
||||
|
||||
// Set Placeholder Text for Modal
|
||||
this.setPlaceholder('Search with Khoj...');
|
||||
}
|
||||
|
||||
async getSuggestions(query: string): Promise<SearchResult[]> {
|
||||
// Query Khoj backend for search results
|
||||
var searchUrl = `${this.setting.khojUrl}/api/search?q=${query}&n=${this.setting.resultsCount}&t=markdown`
|
||||
var results = await request(searchUrl)
|
||||
let searchUrl = `${this.setting.khojUrl}/api/search?q=${query}&n=${this.setting.resultsCount}&r=${this.rerank}&t=markdown`
|
||||
let results = await request(searchUrl)
|
||||
.then(response => JSON.parse(response))
|
||||
.then(data => {
|
||||
return data.map((result: any) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { App, PluginSettingTab, Setting } from 'obsidian';
|
||||
import { App, PluginSettingTab, request, Setting } from 'obsidian';
|
||||
import Khoj from 'src/main';
|
||||
import { getVaultAbsolutePath } from 'src/utils';
|
||||
|
||||
@@ -6,12 +6,14 @@ export interface KhojSetting {
|
||||
resultsCount: number;
|
||||
khojUrl: string;
|
||||
obsidianVaultPath: string;
|
||||
connectedToBackend: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: KhojSetting = {
|
||||
resultsCount: 6,
|
||||
khojUrl: 'http://localhost:8000',
|
||||
obsidianVaultPath: getVaultAbsolutePath()
|
||||
obsidianVaultPath: getVaultAbsolutePath(),
|
||||
connectedToBackend: false,
|
||||
}
|
||||
|
||||
export class KhojSettingTab extends PluginSettingTab {
|
||||
@@ -25,8 +27,15 @@ export class KhojSettingTab extends PluginSettingTab {
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
|
||||
// Add notice if unable to connect to khoj backend
|
||||
if (!this.plugin.settings.connectedToBackend) {
|
||||
containerEl.createEl('small', { text: '❗Ensure Khoj backend is running and Khoj URL is correctly set below' });
|
||||
}
|
||||
|
||||
// Add khoj settings configurable from the plugin settings tab
|
||||
new Setting(containerEl)
|
||||
.setName('Vault Paths')
|
||||
.setName('Vault Path')
|
||||
.setDesc('The Obsidian Vault to search with Khoj')
|
||||
.addText(text => text
|
||||
.setValue(`${this.plugin.settings.obsidianVaultPath}`)
|
||||
@@ -44,7 +53,7 @@ export class KhojSettingTab extends PluginSettingTab {
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
new Setting(containerEl)
|
||||
.setName('Number of Results')
|
||||
.setName('Results Count')
|
||||
.setDesc('The number of search results to show')
|
||||
.addText(text => text
|
||||
.setPlaceholder('6')
|
||||
@@ -53,5 +62,14 @@ export class KhojSettingTab extends PluginSettingTab {
|
||||
this.plugin.settings.resultsCount = parseInt(value);
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
new Setting(containerEl)
|
||||
.setName('Index Vault')
|
||||
.setDesc('Manually force Khoj to re-index your Obsidian Vault')
|
||||
.addButton(button => button
|
||||
.setButtonText('Update')
|
||||
.onClick(async () => {
|
||||
await request(`${this.plugin.settings.khojUrl}/api/update?t=markdown&force=true`);
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,16 +13,25 @@ export async function configureKhojBackend(setting: KhojSetting) {
|
||||
let mdInVault = `${setting.obsidianVaultPath}/**/*.md`;
|
||||
let khojConfigUrl = `${setting.khojUrl}/api/config/data`;
|
||||
|
||||
// Load khoj app config from backend API, Update Markdown config and save
|
||||
let khoj_configured = await request(khojConfigUrl)
|
||||
.then(response => response !== "null");
|
||||
// Check if khoj backend is configured, show error if backend is not running
|
||||
let khoj_already_configured = await request(khojConfigUrl)
|
||||
.then(response => {
|
||||
setting.connectedToBackend = true;
|
||||
return response !== "null"
|
||||
})
|
||||
.catch(error => {
|
||||
setting.connectedToBackend = false;
|
||||
new Notice(`❗️Ensure Khoj backend is running and Khoj URL is pointing to it in the plugin settings.\n\n${error}`);
|
||||
})
|
||||
// Short-circuit configuring khoj if unable to connect to khoj backend
|
||||
if (!setting.connectedToBackend) return;
|
||||
|
||||
// Get current config if khoj backend configured, else get default config from khoj backend
|
||||
await request(khoj_configured ? khojConfigUrl : `${khojConfigUrl}/default`)
|
||||
await request(khoj_already_configured ? khojConfigUrl : `${khojConfigUrl}/default`)
|
||||
.then(response => JSON.parse(response))
|
||||
.then(data => {
|
||||
// If khoj backend not configured yet
|
||||
if (!khoj_configured) {
|
||||
if (!khoj_already_configured) {
|
||||
// Create khoj content-type config with only markdown configured
|
||||
let khojObsidianPluginPath = `${setting.obsidianVaultPath}/${this.app.vault.configDir}/plugins/khoj/`;
|
||||
data["content-type"] = {
|
||||
@@ -70,9 +79,10 @@ export async function configureKhojBackend(setting: KhojSetting) {
|
||||
updateKhojBackend(setting.khojUrl, data);
|
||||
console.log(`Khoj: Updated markdown config in khoj backend config:\n${JSON.stringify(data["content-type"]["markdown"])}`)
|
||||
}
|
||||
new Notice(`✅ Successfully Setup Khoj`);
|
||||
})
|
||||
.catch(error => {
|
||||
new Notice(`Ensure Khoj backend is running and Khoj URL is correct in the Khoj plugin settings.\nError: ${error}`);
|
||||
new Notice(`❗️Failed to configure Khoj backend. Contact developer on Github. \n\nError: ${error}`);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user