Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/ui/integration-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export function IntegrationSelector({
<div className="rounded-full bg-orange-500/50 p-0.5">
<AlertTriangle className="size-3 text-white" />
</div>
<SelectValue placeholder="No integrations configured" />
<SelectValue placeholder="No integrations" />
</div>
</SelectTrigger>
<SelectContent>
Expand Down
45 changes: 37 additions & 8 deletions components/workflow/node-config-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { useAtom, useAtomValue, useSetAtom } from "jotai";
import {
Copy,
Eraser,
Eye,
EyeOff,
FileCode,
MenuIcon,
RefreshCw,
Expand Down Expand Up @@ -203,6 +205,16 @@ export const PanelInner = () => {
}
};

const handleToggleEnabled = () => {
if (selectedNode) {
const currentEnabled = selectedNode.data.enabled ?? true;
updateNodeData({
id: selectedNode.id,
data: { enabled: !currentEnabled },
});
}
};

const handleDeleteEdge = () => {
if (selectedEdgeId) {
deleteEdge(selectedEdgeId);
Expand Down Expand Up @@ -614,14 +626,31 @@ export const PanelInner = () => {
</div>
{selectedNode.data.type === "action" && (
<div className="flex shrink-0 items-center justify-between border-t p-4">
<Button
onClick={() => setShowDeleteNodeAlert(true)}
size="sm"
variant="ghost"
>
<Trash2 className="mr-2 size-4" />
Delete Step
</Button>
<div className="flex items-center gap-2">
<Button
onClick={handleToggleEnabled}
size="icon"
title={
selectedNode.data.enabled === false
? "Enable Step"
: "Disable Step"
}
variant="ghost"
>
{selectedNode.data.enabled === false ? (
<EyeOff className="size-4" />
) : (
<Eye className="size-4" />
)}
</Button>
<Button
onClick={() => setShowDeleteNodeAlert(true)}
size="icon"
variant="ghost"
>
<Trash2 className="size-4" />
</Button>
</div>

{(() => {
const actionType = selectedNode.data.config
Expand Down
26 changes: 22 additions & 4 deletions components/workflow/nodes/action-node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Check,
Code,
Database,
EyeOff,
GitBranch,
XCircle,
Zap,
Expand Down Expand Up @@ -233,6 +234,7 @@ type ActionNodeProps = NodeProps & {
id: string;
};

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

// Handle empty action type (new node without selected action)
if (!actionType) {
const isDisabled = data.enabled === false;
return (
<Node
className={cn(
"flex h-48 w-48 flex-col items-center justify-center shadow-none transition-all duration-150 ease-out",
selected && "border-primary"
selected && "border-primary",
isDisabled && "opacity-50"
)}
handles={{ target: true, source: true }}
status={status}
>
{isDisabled && (
<div className="absolute top-2 left-2 rounded-full bg-gray-500/50 p-1">
<EyeOff className="size-3.5 text-white" />
</div>
)}
<div className="flex flex-col items-center justify-center gap-3 p-6">
<Zap className="size-12 text-muted-foreground" strokeWidth={1.5} />
<div className="flex flex-col items-center gap-1 text-center">
Expand Down Expand Up @@ -300,18 +309,27 @@ export const ActionNode = memo(({ data, selected, id }: ActionNodeProps) => {
};

const aiModel = getAiModel();
const isDisabled = data.enabled === false;

return (
<Node
className={cn(
"relative flex h-48 w-48 flex-col items-center justify-center shadow-none transition-all duration-150 ease-out",
selected && "border-primary"
selected && "border-primary",
isDisabled && "opacity-50"
)}
handles={{ target: true, source: true }}
status={status}
>
{/* Integration warning badge in top left */}
{integrationMissing && (
{/* Disabled badge in top left */}
{isDisabled && (
<div className="absolute top-2 left-2 rounded-full bg-gray-500/50 p-1">
<EyeOff className="size-3.5 text-white" />
</div>
)}

{/* Integration warning badge in top left (only if not disabled) */}
{!isDisabled && integrationMissing && (
<div className="absolute top-2 left-2 rounded-full bg-orange-500/50 p-1">
<AlertTriangle className="size-3.5 text-white" />
</div>
Expand Down
Loading