feat: Nachrichten als wichtig markieren (Stern-Button)
- MessageRecord: neues Property IsMarked
- DatabaseService: Migration is_marked, ToggleMessageMark(), GetMarkedMessages()
- HistoryEndpoint: PUT /api/messages/{id}/mark (Toggle)
- SystemPromptBuilder: markierte Nachrichten als Referenz im System-Prompt
- ChatEndpoint + SessionEndpoint: markierte Nachrichten laden und an Builder übergeben
- Frontend: Stern-Button (☆/★) auf jeder Nachricht, Toggle per API
- CSS: .marked-Klasse mit gelbem Seitenrand, Button-Styling
This commit is contained in:
1 parent
21ca3a451b
commit
19f32442b1
11 files changed
+124
-13
No files matched your search
@@ -131,6 +131,11 @@ async function apiGetChain(chainId) {
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiToggleMessageMark(messageId) {
|
||||
const resp = await fetch(`/api/messages/${messageId}/mark`, { method: 'PUT' });
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
async function apiGitStatus(sessionId) {
|
||||
const resp = await fetch(`/api/sessions/${sessionId}/git-status`);
|
||||
if (!resp.ok) return null;
|
||||
|
||||
@@ -35,11 +35,11 @@ function renderMessages(msgs, addToConversation) {
|
||||
switch (msg.type) {
|
||||
case 'text':
|
||||
if (msg.role === 'user') {
|
||||
addUserBubble(msg.content, false, msg.createdAt);
|
||||
addUserBubble(msg.content, false, msg.createdAt, msg.id, msg.isMarked);
|
||||
if (msg.attachmentCount > 0) addAttachmentIndicator(msg.id, msg.attachmentCount, msg.attachmentNames);
|
||||
if (addToConversation) messages.push({ role: 'user', content: msg.content });
|
||||
} else if (msg.role === 'assistant') {
|
||||
addAssistantBubble(msg.content, msg.createdAt);
|
||||
addAssistantBubble(msg.content, msg.createdAt, msg.id, msg.isMarked);
|
||||
if (addToConversation) messages.push({ role: 'assistant', content: msg.content });
|
||||
}
|
||||
break;
|
||||
|
||||
+30
-4
@@ -33,6 +33,28 @@ function truncate(s, max) {
|
||||
return s && s.length > max ? s.substring(0, max) + '...' : (s || '');
|
||||
}
|
||||
|
||||
// ── Mark Button ──
|
||||
|
||||
function _addMarkButton(div, messageId, isMarked) {
|
||||
if (!messageId) return; // kein DB-Eintrag → kein Button
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'msg-mark-btn icon-btn' + (isMarked ? ' marked' : '');
|
||||
btn.innerHTML = isMarked ? '<i class="fa fa-star"></i>' : '<i class="fa fa-star-o"></i>';
|
||||
btn.title = 'Als wichtig markieren';
|
||||
btn.addEventListener('click', async (e) => {
|
||||
e.stopPropagation();
|
||||
try {
|
||||
const result = await apiToggleMessageMark(messageId);
|
||||
btn.classList.toggle('marked', result.isMarked);
|
||||
btn.innerHTML = result.isMarked ? '<i class="fa fa-star"></i>' : '<i class="fa fa-star-o"></i>';
|
||||
div.classList.toggle('marked', result.isMarked);
|
||||
} catch (err) {
|
||||
console.error('Mark toggle failed:', err);
|
||||
}
|
||||
});
|
||||
div.prepend(btn);
|
||||
}
|
||||
|
||||
// ── Reply Button ──
|
||||
|
||||
function _addReplyButton(div) {
|
||||
@@ -129,25 +151,29 @@ function _renderUserTextContent(container, raw) {
|
||||
container.appendChild(frag);
|
||||
}
|
||||
|
||||
function addUserBubble(text, streamed = false, timestamp = '') {
|
||||
function addUserBubble(text, streamed = false, timestamp = '', messageId = null, isMarked = false) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'msg user';
|
||||
div.className = 'msg user' + (isMarked ? ' marked' : '');
|
||||
div.dataset.role = 'user';
|
||||
div.dataset.timestamp = timestamp || new Date().toISOString();
|
||||
if (messageId) div.dataset.messageId = messageId;
|
||||
if (streamed) div.classList.add('streamed');
|
||||
renderUserContent(div, text);
|
||||
_addReplyButton(div);
|
||||
_addMarkButton(div, messageId, isMarked);
|
||||
chatEl().appendChild(div);
|
||||
scrollDown();
|
||||
}
|
||||
|
||||
function addAssistantBubble(text, timestamp = '') {
|
||||
function addAssistantBubble(text, timestamp = '', messageId = null, isMarked = false) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'msg assistant markdown';
|
||||
div.className = 'msg assistant markdown' + (isMarked ? ' marked' : '');
|
||||
div.dataset.role = 'assistant';
|
||||
div.dataset.timestamp = timestamp || new Date().toISOString();
|
||||
if (messageId) div.dataset.messageId = messageId;
|
||||
div.innerHTML = renderMarkdown(text);
|
||||
_addReplyButton(div);
|
||||
_addMarkButton(div, messageId, isMarked);
|
||||
chatEl().appendChild(div);
|
||||
scrollDown();
|
||||
return div;
|
||||
|
||||
Reference in new issue
Block a user