From cce966a8daaa5467bb3b62e662cb470aedf904e3 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 9 Jan 2026 17:34:01 -0300 Subject: [PATCH 01/20] First prototype of inspection panel --- .../components/InspectionPanelField.tsx | 184 ++++++++++++++++++ .../components/InspectionPanelFields.tsx | 144 ++++++++++++++ .../components/InspectionPanelHeader.tsx | 36 ++++ .../components/InspectionPanel/index.tsx | 53 +++++ .../components/PageComponent/index.tsx | 16 ++ 5 files changed, 433 insertions(+) create mode 100644 src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx create mode 100644 src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx create mode 100644 src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx create mode 100644 src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx new file mode 100644 index 000000000000..45595b98fd6f --- /dev/null +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx @@ -0,0 +1,184 @@ +import { useMemo } from "react"; +import { AssistantButton } from "@/components/common/assistant"; +import IconComponent from "@/components/common/genericIconComponent"; +import ShadTooltip from "@/components/common/shadTooltipComponent"; +import { + CustomParameterComponent, + CustomParameterLabel, + getCustomParameterTitle, +} from "@/customization/components/custom-parameter"; +import { LANGFLOW_AGENTIC_EXPERIENCE } from "@/customization/feature-flags"; +import { useIsAutoLogin } from "@/hooks/use-is-auto-login"; +import useAuthStore from "@/stores/authStore"; +import useFlowStore from "@/stores/flowStore"; +import { useTypesStore } from "@/stores/typesStore"; +import type { NodeInputFieldComponentType } from "@/types/components"; +import { cn } from "@/utils/utils"; +import { + DEFAULT_TOOLSET_PLACEHOLDER, + FLEX_VIEW_TYPES, + ICON_STROKE_WIDTH, +} from "@/constants/constants"; +import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class"; +import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value"; +import useFetchDataOnMount from "@/CustomNodes/hooks/use-fetch-data-on-mount"; +import useHandleOnNewValue from "@/CustomNodes/hooks/use-handle-new-value"; +import getFieldTitle from "@/CustomNodes/utils/get-field-title"; +import NodeInputInfo from "@/CustomNodes/GenericNode/components/NodeInputInfo"; + +export default function InspectionPanelField({ + id, + data, + title, + name = "", + required = false, + info = "", + showNode, + isToolMode = false, + proxy, +}: Omit) { + const isAuthenticated = useAuthStore((state) => state.isAuthenticated); + const isAutoLogin = useIsAutoLogin(); + const shouldDisplayApiKey = isAuthenticated && !isAutoLogin; + + const { currentFlowId, currentFlowName } = useFlowStore((state) => ({ + currentFlowId: state.currentFlow?.id, + currentFlowName: state.currentFlow?.name, + })); + + const myData = useTypesStore((state) => state.data); + const postTemplateValue = usePostTemplateValue({ + node: data.node!, + nodeId: data.id, + parameterId: name, + }); + + const { handleNodeClass } = useHandleNodeClass(data.id); + + const { handleOnNewValue } = useHandleOnNewValue({ + node: data.node!, + nodeId: data.id, + name, + }); + + const nodeInformationMetadata = useMemo(() => { + return { + flowId: currentFlowId ?? "", + nodeType: data?.type?.toLowerCase() ?? "", + flowName: currentFlowName ?? "", + isAuth: shouldDisplayApiKey!, + variableName: name, + }; + }, [data?.node?.id, shouldDisplayApiKey, name]); + + useFetchDataOnMount( + data.node!, + data.id, + handleNodeClass, + name, + postTemplateValue, + ); + + const template = data.node?.template[name]; + const type = template?.type; + const isFlexView = FLEX_VIEW_TYPES.includes(type ?? ""); + + return ( +
+
+
+
+ {proxy ? ( + {proxy.id}}> + + {getCustomParameterTitle({ + title, + nodeId: data.id, + isFlexView, + required, + })} + + + ) : ( +
+ + {getCustomParameterTitle({ + title, + nodeId: data.id, + isFlexView, + required, + })} + +
+ )} +
+ {info !== "" && ( + }> +
+ +
+
+ )} +
+ {LANGFLOW_AGENTIC_EXPERIENCE && + data.node?.template[name]?.ai_enabled && ( + + )} +
+ +
+ + {data.node?.template[name] !== undefined && ( + + )} +
+
+ ); +} + +// Made with Bob diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx new file mode 100644 index 000000000000..36ccf4c0c893 --- /dev/null +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx @@ -0,0 +1,144 @@ +import { useMemo } from "react"; +import { sortToolModeFields } from "@/CustomNodes/helpers/sort-tool-mode-field"; +import getFieldTitle from "@/CustomNodes/utils/get-field-title"; +import type { NodeDataType } from "@/types/flow"; +import { LANGFLOW_SUPPORTED_TYPES } from "@/constants/constants"; +import InspectionPanelField from "./InspectionPanelField"; + +interface InspectionPanelFieldsProps { + data: NodeDataType; +} + +export default function InspectionPanelFields({ + data, +}: InspectionPanelFieldsProps) { + // Separate basic and advanced fields, excluding handle-only fields + const { basicFields, advancedFields } = useMemo(() => { + const allFields = Object.keys(data.node?.template || {}) + .filter((templateField) => { + const template = data.node?.template[templateField]; + + // Filter out fields that shouldn't be shown + if ( + templateField.charAt(0) === "_" || + !template?.show || + (templateField === "code" && template.type === "code") || + (templateField.includes("code") && template.proxy) + ) { + return false; + } + + // Filter out handle-only fields (fields that are not in LANGFLOW_SUPPORTED_TYPES) + // These are fields that only serve as connection points without actual input components + const isHandleOnly = !LANGFLOW_SUPPORTED_TYPES.has(template.type ?? ""); + + return !isHandleOnly; + }) + .sort((a, b) => + sortToolModeFields( + a, + b, + data.node!.template, + data.node?.field_order ?? [], + false, + ), + ); + + const basic: string[] = []; + const advanced: string[] = []; + + allFields.forEach((field) => { + const template = data.node?.template[field]; + if (template?.advanced === true) { + advanced.push(field); + } else { + basic.push(field); + } + }); + + return { basicFields: basic, advancedFields: advanced }; + }, [data.node?.template, data.node?.field_order]); + + const allFields = [...basicFields, ...advancedFields]; + + if (allFields.length === 0) { + return ( +
+ No fields available +
+ ); + } + + return ( +
+ {/* Basic fields first */} + {basicFields.length > 0 && ( +
+ {basicFields.map((templateField: string) => { + const template = data.node?.template[templateField]; + + return ( + + ); + })} +
+ )} + + {/* Advanced fields at the bottom */} + {advancedFields.length > 0 && ( + <> + {basicFields.length > 0 && ( +
+
+ Advanced Settings +
+
+ )} +
+ {advancedFields.map((templateField: string) => { + const template = data.node?.template[templateField]; + + return ( + + ); + })} +
+ + )} +
+ ); +} + +// Made with Bob diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx new file mode 100644 index 000000000000..fc0b627d1823 --- /dev/null +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx @@ -0,0 +1,36 @@ +import { Badge } from "@/components/ui/badge"; +import { NodeIcon } from "@/CustomNodes/GenericNode/components/nodeIcon"; +import type { NodeDataType } from "@/types/flow"; + +interface InspectionPanelHeaderProps { + data: NodeDataType; +} + +export default function InspectionPanelHeader({ + data, +}: InspectionPanelHeaderProps) { + return ( +
+
+ +
+ + {data.node?.display_name ?? data.type} + + + Component Settings + +
+
+ + ID: {data.id} + +
+ ); +} + +// Made with Bob diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx new file mode 100644 index 000000000000..cd07d9659912 --- /dev/null +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx @@ -0,0 +1,53 @@ +import { Panel } from "@xyflow/react"; +import { motion, AnimatePresence } from "framer-motion"; +import { memo } from "react"; +import type { AllNodeType } from "@/types/flow"; +import { cn } from "@/utils/utils"; +import InspectionPanelFields from "./components/InspectionPanelFields"; +import InspectionPanelHeader from "./components/InspectionPanelHeader"; + +interface InspectionPanelProps { + selectedNode: AllNodeType | null; + isVisible: boolean; +} + +const InspectionPanel = memo(function InspectionPanel({ + selectedNode, + isVisible, +}: InspectionPanelProps) { + return ( + + {isVisible && selectedNode && selectedNode.type === "genericNode" && ( + + + +
+ +
+
+
+ )} +
+ ); +}); + +export default InspectionPanel; + +// Made with Bob diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index bc678414f8df..c40c9b45be43 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -22,6 +22,7 @@ import { useShallow } from "zustand/react/shallow"; import { DefaultEdge } from "@/CustomEdges"; import NoteNode from "@/CustomNodes/NoteNode"; import FlowToolbar from "@/components/core/flowToolbarComponent"; +import InspectionPanel from "@/pages/FlowPage/components/InspectionPanel"; import { COLOR_OPTIONS, DEFAULT_NOTE_SIZE, @@ -744,6 +745,17 @@ export default function Page({ maxZoom: MAX_ZOOM, }; + // Determine if InspectionPanel should be visible + const showInspectionPanel = + lastSelection?.nodes?.length === 1 && + lastSelection.nodes[0].type === "genericNode"; + + // Get the fresh node data from the store instead of using stale reference + const selectedNodeId = showInspectionPanel ? lastSelection.nodes[0].id : null; + const selectedNode = selectedNodeId + ? (nodes.find((n) => n.id === selectedNodeId) as AllNodeType) + : null; + return (
{showCanvas ? ( @@ -758,6 +770,10 @@ export default function Page({ shadowBoxHeight={shadowBoxHeight} /> + )} From 5429a4b8ec81f0c712cd93d941270cf677a8975e Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 9 Jan 2026 17:41:12 -0300 Subject: [PATCH 02/20] fixed value not being set --- .../components/InspectionPanelHeader.tsx | 98 +++++++++++++++---- 1 file changed, 79 insertions(+), 19 deletions(-) diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx index fc0b627d1823..2dceefd1c9b7 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx @@ -1,5 +1,11 @@ -import { Badge } from "@/components/ui/badge"; +import { useState, useCallback } from "react"; import { NodeIcon } from "@/CustomNodes/GenericNode/components/nodeIcon"; +import IconComponent from "@/components/common/genericIconComponent"; +import ShadTooltip from "@/components/common/shadTooltipComponent"; +import { Button } from "@/components/ui/button"; +import CodeAreaModal from "@/modals/codeAreaModal"; +import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class"; +import useHandleOnNewValue from "@/CustomNodes/hooks/use-handle-new-value"; import type { NodeDataType } from "@/types/flow"; interface InspectionPanelHeaderProps { @@ -9,27 +15,81 @@ interface InspectionPanelHeaderProps { export default function InspectionPanelHeader({ data, }: InspectionPanelHeaderProps) { + const [openCodeModal, setOpenCodeModal] = useState(false); + const { handleNodeClass } = useHandleNodeClass(data.id); + const { handleOnNewValue } = useHandleOnNewValue({ + node: data.node!, + nodeId: data.id, + name: "code", + }); + + const hasCode = data.node?.template?.code !== undefined; + + const handleOpenCode = useCallback(() => { + if (hasCode) { + setOpenCodeModal(true); + } + }, [hasCode]); + + // Wrapper to match CodeAreaModal's expected signature + const handleSetValue = useCallback( + (value: string) => { + handleOnNewValue({ value }); + }, + [handleOnNewValue], + ); + return ( -
-
- -
- - {data.node?.display_name ?? data.type} - - - Component Settings - + <> +
+
+ +
+ + {data.node?.display_name ?? data.type} + + + Component Settings + +
+ {hasCode && ( + + + + )}
- - ID: {data.id} - -
+ + {hasCode && openCodeModal && ( +
+ { + handleNodeClass(apiClassType, type); + }} + nodeClass={data.node} + value={data.node?.template?.code?.value ?? ""} + componentId={data.id} + > + <> + +
+ )} + ); } From ebe88869d3e64be0d49854b62ca3bd19e8ec06a6 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 9 Jan 2026 18:06:31 -0300 Subject: [PATCH 03/20] Hide inputs that are not handles from the node, show everything else on the inspection panel --- .../components/NodeInputField/index.tsx | 3 +- .../RenderInputParameters/index.tsx | 18 ++- .../components/InspectionPanelField.tsx | 1 - .../components/InspectionPanelFields.tsx | 115 ++++-------------- 4 files changed, 41 insertions(+), 96 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx index 0d6c0dc68863..e54d770c803d 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx @@ -226,7 +226,8 @@ export default function NodeInputField({ />
- {data.node?.template[name] !== undefined && ( + {/* Hide the input component when field has a handle - inputs are edited in Inspection Panel */} + {!optionalHandle && data.node?.template[name] !== undefined && ( { return templateFields.filter((templateField) => { const template = data.node?.template[templateField]; - return ( - template?.show && - !template?.advanced && - !(template?.tool_mode && isToolMode) - ); + + // Basic visibility check + if (!template?.show || template?.advanced || (template?.tool_mode && isToolMode)) { + return false; + } + + // Only show fields that have handles (input_types) + const hasHandle = template.input_types && template.input_types.length > 0; + if (!hasHandle) { + return false; + } + + return true; }); }, [templateFields, data.node?.template, isToolMode]); diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx index 45595b98fd6f..66a6a314a86b 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx @@ -23,7 +23,6 @@ import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class"; import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value"; import useFetchDataOnMount from "@/CustomNodes/hooks/use-fetch-data-on-mount"; import useHandleOnNewValue from "@/CustomNodes/hooks/use-handle-new-value"; -import getFieldTitle from "@/CustomNodes/utils/get-field-title"; import NodeInputInfo from "@/CustomNodes/GenericNode/components/NodeInputInfo"; export default function InspectionPanelField({ diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx index 36ccf4c0c893..1712e1667714 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx @@ -12,9 +12,9 @@ interface InspectionPanelFieldsProps { export default function InspectionPanelFields({ data, }: InspectionPanelFieldsProps) { - // Separate basic and advanced fields, excluding handle-only fields - const { basicFields, advancedFields } = useMemo(() => { - const allFields = Object.keys(data.node?.template || {}) + // Get all fields in one list - show ALL fields in Inspection Panel + const allFields = useMemo(() => { + return Object.keys(data.node?.template || {}) .filter((templateField) => { const template = data.node?.template[templateField]; @@ -28,11 +28,7 @@ export default function InspectionPanelFields({ return false; } - // Filter out handle-only fields (fields that are not in LANGFLOW_SUPPORTED_TYPES) - // These are fields that only serve as connection points without actual input components - const isHandleOnly = !LANGFLOW_SUPPORTED_TYPES.has(template.type ?? ""); - - return !isHandleOnly; + return true; }) .sort((a, b) => sortToolModeFields( @@ -43,24 +39,8 @@ export default function InspectionPanelFields({ false, ), ); - - const basic: string[] = []; - const advanced: string[] = []; - - allFields.forEach((field) => { - const template = data.node?.template[field]; - if (template?.advanced === true) { - advanced.push(field); - } else { - basic.push(field); - } - }); - - return { basicFields: basic, advancedFields: advanced }; }, [data.node?.template, data.node?.field_order]); - const allFields = [...basicFields, ...advancedFields]; - if (allFields.length === 0) { return (
@@ -71,72 +51,29 @@ export default function InspectionPanelFields({ return (
- {/* Basic fields first */} - {basicFields.length > 0 && ( -
- {basicFields.map((templateField: string) => { - const template = data.node?.template[templateField]; - - return ( - - ); - })} -
- )} - - {/* Advanced fields at the bottom */} - {advancedFields.length > 0 && ( - <> - {basicFields.length > 0 && ( -
-
- Advanced Settings -
-
- )} -
- {advancedFields.map((templateField: string) => { - const template = data.node?.template[templateField]; + {allFields.map((templateField: string) => { + const template = data.node?.template[templateField]; - return ( - - ); - })} -
- - )} + return ( + + ); + })}
); } From b6bb0d457b0d2976cd074ced7c905025fe2e37b2 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 9 Jan 2026 21:13:52 +0000 Subject: [PATCH 04/20] [autofix.ci] apply automated fixes --- .../components/RenderInputParameters/index.tsx | 12 ++++++++---- .../components/InspectionPanelField.tsx | 10 +++++++++- .../components/InspectionPanelFields.tsx | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/RenderInputParameters/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/RenderInputParameters/index.tsx index 8676b4a8e001..b8d15e0a53fb 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/RenderInputParameters/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/RenderInputParameters/index.tsx @@ -31,18 +31,22 @@ const RenderInputParameters = ({ const shownTemplateFields = useMemo(() => { return templateFields.filter((templateField) => { const template = data.node?.template[templateField]; - + // Basic visibility check - if (!template?.show || template?.advanced || (template?.tool_mode && isToolMode)) { + if ( + !template?.show || + template?.advanced || + (template?.tool_mode && isToolMode) + ) { return false; } - + // Only show fields that have handles (input_types) const hasHandle = template.input_types && template.input_types.length > 0; if (!hasHandle) { return false; } - + return true; }); }, [templateFields, data.node?.template, isToolMode]); diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx index 66a6a314a86b..e323a0b106f8 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx @@ -35,7 +35,15 @@ export default function InspectionPanelField({ showNode, isToolMode = false, proxy, -}: Omit) { +}: Omit< + NodeInputFieldComponentType, + | "colors" + | "tooltipTitle" + | "type" + | "optionalHandle" + | "colorName" + | "lastInput" +>) { const isAuthenticated = useAuthStore((state) => state.isAuthenticated); const isAutoLogin = useIsAutoLogin(); const shouldDisplayApiKey = isAuthenticated && !isAutoLogin; diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx index 1712e1667714..c9469fd40702 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx @@ -17,7 +17,7 @@ export default function InspectionPanelFields({ return Object.keys(data.node?.template || {}) .filter((templateField) => { const template = data.node?.template[templateField]; - + // Filter out fields that shouldn't be shown if ( templateField.charAt(0) === "_" || From 2369db50380bd634c9dd1e8a559bd87131740dd3 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Tue, 13 Jan 2026 16:26:53 -0300 Subject: [PATCH 05/20] Implemented close button on inspection panel --- .../components/InspectionPanelHeader.tsx | 40 +++++++++++++------ .../components/InspectionPanel/index.tsx | 4 +- .../components/PageComponent/index.tsx | 11 +++++ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx index 2dceefd1c9b7..4db537f18ab9 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx @@ -10,10 +10,12 @@ import type { NodeDataType } from "@/types/flow"; interface InspectionPanelHeaderProps { data: NodeDataType; + onClose?: () => void; } export default function InspectionPanelHeader({ data, + onClose, }: InspectionPanelHeaderProps) { const [openCodeModal, setOpenCodeModal] = useState(false); const { handleNodeClass } = useHandleNodeClass(data.id); @@ -57,18 +59,32 @@ export default function InspectionPanelHeader({
- {hasCode && ( - - - - )} +
+ {hasCode && ( + + + + )} + {onClose && ( + + + + )} +
{hasCode && openCodeModal && ( diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx index cd07d9659912..bcaff70cc4eb 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx @@ -9,11 +9,13 @@ import InspectionPanelHeader from "./components/InspectionPanelHeader"; interface InspectionPanelProps { selectedNode: AllNodeType | null; isVisible: boolean; + onClose?: () => void; } const InspectionPanel = memo(function InspectionPanel({ selectedNode, isVisible, + onClose, }: InspectionPanelProps) { return ( @@ -37,7 +39,7 @@ const InspectionPanel = memo(function InspectionPanel({ "overflow-hidden flex flex-col", )} > - +
diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index c40c9b45be43..5c57844b72cf 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -756,6 +756,16 @@ export default function Page({ ? (nodes.find((n) => n.id === selectedNodeId) as AllNodeType) : null; + // Handler to close the inspection panel by deselecting all nodes + const handleCloseInspectionPanel = useCallback(() => { + setNodes((nds) => + nds.map((node) => ({ + ...node, + selected: false, + })), + ); + }, [setNodes]); + return (
{showCanvas ? ( @@ -773,6 +783,7 @@ export default function Page({ )} From deedd214319dc6486bb1d429ff8b8aba21c1b534 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Wed, 14 Jan 2026 14:44:44 -0300 Subject: [PATCH 06/20] Re-show inputs on the node --- .../components/NodeInputField/index.tsx | 3 +-- .../RenderInputParameters/index.tsx | 22 +++++-------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx index e54d770c803d..0d6c0dc68863 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx @@ -226,8 +226,7 @@ export default function NodeInputField({ />
- {/* Hide the input component when field has a handle - inputs are edited in Inspection Panel */} - {!optionalHandle && data.node?.template[name] !== undefined && ( + {data.node?.template[name] !== undefined && ( { return templateFields.filter((templateField) => { const template = data.node?.template[templateField]; - - // Basic visibility check - if ( - !template?.show || - template?.advanced || - (template?.tool_mode && isToolMode) - ) { - return false; - } - - // Only show fields that have handles (input_types) - const hasHandle = template.input_types && template.input_types.length > 0; - if (!hasHandle) { - return false; - } - - return true; + return ( + template?.show && + !template?.advanced && + !(template?.tool_mode && isToolMode) + ); }); }, [templateFields, data.node?.template, isToolMode]); From bc12b15b0bcbe6e9e3b7c641c016954ebf1f080e Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Wed, 14 Jan 2026 15:07:00 -0300 Subject: [PATCH 07/20] remove code from node toolbar --- .../components/nodeToolbarComponent/index.tsx | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx index 1b1430a5f228..3e0c3f6266d3 100644 --- a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx @@ -467,29 +467,9 @@ const NodeToolbarComponent = memo( } }; - const isCustomComponent = useMemo(() => { - const isCustom = data.type === "CustomComponent" && !data.node?.edited; - if (isCustom) { - data.node.edited = true; - } - return isCustom; - }, [data.type, data.node]); - const renderToolbarButtons = useMemo( () => ( <> - {hasCode && ( - setOpenModal(true)} - shortcut={shortcuts.find((s) => - s.name.toLowerCase().startsWith("code"), - )} - dataTestId="code-button-modal" - /> - )} {nodeLength > 0 && ( Date: Wed, 14 Jan 2026 15:07:13 -0300 Subject: [PATCH 08/20] change code design on inspection panel --- .../components/InspectionPanelHeader.tsx | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx index 4db537f18ab9..979a5e91d264 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback } from "react"; +import { useState, useCallback, useMemo } from "react"; import { NodeIcon } from "@/CustomNodes/GenericNode/components/nodeIcon"; import IconComponent from "@/components/common/genericIconComponent"; import ShadTooltip from "@/components/common/shadTooltipComponent"; @@ -7,6 +7,8 @@ import CodeAreaModal from "@/modals/codeAreaModal"; import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class"; import useHandleOnNewValue from "@/CustomNodes/hooks/use-handle-new-value"; import type { NodeDataType } from "@/types/flow"; +import { ToolbarButton } from "../../nodeToolbarComponent/components/toolbar-button"; +import { useShortcutsStore } from "@/stores/shortcuts"; interface InspectionPanelHeaderProps { data: NodeDataType; @@ -25,7 +27,10 @@ export default function InspectionPanelHeader({ name: "code", }); - const hasCode = data.node?.template?.code !== undefined; + const hasCode = useMemo( + () => Object.keys(data.node!.template).includes("code"), + [data.node], + ); const handleOpenCode = useCallback(() => { if (hasCode) { @@ -41,6 +46,16 @@ export default function InspectionPanelHeader({ [handleOnNewValue], ); + const shortcuts = useShortcutsStore((state) => state.shortcuts); + + const isCustomComponent = useMemo(() => { + const isCustom = data.type === "CustomComponent" && !data.node?.edited; + if (isCustom) { + data.node.edited = true; + } + return isCustom; + }, [data.type, data.node]); + return ( <>
@@ -59,21 +74,23 @@ export default function InspectionPanelHeader({
-
+
{hasCode && ( - + + s.name.toLowerCase().startsWith("code"), + )} + dataTestId="code-button-modal" + /> )} {onClose && ( - + - ), - ), + ) + ) ); InspectButton.displayName = "InspectButton"; @@ -141,7 +142,7 @@ function NodeOutputField({ const realOutput = getGroupOutputNodeId( data.node.flow, outputProxy.name, - outputProxy.id, + outputProxy.id ); if (realOutput) { return { @@ -166,24 +167,24 @@ function NodeOutputField({ unknownOutput: logTypeIsUnknown(flowPoolNode?.data, internalOutputName), errorOutput: logTypeIsError(flowPoolNode?.data, internalOutputName), }), - [flowPool, flowPoolId, flowPoolNode?.data, internalOutputName], + [flowPool, flowPoolId, flowPoolNode?.data, internalOutputName] ); const emptyOutput = useMemo(() => { return Object.keys(flowPoolNode?.data?.outputs ?? {})?.every( - (key) => flowPoolNode?.data?.outputs[key]?.message?.length === 0, + (key) => flowPoolNode?.data?.outputs[key]?.message?.length === 0 ); }, [flowPoolNode?.data?.outputs]); const disabledOutput = useMemo( () => edges.some((edge) => edge.sourceHandle === scapedJSONStringfy(id)), - [edges, id], + [edges, id] ); const looping = useMemo(() => { return edges.some((edge) => { const targetHandleObject: targetHandleType = scapeJSONParse( - edge.targetHandle!, + edge.targetHandle! ); return ( targetHandleObject.output_types && @@ -213,7 +214,7 @@ function NodeOutputField({ }); updateNodeInternals(data.id); }, - [data.id, index, setNode, updateNodeInternals], + [data.id, index, setNode, updateNodeInternals] ); useEffect(() => { @@ -241,11 +242,11 @@ function NodeOutputField({ .toSorted((a, b) => { const indexA = data?.node?.outputs?.findIndex( - (output) => output.name === a.data?.sourceHandle?.name, + (output) => output.name === a.data?.sourceHandle?.name ) ?? 0; const indexB = data?.node?.outputs?.findIndex( - (output) => output.name === b.data?.sourceHandle?.name, + (output) => output.name === b.data?.sourceHandle?.name ) ?? 0; return indexA - indexB; }); @@ -305,7 +306,9 @@ function NodeOutputField({ colors={colors} setFilterEdge={setFilterEdge} showNode={showNode} - testIdComplement={`${data?.type?.toLowerCase()}-${showNode ? "shownode" : "noshownode"}`} + testIdComplement={`${data?.type?.toLowerCase()}-${ + showNode ? "shownode" : "noshownode" + }`} colorName={loopInputColorName} /> ); @@ -335,7 +338,9 @@ function NodeOutputField({ colors={colors} setFilterEdge={setFilterEdge} showNode={showNode} - testIdComplement={`${data?.type?.toLowerCase()}-${showNode ? "shownode" : "noshownode"}`} + testIdComplement={`${data?.type?.toLowerCase()}-${ + showNode ? "shownode" : "noshownode" + }`} colorName={ data.node?.outputs?.[index].allows_loop ? loopInputColorName @@ -357,7 +362,7 @@ function NodeOutputField({ data.node?.outputs?.[index].allows_loop, loopInputColorName, index, - ], + ] ); const disabledInspectButton = @@ -372,7 +377,7 @@ function NodeOutputField({ className={cn( "relative flex h-11 w-full flex-wrap items-center justify-between bg-muted px-5 py-2", lastOutput ? "rounded-b-[0.69rem]" : "", - isToolMode && "bg-primary", + isToolMode && "bg-primary" )} > {LoopHandle} @@ -412,42 +417,44 @@ function NodeOutputField({ /> - -
- - +
+ {}} - id={data?.type} - /> - - {looping && ( - - Looping - - )} -
- + nodeId={flowPoolId} + outputName={internalOutputName} + > + {}} + id={data?.type} + /> +
+ {looping && ( + + Looping + + )} +
+
+ )}
{Handle} diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx index e5a95d9d619b..673f40e7b440 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx @@ -58,7 +58,7 @@ export default function InspectionPanelHeader({ return ( <> -
+
{data.node?.display_name ?? data.type} - - Component Settings -
diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelLogs.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelLogs.tsx new file mode 100644 index 000000000000..3455c3ff6f4e --- /dev/null +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelLogs.tsx @@ -0,0 +1,79 @@ +import { useMemo } from "react"; +import type { NodeDataType } from "@/types/flow"; +import useFlowStore from "@/stores/flowStore"; +import SwitchOutputView from "@/CustomNodes/GenericNode/components/outputModal/components/switchOutputView"; +import { getGroupOutputNodeId } from "@/utils/reactflowUtils"; + +interface InspectionPanelLogsProps { + data: NodeDataType; +} + +export default function InspectionPanelLogs({ + data, +}: InspectionPanelLogsProps) { + const flowPool = useFlowStore((state) => state.flowPool); + + // Get all outputs from the node + const outputs = useMemo(() => { + return data.node?.outputs?.filter((output) => !output.hidden) ?? []; + }, [data.node?.outputs]); + + // Get the first output with logs + const firstOutputWithLogs = useMemo(() => { + for (const output of outputs) { + const outputProxy = output.proxy; + let flowPoolId = data.id; + let internalOutputName = output.name; + + if (data.node?.flow && outputProxy) { + const realOutput = getGroupOutputNodeId( + data.node.flow, + outputProxy.name, + outputProxy.id, + ); + if (realOutput) { + flowPoolId = realOutput.id; + internalOutputName = realOutput.outputName; + } + } + + const flowPoolNode = flowPool[flowPoolId]?.[ + (flowPool[flowPoolId]?.length ?? 1) - 1 + ]; + + if (flowPoolNode?.data?.logs?.[internalOutputName]) { + return { + nodeId: flowPoolId, + outputName: internalOutputName, + displayName: output.display_name || output.name, + }; + } + } + return null; + }, [outputs, data.id, data.node?.flow, flowPool]); + + if (!firstOutputWithLogs) { + return ( +
+ No logs available. Please build the component first. +
+ ); + } + + return ( +
+
+ {firstOutputWithLogs.displayName} +
+
+ +
+
+ ); +} + +// Made with Bob \ No newline at end of file diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelOutputs.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelOutputs.tsx new file mode 100644 index 000000000000..2781d7364cdd --- /dev/null +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelOutputs.tsx @@ -0,0 +1,79 @@ +import { useMemo } from "react"; +import type { NodeDataType } from "@/types/flow"; +import useFlowStore from "@/stores/flowStore"; +import SwitchOutputView from "@/CustomNodes/GenericNode/components/outputModal/components/switchOutputView"; +import { getGroupOutputNodeId } from "@/utils/reactflowUtils"; + +interface InspectionPanelOutputsProps { + data: NodeDataType; +} + +export default function InspectionPanelOutputs({ + data, +}: InspectionPanelOutputsProps) { + const flowPool = useFlowStore((state) => state.flowPool); + + // Get all outputs from the node + const outputs = useMemo(() => { + return data.node?.outputs?.filter((output) => !output.hidden) ?? []; + }, [data.node?.outputs]); + + // Get the first output with data + const firstOutputWithData = useMemo(() => { + for (const output of outputs) { + const outputProxy = output.proxy; + let flowPoolId = data.id; + let internalOutputName = output.name; + + if (data.node?.flow && outputProxy) { + const realOutput = getGroupOutputNodeId( + data.node.flow, + outputProxy.name, + outputProxy.id, + ); + if (realOutput) { + flowPoolId = realOutput.id; + internalOutputName = realOutput.outputName; + } + } + + const flowPoolNode = flowPool[flowPoolId]?.[ + (flowPool[flowPoolId]?.length ?? 1) - 1 + ]; + + if (flowPoolNode?.data?.outputs?.[internalOutputName]?.message) { + return { + nodeId: flowPoolId, + outputName: internalOutputName, + displayName: output.display_name || output.name, + }; + } + } + return null; + }, [outputs, data.id, data.node?.flow, flowPool]); + + if (!firstOutputWithData) { + return ( +
+ No output data available. Please build the component first. +
+ ); + } + + return ( +
+
+ {firstOutputWithData.displayName} +
+
+ +
+
+ ); +} + +// Made with Bob \ No newline at end of file diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx index c3e4ad951d12..01bf075b439d 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx @@ -1,10 +1,13 @@ import { Panel } from "@xyflow/react"; import { motion, AnimatePresence } from "framer-motion"; -import { memo } from "react"; +import { memo, useState } from "react"; import type { AllNodeType } from "@/types/flow"; import { cn } from "@/utils/utils"; +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; import InspectionPanelFields from "./components/InspectionPanelFields"; import InspectionPanelHeader from "./components/InspectionPanelHeader"; +import InspectionPanelOutputs from "./components/InspectionPanelOutputs"; +import InspectionPanelLogs from "./components/InspectionPanelLogs"; interface InspectionPanelProps { selectedNode: AllNodeType | null; @@ -17,6 +20,10 @@ const InspectionPanel = memo(function InspectionPanel({ isVisible, onClose, }: InspectionPanelProps) { + const [activeTab, setActiveTab] = useState<"controls" | "outputs" | "logs">( + "controls", + ); + return ( {isVisible && selectedNode && selectedNode.type === "genericNode" && ( @@ -40,9 +47,40 @@ const InspectionPanel = memo(function InspectionPanel({ )} > -
- -
+ + setActiveTab(value as "controls" | "outputs" | "logs") + } + className="flex flex-col flex-1 overflow-hidden" + > + + + Controls + + + Outputs + + + Logs + + + + + + + + + + + + )} From 12407f9d31af6d3cd7aea3475a2f3b2a1bf25001 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 19:54:05 +0000 Subject: [PATCH 18/20] [autofix.ci] apply automated fixes --- .../components/NodeOutputfield/index.tsx | 34 +++++++++---------- .../components/InspectionPanelLogs.tsx | 7 ++-- .../components/InspectionPanelOutputs.tsx | 7 ++-- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/NodeOutputfield/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/NodeOutputfield/index.tsx index b35ede52c22b..df0016361f00 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/NodeOutputfield/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/NodeOutputfield/index.tsx @@ -47,7 +47,7 @@ const _EyeIcon = memo( strokeWidth={ICON_STROKE_WIDTH} name={hidden ? "EyeOff" : "Eye"} /> - ) + ), ); const SnowflakeIcon = memo(() => ( @@ -75,7 +75,7 @@ const InspectButton = memo( onClick: () => void; id: string; }, - ref: React.ForwardedRef + ref: React.ForwardedRef, ) => ( - ) - ) + ), + ), ); InspectButton.displayName = "InspectButton"; @@ -142,7 +142,7 @@ function NodeOutputField({ const realOutput = getGroupOutputNodeId( data.node.flow, outputProxy.name, - outputProxy.id + outputProxy.id, ); if (realOutput) { return { @@ -167,24 +167,24 @@ function NodeOutputField({ unknownOutput: logTypeIsUnknown(flowPoolNode?.data, internalOutputName), errorOutput: logTypeIsError(flowPoolNode?.data, internalOutputName), }), - [flowPool, flowPoolId, flowPoolNode?.data, internalOutputName] + [flowPool, flowPoolId, flowPoolNode?.data, internalOutputName], ); const emptyOutput = useMemo(() => { return Object.keys(flowPoolNode?.data?.outputs ?? {})?.every( - (key) => flowPoolNode?.data?.outputs[key]?.message?.length === 0 + (key) => flowPoolNode?.data?.outputs[key]?.message?.length === 0, ); }, [flowPoolNode?.data?.outputs]); const disabledOutput = useMemo( () => edges.some((edge) => edge.sourceHandle === scapedJSONStringfy(id)), - [edges, id] + [edges, id], ); const looping = useMemo(() => { return edges.some((edge) => { const targetHandleObject: targetHandleType = scapeJSONParse( - edge.targetHandle! + edge.targetHandle!, ); return ( targetHandleObject.output_types && @@ -214,7 +214,7 @@ function NodeOutputField({ }); updateNodeInternals(data.id); }, - [data.id, index, setNode, updateNodeInternals] + [data.id, index, setNode, updateNodeInternals], ); useEffect(() => { @@ -242,11 +242,11 @@ function NodeOutputField({ .toSorted((a, b) => { const indexA = data?.node?.outputs?.findIndex( - (output) => output.name === a.data?.sourceHandle?.name + (output) => output.name === a.data?.sourceHandle?.name, ) ?? 0; const indexB = data?.node?.outputs?.findIndex( - (output) => output.name === b.data?.sourceHandle?.name + (output) => output.name === b.data?.sourceHandle?.name, ) ?? 0; return indexA - indexB; }); @@ -362,7 +362,7 @@ function NodeOutputField({ data.node?.outputs?.[index].allows_loop, loopInputColorName, index, - ] + ], ); const disabledInspectButton = @@ -377,7 +377,7 @@ function NodeOutputField({ className={cn( "relative flex h-11 w-full flex-wrap items-center justify-between bg-muted px-5 py-2", lastOutput ? "rounded-b-[0.69rem]" : "", - isToolMode && "bg-primary" + isToolMode && "bg-primary", )} > {LoopHandle} diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelLogs.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelLogs.tsx index 3455c3ff6f4e..b743889e6b33 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelLogs.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelLogs.tsx @@ -37,9 +37,8 @@ export default function InspectionPanelLogs({ } } - const flowPoolNode = flowPool[flowPoolId]?.[ - (flowPool[flowPoolId]?.length ?? 1) - 1 - ]; + const flowPoolNode = + flowPool[flowPoolId]?.[(flowPool[flowPoolId]?.length ?? 1) - 1]; if (flowPoolNode?.data?.logs?.[internalOutputName]) { return { @@ -76,4 +75,4 @@ export default function InspectionPanelLogs({ ); } -// Made with Bob \ No newline at end of file +// Made with Bob diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelOutputs.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelOutputs.tsx index 2781d7364cdd..e8001879bc69 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelOutputs.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelOutputs.tsx @@ -37,9 +37,8 @@ export default function InspectionPanelOutputs({ } } - const flowPoolNode = flowPool[flowPoolId]?.[ - (flowPool[flowPoolId]?.length ?? 1) - 1 - ]; + const flowPoolNode = + flowPool[flowPoolId]?.[(flowPool[flowPoolId]?.length ?? 1) - 1]; if (flowPoolNode?.data?.outputs?.[internalOutputName]?.message) { return { @@ -76,4 +75,4 @@ export default function InspectionPanelOutputs({ ); } -// Made with Bob \ No newline at end of file +// Made with Bob From 1dd1bb691564e6da07b3c503ab2d1013d41f0d39 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 16 Jan 2026 17:23:26 -0300 Subject: [PATCH 19/20] removed label from code button --- .../InspectionPanel/components/InspectionPanelHeader.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx index 673f40e7b440..5f67e7f9a2bf 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx @@ -77,7 +77,6 @@ export default function InspectionPanelHeader({ s.name.toLowerCase().startsWith("code"), From f494cc4f16c633482dbb624b5a95b722d08a1570 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 16 Jan 2026 17:34:24 -0300 Subject: [PATCH 20/20] filter handleinputs --- .../InspectionPanel/components/InspectionPanelFields.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx index 55c70c7a85b1..2d2fa470df96 100644 --- a/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx +++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx @@ -28,6 +28,12 @@ export default function InspectionPanelFields({ return false; } + // Filter out fields that are just handles (HandleInput type) + // These are fields that only serve as connection points + if (template._input_type === "HandleInput") { + return false; + } + return true; }) .sort((a, b) =>