fix(988): hide inapplicable actions in agent context menu
Per mara feedback: don't show disabled actions at all. - restart/stop only rendered when agent is running - start only rendered when agent is stopped - removed .agent-menu-item:disabled CSS rule (no longer needed) Also switch Escape handler to stopImmediatePropagation so the selection-clear keydown listener doesn't co-fire when closing a menu.
This commit is contained in:
parent
28e0d1b7fa
commit
ba43b5f869
2 changed files with 23 additions and 42 deletions
|
|
@ -384,13 +384,9 @@ a:hover {
|
||||||
padding: 0.4em 0.9em;
|
padding: 0.4em 0.9em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.agent-menu-item:not(:disabled):hover {
|
.agent-menu-item:hover {
|
||||||
background: var(--surface1);
|
background: var(--surface1);
|
||||||
}
|
}
|
||||||
.agent-menu-item:disabled {
|
|
||||||
opacity: 0.35;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
.agent-menu-sep {
|
.agent-menu-sep {
|
||||||
height: 1px;
|
height: 1px;
|
||||||
background: var(--surface2);
|
background: var(--surface2);
|
||||||
|
|
|
||||||
|
|
@ -328,8 +328,8 @@ window.marked = marked;
|
||||||
// ─── per-agent context menu ──────────────────────────────────────────
|
// ─── per-agent context menu ──────────────────────────────────────────
|
||||||
// Three-dot (⋮) button on each agent card for quick single-agent
|
// Three-dot (⋮) button on each agent card for quick single-agent
|
||||||
// lifecycle actions without needing to select first. State-aware:
|
// lifecycle actions without needing to select first. State-aware:
|
||||||
// restart/stop disabled when agent is stopped, start disabled when
|
// restart/stop only shown when running, start only shown when stopped,
|
||||||
// running, destroy/purge hidden for the manager.
|
// destroy/purge hidden for the manager.
|
||||||
// The button is CSS-invisible until the row is hovered (or menu is
|
// The button is CSS-invisible until the row is hovered (or menu is
|
||||||
// open) so it doesn't clutter quiet rows.
|
// open) so it doesn't clutter quiet rows.
|
||||||
|
|
||||||
|
|
@ -351,12 +351,12 @@ window.marked = marked;
|
||||||
document.addEventListener('click', (e) => {
|
document.addEventListener('click', (e) => {
|
||||||
if (!e.target.closest('.agent-menu')) closeAllAgentMenus();
|
if (!e.target.closest('.agent-menu')) closeAllAgentMenus();
|
||||||
}, true);
|
}, true);
|
||||||
// Close on Escape (shares the keydown listener below with selection-clear;
|
// Close on Escape. stopImmediatePropagation so the selection-clear
|
||||||
// close happens first since no selection change is needed here).
|
// handler on the same element doesn't also fire when a menu is open.
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
if (e.key === 'Escape' && openAgentMenu) {
|
if (e.key === 'Escape' && openAgentMenu) {
|
||||||
closeAllAgentMenus();
|
closeAllAgentMenus();
|
||||||
e.stopPropagation();
|
e.stopImmediatePropagation();
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
|
@ -401,16 +401,11 @@ window.marked = marked;
|
||||||
class: 'agent-menu-item',
|
class: 'agent-menu-item',
|
||||||
role: 'menuitem',
|
role: 'menuitem',
|
||||||
}, label);
|
}, label);
|
||||||
if (opts.disabled) {
|
item.addEventListener('click', async () => {
|
||||||
item.disabled = true;
|
closeAllAgentMenus();
|
||||||
if (opts.title) item.title = opts.title;
|
if (opts.confirm && !confirm(opts.confirm)) return;
|
||||||
} else {
|
await agentMenuPost(opts.action, c.name, opts.body || null);
|
||||||
item.addEventListener('click', async () => {
|
});
|
||||||
closeAllAgentMenus();
|
|
||||||
if (opts.confirm && !confirm(opts.confirm)) return;
|
|
||||||
await agentMenuPost(opts.action, c.name, opts.body || null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
li.append(item);
|
li.append(item);
|
||||||
return li;
|
return li;
|
||||||
}
|
}
|
||||||
|
|
@ -419,29 +414,19 @@ window.marked = marked;
|
||||||
return el('li', { class: 'agent-menu-sep', role: 'separator' });
|
return el('li', { class: 'agent-menu-sep', role: 'separator' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show only actions that are applicable in the current state.
|
||||||
|
if (c.running) {
|
||||||
|
dropdown.append(
|
||||||
|
menuItem('↺ R3ST4RT', { action: '/restart/', confirm: `restart ${c.name}?` }),
|
||||||
|
menuItem('■ ST0P', { action: '/kill/', confirm: `stop ${c.name}?` }),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
dropdown.append(
|
||||||
|
menuItem('▶ ST4RT', { action: '/start/', confirm: `start ${c.name}?` }),
|
||||||
|
);
|
||||||
|
}
|
||||||
dropdown.append(
|
dropdown.append(
|
||||||
menuItem('↺ R3ST4RT', {
|
menuItem('↻ R3BU1LD', { action: '/rebuild/', confirm: `rebuild ${c.name}? hot-reloads the container.` }),
|
||||||
action: '/restart/',
|
|
||||||
disabled: !c.running,
|
|
||||||
title: 'agent is stopped',
|
|
||||||
confirm: `restart ${c.name}?`,
|
|
||||||
}),
|
|
||||||
menuItem('■ ST0P', {
|
|
||||||
action: '/kill/',
|
|
||||||
disabled: !c.running,
|
|
||||||
title: 'agent is already stopped',
|
|
||||||
confirm: `stop ${c.name}?`,
|
|
||||||
}),
|
|
||||||
menuItem('▶ ST4RT', {
|
|
||||||
action: '/start/',
|
|
||||||
disabled: c.running,
|
|
||||||
title: 'agent is already running',
|
|
||||||
confirm: `start ${c.name}?`,
|
|
||||||
}),
|
|
||||||
menuItem('↻ R3BU1LD', {
|
|
||||||
action: '/rebuild/',
|
|
||||||
confirm: `rebuild ${c.name}? hot-reloads the container.`,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!c.is_manager) {
|
if (!c.is_manager) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue