Skip to content

Commit d32e046

Browse files
authored
enable/disable steps (#47)
* enable/disable steps * fix downstream outputs * add cmd+/ to fit view
1 parent 7a80427 commit d32e046

File tree

7 files changed

+114
-619
lines changed

7 files changed

+114
-619
lines changed

components/ui/integration-selector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export function IntegrationSelector({
9292
<div className="rounded-full bg-orange-500/50 p-0.5">
9393
<AlertTriangle className="size-3 text-white" />
9494
</div>
95-
<SelectValue placeholder="No integrations configured" />
95+
<SelectValue placeholder="No integrations" />
9696
</div>
9797
</SelectTrigger>
9898
<SelectContent>

components/workflow/node-config-panel.tsx

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { useAtom, useAtomValue, useSetAtom } from "jotai";
22
import {
33
Copy,
44
Eraser,
5+
Eye,
6+
EyeOff,
57
FileCode,
68
MenuIcon,
79
RefreshCw,
@@ -203,6 +205,16 @@ export const PanelInner = () => {
203205
}
204206
};
205207

208+
const handleToggleEnabled = () => {
209+
if (selectedNode) {
210+
const currentEnabled = selectedNode.data.enabled ?? true;
211+
updateNodeData({
212+
id: selectedNode.id,
213+
data: { enabled: !currentEnabled },
214+
});
215+
}
216+
};
217+
206218
const handleDeleteEdge = () => {
207219
if (selectedEdgeId) {
208220
deleteEdge(selectedEdgeId);
@@ -614,14 +626,31 @@ export const PanelInner = () => {
614626
</div>
615627
{selectedNode.data.type === "action" && (
616628
<div className="flex shrink-0 items-center justify-between border-t p-4">
617-
<Button
618-
onClick={() => setShowDeleteNodeAlert(true)}
619-
size="sm"
620-
variant="ghost"
621-
>
622-
<Trash2 className="mr-2 size-4" />
623-
Delete Step
624-
</Button>
629+
<div className="flex items-center gap-2">
630+
<Button
631+
onClick={handleToggleEnabled}
632+
size="icon"
633+
title={
634+
selectedNode.data.enabled === false
635+
? "Enable Step"
636+
: "Disable Step"
637+
}
638+
variant="ghost"
639+
>
640+
{selectedNode.data.enabled === false ? (
641+
<EyeOff className="size-4" />
642+
) : (
643+
<Eye className="size-4" />
644+
)}
645+
</Button>
646+
<Button
647+
onClick={() => setShowDeleteNodeAlert(true)}
648+
size="icon"
649+
variant="ghost"
650+
>
651+
<Trash2 className="size-4" />
652+
</Button>
653+
</div>
625654

626655
{(() => {
627656
const actionType = selectedNode.data.config

components/workflow/nodes/action-node.tsx

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Check,
88
Code,
99
Database,
10+
EyeOff,
1011
GitBranch,
1112
XCircle,
1213
Zap,
@@ -233,6 +234,7 @@ type ActionNodeProps = NodeProps & {
233234
id: string;
234235
};
235236

237+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Complex UI logic with multiple conditions including disabled state
236238
export const ActionNode = memo(({ data, selected, id }: ActionNodeProps) => {
237239
const selectedExecutionId = useAtomValue(selectedExecutionIdAtom);
238240
const executionLogs = useAtomValue(executionLogsAtom);
@@ -254,15 +256,22 @@ export const ActionNode = memo(({ data, selected, id }: ActionNodeProps) => {
254256

255257
// Handle empty action type (new node without selected action)
256258
if (!actionType) {
259+
const isDisabled = data.enabled === false;
257260
return (
258261
<Node
259262
className={cn(
260263
"flex h-48 w-48 flex-col items-center justify-center shadow-none transition-all duration-150 ease-out",
261-
selected && "border-primary"
264+
selected && "border-primary",
265+
isDisabled && "opacity-50"
262266
)}
263267
handles={{ target: true, source: true }}
264268
status={status}
265269
>
270+
{isDisabled && (
271+
<div className="absolute top-2 left-2 rounded-full bg-gray-500/50 p-1">
272+
<EyeOff className="size-3.5 text-white" />
273+
</div>
274+
)}
266275
<div className="flex flex-col items-center justify-center gap-3 p-6">
267276
<Zap className="size-12 text-muted-foreground" strokeWidth={1.5} />
268277
<div className="flex flex-col items-center gap-1 text-center">
@@ -300,18 +309,27 @@ export const ActionNode = memo(({ data, selected, id }: ActionNodeProps) => {
300309
};
301310

302311
const aiModel = getAiModel();
312+
const isDisabled = data.enabled === false;
303313

304314
return (
305315
<Node
306316
className={cn(
307317
"relative flex h-48 w-48 flex-col items-center justify-center shadow-none transition-all duration-150 ease-out",
308-
selected && "border-primary"
318+
selected && "border-primary",
319+
isDisabled && "opacity-50"
309320
)}
310321
handles={{ target: true, source: true }}
311322
status={status}
312323
>
313-
{/* Integration warning badge in top left */}
314-
{integrationMissing && (
324+
{/* Disabled badge in top left */}
325+
{isDisabled && (
326+
<div className="absolute top-2 left-2 rounded-full bg-gray-500/50 p-1">
327+
<EyeOff className="size-3.5 text-white" />
328+
</div>
329+
)}
330+
331+
{/* Integration warning badge in top left (only if not disabled) */}
332+
{!isDisabled && integrationMissing && (
315333
<div className="absolute top-2 left-2 rounded-full bg-orange-500/50 p-1">
316334
<AlertTriangle className="size-3.5 text-white" />
317335
</div>

components/workflow/workflow-canvas.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,22 @@ export function WorkflowCanvas() {
200200
}
201201
}, [currentWorkflowId, hasRealNodes, fitView]);
202202

203+
// Keyboard shortcut for fit view (Cmd+/ or Ctrl+/)
204+
useEffect(() => {
205+
const handleKeyDown = (event: KeyboardEvent) => {
206+
// Check for Cmd+/ (Mac) or Ctrl+/ (Windows/Linux)
207+
if ((event.metaKey || event.ctrlKey) && event.key === "/") {
208+
event.preventDefault();
209+
fitView({ padding: 0.2, duration: 300 });
210+
}
211+
};
212+
213+
window.addEventListener("keydown", handleKeyDown);
214+
return () => {
215+
window.removeEventListener("keydown", handleKeyDown);
216+
};
217+
}, [fitView]);
218+
203219
const nodeTypes = useMemo(
204220
() => ({
205221
trigger: TriggerNode,

0 commit comments

Comments
 (0)