feat(stacks): add Schedule task shortcut to stack context and kebab menus (#772)

Right-clicking a stack or opening its 3-dot menu now shows a
'Schedule task' entry in the lifecycle group (visible to paid tiers).
Clicking it navigates to Scheduled Operations and opens the New
Schedule dialog pre-filled with the stack name and active node,
removing the need to navigate there manually and re-enter the target.

- Added openScheduleTask to StackMenuCtx; wired in buildMenuCtx using
  the active node from NodeContext
- Extended ScheduledOperationsView with optional prefill/onPrefillConsumed
  props; a ref-guarded effect calls openCreate() with the prefill data
- openCreate refactored to accept an optional prefill arg, removing the
  duplication between the effect and the existing 'New Schedule' button
This commit is contained in:
Anso
2026-04-25 11:49:01 -04:00
committed by GitHub
parent af9cb0aa63
commit 819d2a63fc
5 changed files with 58 additions and 27 deletions
+4 -2
View File
@@ -3,6 +3,7 @@ import {
Activity,
ArrowUpRight,
BellRing,
CalendarClock,
CircleSlash,
Download,
Pin,
@@ -21,7 +22,7 @@ export function useStackMenuItems(_file: string, ctx: StackMenuCtx): MenuGroup[]
stackStatus, hasPort, isBusy, isPaid, canDelete, isPinned, labels,
openAlertSheet, openAutoHeal, checkUpdates, openStackApp,
deploy, stop, restart, update, remove, pin, unpin, toggleLabel,
menuVisibility, autoUpdateEnabled, setAutoUpdateEnabled,
menuVisibility, autoUpdateEnabled, setAutoUpdateEnabled, openScheduleTask,
} = ctx;
const { showDeploy, showStop, showRestart, showUpdate } = menuVisibility;
@@ -74,6 +75,7 @@ export function useStackMenuItems(_file: string, ctx: StackMenuCtx): MenuGroup[]
if (showStop) lifecycle.push({ id: 'stop', label: 'Stop', icon: Square, shortcut: '⌘.', onSelect: stop, disabled: isBusy });
if (showRestart) lifecycle.push({ id: 'restart', label: 'Restart', icon: RotateCw, shortcut: '⌘R', onSelect: restart, disabled: isBusy });
if (showUpdate) lifecycle.push({ id: 'update', label: 'Update', icon: Download, shortcut: '⌘↑', onSelect: update, disabled: isBusy });
if (isPaid) lifecycle.push({ id: 'schedule', label: 'Schedule task', icon: CalendarClock, onSelect: openScheduleTask });
if (lifecycle.length > 0) groups.push({ id: 'lifecycle', items: lifecycle });
if (canDelete) {
@@ -89,6 +91,6 @@ export function useStackMenuItems(_file: string, ctx: StackMenuCtx): MenuGroup[]
showDeploy, showStop, showRestart, showUpdate,
autoUpdateEnabled, setAutoUpdateEnabled,
openAlertSheet, openAutoHeal, checkUpdates, openStackApp,
deploy, stop, restart, update, remove, pin, unpin, toggleLabel,
deploy, stop, restart, update, remove, pin, unpin, toggleLabel, openScheduleTask,
]);
}