Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/frontend/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -1658,6 +1658,19 @@ function renderSettings(container) {
html += '<p style="font-size:12px;color:var(--text-muted);margin:10px 0 0">Applies to grouped session views like All Sessions and Claude Code. Projects always stay repository-based.</p>';
html += '</div>';

// Message Sort Order
var savedMsgSort = localStorage.getItem('codedash-msg-sort') || 'asc';
html += '<div class="settings-group">';
html += '<label class="settings-label">Message Sort Order</label>';
html += '<p style="font-size:12px;color:var(--text-muted);margin:0 0 8px">Default order for messages in session drawer</p>';
html += '<div class="settings-theme-btns">';
[['asc', '&#8593; Oldest first'], ['desc', '&#8595; Newest first']].forEach(function(pair) {
var active = savedMsgSort === pair[0] ? ' active' : '';
html += '<button class="theme-btn' + active + '" onclick="localStorage.setItem(\'codedash-msg-sort\',\'' + pair[0] + '\');renderSettings(document.getElementById(\'content\'))">' + pair[1] + '</button>';
});
html += '</div>';
html += '</div>';

// LLM Configuration
html += '<div class="settings-group">';
html += '<label class="settings-label">LLM Configuration</label>';
Expand Down
68 changes: 44 additions & 24 deletions src/frontend/detail.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,30 +101,8 @@ async function openDetail(s) {
var data = await resp.json();
var msgContainer = body.querySelector('.detail-messages');
if (data.messages && data.messages.length > 0) {
var msgsHtml = '<h3>Conversation</h3>';
data.messages.forEach(function(m) {
var roleClass = m.role === 'user' ? 'msg-user' : 'msg-assistant';
var roleLabel = m.role === 'user' ? 'You' : 'Assistant';
var hasTools = m.tools && m.tools.length > 0;
msgsHtml += '<div class="message ' + roleClass + (hasTools ? ' has-tools' : '') + '">';
msgsHtml += '<div class="msg-inner">';
msgsHtml += '<div class="msg-role">' + roleLabel + '</div>';
msgsHtml += '<div class="msg-content">' + escHtml(m.content) + '</div>';
msgsHtml += '</div>';
if (hasTools) {
msgsHtml += '<div class="msg-tools">';
m.tools.forEach(function(t) {
if (t.type === 'mcp') {
msgsHtml += '<span class="tool-badge badge-mcp">' + escHtml(t.tool) + '</span>';
} else if (t.type === 'skill') {
msgsHtml += '<span class="tool-badge badge-skill">' + escHtml(t.skill) + '</span>';
}
});
msgsHtml += '</div>';
}
msgsHtml += '</div>';
});
msgContainer.innerHTML = msgsHtml;
window._detailMessages = data.messages;
renderDetailMessages(msgContainer, data.messages);
} else {
msgContainer.innerHTML = '<div class="empty-state">No messages found in detail file.</div>';
}
Expand Down Expand Up @@ -206,6 +184,48 @@ function closeDetail() {
if (overlay) overlay.classList.remove('open');
}

function renderDetailMessages(container, messages) {
var sort = localStorage.getItem('codedash-msg-sort') || 'asc';
var sorted = sort === 'desc' ? messages.slice().reverse() : messages;
var btnLabel = sort === 'asc' ? '&#8593; Oldest first' : '&#8595; Newest first';
var msgsHtml = '<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px">';
msgsHtml += '<h3 style="margin:0">Conversation</h3>';
msgsHtml += '<button class="theme-btn" onclick="toggleMsgSort()" title="Toggle sort order" style="font-size:11px;padding:3px 10px">' + btnLabel + '</button>';
msgsHtml += '</div>';
sorted.forEach(function(m) {
var roleClass = m.role === 'user' ? 'msg-user' : 'msg-assistant';
var roleLabel = m.role === 'user' ? 'You' : 'Assistant';
var hasTools = m.tools && m.tools.length > 0;
msgsHtml += '<div class="message ' + roleClass + (hasTools ? ' has-tools' : '') + '">';
msgsHtml += '<div class="msg-inner">';
msgsHtml += '<div class="msg-role">' + roleLabel + '</div>';
msgsHtml += '<div class="msg-content">' + escHtml(m.content) + '</div>';
msgsHtml += '</div>';
if (hasTools) {
msgsHtml += '<div class="msg-tools">';
m.tools.forEach(function(t) {
if (t.type === 'mcp') {
msgsHtml += '<span class="tool-badge badge-mcp">' + escHtml(t.tool) + '</span>';
} else if (t.type === 'skill') {
msgsHtml += '<span class="tool-badge badge-skill">' + escHtml(t.skill) + '</span>';
}
});
msgsHtml += '</div>';
}
msgsHtml += '</div>';
});
container.innerHTML = msgsHtml;
}

function toggleMsgSort() {
var current = localStorage.getItem('codedash-msg-sort') || 'asc';
localStorage.setItem('codedash-msg-sort', current === 'asc' ? 'desc' : 'asc');
var container = document.querySelector('.detail-messages');
if (container && window._detailMessages) {
renderDetailMessages(container, window._detailMessages);
}
}

// ── Detail panel resize ───────────────────────────────────────
(function initDetailResize() {
var handle = document.getElementById('detailResizeHandle');
Expand Down
Loading