Added Hide Outputs functionality

This commit is contained in:
Lucas Oliveira 2024-06-12 19:40:38 -03:00
commit c65f2e1ab1
5 changed files with 161 additions and 40 deletions

View file

@ -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."""

View file

@ -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 && (
<div className="flex-1">
<Button
disabled={disabledOutput}
variant="none"
size="none"
onClick={() => handleUpdateOutputHide()}
data-testid={`output-inspection-${title.toLowerCase()}`}
>
<IconComponent
className="h-4 w-4"
strokeWidth={1.5}
name={data.node?.outputs![index].hide ? "EyeOff" : "Eye"}
/>
</Button>
</div>
)}
<Case condition={left && data.node?.frozen}>
<div className="pr-1">
<IconComponent className="h-5 w-5 text-ice" name={"Snowflake"} />
@ -325,6 +374,7 @@ export default function ParameterComponent({
)}
</div>
</div>
{left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
<></>
) : (

View file

@ -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 (
<ParameterComponent
index={idx}
key={
scapedJSONStringfy({
output_types: output.types,
name: output.name,
id: data.id,
dataType: data.type,
}) + idx
}
data={data}
color={
nodeColors[output.selected ?? output.types[0]] ??
nodeColors[types[output.selected ?? output.types[0]]] ??
nodeColors[types[data.type]] ??
nodeColors.unknown
}
outputProxy={output.proxy}
title={output.display_name ?? output.name}
tooltipTitle={output.selected ?? output.types[0]}
id={{
output_types: [output.selected ?? output.types[0]],
id: data.id,
dataType: data.type,
name: output.name,
}}
type={output.types.join("|")}
left={false}
showNode={showNode}
outputName={output.name}
/>
);
};
const memoizedNodeToolbarComponent = useMemo(() => {
return (
<NodeToolbar>
@ -582,13 +628,14 @@ export default function GenericNode({
{showNode && (
<div
className={
className={cn(
showNode
? data.node?.description === "" && !nameEditable
? "pb-5"
: "py-5"
: ""
}
? "pb-8"
: "pb-8 pt-5"
: "",
"relative",
)}
>
{/* increase height!! */}
<div className="generic-node-desc">
@ -751,39 +798,58 @@ export default function GenericNode({
>
{" "}
</div>
{data.node!.outputs &&
data.node!.outputs.length > 0 &&
data.node!.outputs.map((output, idx) => (
<ParameterComponent
index={idx}
key={scapedJSONStringfy({
output_types: output.types,
name: output.name,
id: data.id,
dataType: data.type,
})}
data={data}
color={
nodeColors[output.selected ?? output.types[0]] ??
nodeColors[types[output.selected ?? output.types[0]]] ??
nodeColors[types[data.type]] ??
nodeColors.unknown
}
outputProxy={output.proxy}
title={output.display_name ?? output.name}
tooltipTitle={output.selected ?? output.types[0]}
id={{
output_types: [output.selected ?? output.types[0]],
id: data.id,
dataType: data.type,
name: output.name,
}}
type={output.types.join("|")}
left={false}
showNode={showNode}
outputName={output.name}
/>
))}
{!showHiddenOutputs &&
shownOutputs &&
shownOutputs.map((output, idx) =>
renderOutputParameter(
output,
data.node!.outputs?.findIndex(
(out) => out.name === output.name,
) ?? idx,
),
)}
<div
className={cn(showHiddenOutputs ? "" : "h-0 overflow-hidden")}
>
<div className="block">
{data.node!.outputs &&
data.node!.outputs.map((output, idx) =>
renderOutputParameter(
output,
data.node!.outputs?.findIndex(
(out) => out.name === output.name,
) ?? idx,
),
)}
</div>
</div>
{hiddenOutputs && hiddenOutputs.length > 0 && (
<div
className={cn(
"absolute left-0 right-0 flex justify-center",
(shownOutputs && shownOutputs.length > 0) ||
showHiddenOutputs
? "bottom-5"
: "bottom-1.5",
)}
>
<Button
variant="none"
size="none"
className="left-0 right-0 rounded-full border bg-background"
onClick={() => setShowHiddenOutputs(!showHiddenOutputs)}
>
<ForwardedIconComponent
name={"ChevronDown"}
strokeWidth={1.5}
className={cn(
"h-5 w-5 pt-px text-muted-foreground transition-all group-hover:text-medium-indigo group-hover/node:opacity-100",
showHiddenOutputs ? "rotate-180 transform" : "",
)}
/>
</Button>
</div>
)}
</>
</div>
)}

View file

@ -76,6 +76,7 @@ export type OutputFieldType = {
selected?: string;
name: string;
display_name: string;
hide?: boolean;
proxy?: OutputFieldProxyType;
};
export type sendAllProps = {

View file

@ -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;