fix: OWUI hover-delete on saved-chat rows (row click opens, trash icon deletes)
This commit is contained in:
parent
da86c7db79
commit
cc9188fa08
3 changed files with 46 additions and 0 deletions
|
|
@ -219,3 +219,7 @@ body.assistant-workspace .assistant-learning-view { min-height: 0; height: 100vh
|
|||
/* Saved chats occupy the full left rail and scroll inside it */
|
||||
.assistant-history { display:flex; flex-direction:column; height:100%; min-height:0; }
|
||||
.assistant-history .card { flex:1 1 auto; display:flex; flex-direction:column; min-height:0; overflow:hidden; }
|
||||
.assistant-saved-chat { position:relative; }
|
||||
.assistant-saved-chat-delete { position:absolute; top:6px; right:8px; display:flex; align-items:center; justify-content:center; width:24px; height:24px; border-radius:6px; color:var(--g500, #6b7280); opacity:0; transition:opacity .12s ease; pointer-events:none; }
|
||||
.assistant-saved-chat:hover .assistant-saved-chat-delete, .assistant-saved-chat:focus-within .assistant-saved-chat-delete { opacity:1; pointer-events:auto; }
|
||||
.assistant-saved-chat-delete:hover { color:var(--danger, #dc2626); background:rgba(220,38,38,.08); }
|
||||
|
|
|
|||
|
|
@ -861,6 +861,13 @@ import {
|
|||
renderAttachments();
|
||||
return;
|
||||
}
|
||||
var deleteBtn = e.target.closest('[data-assistant-delete-chat]');
|
||||
if (deleteBtn) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
deleteSavedChat(deleteBtn.getAttribute('data-assistant-delete-chat'));
|
||||
return;
|
||||
}
|
||||
var loadBtn = e.target.closest('[data-assistant-load-chat]');
|
||||
if (loadBtn) {
|
||||
e.preventDefault();
|
||||
|
|
@ -1495,13 +1502,29 @@ import {
|
|||
}
|
||||
// Open WebUI behavior: the whole row opens the chat — no Load/Delete buttons.
|
||||
wrap.innerHTML = chats.map(function (chat) {
|
||||
// Open WebUI behavior: the row opens the chat; a hover trash icon deletes it.
|
||||
return '<button type="button" class="assistant-saved-chat" data-assistant-load-chat="' + escapeAttr(chat.id) + '" aria-label="Open saved chat">' +
|
||||
'<span class="assistant-saved-chat-title">' + escapeHtml(chat.title || 'Saved chat') + '</span>' +
|
||||
'<span class="assistant-saved-chat-meta">' + escapeHtml(formatSavedDate(chat.updated_at || chat.created_at)) + '</span>' +
|
||||
'<span class="assistant-saved-chat-delete" role="button" tabindex="0" data-assistant-delete-chat="' + escapeAttr(chat.id) + '" aria-label="Delete saved chat" title="Delete chat"><i class="fas fa-trash"></i></span>' +
|
||||
'</button>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function deleteSavedChat(id) {
|
||||
if (assistantBusy) return;
|
||||
return deleteSavedAssistantChat(id)
|
||||
.then(function (data) {
|
||||
if (!data.success) throw new Error(data.error || 'Delete failed');
|
||||
if (String(currentChatId) === String(id)) performClearConversation();
|
||||
loadSavedChats();
|
||||
if (typeof showToast === 'function') showToast('Chat deleted', 'success');
|
||||
})
|
||||
.catch(function (err) {
|
||||
if (typeof showToast === 'function') showToast(err.message, 'error');
|
||||
});
|
||||
}
|
||||
|
||||
function loadSavedChat(id) {
|
||||
if (assistantBusy) return;
|
||||
setBusy(true, 'Loading chat...');
|
||||
|
|
|
|||
|
|
@ -85,6 +85,25 @@ test('regenerate replays the preceding question for the latest answer and never
|
|||
assert.match(all[all.length - 1].textContent, /Regenerated answer/);
|
||||
});
|
||||
|
||||
test('saved-chat rows open on click; the hover trash deletes without opening', async t => {
|
||||
const app = ui(t);
|
||||
const c = app.context;
|
||||
c.fetchSavedAssistantChats = async () => ({ success: true, chats: [{ id: 7, title: 'Stored chat', updated_at: new Date().toISOString() }] });
|
||||
c.fetchSavedAssistantChat = async id => ({ success: true, chat: { id: id, title: 'Stored chat', payload: { version: 2, messages: [], sources: [], lastAnswer: '' } } });
|
||||
await c.loadSavedChats();
|
||||
const row = app.document.querySelector('[data-assistant-load-chat="7"]');
|
||||
assert.ok(row, 'row rendered as the click target');
|
||||
assert.ok(row.querySelector('[data-assistant-delete-chat="7"]'), 'hover delete icon present');
|
||||
row.click();
|
||||
await new Promise(r => setImmediate(r)); await new Promise(r => setImmediate(r));
|
||||
assert.equal(String(c.currentChatId), '7', 'row click opens the chat');
|
||||
const deleted = [];
|
||||
app.context.deleteSavedAssistantChat = async id => { deleted.push(id); return { success: true }; };
|
||||
row.querySelector('[data-assistant-delete-chat="7"]').click();
|
||||
await new Promise(r => setImmediate(r));
|
||||
assert.deepEqual(deleted, ['7'], 'delete icon deletes');
|
||||
});
|
||||
|
||||
test('regenerate on a non-latest answer refuses honestly without touching the chat', t => {
|
||||
const app = ui(t);
|
||||
const c = app.context;
|
||||
|
|
|
|||
Loading…
Reference in a new issue