diff --git a/CLAUDE.md b/CLAUDE.md index a6d3712a..98ccc331 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,7 +26,7 @@ When user says "COM": 1. Increment version in BOTH `package.json` AND `CLAUDE.md` (verify they match with `grep version package.json && grep Version CLAUDE.md`) 2. Run: `git add -A && git commit -m "chore: bump version to X.XXXX" && git push && npm run build && systemctl --user restart claudeman-web` -**Version**: 0.1479 (must match `package.json` for npm publish) +**Version**: 0.1480 (must match `package.json` for npm publish) ## Project Overview diff --git a/package.json b/package.json index 8801d5f1..28f6aed1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claudeman", - "version": "0.1479", + "version": "0.1480", "description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence", "type": "module", "main": "dist/index.js", diff --git a/src/web/public/app.js b/src/web/public/app.js index ca263875..06d652ef 100644 --- a/src/web/public/app.js +++ b/src/web/public/app.js @@ -12004,7 +12004,8 @@ class ClaudemanApp { ` : ''; - const windowTitle = agent.description || agentId.substring(0, 7); + const teammateInfo = this.getTeammateInfo(agent); + const windowTitle = teammateInfo ? teammateInfo.name : (agent.description || agentId.substring(0, 7)); const truncatedTitle = windowTitle.length > 50 ? windowTitle.substring(0, 50) + '...' : windowTitle; const modelBadge = agent.modelShort ? `${agent.modelShort}` @@ -12282,6 +12283,13 @@ class ClaudemanApp { this.activeFocusTrap = null; } + // Clean up team tasks panel drag listeners + if (this.teamTasksDragListeners) { + document.removeEventListener('mousemove', this.teamTasksDragListeners.move); + document.removeEventListener('mouseup', this.teamTasksDragListeners.up); + this.teamTasksDragListeners = null; + } + // Clear minimized agents tracking this.minimizedSubagents.clear(); @@ -12585,7 +12593,23 @@ class ClaudemanApp { return; } - panel.style.display = ''; + // Set initial position and make draggable on first show + const wasHidden = panel.style.display === 'none'; + panel.style.display = 'flex'; + + if (wasHidden && !this.teamTasksDragListeners) { + // Position bottom-right + const panelWidth = 360; + const panelHeight = 300; + panel.style.left = `${Math.max(10, window.innerWidth - panelWidth - 20)}px`; + panel.style.top = `${Math.max(10, window.innerHeight - panelHeight - 70)}px`; + // Make draggable + const header = panel.querySelector('.team-tasks-header'); + if (header) { + this.teamTasksDragListeners = this.makeWindowDraggable(panel, header); + } + } + const tasks = this.teamTasks.get(activeTeamName) || []; const completed = tasks.filter(t => t.status === 'completed').length; const total = tasks.length; @@ -12631,6 +12655,17 @@ class ClaudemanApp { listEl.innerHTML = html; } + /** Hide team tasks panel and clean up drag listeners */ + hideTeamTasksPanel() { + const panel = document.getElementById('teamTasksPanel'); + if (panel) panel.style.display = 'none'; + if (this.teamTasksDragListeners) { + document.removeEventListener('mousemove', this.teamTasksDragListeners.move); + document.removeEventListener('mouseup', this.teamTasksDragListeners.up); + this.teamTasksDragListeners = null; + } + } + /** Get teammate color by name */ getTeammateColor(name) { const info = this.teammateMap.get(name); diff --git a/src/web/public/index.html b/src/web/public/index.html index 2dcc8690..9990ecb0 100644 --- a/src/web/public/index.html +++ b/src/web/public/index.html @@ -435,6 +435,7 @@ 0/0 +
diff --git a/src/web/public/styles.css b/src/web/public/styles.css index bf408e8f..08baf11d 100644 --- a/src/web/public/styles.css +++ b/src/web/public/styles.css @@ -5530,17 +5530,34 @@ kbd { /* Team Tasks Panel */ .team-tasks-panel { position: fixed; - bottom: 50px; - right: 10px; - width: 320px; - max-height: 300px; - background: var(--bg-secondary); + width: 360px; + min-width: 260px; + min-height: 120px; + max-width: 90vw; + max-height: 80vh; + background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); z-index: 900; overflow: hidden; font-size: 12px; + display: flex; + flex-direction: column; + resize: both; +} + +/* Resize handle indicator */ +.team-tasks-panel::after { + content: ''; + position: absolute; + bottom: 4px; + right: 4px; + width: 12px; + height: 12px; + background: linear-gradient(135deg, transparent 50%, var(--border-light) 50%, var(--border-light) 60%, transparent 60%, transparent 70%, var(--border-light) 70%, var(--border-light) 80%, transparent 80%); + pointer-events: none; + opacity: 0.6; } .team-tasks-header { @@ -5548,8 +5565,24 @@ kbd { align-items: center; justify-content: space-between; padding: 8px 12px; - background: var(--bg-tertiary); + background: var(--bg-input); border-bottom: 1px solid var(--border); + cursor: move; + gap: 8px; +} + +.team-tasks-close { + background: transparent; + border: none; + color: var(--text-muted); + cursor: pointer; + padding: 0.2rem 0.4rem; + font-size: 0.9rem; + flex-shrink: 0; +} + +.team-tasks-close:hover { + color: var(--text); } .team-tasks-header-text { @@ -5585,7 +5618,8 @@ kbd { .team-tasks-list { overflow-y: auto; - max-height: 250px; + flex: 1; + min-height: 0; padding: 4px 0; }