diff --git a/src/backend/base/langflow/template/field/base.py b/src/backend/base/langflow/template/field/base.py index 22f86b3c8..d06655211 100644 --- a/src/backend/base/langflow/template/field/base.py +++ b/src/backend/base/langflow/template/field/base.py @@ -164,6 +164,9 @@ class Output(BaseModel): name: str = Field(default=None) """The name of the field.""" + hide: Optional[bool] = Field(default=None) + """Dictates if the field is hidden.""" + display_name: Optional[str] = Field(default=None) """The display name of the field.""" diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 65d36d90a..eea25e5b2 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -135,6 +135,12 @@ export default function ParameterComponent({ edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id) ) ?? false; + let disabledOutput = + edges.some( + (edge) => + edge.sourceHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id), + ) ?? false; + const handleRefreshButtonPress = async (name, data) => { handleRefreshButtonPressHook(name, data); }; @@ -190,6 +196,32 @@ export default function ParameterComponent({ optionalHandle = null; } + const handleUpdateOutputHide = (value?: boolean) => { + setNode(data.id, (oldNode) => { + let newNode = cloneDeep(oldNode); + newNode.data = { + ...newNode.data, + node: { + ...newNode.data.node, + outputs: newNode.data.node.outputs?.map((output, i) => { + if (i === index) { + output.hide = value ?? !output.hide; + } + return output; + }), + }, + }; + return newNode; + }); + updateNodeInternals(data.id); + }; + + useEffect(() => { + if (disabledOutput) { + handleUpdateOutputHide(false); + } + }, [disabledOutput]); + return !showNode ? ( left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? ( <> @@ -262,6 +294,23 @@ export default function ParameterComponent({ (left ? "" : " justify-end") } > + {!left && ( +
+ +
+ )}
@@ -325,6 +374,7 @@ export default function ParameterComponent({ )}
+ {left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? ( <> ) : ( diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index 31f5852dd..efe3984c2 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -3,7 +3,9 @@ import { useEffect, useMemo, useState } from "react"; import { useHotkeys } from "react-hotkeys-hook"; import Markdown from "react-markdown"; import { NodeToolbar, useUpdateNodeInternals } from "reactflow"; -import IconComponent from "../../components/genericIconComponent"; +import IconComponent, { + ForwardedIconComponent, +} from "../../components/genericIconComponent"; import InputComponent from "../../components/inputComponent"; import ShadTooltip from "../../components/shadTooltipComponent"; import { Button } from "../../components/ui/button"; @@ -210,6 +212,8 @@ export default function GenericNode({ const [loadingUpdate, setLoadingUpdate] = useState(false); + const [showHiddenOutputs, setShowHiddenOutputs] = useState(false); + const handleUpdateCode = () => { setLoadingUpdate(true); takeSnapshot(); @@ -241,6 +245,12 @@ export default function GenericNode({ } } + const shownOutputs = + data.node!.outputs?.filter((output) => !output.hide) ?? []; + + const hiddenOutputs = + data.node!.outputs?.filter((output) => output.hide) ?? []; + function handlePlayWShortcut() { if (buildStatus === BuildStatus.BUILDING || isBuilding || !selected) return; setValidationStatus(null); @@ -256,6 +266,42 @@ export default function GenericNode({ const shortcuts = useShortcutsStore((state) => state.shortcuts); + const renderOutputParameter = (output, idx) => { + return ( + + ); + }; + const memoizedNodeToolbarComponent = useMemo(() => { return ( @@ -582,13 +628,14 @@ export default function GenericNode({ {showNode && (
{/* increase height!! */}
@@ -751,39 +798,58 @@ export default function GenericNode({ > {" "}
- {data.node!.outputs && - data.node!.outputs.length > 0 && - data.node!.outputs.map((output, idx) => ( - - ))} + {!showHiddenOutputs && + shownOutputs && + shownOutputs.map((output, idx) => + renderOutputParameter( + output, + data.node!.outputs?.findIndex( + (out) => out.name === output.name, + ) ?? idx, + ), + )} +
+
+ {data.node!.outputs && + data.node!.outputs.map((output, idx) => + renderOutputParameter( + output, + data.node!.outputs?.findIndex( + (out) => out.name === output.name, + ) ?? idx, + ), + )} +
+
+ {hiddenOutputs && hiddenOutputs.length > 0 && ( +
0) || + showHiddenOutputs + ? "bottom-5" + : "bottom-1.5", + )} + > + +
+ )}
)} diff --git a/src/frontend/src/types/api/index.ts b/src/frontend/src/types/api/index.ts index a228e9f29..16c1b6c70 100644 --- a/src/frontend/src/types/api/index.ts +++ b/src/frontend/src/types/api/index.ts @@ -76,6 +76,7 @@ export type OutputFieldType = { selected?: string; name: string; display_name: string; + hide?: boolean; proxy?: OutputFieldProxyType; }; export type sendAllProps = { diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 0b96fd017..5dbfd7b88 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -59,10 +59,11 @@ export type DropDownComponentType = { children?: ReactNode; }; export type ParameterComponentType = { - selected: boolean; + selected?: boolean; data: NodeDataType; title: string; conditionPath?: string | null; + key: string; id: sourceHandleType | targetHandleType; color: string; left: boolean;