Add git widget to session cards in dashboard
This commit is contained in:
parent
599f911964
commit
ae0251b6d3
1 changed files with 151 additions and 0 deletions
|
|
@ -500,6 +500,69 @@
|
|||
font-size: 11px;
|
||||
}
|
||||
|
||||
.git-line {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.git-icon {
|
||||
margin-right: 4px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.git-additions {
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.git-deletions {
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.git-file {
|
||||
font-family: monospace;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
.git-file-modified {
|
||||
color: #ff9800;
|
||||
}
|
||||
|
||||
.git-file-added {
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.git-file-deleted {
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.git-file-untracked {
|
||||
color: #9e9e9e;
|
||||
}
|
||||
|
||||
.git-files {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.git-files summary {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.git-files summary:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.git-file-list {
|
||||
margin-top: 4px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.git-file-more {
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
padding: 32px 16px;
|
||||
text-align: center;
|
||||
|
|
@ -696,6 +759,8 @@
|
|||
mode: 'normal',
|
||||
model: null,
|
||||
idle_since: null,
|
||||
git_branch: null,
|
||||
git_files_json: null,
|
||||
});
|
||||
renderSessions();
|
||||
});
|
||||
|
|
@ -758,6 +823,16 @@
|
|||
}
|
||||
});
|
||||
|
||||
es.addEventListener('git', (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
const session = state.sessions.get(data.session_id);
|
||||
if (session) {
|
||||
session.git_branch = data.branch;
|
||||
session.git_files_json = data.files_json;
|
||||
updateStatsWidget(data.session_id);
|
||||
}
|
||||
});
|
||||
|
||||
state.eventSource = es;
|
||||
}
|
||||
|
||||
|
|
@ -790,6 +865,14 @@
|
|||
return `${Math.floor(seconds / 3600)}h`;
|
||||
}
|
||||
|
||||
function getFileClass(status) {
|
||||
if (status === 'M') return 'git-file-modified';
|
||||
if (status === 'A') return 'git-file-added';
|
||||
if (status === 'D') return 'git-file-deleted';
|
||||
if (status === '??') return 'git-file-untracked';
|
||||
return '';
|
||||
}
|
||||
|
||||
function renderStatsWidget(session) {
|
||||
const lines = [];
|
||||
|
||||
|
|
@ -831,6 +914,74 @@
|
|||
lines.push(`<div class="stats-line">${badges.join(' ')}</div>`);
|
||||
}
|
||||
|
||||
// Git info
|
||||
if (session.git_branch || session.git_files_json) {
|
||||
const gitParts = [];
|
||||
let files = [];
|
||||
let totalAdditions = 0;
|
||||
let totalDeletions = 0;
|
||||
|
||||
// Parse files if available
|
||||
if (session.git_files_json) {
|
||||
try {
|
||||
files = JSON.parse(session.git_files_json);
|
||||
files.forEach(f => {
|
||||
totalAdditions += f.additions || 0;
|
||||
totalDeletions += f.deletions || 0;
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Failed to parse git files JSON:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Build git summary line
|
||||
if (session.git_branch) {
|
||||
gitParts.push(`<span class="git-icon">⎇</span>`);
|
||||
gitParts.push(`<span class="stats-value">${escapeHtml(session.git_branch)}</span>`);
|
||||
}
|
||||
|
||||
if (files.length > 0) {
|
||||
gitParts.push(`| <span class="stats-value">${files.length}</span> file${files.length === 1 ? '' : 's'}`);
|
||||
}
|
||||
|
||||
if (totalAdditions > 0) {
|
||||
gitParts.push(`| <span class="git-additions">+${totalAdditions}</span>`);
|
||||
}
|
||||
|
||||
if (totalDeletions > 0) {
|
||||
gitParts.push(`| <span class="git-deletions">-${totalDeletions}</span>`);
|
||||
}
|
||||
|
||||
if (gitParts.length > 0) {
|
||||
let gitLine = `<div class="stats-line git-line">${gitParts.join(' ')}</div>`;
|
||||
|
||||
// Add collapsible file list if there are files
|
||||
if (files.length > 0) {
|
||||
const fileListItems = files.slice(0, 10).map(f => {
|
||||
const filePath = escapeHtml(f.path);
|
||||
const fileClass = getFileClass(f.status);
|
||||
const additions = f.additions ? `<span class="git-additions">+${f.additions}</span>` : '';
|
||||
const deletions = f.deletions ? `<span class="git-deletions">-${f.deletions}</span>` : '';
|
||||
return `<div class="git-file ${fileClass}">${escapeHtml(f.status)} ${filePath} ${additions} ${deletions}</div>`;
|
||||
}).join('');
|
||||
|
||||
const moreText = files.length > 10 ? `<div class="git-file-more">and ${files.length - 10} more...</div>` : '';
|
||||
|
||||
gitLine += `
|
||||
<details class="git-files">
|
||||
<summary>${files.length} changed file${files.length === 1 ? '' : 's'}</summary>
|
||||
<div class="git-file-list">
|
||||
${fileListItems}
|
||||
${moreText}
|
||||
</div>
|
||||
</details>
|
||||
`;
|
||||
}
|
||||
|
||||
lines.push(gitLine);
|
||||
}
|
||||
}
|
||||
|
||||
if (lines.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue