diff --git a/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx
index 0d6c0dc68863..85d60356c216 100644
--- a/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx
+++ b/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx
@@ -9,7 +9,10 @@ import {
CustomParameterLabel,
getCustomParameterTitle,
} from "@/customization/components/custom-parameter";
-import { LANGFLOW_AGENTIC_EXPERIENCE } from "@/customization/feature-flags";
+import {
+ ENABLE_INSPECTION_PANEL,
+ LANGFLOW_AGENTIC_EXPERIENCE,
+} from "@/customization/feature-flags";
import { useIsAutoLogin } from "@/hooks/use-is-auto-login";
import useAuthStore from "@/stores/authStore";
import { cn } from "@/utils/utils";
@@ -226,27 +229,28 @@ export default function NodeInputField({
/>
- {data.node?.template[name] !== undefined && (
-
- )}
+ {(!ENABLE_INSPECTION_PANEL || !optionalHandle) &&
+ data.node?.template[name] !== undefined && (
+
+ )}
);
diff --git a/src/frontend/src/CustomNodes/GenericNode/components/NodeOutputfield/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/NodeOutputfield/index.tsx
index a3f84fbc6ea9..df0016361f00 100644
--- a/src/frontend/src/CustomNodes/GenericNode/components/NodeOutputfield/index.tsx
+++ b/src/frontend/src/CustomNodes/GenericNode/components/NodeOutputfield/index.tsx
@@ -38,6 +38,7 @@ import { nodeColorsName } from "../../../../utils/styleUtils";
import HandleRenderComponent from "../handleRenderComponent";
import OutputComponent from "../OutputComponent";
import OutputModal from "../outputModal";
+import { ENABLE_INSPECTION_PANEL } from "@/customization/feature-flags";
const _EyeIcon = memo(
({ hidden, className }: { hidden: boolean; className: string }) => (
@@ -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
@@ -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/CustomNodes/GenericNode/components/RenderInputParameters/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/RenderInputParameters/index.tsx
index d219722160b2..426c6f2fff33 100644
--- a/src/frontend/src/CustomNodes/GenericNode/components/RenderInputParameters/index.tsx
+++ b/src/frontend/src/CustomNodes/GenericNode/components/RenderInputParameters/index.tsx
@@ -5,6 +5,7 @@ import { sortToolModeFields } from "@/CustomNodes/helpers/sort-tool-mode-field";
import getFieldTitle from "@/CustomNodes/utils/get-field-title";
import { scapedJSONStringfy } from "@/utils/reactflowUtils";
import NodeInputField from "../NodeInputField";
+import { ENABLE_INSPECTION_PANEL } from "@/customization/feature-flags";
const RenderInputParameters = ({
data,
@@ -31,11 +32,31 @@ const RenderInputParameters = ({
const shownTemplateFields = useMemo(() => {
return templateFields.filter((templateField) => {
const template = data.node?.template[templateField];
- return (
- template?.show &&
- !template?.advanced &&
- !(template?.tool_mode && isToolMode)
- );
+
+ if (!ENABLE_INSPECTION_PANEL) {
+ 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/customization/feature-flags.ts b/src/frontend/src/customization/feature-flags.ts
index 9efa82c663a8..0e7225566109 100644
--- a/src/frontend/src/customization/feature-flags.ts
+++ b/src/frontend/src/customization/feature-flags.ts
@@ -17,6 +17,7 @@ export const ENABLE_IMAGE_ON_PLAYGROUND = false;
export const ENABLE_MCP = true;
export const ENABLE_MCP_NOTICE = false;
export const ENABLE_KNOWLEDGE_BASES = false;
+export const ENABLE_INSPECTION_PANEL = true;
export const ENABLE_MCP_COMPOSER =
import.meta.env.LANGFLOW_MCP_COMPOSER_ENABLED === "true";
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..e323a0b106f8
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelField.tsx
@@ -0,0 +1,191 @@
+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 NodeInputInfo from "@/CustomNodes/GenericNode/components/NodeInputInfo";
+
+export default function InspectionPanelField({
+ id,
+ data,
+ title,
+ name = "",
+ required = false,
+ info = "",
+ showNode,
+ isToolMode = false,
+ proxy,
+}: Omit<
+ NodeInputFieldComponentType,
+ | "colors"
+ | "tooltipTitle"
+ | "type"
+ | "optionalHandle"
+ | "colorName"
+ | "lastInput"
+>) {
+ 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..2d2fa470df96
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelFields.tsx
@@ -0,0 +1,87 @@
+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) {
+ // 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];
+
+ // 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 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) =>
+ sortToolModeFields(
+ a,
+ b,
+ data.node!.template,
+ data.node?.field_order ?? [],
+ false,
+ ),
+ );
+ }, [data.node?.template, data.node?.field_order]);
+
+ if (allFields.length === 0) {
+ return (
+
+ No fields available
+
+ );
+ }
+
+ return (
+
+ {allFields.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..5f67e7f9a2bf
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelHeader.tsx
@@ -0,0 +1,125 @@
+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";
+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";
+import { ToolbarButton } from "../../nodeToolbarComponent/components/toolbar-button";
+import { useShortcutsStore } from "@/stores/shortcuts";
+
+interface InspectionPanelHeaderProps {
+ data: NodeDataType;
+ onClose?: () => void;
+}
+
+export default function InspectionPanelHeader({
+ data,
+ onClose,
+}: InspectionPanelHeaderProps) {
+ const [openCodeModal, setOpenCodeModal] = useState(false);
+ const { handleNodeClass } = useHandleNodeClass(data.id);
+ const { handleOnNewValue } = useHandleOnNewValue({
+ node: data.node!,
+ nodeId: data.id,
+ name: "code",
+ });
+
+ const hasCode = useMemo(
+ () => Object.keys(data.node!.template).includes("code"),
+ [data.node],
+ );
+
+ const handleOpenCode = useCallback(() => {
+ if (hasCode) {
+ setOpenCodeModal(true);
+ }
+ }, [hasCode]);
+
+ // Wrapper to match CodeAreaModal's expected signature
+ const handleSetValue = useCallback(
+ (value: string) => {
+ handleOnNewValue({ value });
+ },
+ [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 (
+ <>
+
+
+
+
+
+ {data.node?.display_name ?? data.type}
+
+
+
+
+ {hasCode && (
+
+
+ s.name.toLowerCase().startsWith("code"),
+ )}
+ dataTestId="code-button-modal"
+ />
+
+ )}
+ {onClose && (
+
+
+
+ )}
+
+
+
+ {hasCode && openCodeModal && (
+
+ {
+ handleNodeClass(apiClassType, type);
+ }}
+ nodeClass={data.node}
+ value={data.node?.template?.code?.value ?? ""}
+ componentId={data.id}
+ >
+ <>>
+
+
+ )}
+ >
+ );
+}
+
+// Made with Bob
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..b743889e6b33
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelLogs.tsx
@@ -0,0 +1,78 @@
+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
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..e8001879bc69
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelOutputs.tsx
@@ -0,0 +1,78 @@
+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
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..01bf075b439d
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/InspectionPanel/index.tsx
@@ -0,0 +1,93 @@
+import { Panel } from "@xyflow/react";
+import { motion, AnimatePresence } from "framer-motion";
+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;
+ isVisible: boolean;
+ onClose?: () => void;
+}
+
+const InspectionPanel = memo(function InspectionPanel({
+ selectedNode,
+ isVisible,
+ onClose,
+}: InspectionPanelProps) {
+ const [activeTab, setActiveTab] = useState<"controls" | "outputs" | "logs">(
+ "controls",
+ );
+
+ return (
+
+ {isVisible && selectedNode && selectedNode.type === "genericNode" && (
+
+
+
+
+ setActiveTab(value as "controls" | "outputs" | "logs")
+ }
+ className="flex flex-col flex-1 overflow-hidden"
+ >
+
+
+ Controls
+
+
+ Outputs
+
+
+ Logs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ );
+});
+
+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..ad2db9e2e0dd 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,
@@ -82,6 +83,7 @@ import {
} from "./MemoizedComponents";
import getRandomName from "./utils/get-random-name";
import isWrappedWithClass from "./utils/is-wrapped-with-class";
+import { ENABLE_INSPECTION_PANEL } from "@/customization/feature-flags";
const nodeTypes = {
genericNode: GenericNode,
@@ -744,6 +746,27 @@ 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;
+
+ // Handler to close the inspection panel by deselecting all nodes
+ const handleCloseInspectionPanel = useCallback(() => {
+ setNodes((nds) =>
+ nds.map((node) => ({
+ ...node,
+ selected: false,
+ })),
+ );
+ }, [setNodes]);
+
return (
{showCanvas ? (
@@ -758,6 +781,13 @@ export default function Page({
shadowBoxHeight={shadowBoxHeight}
/>
+ {ENABLE_INSPECTION_PANEL && (
+
+ )}
>
)}
diff --git a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx
index 1b1430a5f228..0b237972c38d 100644
--- a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx
+++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx
@@ -40,6 +40,7 @@ import ToolbarModals from "./components/toolbar-modals";
import useShortcuts from "./hooks/use-shortcuts";
import ShortcutDisplay from "./shortcutDisplay";
import ToolbarSelectItem from "./toolbarSelectItem";
+import { ENABLE_INSPECTION_PANEL } from "@/customization/feature-flags";
const NodeToolbarComponent = memo(
({
@@ -478,7 +479,7 @@ const NodeToolbarComponent = memo(
const renderToolbarButtons = useMemo(
() => (
<>
- {hasCode && (
+ {hasCode && !ENABLE_INSPECTION_PANEL && (
)}
- {nodeLength > 0 && (
+ {nodeLength > 0 && !ENABLE_INSPECTION_PANEL && (