Skip to content

Commit d78b343

Browse files
committed
Add debug mode for viewing ReactFlow Node ids
1 parent a25a48a commit d78b343

File tree

6 files changed

+136
-65
lines changed

6 files changed

+136
-65
lines changed

.env.example

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,7 @@ VITE_ENABLE_GOOGLE_CLOUD_SUBMITTER=<boolean>
1717

1818
# Github
1919
VITE_REQUIRE_AUTHORIZATION=<boolean>
20-
VITE_GITHUB_CLIENT_ID=<string>
20+
VITE_GITHUB_CLIENT_ID=<string>
21+
22+
# Dev Tools
23+
VITE_ENABLE_DEBUG_MODE=<boolean>

src/components/shared/ReactFlow/FlowCanvas/IONode/IONode.tsx

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@ import { OutputNameEditor } from "@/components/Editor/IOEditor/OutputNameEditor"
66
import { getOutputConnectedDetails } from "@/components/Editor/utils/getOutputConnectedDetails";
77
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
88
import { BlockStack, InlineStack } from "@/components/ui/layout";
9+
import {
10+
Tooltip,
11+
TooltipContent,
12+
TooltipTrigger,
13+
} from "@/components/ui/tooltip";
914
import { Paragraph } from "@/components/ui/typography";
1015
import { useNodeManager } from "@/hooks/useNodeManager";
1116
import { cn } from "@/lib/utils";
1217
import { useComponentSpec } from "@/providers/ComponentSpecProvider";
1318
import { useContextPanel } from "@/providers/ContextPanelProvider";
1419
import type { IONodeData } from "@/types/nodes";
1520
import { isInputSpec, typeSpecToString } from "@/utils/componentSpec";
21+
import { ENABLE_DEBUG_MODE } from "@/utils/constants";
1622

1723
interface IONodeProps {
1824
type: "input" | "output";
@@ -24,7 +30,7 @@ interface IONodeProps {
2430
const IONode = ({ type, data, selected = false }: IONodeProps) => {
2531
const { currentGraphSpec, currentSubgraphSpec } = useComponentSpec();
2632
const { setContent, clearContent } = useContextPanel();
27-
const { getHandleNodeId } = useNodeManager();
33+
const { getNodeId, getHandleNodeId } = useNodeManager();
2834

2935
const { spec, readOnly } = data;
3036

@@ -51,6 +57,7 @@ const IONode = ({ type, data, selected = false }: IONodeProps) => {
5157
[currentSubgraphSpec.outputs, spec.name],
5258
);
5359

60+
const nodeId = getNodeId(spec.name, type);
5461
const handleNodeType = isInput ? "handle-out" : "handle-in";
5562
const nodeHandleId = getHandleNodeId(spec.name, spec.name, handleNodeType);
5663

@@ -107,6 +114,11 @@ const IONode = ({ type, data, selected = false }: IONodeProps) => {
107114
<Card className={cn("border-2 max-w-[300px] p-0", borderColor)}>
108115
<CardHeader className="px-2 py-2.5">
109116
<CardTitle className="break-words">{spec.name}</CardTitle>
117+
{ENABLE_DEBUG_MODE && (
118+
<Paragraph size="xs" tone="subdued">
119+
Node Id: {nodeId}
120+
</Paragraph>
121+
)}
110122
</CardHeader>
111123
<CardContent className="p-2 max-w-[250px]">
112124
<BlockStack gap="2">
@@ -141,12 +153,24 @@ const IONode = ({ type, data, selected = false }: IONodeProps) => {
141153
</Paragraph>
142154
</InlineStack>
143155
</BlockStack>
144-
<Handle
145-
id={nodeHandleId}
146-
type={handleType}
147-
position={handlePosition}
148-
className={cn(handleDefaultClassName, handleClassName)}
149-
/>
156+
<Tooltip>
157+
<TooltipTrigger asChild>
158+
<Handle
159+
id={nodeHandleId}
160+
type={handleType}
161+
position={handlePosition}
162+
className={cn(handleDefaultClassName, handleClassName)}
163+
/>
164+
</TooltipTrigger>
165+
<TooltipContent disabled={!ENABLE_DEBUG_MODE}>
166+
<div className="capitalize">
167+
{type} Name: {spec.name}
168+
</div>
169+
<div>Handle Name: {spec.name}</div>
170+
<div>parentNodeId: {nodeId}</div>
171+
<div>handleNodeId: {nodeHandleId}</div>
172+
</TooltipContent>
173+
</Tooltip>
150174
</CardContent>
151175
</Card>
152176
);

src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskNodeCard/Handles.tsx

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { useNodeManager } from "@/hooks/useNodeManager";
1515
import { cn } from "@/lib/utils";
1616
import { useTaskNode } from "@/providers/TaskNodeProvider";
1717
import type { InputSpec, OutputSpec } from "@/utils/componentSpec";
18+
import { ENABLE_DEBUG_MODE } from "@/utils/constants";
1819

1920
type InputHandleProps = {
2021
input: InputSpec;
@@ -34,7 +35,7 @@ export const InputHandle = ({
3435
onHandleSelectionChange,
3536
}: InputHandleProps) => {
3637
const { getInputHandleNodeId } = useNodeManager();
37-
const { taskId, nodeId, state } = useTaskNode();
38+
const { taskId, nodeId, state, name } = useTaskNode();
3839

3940
const fromHandle = useConnection((connection) => connection.fromHandle?.id);
4041
const toHandle = useConnection((connection) => connection.toHandle?.id);
@@ -131,23 +132,33 @@ export const InputHandle = ({
131132
data-active={active}
132133
>
133134
<div className="absolute -translate-x-6 flex items-center h-3 w-3">
134-
<Handle
135-
ref={handleRef}
136-
type="target"
137-
id={handleId}
138-
position={Position.Left}
139-
isConnectable={true}
140-
className={cn(
141-
"border-0! h-full! w-full! transform-none!",
142-
missing,
143-
(selected || active) && "bg-blue-500!",
144-
highlight && "bg-green-500!",
145-
state.readOnly && "cursor-pointer!",
146-
)}
147-
onClick={handleHandleClick}
148-
data-invalid={invalid}
149-
data-testid={`input-handle-${input.name}`}
150-
/>
135+
<Tooltip>
136+
<TooltipTrigger asChild>
137+
<Handle
138+
ref={handleRef}
139+
type="target"
140+
id={handleId}
141+
position={Position.Left}
142+
isConnectable={true}
143+
className={cn(
144+
"border-0! h-full! w-full! transform-none!",
145+
missing,
146+
(selected || active) && "bg-blue-500!",
147+
highlight && "bg-green-500!",
148+
state.readOnly && "cursor-pointer!",
149+
)}
150+
onClick={handleHandleClick}
151+
data-invalid={invalid}
152+
data-testid={`input-handle-${input.name}`}
153+
/>
154+
</TooltipTrigger>
155+
<TooltipContent disabled={!ENABLE_DEBUG_MODE}>
156+
<div>Task Name: {name}</div>
157+
<div>Handle Name: {input.name}</div>
158+
<div>parentNodeId: {nodeId}</div>
159+
<div>handleNodeId: {handleId}</div>
160+
</TooltipContent>
161+
</Tooltip>
151162
</div>
152163
<div
153164
className={cn(
@@ -221,7 +232,7 @@ export const OutputHandle = ({
221232
onHandleSelectionChange,
222233
}: OutputHandleProps) => {
223234
const { getOutputHandleNodeId } = useNodeManager();
224-
const { taskId, nodeId, state } = useTaskNode();
235+
const { taskId, nodeId, state, name } = useTaskNode();
225236

226237
const fromHandle = useConnection((connection) => connection.fromHandle?.id);
227238
const toHandle = useConnection((connection) => connection.toHandle?.id);
@@ -339,21 +350,31 @@ export const OutputHandle = ({
339350
</div>
340351
)}
341352
</div>
342-
<Handle
343-
ref={handleRef}
344-
type="source"
345-
id={handleId}
346-
position={Position.Right}
347-
isConnectable={true}
348-
onClick={handleHandleClick}
349-
className={cn(
350-
"relative! border-0! !w-[12px] !h-[12px] transform-none! translate-x-6 cursor-pointer bg-gray-500!",
351-
(selected || active) && "bg-blue-500!",
352-
highlight && "bg-green-500!",
353-
state.readOnly && "cursor-pointer!",
354-
)}
355-
data-testid={`output-handle-${output.name}`}
356-
/>
353+
<Tooltip>
354+
<TooltipTrigger asChild>
355+
<Handle
356+
ref={handleRef}
357+
type="source"
358+
id={handleId}
359+
position={Position.Right}
360+
isConnectable={true}
361+
onClick={handleHandleClick}
362+
className={cn(
363+
"relative! border-0! !w-[12px] !h-[12px] transform-none! translate-x-6 cursor-pointer bg-gray-500!",
364+
(selected || active) && "bg-blue-500!",
365+
highlight && "bg-green-500!",
366+
state.readOnly && "cursor-pointer!",
367+
)}
368+
data-testid={`output-handle-${output.name}`}
369+
/>
370+
</TooltipTrigger>
371+
<TooltipContent disabled={!ENABLE_DEBUG_MODE}>
372+
<div>Task Name: {name}</div>
373+
<div>Handle Name: {output.name}</div>
374+
<div>parentNodeId: {nodeId}</div>
375+
<div>handleNodeId: {handleId}</div>
376+
</TooltipContent>
377+
</Tooltip>
357378
</div>
358379
);
359380
};

src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskNodeCard/TaskNodeCard.tsx

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { useComponentSpec } from "@/providers/ComponentSpecProvider";
1717
import { useContextPanel } from "@/providers/ContextPanelProvider";
1818
import { useTaskNode } from "@/providers/TaskNodeProvider";
1919
import { isCacheDisabled } from "@/utils/cache";
20+
import { ENABLE_DEBUG_MODE } from "@/utils/constants";
2021
import { getSubgraphDescription, isSubgraph } from "@/utils/subgraphUtils";
2122

2223
import {
@@ -254,25 +255,40 @@ const TaskNodeCard = () => {
254255
ref={nodeRef}
255256
onDoubleClick={handleDoubleClick}
256257
>
257-
<CardHeader className="border-b border-slate-200 px-2 py-2.5 flex flex-row justify-between items-start">
258+
<CardHeader className="border-b border-slate-200 px-2 py-2.5 items-start">
258259
<BlockStack>
259-
<InlineStack gap="2" blockAlign="center" wrap="nowrap">
260-
{isSubgraphNode && isSubgraphNavigationEnabled && (
261-
<QuickTooltip content={`Subgraph: ${subgraphDescription}`}>
262-
<Icon name="Workflow" size="sm" className="text-blue-600" />
263-
</QuickTooltip>
260+
<InlineStack
261+
gap="2"
262+
align="space-between"
263+
blockAlign="start"
264+
wrap="nowrap"
265+
className="w-full"
266+
>
267+
<InlineStack gap="2" blockAlign="center" wrap="nowrap">
268+
{isSubgraphNode && isSubgraphNavigationEnabled && (
269+
<QuickTooltip content={`Subgraph: ${subgraphDescription}`}>
270+
<Icon name="Workflow" size="sm" className="text-blue-600" />
271+
</QuickTooltip>
272+
)}
273+
{disabledCache && !readOnly && (
274+
<QuickTooltip
275+
content="Cache Disabled"
276+
className="whitespace-nowrap"
277+
>
278+
<Icon name="ZapOff" size="sm" className="text-orange-400" />
279+
</QuickTooltip>
280+
)}
281+
<CardTitle className="break-words text-left text-xs text-slate-900">
282+
{name}
283+
</CardTitle>
284+
</InlineStack>
285+
{isRemoteComponentLibrarySearchEnabled ? (
286+
<PublishedComponentBadge componentRef={taskSpec.componentRef}>
287+
{digestMarkup}
288+
</PublishedComponentBadge>
289+
) : (
290+
digestMarkup
264291
)}
265-
{disabledCache && !readOnly && (
266-
<QuickTooltip
267-
content="Cache Disabled"
268-
className="whitespace-nowrap"
269-
>
270-
<Icon name="ZapOff" size="sm" className="text-orange-400" />
271-
</QuickTooltip>
272-
)}
273-
<CardTitle className="break-words text-left text-xs text-slate-900">
274-
{name}
275-
</CardTitle>
276292
</InlineStack>
277293
{taskId &&
278294
taskId !== name &&
@@ -283,12 +299,10 @@ const TaskNodeCard = () => {
283299
)}
284300
</BlockStack>
285301

286-
{isRemoteComponentLibrarySearchEnabled ? (
287-
<PublishedComponentBadge componentRef={taskSpec.componentRef}>
288-
{digestMarkup}
289-
</PublishedComponentBadge>
290-
) : (
291-
digestMarkup
302+
{ENABLE_DEBUG_MODE && (
303+
<Text size="xs" tone="subdued">
304+
Node Id: {nodeId}
305+
</Text>
292306
)}
293307
</CardHeader>
294308
<CardContent className="p-2 flex flex-col gap-2">

src/components/ui/tooltip.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,21 @@ function TooltipTrigger({
4040
interface TooltipContentProps
4141
extends React.ComponentProps<typeof TooltipPrimitive.Content> {
4242
arrowClassName?: string;
43+
disabled?: boolean;
4344
}
4445

4546
function TooltipContent({
4647
className,
4748
sideOffset = 0,
4849
children,
4950
arrowClassName,
51+
disabled,
5052
...props
5153
}: TooltipContentProps) {
54+
if (disabled) {
55+
return null;
56+
}
57+
5258
return (
5359
<TooltipPrimitive.Portal>
5460
<TooltipPrimitive.Content

src/utils/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
/* Environment Config */
2+
export const ENABLE_DEBUG_MODE =
3+
import.meta.env.VITE_ENABLE_DEBUG_MODE === "true";
4+
25
export const ABOUT_URL =
36
import.meta.env.VITE_ABOUT_URL || "https://cloud-pipelines.net/";
47

0 commit comments

Comments
 (0)