feat: add context menu to service cards#4219
Conversation
Right-click on service cards to quickly Start, Deploy, Stop, or Delete a service without navigating into it. Uses shadcn/ui ContextMenu component built on @radix-ui/react-context-menu. Delete action shows a confirmation dialog. LibSQL services are excluded since they lack standard mutation endpoints.
Use toast.promise for loading/success/error states and invalidate environment query after actions complete to update service status.
| await actions.delete.mutateAsync({ | ||
| [idKey]: service.id, | ||
| } as any); |
There was a problem hiding this comment.
Compose delete always fails —
deleteVolumes is required
handleServiceDelete passes only { [idKey]: service.id } to every mutation. For compose services the backend schema is apiDeleteCompose = z.object({ composeId: z.string().min(1), deleteVolumes: z.boolean() }) — deleteVolumes is required (no .optional()), so the tRPC input validation will reject the call and the delete will always error. The as any cast hides the TypeScript mismatch.
The single-service delete dialog also has no "Delete volumes" checkbox, so this can't be inferred from user input. Fix by adding the checkbox to the dialog (mirroring the bulk-delete UX) and forwarding the value:
await actions.delete.mutateAsync(
service.type === "compose"
? { composeId: service.id, deleteVolumes: deleteVolumes }
: ({ [idKey]: service.id } as any),
);| <ContextMenuItem | ||
| className="flex items-center gap-2 text-orange-500 focus:text-orange-500" | ||
| onClick={() => | ||
| handleServiceAction(service, "stop") |
There was a problem hiding this comment.
LibSQL cards suppress browser context menu without showing custom one
When service.type === "libsql", no ContextMenuContent is rendered but the ContextMenuTrigger still intercepts the contextmenu event, preventing the browser's native context menu from appearing. Users right-clicking a LibSQL card will silently get nothing. Consider skipping the ContextMenu wrapper entirely for libsql services so the native browser context menu remains accessible.
Summary
@radix-ui/react-context-menu)🤖 Generated with Claude Code
Greptile Summary
This PR adds a right-click context menu to service cards on the environment page, offering Start, Deploy, Stop, and Delete actions. The implementation uses the standard shadcn/ui
ContextMenucomponent over@radix-ui/react-context-menuand a newserviceToDeleteconfirmation dialog.handleServiceDeletecalls the compose delete mutation with only{ composeId }, but the backend schema (apiDeleteCompose) declaresdeleteVolumes: z.boolean()as a required field. Theas anycast hides the TypeScript error. Every compose service delete triggered from this context menu will fail with a tRPC validation error at runtime. The fix is to add a "Delete volumes" checkbox to the single-delete dialog (matching the bulk-delete UX) and pass the value explicitly.Confidence Score: 4/5
deleteVolumes: z.boolean()per the Zod schema, buthandleServiceDeleteomits it (masked byas any). This means every compose-service delete from the new context menu throws a tRPC validation error. All other service types (application, postgres, mysql, mariadb, redis, mongo) are unaffected since their delete schemas only need the ID.apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId].tsx— specifically thehandleServiceDeletefunction and the single-service delete dialog.Reviews (1): Last reviewed commit: "feat: add context menu to service cards" | Re-trigger Greptile