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:
1 parent
5037c7d24e
commit
92b1c8a9bc
2 files changed
+126
-4
No files matched your search
@@ -21,11 +21,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
|
position: relative;
|
||||||
background: var(--f3-bg);
|
background: var(--f3-bg);
|
||||||
border: var(--border-width) solid var(--f3-border);
|
border: var(--border-width) solid var(--f3-border);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: visible;
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
background: var(--f2-bg);
|
background: var(--f2-bg);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
border-radius: var(--border-radius) var(--border-radius) 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-image img {
|
.card-image img {
|
||||||
@@ -99,6 +101,66 @@
|
|||||||
padding: var(--button-padding);
|
padding: var(--button-padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Card Menu */
|
||||||
|
|
||||||
|
.card-menu {
|
||||||
|
position: absolute;
|
||||||
|
top: var(--badge-spacing);
|
||||||
|
right: var(--badge-spacing);
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-menu-trigger {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity .15s;
|
||||||
|
padding: .15em .45em;
|
||||||
|
font-size: var(--font-size);
|
||||||
|
background: var(--f3-bg);
|
||||||
|
border: var(--border-width) solid var(--f3-border);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover .card-menu-trigger {
|
||||||
|
opacity: var(--semi-transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-menu-trigger:hover {
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-menu-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
margin-top: .3em;
|
||||||
|
background: var(--f3-bg);
|
||||||
|
border: var(--border-width) solid var(--f3-border);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
min-width: 10em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-block: calc(var(--badge-spacing) / 2) var(--badge-spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-menu-dropdown[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-menu-item {
|
||||||
|
border: none;
|
||||||
|
border-radius: unset;
|
||||||
|
text-align: left;
|
||||||
|
padding: var(--menu-item-padding);
|
||||||
|
background: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-menu-item:not(:disabled):hover {
|
||||||
|
background: var(--f2-bg);
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
.card-meta {
|
.card-meta {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
registerPage('dashboard', {
|
registerPage('dashboard', {
|
||||||
async init() {
|
async init() {
|
||||||
|
// Globaler Click-Handler zum Schließen aller Card-Menüs
|
||||||
|
document.addEventListener('click', this._closeCardMenus = () => closeAllCardMenus());
|
||||||
|
|
||||||
const agents = await apiGetAgents();
|
const agents = await apiGetAgents();
|
||||||
const agentMap = {};
|
const agentMap = {};
|
||||||
for (const a of agents) agentMap[a.agentId] = a;
|
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>` : ''}
|
${workspaceLabel ? `<span class="card-meta-item card-workspace" title="${esc(workspaceLabel)}"><i class="fa fa-folder"></i> ${esc(workspaceLabel)}</span>` : ''}
|
||||||
</div>
|
</div>
|
||||||
</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);
|
grid.appendChild(card);
|
||||||
|
|
||||||
// Git-Status asynchron laden
|
// Git-Status asynchron laden
|
||||||
@@ -100,8 +130,29 @@ registerPage('dashboard', {
|
|||||||
${a.description ? `<div class="card-desc">${esc(a.description)}</div>` : ''}
|
${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>` : ''}
|
${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>
|
||||||
|
<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);
|
agentGrid.appendChild(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,9 +162,18 @@ registerPage('dashboard', {
|
|||||||
placeholder.addEventListener('click', () => navigateTo('agent'));
|
placeholder.addEventListener('click', () => navigateTo('agent'));
|
||||||
document.getElementById('newAgentCard').appendChild(placeholder);
|
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) {
|
function esc(s) {
|
||||||
const d = document.createElement('div');
|
const d = document.createElement('div');
|
||||||
d.textContent = s;
|
d.textContent = s;
|
||||||
|
|||||||
Reference in new issue
Block a user