Added Hide Outputs functionality
This commit is contained in:
parent
b0e6e42115
commit
c65f2e1ab1
5 changed files with 161 additions and 40 deletions
|
|
@ -164,6 +164,9 @@ class Output(BaseModel):
|
||||||
name: str = Field(default=None)
|
name: str = Field(default=None)
|
||||||
"""The name of the field."""
|
"""The name of the field."""
|
||||||
|
|
||||||
|
hide: Optional[bool] = Field(default=None)
|
||||||
|
"""Dictates if the field is hidden."""
|
||||||
|
|
||||||
display_name: Optional[str] = Field(default=None)
|
display_name: Optional[str] = Field(default=None)
|
||||||
"""The display name of the field."""
|
"""The display name of the field."""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,12 @@ export default function ParameterComponent({
|
||||||
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id)
|
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id)
|
||||||
) ?? false;
|
) ?? false;
|
||||||
|
|
||||||
|
let disabledOutput =
|
||||||
|
edges.some(
|
||||||
|
(edge) =>
|
||||||
|
edge.sourceHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
|
||||||
|
) ?? false;
|
||||||
|
|
||||||
const handleRefreshButtonPress = async (name, data) => {
|
const handleRefreshButtonPress = async (name, data) => {
|
||||||
handleRefreshButtonPressHook(name, data);
|
handleRefreshButtonPressHook(name, data);
|
||||||
};
|
};
|
||||||
|
|
@ -190,6 +196,32 @@ export default function ParameterComponent({
|
||||||
optionalHandle = null;
|
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 ? (
|
return !showNode ? (
|
||||||
left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
|
left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
|
||||||
<></>
|
<></>
|
||||||
|
|
@ -262,6 +294,23 @@ export default function ParameterComponent({
|
||||||
(left ? "" : " justify-end")
|
(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}>
|
<Case condition={left && data.node?.frozen}>
|
||||||
<div className="pr-1">
|
<div className="pr-1">
|
||||||
<IconComponent className="h-5 w-5 text-ice" name={"Snowflake"} />
|
<IconComponent className="h-5 w-5 text-ice" name={"Snowflake"} />
|
||||||
|
|
@ -325,6 +374,7 @@ export default function ParameterComponent({
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
|
{left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
|
||||||
<></>
|
<></>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@ import { useEffect, useMemo, useState } from "react";
|
||||||
import { useHotkeys } from "react-hotkeys-hook";
|
import { useHotkeys } from "react-hotkeys-hook";
|
||||||
import Markdown from "react-markdown";
|
import Markdown from "react-markdown";
|
||||||
import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
|
import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent, {
|
||||||
|
ForwardedIconComponent,
|
||||||
|
} from "../../components/genericIconComponent";
|
||||||
import InputComponent from "../../components/inputComponent";
|
import InputComponent from "../../components/inputComponent";
|
||||||
import ShadTooltip from "../../components/shadTooltipComponent";
|
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
|
|
@ -210,6 +212,8 @@ export default function GenericNode({
|
||||||
|
|
||||||
const [loadingUpdate, setLoadingUpdate] = useState(false);
|
const [loadingUpdate, setLoadingUpdate] = useState(false);
|
||||||
|
|
||||||
|
const [showHiddenOutputs, setShowHiddenOutputs] = useState(false);
|
||||||
|
|
||||||
const handleUpdateCode = () => {
|
const handleUpdateCode = () => {
|
||||||
setLoadingUpdate(true);
|
setLoadingUpdate(true);
|
||||||
takeSnapshot();
|
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() {
|
function handlePlayWShortcut() {
|
||||||
if (buildStatus === BuildStatus.BUILDING || isBuilding || !selected) return;
|
if (buildStatus === BuildStatus.BUILDING || isBuilding || !selected) return;
|
||||||
setValidationStatus(null);
|
setValidationStatus(null);
|
||||||
|
|
@ -256,6 +266,42 @@ export default function GenericNode({
|
||||||
|
|
||||||
const shortcuts = useShortcutsStore((state) => state.shortcuts);
|
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(() => {
|
const memoizedNodeToolbarComponent = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
<NodeToolbar>
|
<NodeToolbar>
|
||||||
|
|
@ -582,13 +628,14 @@ export default function GenericNode({
|
||||||
|
|
||||||
{showNode && (
|
{showNode && (
|
||||||
<div
|
<div
|
||||||
className={
|
className={cn(
|
||||||
showNode
|
showNode
|
||||||
? data.node?.description === "" && !nameEditable
|
? data.node?.description === "" && !nameEditable
|
||||||
? "pb-5"
|
? "pb-8"
|
||||||
: "py-5"
|
: "pb-8 pt-5"
|
||||||
: ""
|
: "",
|
||||||
}
|
"relative",
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{/* increase height!! */}
|
{/* increase height!! */}
|
||||||
<div className="generic-node-desc">
|
<div className="generic-node-desc">
|
||||||
|
|
@ -751,39 +798,58 @@ export default function GenericNode({
|
||||||
>
|
>
|
||||||
{" "}
|
{" "}
|
||||||
</div>
|
</div>
|
||||||
|
{!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 &&
|
||||||
data.node!.outputs.length > 0 &&
|
data.node!.outputs.map((output, idx) =>
|
||||||
data.node!.outputs.map((output, idx) => (
|
renderOutputParameter(
|
||||||
<ParameterComponent
|
output,
|
||||||
index={idx}
|
data.node!.outputs?.findIndex(
|
||||||
key={scapedJSONStringfy({
|
(out) => out.name === output.name,
|
||||||
output_types: output.types,
|
) ?? idx,
|
||||||
name: output.name,
|
),
|
||||||
id: data.id,
|
)}
|
||||||
dataType: data.type,
|
</div>
|
||||||
})}
|
</div>
|
||||||
data={data}
|
{hiddenOutputs && hiddenOutputs.length > 0 && (
|
||||||
color={
|
<div
|
||||||
nodeColors[output.selected ?? output.types[0]] ??
|
className={cn(
|
||||||
nodeColors[types[output.selected ?? output.types[0]]] ??
|
"absolute left-0 right-0 flex justify-center",
|
||||||
nodeColors[types[data.type]] ??
|
(shownOutputs && shownOutputs.length > 0) ||
|
||||||
nodeColors.unknown
|
showHiddenOutputs
|
||||||
}
|
? "bottom-5"
|
||||||
outputProxy={output.proxy}
|
: "bottom-1.5",
|
||||||
title={output.display_name ?? output.name}
|
)}
|
||||||
tooltipTitle={output.selected ?? output.types[0]}
|
>
|
||||||
id={{
|
<Button
|
||||||
output_types: [output.selected ?? output.types[0]],
|
variant="none"
|
||||||
id: data.id,
|
size="none"
|
||||||
dataType: data.type,
|
className="left-0 right-0 rounded-full border bg-background"
|
||||||
name: output.name,
|
onClick={() => setShowHiddenOutputs(!showHiddenOutputs)}
|
||||||
}}
|
>
|
||||||
type={output.types.join("|")}
|
<ForwardedIconComponent
|
||||||
left={false}
|
name={"ChevronDown"}
|
||||||
showNode={showNode}
|
strokeWidth={1.5}
|
||||||
outputName={output.name}
|
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>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ export type OutputFieldType = {
|
||||||
selected?: string;
|
selected?: string;
|
||||||
name: string;
|
name: string;
|
||||||
display_name: string;
|
display_name: string;
|
||||||
|
hide?: boolean;
|
||||||
proxy?: OutputFieldProxyType;
|
proxy?: OutputFieldProxyType;
|
||||||
};
|
};
|
||||||
export type sendAllProps = {
|
export type sendAllProps = {
|
||||||
|
|
|
||||||
|
|
@ -59,10 +59,11 @@ export type DropDownComponentType = {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
};
|
};
|
||||||
export type ParameterComponentType = {
|
export type ParameterComponentType = {
|
||||||
selected: boolean;
|
selected?: boolean;
|
||||||
data: NodeDataType;
|
data: NodeDataType;
|
||||||
title: string;
|
title: string;
|
||||||
conditionPath?: string | null;
|
conditionPath?: string | null;
|
||||||
|
key: string;
|
||||||
id: sourceHandleType | targetHandleType;
|
id: sourceHandleType | targetHandleType;
|
||||||
color: string;
|
color: string;
|
||||||
left: boolean;
|
left: boolean;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue