Dashboard: Card-Menü für Sessions und Agents

- Session-Cards: Menü mit 'Chat öffnen' und 'Bearbeiten'
- Agent-Cards: Menü mit 'Bearbeiten'
- Drei-Punkte-Trigger (ellipsis-v) erscheint bei Hover
- Click-outside schließt offene Menüs
- Card overflow auf visible geändert für Dropdown-Anzeige
This commit is contained in:
Meleki committed 2026-03-01 11:18:12 +01:00
1 parent 5037c7d24e
commit 92b1c8a9bc
2 files changed
+126 -4

No files matched your search

+63 -3
View File
@@ -2,6 +2,9 @@
registerPage('dashboard', {
async init() {
// Globaler Click-Handler zum Schließen aller Card-Menüs
document.addEventListener('click', this._closeCardMenus = () => closeAllCardMenus());
const agents = await apiGetAgents();
const agentMap = {};
for (const a of agents) agentMap[a.agentId] = a;
@@ -33,8 +36,35 @@ registerPage('dashboard', {
${workspaceLabel ? `<span class="card-meta-item card-workspace" title="${esc(workspaceLabel)}"><i class="fa fa-folder"></i> ${esc(workspaceLabel)}</span>` : ''}
</div>
</div>
<div class="card-menu">
<button class="card-menu-trigger icon-btn"><i class="fa fa-ellipsis-v"></i></button>
<div class="card-menu-dropdown" hidden>
<button class="card-menu-item" data-action="chat">Chat öffnen</button>
<button class="card-menu-item" data-action="edit">Bearbeiten</button>
</div>
</div>
`;
card.addEventListener('click', () => navigateTo('session', { id: s.sessionId }));
card.addEventListener('click', (e) => {
if (e.target.closest('.card-menu')) return;
navigateTo('session', { id: s.sessionId });
});
const menuTrigger = card.querySelector('.card-menu-trigger');
const menuDropdown = card.querySelector('.card-menu-dropdown');
menuTrigger.addEventListener('click', (e) => {
e.stopPropagation();
closeAllCardMenus();
menuDropdown.hidden = !menuDropdown.hidden;
});
menuDropdown.querySelector('[data-action="chat"]').addEventListener('click', (e) => {
e.stopPropagation();
menuDropdown.hidden = true;
navigateTo('chat', { id: s.sessionId });
});
menuDropdown.querySelector('[data-action="edit"]').addEventListener('click', (e) => {
e.stopPropagation();
menuDropdown.hidden = true;
navigateTo('session', { id: s.sessionId });
});
grid.appendChild(card);
// Git-Status asynchron laden
@@ -100,8 +130,29 @@ registerPage('dashboard', {
${a.description ? `<div class="card-desc">${esc(a.description)}</div>` : ''}
${a.persona ? `<div class="card-meta"><span class="card-meta-item card-persona"><i class="fa fa-user-secret"></i> ${esc(a.persona)}</span></div>` : ''}
</div>
<div class="card-menu">
<button class="card-menu-trigger icon-btn"><i class="fa fa-ellipsis-v"></i></button>
<div class="card-menu-dropdown" hidden>
<button class="card-menu-item" data-action="edit">Bearbeiten</button>
</div>
</div>
`;
card.addEventListener('click', () => navigateTo('agent', { id: a.agentId }));
card.addEventListener('click', (e) => {
if (e.target.closest('.card-menu')) return;
navigateTo('agent', { id: a.agentId });
});
const menuTrigger = card.querySelector('.card-menu-trigger');
const menuDropdown = card.querySelector('.card-menu-dropdown');
menuTrigger.addEventListener('click', (e) => {
e.stopPropagation();
closeAllCardMenus();
menuDropdown.hidden = !menuDropdown.hidden;
});
menuDropdown.querySelector('[data-action="edit"]').addEventListener('click', (e) => {
e.stopPropagation();
menuDropdown.hidden = true;
navigateTo('agent', { id: a.agentId });
});
agentGrid.appendChild(card);
}
@@ -111,9 +162,18 @@ registerPage('dashboard', {
placeholder.addEventListener('click', () => navigateTo('agent'));
document.getElementById('newAgentCard').appendChild(placeholder);
},
destroy() {}
destroy() {
if (this._closeCardMenus) {
document.removeEventListener('click', this._closeCardMenus);
this._closeCardMenus = null;
}
}
});
function closeAllCardMenus() {
document.querySelectorAll('.card-menu-dropdown').forEach(d => d.hidden = true);
}
function esc(s) {
const d = document.createElement('div');
d.textContent = s;