feat: Gravity Web Phase 1 - CDP remote control dashboard
This commit is contained in:
91
public/js/session-panel.js
Normal file
91
public/js/session-panel.js
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Session Panel — 세션 목록 UI 관리
|
||||
*/
|
||||
|
||||
class SessionPanel {
|
||||
constructor() {
|
||||
this.sessions = [];
|
||||
this.activeSessionId = null;
|
||||
this.onSessionSelect = null; // callback(sessionId)
|
||||
this.onSessionRemove = null; // callback(sessionId)
|
||||
|
||||
this.listEl = document.getElementById('sessionList');
|
||||
}
|
||||
|
||||
/**
|
||||
* 세션 목록 업데이트
|
||||
*/
|
||||
update(sessions) {
|
||||
this.sessions = sessions;
|
||||
this.render();
|
||||
}
|
||||
|
||||
/**
|
||||
* 활성 세션 설정
|
||||
*/
|
||||
setActive(sessionId) {
|
||||
this.activeSessionId = sessionId;
|
||||
this.render();
|
||||
}
|
||||
|
||||
/**
|
||||
* 세션 목록 렌더링
|
||||
*/
|
||||
render() {
|
||||
if (!this.listEl) return;
|
||||
|
||||
if (this.sessions.length === 0) {
|
||||
this.listEl.innerHTML = `
|
||||
<div style="padding: 20px; text-align: center; color: var(--text-muted); font-size: 12px;">
|
||||
세션이 없습니다<br>+ 버튼으로 추가하세요
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
this.listEl.innerHTML = this.sessions.map(s => `
|
||||
<div class="session-card ${s.id === this.activeSessionId ? 'active' : ''}"
|
||||
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.host}:${s.cdpPort} · ${this._statusText(s.status)}</div>
|
||||
</div>
|
||||
<button class="session-remove" data-remove-id="${s.id}" title="세션 제거">✕</button>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
// 이벤트 바인딩
|
||||
this.listEl.querySelectorAll('.session-card').forEach(card => {
|
||||
card.addEventListener('click', (e) => {
|
||||
if (e.target.closest('.session-remove')) return;
|
||||
const id = card.dataset.sessionId;
|
||||
if (this.onSessionSelect) this.onSessionSelect(id);
|
||||
});
|
||||
});
|
||||
|
||||
this.listEl.querySelectorAll('.session-remove').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const id = btn.dataset.removeId;
|
||||
if (this.onSessionRemove) this.onSessionRemove(id);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_statusText(status) {
|
||||
const map = {
|
||||
connected: '연결됨',
|
||||
connecting: '연결 중...',
|
||||
disconnected: '연결 끊김',
|
||||
error: '오류',
|
||||
};
|
||||
return map[status] || status;
|
||||
}
|
||||
|
||||
_escapeHtml(str) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = str;
|
||||
return div.innerHTML;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user