diff --git a/src/public/app/widgets/llm_chat_panel.ts b/src/public/app/widgets/llm_chat_panel.ts index 18749c422..0683ac279 100644 --- a/src/public/app/widgets/llm_chat_panel.ts +++ b/src/public/app/widgets/llm_chat_panel.ts @@ -42,8 +42,11 @@ export default class LlmChatPanel extends BasicWidget {
@@ -286,16 +289,84 @@ export default class LlmChatPanel extends BasicWidget { private showSources(sources: Array<{noteId: string, title: string}>) { this.sourcesList.innerHTML = ''; + // Update the sources count + const sourcesCount = this.$widget[0].querySelector('.sources-count') as HTMLElement; + if (sourcesCount) { + sourcesCount.textContent = sources.length.toString(); + } + sources.forEach(source => { const sourceElement = document.createElement('div'); - sourceElement.className = 'source-item p-1'; - sourceElement.innerHTML = `${source.title}`; + sourceElement.className = 'source-item p-2 mb-1 border rounded'; + // Use the proper note URL format instead of "#" + // This creates a direct hyperlink to the note using the application's URL schema + sourceElement.innerHTML = ` +
+ + ${source.title} + +
+ +
+
+ `; + + // Keep the click handler for better UX - this ensures the note opens in the right context sourceElement.querySelector('.source-link')?.addEventListener('click', (e) => { e.preventDefault(); appContext.tabManager.openTabWithNoteWithHoisting(source.noteId); }); + // Add preview functionality + sourceElement.querySelector('.preview-button')?.addEventListener('click', async () => { + const previewElement = sourceElement.querySelector('.source-preview') as HTMLElement; + + if (previewElement.style.display === 'none') { + // Show preview + previewElement.style.display = 'block'; + + // If we don't have a preview yet, load it + if (!previewElement.innerHTML.trim()) { + previewElement.innerHTML = '
Loading preview...
'; + + try { + // Fetch note content using the correct API endpoint + const result = await server.get(`etapi/notes/${source.noteId}/content`); + + // For plain text or short content, display directly + let previewContent = result as string; + + // If it's HTML, extract text or simplify + if (typeof result === 'string' && result.trim().startsWith('<')) { + const tempDiv = document.createElement('div'); + tempDiv.innerHTML = result; + previewContent = tempDiv.textContent || tempDiv.innerText || result; + } + + // Limit preview length + const maxLength = 300; + if (previewContent.length > maxLength) { + previewContent = previewContent.substring(0, maxLength) + '...'; + } + + previewElement.innerHTML = `
${previewContent}
`; + } catch (error) { + previewElement.innerHTML = '
Error loading preview
'; + } + } + } else { + // Hide preview + previewElement.style.display = 'none'; + } + }); + this.sourcesList.appendChild(sourceElement); });