Formatting project

This commit is contained in:
Cristhian Zanforlin Lousa 2023-06-14 21:22:45 -03:00
commit 86eb9af794
21 changed files with 470 additions and 492 deletions

View file

@ -59,8 +59,7 @@ export default function ParameterComponent({
data.node.template[name]?.value ?? false
);
useEffect(() => {
}, [closePopUp, data.node.template]);
useEffect(() => {}, [closePopUp, data.node.template]);
const { reactFlowInstance } = useContext(typesContext);
let disabled =
@ -69,216 +68,209 @@ export default function ParameterComponent({
const [myData, setMyData] = useState(useContext(typesContext).data);
useEffect(() => {
const groupedObj = groupByFamily(myData, tooltipTitle);
refHtml.current = groupedObj.map((item, i) => (
<span
key={i}
className={classNames(
i > 0 ? "items-center flex mt-3" : "items-center flex"
)}
const groupedObj = groupByFamily(myData, tooltipTitle);
refHtml.current = groupedObj.map((item, i) => (
<span
key={i}
className={classNames(
i > 0 ? "items-center flex mt-3" : "items-center flex"
)}
>
<div
className="h-5 w-5"
style={{
color: nodeColors[item.family],
}}
>
<div
className="h-5 w-5"
style={{
color: nodeColors[item.family],
}}
>
{React.createElement(nodeIcons[item.family])}
</div>
<span className="ps-2 text-gray-950">
{nodeNames[item.family] ?? ""}{" "}
<span className={classNames(left ? "hidden" : "")}>
{" "}
-&nbsp;
{item.type.split(", ").length > 2
? item.type.split(", ").map((el, i) => (
<>
<span key={i}>
{i == item.type.split(", ").length - 1
? el
: (el += `, `)}
</span>
{i % 2 == 0 && i > 0 && <br></br>}
</>
))
: item.type}
</span>
{React.createElement(nodeIcons[item.family])}
</div>
<span className="ps-2 text-gray-950">
{nodeNames[item.family] ?? ""}{" "}
<span className={classNames(left ? "hidden" : "")}>
{" "}
-&nbsp;
{item.type.split(", ").length > 2
? item.type.split(", ").map((el, i) => (
<>
<span key={i}>
{i == item.type.split(", ").length - 1
? el
: (el += `, `)}
</span>
{i % 2 == 0 && i > 0 && <br></br>}
</>
))
: item.type}
</span>
</span>
));
</span>
));
}, [tooltipTitle]);
return (
<>
<div
ref={ref}
className="w-full flex flex-wrap justify-between items-center bg-muted dark:bg-gray-800 dark:text-white mt-1 px-5 py-2"
>
<>
<div className={"text-sm truncate w-full " + (left ? "" : "text-end")}>
{title}
<span className="text-red-600">{required ? " *" : ""}</span>
</div>
{left &&
(type === "str" ||
type === "bool" ||
type === "float" ||
type === "code" ||
type === "prompt" ||
type === "file" ||
type === "int") ? (
<></>
) : (
<ShadTooltip
delayDuration={0}
content={refHtml.current}
side={left ? "left" : "right"}
open={refHtml?.current?.length > 0}
<div
ref={ref}
className="w-full flex flex-wrap justify-between items-center bg-muted dark:bg-gray-800 dark:text-white mt-1 px-5 py-2"
>
<>
<div
className={"text-sm truncate w-full " + (left ? "" : "text-end")}
>
<Handle
type={left ? "target" : "source"}
position={left ? Position.Left : Position.Right}
id={id}
isValidConnection={(connection) =>
isValidConnection(connection, reactFlowInstance)
}
className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ",
"w-3 h-3 rounded-full border-2 bg-white dark:bg-gray-800"
)}
style={{
borderColor: color,
top: position,
}}
></Handle>
</ShadTooltip>
)}
{left === true &&
type === "str" &&
!data.node.template[name].options ? (
<div className="mt-2 w-full">
{data.node.template[name].list ? (
<InputListComponent
disabled={disabled}
value={
!data.node.template[name].value ||
data.node.template[name].value === ""
? [""]
: data.node.template[name].value
{title}
<span className="text-red-600">{required ? " *" : ""}</span>
</div>
{left &&
(type === "str" ||
type === "bool" ||
type === "float" ||
type === "code" ||
type === "prompt" ||
type === "file" ||
type === "int") ? (
<></>
) : (
<ShadTooltip
delayDuration={0}
content={refHtml.current}
side={left ? "left" : "right"}
open={refHtml?.current?.length > 0}
>
<Handle
type={left ? "target" : "source"}
position={left ? Position.Left : Position.Right}
id={id}
isValidConnection={(connection) =>
isValidConnection(connection, reactFlowInstance)
}
onChange={(t: string[]) => {
data.node.template[name].value = t;
className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ",
"w-3 h-3 rounded-full border-2 bg-white dark:bg-gray-800"
)}
style={{
borderColor: color,
top: position,
}}
/>
) : data.node.template[name].multiline ? (
<TextAreaComponent
></Handle>
</ShadTooltip>
)}
{left === true &&
type === "str" &&
!data.node.template[name].options ? (
<div className="mt-2 w-full">
{data.node.template[name].list ? (
<InputListComponent
disabled={disabled}
value={
!data.node.template[name].value ||
data.node.template[name].value === ""
? [""]
: data.node.template[name].value
}
onChange={(t: string[]) => {
data.node.template[name].value = t;
}}
/>
) : data.node.template[name].multiline ? (
<TextAreaComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
) : (
<InputComponent
disabled={disabled}
disableCopyPaste={true}
password={data.node.template[name].password ?? false}
value={data.node.template[name].value ?? ""}
onChange={(t) => {
data.node.template[name].value = t;
}}
/>
)}
</div>
) : left === true && type === "bool" ? (
<div className="mt-2">
<ToggleComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
enabled={enabled}
setEnabled={(t) => {
data.node.template[name].value = t;
setEnabled(t);
}}
/>
) : (
<InputComponent
</div>
) : left === true && type === "float" ? (
<div className="mt-2 w-full">
<FloatComponent
disabled={disabled}
disableCopyPaste={true}
password={data.node.template[name].password ?? false}
value={data.node.template[name].value ?? ""}
onChange={(t) => {
data.node.template[name].value = t;
}}
/>
)}
</div>
) : left === true && type === "bool" ? (
<div className="mt-2">
<ToggleComponent
</div>
) : left === true &&
type === "str" &&
data.node.template[name].options ? (
<div className="w-full">
<Dropdown
options={data.node.template[name].options}
onSelect={(newValue) =>
(data.node.template[name].value = newValue)
}
value={data.node.template[name].value ?? "Choose an option"}
></Dropdown>
</div>
) : left === true && type === "code" ? (
<CodeAreaComponent
disabled={disabled}
enabled={enabled}
setEnabled={(t) => {
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
setEnabled(t);
}}
/>
</div>
) : left === true && type === "float" ? (
<div className="mt-2 w-full">
<FloatComponent
) : left === true && type === "file" ? (
<InputFileComponent
disabled={disabled}
disableCopyPaste={true}
value={data.node.template[name].value ?? ""}
onChange={(t) => {
onChange={(t: string) => {
data.node.template[name].value = t;
}}
fileTypes={data.node.template[name].fileTypes}
suffixes={data.node.template[name].suffixes}
onFileChange={(t: string) => {
data.node.template[name].content = t;
}}
></InputFileComponent>
) : left === true && type === "int" ? (
<div className="mt-2 w-full">
<IntComponent
disabled={disabled}
disableCopyPaste={true}
value={data.node.template[name].value ?? ""}
onChange={(t) => {
data.node.template[name].value = t;
}}
/>
</div>
) : left === true &&
type === "str" &&
data.node.template[name].options ? (
<div className="w-full">
<Dropdown
options={data.node.template[name].options}
onSelect={(newValue) =>
(data.node.template[name].value = newValue)
}
value={data.node.template[name].value ?? "Choose an option"}
></Dropdown>
</div>
) : left === true && type === "code" ? (
<CodeAreaComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
) : left === true && type === "file" ? (
<InputFileComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
fileTypes={data.node.template[name].fileTypes}
suffixes={data.node.template[name].suffixes}
onFileChange={(t: string) => {
data.node.template[name].content = t;
}}
></InputFileComponent>
) : left === true && type === "int" ? (
<div className="mt-2 w-full">
<IntComponent
/>
</div>
) : left === true && type === "prompt" ? (
<PromptAreaComponent
disabled={disabled}
disableCopyPaste={true}
value={data.node.template[name].value ?? ""}
onChange={(t) => {
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
</div>
) : left === true && type === "prompt" ? (
<PromptAreaComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
) : (
<></>
)}
</>
</div>
) : (
<></>
)}
</>
</div>
</>
);
}

View file

@ -101,8 +101,7 @@ export default function GenericNode({
return;
}
useEffect(() => {
}, [closePopUp, data.node.template]);
useEffect(() => {}, [closePopUp, data.node.template]);
return (
<>

View file

@ -11,14 +11,13 @@ const ShadTooltip = (props) => {
<Tooltip delayDuration={props.delayDuration}>
<TooltipTrigger asChild>{props.children}</TooltipTrigger>
<TooltipContent
side={props.side}
avoidCollisions={false}
sticky="always"
>
{props.content}
</TooltipContent>
<TooltipContent
side={props.side}
avoidCollisions={false}
sticky="always"
>
{props.content}
</TooltipContent>
</Tooltip>
</TooltipProvider>
);

View file

@ -4,10 +4,25 @@ import { Link } from "react-router-dom";
import { TabsContext } from "../../contexts/tabsContext";
import { FlowType } from "../../types/flow";
import { gradients } from "../../utils";
import { CardTitle, CardDescription, CardFooter, Card, CardHeader } from "../ui/card";
import {
CardTitle,
CardDescription,
CardFooter,
Card,
CardHeader,
} from "../ui/card";
export const CardComponent = ({ flow, id, onDelete, button }: { flow: FlowType; id: string, onDelete?: () => void, button?: JSX.Element }) => {
export const CardComponent = ({
flow,
id,
onDelete,
button,
}: {
flow: FlowType;
id: string;
onDelete?: () => void;
button?: JSX.Element;
}) => {
const { removeFlow } = useContext(TabsContext);
return (
@ -20,19 +35,14 @@ export const CardComponent = ({ flow, id, onDelete, button }: { flow: FlowType;
"rounded-full w-8 h-8 flex items-center justify-center text-2xl " +
gradients[parseInt(flow.id.slice(0, 6), 16) % gradients.length]
}
>
</span>
<span className="flex-1 truncate-doubleline">
{flow.name}
</span>
></span>
<span className="flex-1 truncate-doubleline">{flow.name}</span>
</div>
{onDelete &&
<button
onClick={onDelete}
>
<Trash2 className="w-5 text-primary opacity-0 group-hover:opacity-100 transition-all" />
</button>
}
{onDelete && (
<button onClick={onDelete}>
<Trash2 className="w-5 text-primary opacity-0 group-hover:opacity-100 transition-all" />
</button>
)}
</CardTitle>
<CardDescription className="pt-2 pb-2">
<div className="truncate-doubleline">
@ -53,10 +63,7 @@ export const CardComponent = ({ flow, id, onDelete, button }: { flow: FlowType;
<span className="text-base">&nbsp;</span>OpenAI+
</Badge> */}
</div>
{button &&
button
}
{button && button}
</div>
</CardFooter>
</Card>

View file

@ -29,7 +29,6 @@ export default function Dropdown({
<>
<div className={editNode ? "mt-1" : "relative mt-1"}>
<Listbox.Button
className={
editNode
? "relative pr-8 placeholder:text-center block w-full pt-0.5 pb-0.5 form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md shadow-sm sm:text-sm border-gray-300 border-1" +
@ -38,12 +37,10 @@ export default function Dropdown({
INPUT_STYLE
}
>
<span className="block truncate w-full">{internalValue}</span>
<span
className={
"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
}
>
<ChevronUpDownIcon

View file

@ -27,7 +27,7 @@ export default function FloatComponent({
useEffect(() => {
setMyValue(value);
}, [value]);
return (
<div
className={

View file

@ -49,15 +49,11 @@ export const MenuBar = ({ flows, tabId }) => {
</Link>
<div className="flex items-center font-medium text-sm rounded-md py-1 px-1.5 gap-0.5">
<DropdownMenu>
<DropdownMenuTrigger >
<Button
className="gap-2 flex items-center"
variant="primary"
>
{current_flow.name}
<ChevronDown className="w-4 h-4" />
</Button>
<DropdownMenuTrigger>
<Button className="gap-2 flex items-center" variant="primary">
{current_flow.name}
<ChevronDown className="w-4 h-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-44">
<DropdownMenuLabel>Edit</DropdownMenuLabel>

View file

@ -28,10 +28,7 @@ export default function Header() {
<span className="text-2xl ml-4"></span>
</Link>
{flows.findIndex((f) => tabId === f.id) !== -1 && tabId !== "" && (
<MenuBar
flows={flows}
tabId={tabId}
/>
<MenuBar flows={flows} tabId={tabId} />
)}
</div>
<div className="flex gap-2 items-center">

View file

@ -24,7 +24,7 @@ export default function PromptAreaComponent({
useEffect(() => {
setMyValue(value);
}, [value]);
return (
<div
className={

View file

@ -15,8 +15,7 @@ const buttonVariants = cva(
"border border-input hover:bg-accent hover:text-accent-foreground",
primary:
"border bg-background text-secondary-foreground hover:bg-background/80 hover:shadow-sm",
secondary:
"bg-muted text-secondary-foreground hover:bg-secondary/80",
secondary: "bg-muted text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "underline-offset-4 hover:underline text-primary",
},

View file

@ -129,4 +129,3 @@ export const EXPORT_CODE_DIALOG =
*/
export const INPUT_STYLE =
" focus:ring-1 focus:ring-offset-1 focus:ring-ring focus:outline-none ";

View file

@ -14,17 +14,17 @@ export default function ContextWrapper({ children }: { children: ReactNode }) {
<>
<ReactFlowProvider>
<DarkProvider>
<TypesProvider>
<LocationProvider>
<AlertProvider>
<TabsProvider>
<UndoRedoProvider>
<TypesProvider>
<LocationProvider>
<AlertProvider>
<TabsProvider>
<UndoRedoProvider>
<PopUpProvider>{children}</PopUpProvider>
</UndoRedoProvider>
</TabsProvider>
</AlertProvider>
</LocationProvider>
</TypesProvider>
</UndoRedoProvider>
</TabsProvider>
</AlertProvider>
</LocationProvider>
</TypesProvider>
</DarkProvider>
</ReactFlowProvider>
</>

View file

@ -549,7 +549,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
uploadFlows,
uploadFlow,
getNodeId,
paste
paste,
}}
>
{children}

View file

@ -1,4 +1,10 @@
import { createContext, useCallback, useContext, useEffect, useState } from "react";
import {
createContext,
useCallback,
useContext,
useEffect,
useState,
} from "react";
import { Edge, Node, useReactFlow } from "reactflow";
import { cloneDeep } from "lodash";
import { TabsContext } from "./tabsContext";
@ -10,22 +16,22 @@ type undoRedoContextType = {
};
type UseUndoRedoOptions = {
maxHistorySize: number;
enableShortcuts: boolean;
};
type UseUndoRedo = (options?: UseUndoRedoOptions) => {
undo: () => void;
redo: () => void;
takeSnapshot: () => void;
canUndo: boolean;
canRedo: boolean;
};
type HistoryItem = {
nodes: Node[];
edges: Edge[];
};
maxHistorySize: number;
enableShortcuts: boolean;
};
type UseUndoRedo = (options?: UseUndoRedoOptions) => {
undo: () => void;
redo: () => void;
takeSnapshot: () => void;
canUndo: boolean;
canRedo: boolean;
};
type HistoryItem = {
nodes: Node[];
edges: Edge[];
};
const initialValue = {
undo: () => {},
@ -34,152 +40,144 @@ const initialValue = {
};
const defaultOptions: UseUndoRedoOptions = {
maxHistorySize: 100,
enableShortcuts: true,
};
maxHistorySize: 100,
enableShortcuts: true,
};
export const undoRedoContext = createContext<undoRedoContextType>(initialValue);
export function UndoRedoProvider({ children }) {
const { tabId, flows } = useContext(TabsContext);
const { tabId, flows } = useContext(TabsContext);
const [past, setPast] = useState<HistoryItem[][]>(flows.map(() => []));
const [future, setFuture] = useState<HistoryItem[][]>(flows.map(() => []));
const [tabIndex, setTabIndex] = useState(flows.findIndex((f) => f.id === tabId));
useEffect(() => {
// whenever the flows variable changes, we need to add one array to the past and future states
setPast((old) => flows.map((f, i) => (old[i] ? old[i] : [])));
setFuture((old) => flows.map((f, i) => (old[i] ? old[i] : [])));
setTabIndex(flows.findIndex((f) => f.id === tabId));
const [past, setPast] = useState<HistoryItem[][]>(flows.map(() => []));
const [future, setFuture] = useState<HistoryItem[][]>(flows.map(() => []));
const [tabIndex, setTabIndex] = useState(
flows.findIndex((f) => f.id === tabId)
);
}, [flows, tabId]);
const { setNodes, setEdges, getNodes, getEdges } = useReactFlow();
const takeSnapshot = useCallback(() => {
// push the current graph to the past state
console.log(past);
console.log(tabIndex);
useEffect(() => {
// whenever the flows variable changes, we need to add one array to the past and future states
setPast((old) => flows.map((f, i) => (old[i] ? old[i] : [])));
setFuture((old) => flows.map((f, i) => (old[i] ? old[i] : [])));
setTabIndex(flows.findIndex((f) => f.id === tabId));
}, [flows, tabId]);
const { setNodes, setEdges, getNodes, getEdges } = useReactFlow();
const takeSnapshot = useCallback(() => {
// push the current graph to the past state
console.log(past);
console.log(tabIndex);
setPast((old) => {
let newPast = cloneDeep(old);
newPast[tabIndex] = old[tabIndex].slice(
old[tabIndex].length - defaultOptions.maxHistorySize + 1,
old[tabIndex].length
);
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
return newPast;
});
// whenever we take a new snapshot, the redo operations need to be cleared to avoid state mismatches
setFuture((old) => {
let newFuture = cloneDeep(old);
newFuture[tabIndex] = [];
return newFuture;
});
}, [getNodes, getEdges, past, future, flows, tabId, setPast, setFuture]);
const undo = useCallback(() => {
// get the last state that we want to go back to
const pastState = past[tabIndex][past[tabIndex].length - 1];
if (pastState) {
// first we remove the state from the history
setPast((old) => {
let newPast = cloneDeep(old);
newPast[tabIndex] = old[tabIndex].slice(
old[tabIndex].length - defaultOptions.maxHistorySize + 1,
old[tabIndex].length
);
newPast[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1);
return newPast;
});
// we store the current graph for the redo operation
setFuture((old) => {
let newFuture = cloneDeep(old);
newFuture[tabIndex] = old[tabIndex];
newFuture[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
return newFuture;
});
// now we can set the graph to the past state
setNodes(pastState.nodes);
setEdges(pastState.edges);
}
}, [
setNodes,
setEdges,
getNodes,
getEdges,
future,
past,
setFuture,
setPast,
tabIndex,
]);
const redo = useCallback(() => {
const futureState = future[tabIndex][future[tabIndex].length - 1];
if (futureState) {
setFuture((old) => {
let newFuture = cloneDeep(old);
newFuture[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1);
return newFuture;
});
setPast((old) => {
let newPast = cloneDeep(old);
newPast[tabIndex] = old[tabIndex];
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
return newPast;
});
// whenever we take a new snapshot, the redo operations need to be cleared to avoid state mismatches
setFuture((old) => {
let newFuture = cloneDeep(old);
newFuture[tabIndex] = [];
return newFuture;
});
}, [
getNodes,
getEdges,
past,
future,
flows,
tabId,
setPast,
setFuture,
]);
const undo = useCallback(() => {
// get the last state that we want to go back to
const pastState = past[tabIndex][past[tabIndex].length - 1];
if (pastState) {
// first we remove the state from the history
setPast((old) => {
let newPast = cloneDeep(old);
newPast[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1);
return newPast;
});
// we store the current graph for the redo operation
setFuture((old) => {
let newFuture = cloneDeep(old);
newFuture[tabIndex] = old[tabIndex];
newFuture[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
return newFuture;
});
// now we can set the graph to the past state
setNodes(pastState.nodes);
setEdges(pastState.edges);
setNodes(futureState.nodes);
setEdges(futureState.edges);
}
}, [
future,
past,
setFuture,
setPast,
setNodes,
setEdges,
getNodes,
getEdges,
future,
tabIndex,
]);
useEffect(() => {
// this effect is used to attach the global event handlers
if (!defaultOptions.enableShortcuts) {
return;
}
const keyDownHandler = (event: KeyboardEvent) => {
if (
event.key === "z" &&
(event.ctrlKey || event.metaKey) &&
event.shiftKey
) {
redo();
} else if (event.key === "y" && (event.ctrlKey || event.metaKey)) {
event.preventDefault(); // prevent the default action
redo();
} else if (event.key === "z" && (event.ctrlKey || event.metaKey)) {
undo();
}
}, [
setNodes,
setEdges,
getNodes,
getEdges,
future,
past,
setFuture,
setPast,
tabIndex,
]);
const redo = useCallback(() => {
const futureState = future[tabIndex][future[tabIndex].length - 1];
if (futureState) {
setFuture((old) => {
let newFuture = cloneDeep(old);
newFuture[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1);
return newFuture;
});
setPast((old) => {
let newPast = cloneDeep(old);
newPast[tabIndex] = old[tabIndex];
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
return newPast;
});
setNodes(futureState.nodes);
setEdges(futureState.edges);
}
}, [
future,
past,
setFuture,
setPast,
setNodes,
setEdges,
getNodes,
getEdges,
future,
tabIndex,
]);
useEffect(() => {
// this effect is used to attach the global event handlers
if (!defaultOptions.enableShortcuts) {
return;
}
const keyDownHandler = (event: KeyboardEvent) => {
if (
event.key === "z" &&
(event.ctrlKey || event.metaKey) &&
event.shiftKey
) {
redo();
} else if (event.key === "y" && (event.ctrlKey || event.metaKey)) {
event.preventDefault(); // prevent the default action
redo();
} else if (event.key === "z" && (event.ctrlKey || event.metaKey)) {
undo();
}
};
document.addEventListener("keydown", keyDownHandler);
return () => {
document.removeEventListener("keydown", keyDownHandler);
};
}, [undo, redo]);
};
document.addEventListener("keydown", keyDownHandler);
return () => {
document.removeEventListener("keydown", keyDownHandler);
};
}, [undo, redo]);
return (
<undoRedoContext.Provider
value={{

View file

@ -96,7 +96,7 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">Edit Node</span>
<Edit
<Edit
className="h-5 w-5 text-gray-800 pl-1 dark:text-white"
aria-hidden="true"
/>
@ -172,7 +172,6 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
}
onChange={(t: string[]) => {
data.node.template[n].value = t;
}}
/>
) : data.node.template[n].multiline ? (
@ -182,7 +181,6 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
value={data.node.template[n].value ?? ""}
onChange={(t: string) => {
data.node.template[n].value = t;
}}
/>
) : (
@ -195,7 +193,6 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
value={data.node.template[n].value ?? ""}
onChange={(t) => {
data.node.template[n].value = t;
}}
/>
)}
@ -208,7 +205,6 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
setEnabled={(e) => {
data.node.template[n].value = e;
setEnabled(e);
}}
disabled={false}
/>
@ -221,7 +217,6 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
value={data.node.template[n].value ?? ""}
onChange={(t) => {
data.node.template[n].value = t;
}}
/>
</div>
@ -249,7 +244,6 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
value={data.node.template[n].value ?? ""}
onChange={(t) => {
data.node.template[n].value = t;
}}
/>
</div>
@ -266,7 +260,6 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
suffixes={data.node.template[n].suffixes}
onFileChange={(t: string) => {
data.node.template[n].content = t;
}}
></InputFileComponent>
</div>
@ -278,7 +271,6 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
value={data.node.template[n].value ?? ""}
onChange={(t: string) => {
data.node.template[n].value = t;
}}
/>
</div>

View file

@ -70,7 +70,6 @@ export default function ModalField({
}
onChange={(t: string[]) => {
data.node.template[name].value = t;
}}
/>
) : data.node.template[name].multiline ? (
@ -79,7 +78,6 @@ export default function ModalField({
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
) : (
@ -89,7 +87,6 @@ export default function ModalField({
value={data.node.template[name].value ?? ""}
onChange={(t) => {
data.node.template[name].value = t;
}}
/>
)}
@ -103,7 +100,6 @@ export default function ModalField({
setEnabled={(t) => {
data.node.template[name].value = t;
setEnabled(t);
}}
/>
</div>
@ -114,7 +110,6 @@ export default function ModalField({
value={data.node.template[name].value ?? ""}
onChange={(t) => {
data.node.template[name].value = t;
}}
/>
</div>
@ -133,7 +128,6 @@ export default function ModalField({
value={data.node.template[name].value ?? ""}
onChange={(t) => {
data.node.template[name].value = t;
}}
/>
</div>
@ -149,7 +143,6 @@ export default function ModalField({
suffixes={data.node.template[name].suffixes}
onFileChange={(t: string) => {
data.node.template[name].content = t;
}}
></InputFileComponent>
</div>
@ -160,7 +153,6 @@ export default function ModalField({
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
</div>
@ -171,7 +163,6 @@ export default function ModalField({
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
</div>

View file

@ -20,6 +20,7 @@ import EditFlowSettings from "../../components/nameInputComponent";
import { Label } from "../../components/ui/label";
import { Input } from "../../components/ui/input";
import { Textarea } from "../../components/ui/textarea";
import { Download } from "lucide-react";
export default function ExportModal() {
const [open, setOpen] = useState(true);
@ -48,7 +49,7 @@ export default function ExportModal() {
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">Export</span>
<ArrowDownTrayIcon
<Download
className="h-6 w-6 text-gray-800 pl-1 dark:text-white"
aria-hidden="true"
/>

View file

@ -85,24 +85,33 @@ export default function CommunityPage() {
</div>
</div>
<span className="flex pb-8 px-6 w-[70%] text-muted-foreground">
Discover and learn from shared examples by the LangFlow community. We welcome new example contributions that can help our community explore new and powerful features.
Discover and learn from shared examples by the LangFlow community. We
welcome new example contributions that can help our community explore
new and powerful features.
</span>
<div className="w-full p-4 grid gap-4 md:grid-cols-2 lg:grid-cols-4">
{!loadingExamples &&
examples.map((flow, idx) => (
<CardComponent key={idx} flow={flow} id={flow.id} button={<Button
variant="outline"
size="sm"
className="whitespace-nowrap "
onClick={() => {
addFlow(flow, true).then((id) => {
navigate("/flow/" + id);
});
}}
>
<GitFork className="w-4 mr-2" />
Fork Example
</Button>}/>
<CardComponent
key={idx}
flow={flow}
id={flow.id}
button={
<Button
variant="outline"
size="sm"
className="whitespace-nowrap "
onClick={() => {
addFlow(flow, true).then((id) => {
navigate("/flow/" + id);
});
}}
>
<GitFork className="w-4 mr-2" />
Fork Example
</Button>
}
/>
))}
</div>
</div>

View file

@ -317,53 +317,53 @@ export default function Page({ flow }: { flow: FlowType }) {
<div className="w-full h-full" ref={reactFlowWrapper}>
{Object.keys(templates).length > 0 &&
Object.keys(types).length > 0 ? (
<div className="w-full h-full">
<ReactFlow
nodes={nodes}
onMove={() => {
updateFlow({
...flow,
data: reactFlowInstance.toObject(),
});
}}
edges={edges}
onPaneClick={() => {
setDisableCopyPaste(false);
}}
onPaneMouseLeave={() => {
setDisableCopyPaste(true);
}}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChangeMod}
onConnect={onConnect}
disableKeyboardA11y={true}
onLoad={setReactFlowInstance}
onInit={setReactFlowInstance}
nodeTypes={nodeTypes}
onEdgeUpdate={onEdgeUpdate}
onEdgeUpdateStart={onEdgeUpdateStart}
onEdgeUpdateEnd={onEdgeUpdateEnd}
onNodeDragStart={onNodeDragStart}
onSelectionDragStart={onSelectionDragStart}
onSelectionEnd={onSelectionEnd}
onSelectionStart={onSelectionStart}
onEdgesDelete={onEdgesDelete}
connectionLineComponent={ConnectionLineComponent}
onDragOver={onDragOver}
onDrop={onDrop}
onNodesDelete={onDelete}
onSelectionChange={onSelectionChange}
nodesDraggable={!disableCopyPaste}
panOnDrag={!disableCopyPaste}
zoomOnDoubleClick={!disableCopyPaste}
selectNodesOnDrag={false}
className="theme-attribution"
>
<Background className="dark:bg-gray-900" />
<Controls className="[&>button]:text-black [&>button]:dark:bg-gray-800 hover:[&>button]:dark:bg-gray-700 [&>button]:dark:text-gray-400 [&>button]:dark:fill-gray-400 [&>button]:dark:border-gray-600"></Controls>
</ReactFlow>
<Chat flow={flow} reactFlowInstance={reactFlowInstance} />
</div>
<div className="w-full h-full">
<ReactFlow
nodes={nodes}
onMove={() => {
updateFlow({
...flow,
data: reactFlowInstance.toObject(),
});
}}
edges={edges}
onPaneClick={() => {
setDisableCopyPaste(false);
}}
onPaneMouseLeave={() => {
setDisableCopyPaste(true);
}}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChangeMod}
onConnect={onConnect}
disableKeyboardA11y={true}
onLoad={setReactFlowInstance}
onInit={setReactFlowInstance}
nodeTypes={nodeTypes}
onEdgeUpdate={onEdgeUpdate}
onEdgeUpdateStart={onEdgeUpdateStart}
onEdgeUpdateEnd={onEdgeUpdateEnd}
onNodeDragStart={onNodeDragStart}
onSelectionDragStart={onSelectionDragStart}
onSelectionEnd={onSelectionEnd}
onSelectionStart={onSelectionStart}
onEdgesDelete={onEdgesDelete}
connectionLineComponent={ConnectionLineComponent}
onDragOver={onDragOver}
onDrop={onDrop}
onNodesDelete={onDelete}
onSelectionChange={onSelectionChange}
nodesDraggable={!disableCopyPaste}
panOnDrag={!disableCopyPaste}
zoomOnDoubleClick={!disableCopyPaste}
selectNodesOnDrag={false}
className="theme-attribution"
>
<Background className="dark:bg-gray-900" />
<Controls className="[&>button]:text-black [&>button]:dark:bg-gray-800 hover:[&>button]:dark:bg-gray-700 [&>button]:dark:text-gray-400 [&>button]:dark:fill-gray-400 [&>button]:dark:border-gray-600"></Controls>
</ReactFlow>
<Chat flow={flow} reactFlowInstance={reactFlowInstance} />
</div>
) : (
<></>
)}

View file

@ -3,17 +3,19 @@ import Page from "./components/PageComponent";
import { TabsContext } from "../../contexts/tabsContext";
import { useParams } from "react-router-dom";
export default function FlowPage(){
export default function FlowPage() {
const { flows, tabId, setTabId } = useContext(TabsContext);
const {id} = useParams();
const { id } = useParams();
useEffect(() => {
setTabId(id);
}, [id])
}, [id]);
return (
<div className="h-full w-full overflow-hidden">
{flows.length > 0 && tabId !== "" && flows.findIndex(flow => flow.id === tabId) !== -1 &&
<Page flow={flows.find(flow => flow.id === tabId)} />
}
{flows.length > 0 &&
tabId !== "" &&
flows.findIndex((flow) => flow.id === tabId) !== -1 && (
<Page flow={flows.find((flow) => flow.id === tabId)} />
)}
</div>
)
}
);
}

View file

@ -1,18 +1,18 @@
import { Route, Routes } from "react-router-dom"
import { Route, Routes } from "react-router-dom";
import HomePage from "./pages/MainPage";
import FlowPage from "./pages/FlowPage";
import CommunityPage from "./pages/CommunityPage";
const Router = () => {
return(
<Routes>
<Route path="/" element={<HomePage/>}/>
<Route path="/community" element={<CommunityPage/>}/>
<Route path="/flow/:id/">
<Route path="" element={<FlowPage/>}/>
</Route>
</Routes>
)
}
export default Router;
return (
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/community" element={<CommunityPage />} />
<Route path="/flow/:id/">
<Route path="" element={<FlowPage />} />
</Route>
</Routes>
);
};
export default Router;