mirror of
https://github.com/zadam/trilium.git
synced 2025-11-07 22:05:44 +01:00
Make the sources section fancier
This commit is contained in:
@@ -42,8 +42,11 @@ export default class LlmChatPanel extends BasicWidget {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sources-container p-2 border-top" style="display: none;">
|
<div class="sources-container p-2 border-top" style="display: none;">
|
||||||
<h6 class="m-0 p-1">${t('ai.sources')}</h6>
|
<h6 class="m-0 p-1">
|
||||||
<div class="sources-list"></div>
|
<i class="bx bx-link-alt"></i> ${t('ai.sources')}
|
||||||
|
<span class="badge bg-secondary rounded-pill ms-2 sources-count"></span>
|
||||||
|
</h6>
|
||||||
|
<div class="sources-list mt-2"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form class="note-context-chat-form d-flex flex-column border-top p-2">
|
<form class="note-context-chat-form d-flex flex-column border-top p-2">
|
||||||
@@ -286,16 +289,84 @@ export default class LlmChatPanel extends BasicWidget {
|
|||||||
private showSources(sources: Array<{noteId: string, title: string}>) {
|
private showSources(sources: Array<{noteId: string, title: string}>) {
|
||||||
this.sourcesList.innerHTML = '';
|
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 => {
|
sources.forEach(source => {
|
||||||
const sourceElement = document.createElement('div');
|
const sourceElement = document.createElement('div');
|
||||||
sourceElement.className = 'source-item p-1';
|
sourceElement.className = 'source-item p-2 mb-1 border rounded';
|
||||||
sourceElement.innerHTML = `<a href="#" data-note-id="${source.noteId}" class="source-link">${source.title}</a>`;
|
|
||||||
|
|
||||||
|
// Use the proper note URL format instead of "#"
|
||||||
|
// This creates a direct hyperlink to the note using the application's URL schema
|
||||||
|
sourceElement.innerHTML = `
|
||||||
|
<div class="d-flex align-items-center justify-content-between">
|
||||||
|
<a href="#root/${source.noteId}"
|
||||||
|
data-note-id="${source.noteId}"
|
||||||
|
class="source-link text-truncate"
|
||||||
|
style="max-width: 85%;"
|
||||||
|
title="Open note: ${source.title}">
|
||||||
|
<i class="bx bx-file"></i> ${source.title}
|
||||||
|
</a>
|
||||||
|
<div class="source-actions">
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary preview-button" title="Quick Preview">
|
||||||
|
<i class="bx bx-show"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="source-preview mt-2 p-2 border-top" style="display: none; font-size: 0.85rem;"></div>`;
|
||||||
|
|
||||||
|
// Keep the click handler for better UX - this ensures the note opens in the right context
|
||||||
sourceElement.querySelector('.source-link')?.addEventListener('click', (e) => {
|
sourceElement.querySelector('.source-link')?.addEventListener('click', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
appContext.tabManager.openTabWithNoteWithHoisting(source.noteId);
|
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 = '<div class="text-center"><i class="bx bx-loader-alt bx-spin"></i> Loading preview...</div>';
|
||||||
|
|
||||||
|
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 = `<div class="font-italic">${previewContent}</div>`;
|
||||||
|
} catch (error) {
|
||||||
|
previewElement.innerHTML = '<div class="text-danger">Error loading preview</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Hide preview
|
||||||
|
previewElement.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.sourcesList.appendChild(sourceElement);
|
this.sourcesList.appendChild(sourceElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user