feat(ui): session identification — project badges, relative time, running indicator

This commit is contained in:
2026-03-08 00:11:29 +09:00
parent 808eb66849
commit db70840b7a
3 changed files with 112 additions and 18 deletions

View File

@@ -43,17 +43,28 @@ class SessionPanel {
return;
}
this.listEl.innerHTML = this.sessions.map(s => `
<div class="session-card ${s.id === this.activeSessionId ? 'active' : ''}"
this.listEl.innerHTML = this.sessions.map(s => {
const timeStr = s.lastModified ? this._relativeTime(s.lastModified) : '';
const projectBadge = s.project
? `<span class="session-project" style="background:${this._projectColor(s.project)}">${this._escapeHtml(s.project)}</span>`
: '';
const runningDot = s.isRunning ? '<span class="running-dot">●</span>' : '';
const detail = s.isBridge
? `${s.stepCount || 0} steps${timeStr ? ' · ' + timeStr : ''}`
: `${s.host}:${s.cdpPort} · ${this._statusText(s.status)}`;
return `
<div class="session-card ${s.id === this.activeSessionId ? 'active' : ''} ${s.isRunning ? 'is-running' : ''}"
data-session-id="${s.id}">
<div class="session-indicator ${s.status}"></div>
<div class="session-info">
<div class="session-name">${this._escapeHtml(s.name)}</div>
<div class="session-detail">${s.isBridge ? `${s.stepCount || 0} steps · 대화` : `${s.host}:${s.cdpPort} · ${this._statusText(s.status)}`}</div>
<div class="session-name">${runningDot}${this._escapeHtml(s.name)}</div>
<div class="session-detail">${projectBadge}${detail}</div>
</div>
<button class="session-remove" data-remove-id="${s.id}" title="세션 제거">✕</button>
</div>
`).join('');
`;
}).join('');
// 이벤트 바인딩
this.listEl.querySelectorAll('.session-card').forEach(card => {
@@ -78,11 +89,34 @@ class SessionPanel {
connected: '연결됨',
connecting: '연결 중...',
disconnected: '연결 끊김',
running: '실행 중',
error: '오류',
};
return map[status] || status;
}
_relativeTime(iso) {
const diff = Date.now() - new Date(iso).getTime();
const mins = Math.floor(diff / 60000);
if (mins < 1) return '방금';
if (mins < 60) return `${mins}분 전`;
const hrs = Math.floor(mins / 60);
if (hrs < 24) return `${hrs}시간 전`;
const days = Math.floor(hrs / 24);
return `${days}일 전`;
}
_projectColor(name) {
const colors = {
'gravity_web': '#6366f1',
'Deriva': '#f59e0b',
'MMF': '#10b981',
'test1': '#8b5cf6',
'test2': '#ec4899',
};
return colors[name] || '#64748b';
}
_escapeHtml(str) {
const div = document.createElement('div');
div.textContent = str;