Added flow id and routes logic
This commit is contained in:
parent
09bd1093dd
commit
ceb9b1d155
9 changed files with 262 additions and 183 deletions
BIN
langflow.db
Normal file
BIN
langflow.db
Normal file
Binary file not shown.
|
|
@ -1,7 +1,7 @@
|
||||||
import "reactflow/dist/style.css";
|
import "reactflow/dist/style.css";
|
||||||
import { useState, useEffect, useContext } from "react";
|
import { useState, useEffect, useContext } from "react";
|
||||||
import "./App.css";
|
import "./App.css";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation, useParams } from "react-router-dom";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
|
||||||
import ErrorAlert from "./alerts/error";
|
import ErrorAlert from "./alerts/error";
|
||||||
|
|
@ -15,6 +15,8 @@ import CrashErrorComponent from "./components/CrashErrorComponent";
|
||||||
import { TabsContext } from "./contexts/tabsContext";
|
import { TabsContext } from "./contexts/tabsContext";
|
||||||
import MainPage from "./pages/MainPage";
|
import MainPage from "./pages/MainPage";
|
||||||
import { getVersion } from "./controllers/API";
|
import { getVersion } from "./controllers/API";
|
||||||
|
import Router from "./routes";
|
||||||
|
import Header from "./components/headerComponent";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
let { setCurrent, setShowSideBar, setIsStackedOpen } =
|
let { setCurrent, setShowSideBar, setIsStackedOpen } =
|
||||||
|
|
@ -25,7 +27,7 @@ export default function App() {
|
||||||
setShowSideBar(true);
|
setShowSideBar(true);
|
||||||
setIsStackedOpen(true);
|
setIsStackedOpen(true);
|
||||||
}, [location.pathname, setCurrent, setIsStackedOpen, setShowSideBar]);
|
}, [location.pathname, setCurrent, setIsStackedOpen, setShowSideBar]);
|
||||||
const { hardReset } = useContext(TabsContext);
|
const { hardReset, setTabIndex } = useContext(TabsContext);
|
||||||
const {
|
const {
|
||||||
errorData,
|
errorData,
|
||||||
errorOpen,
|
errorOpen,
|
||||||
|
|
@ -38,6 +40,17 @@ export default function App() {
|
||||||
setSuccessOpen,
|
setSuccessOpen,
|
||||||
} = useContext(alertContext);
|
} = useContext(alertContext);
|
||||||
|
|
||||||
|
const { flows, addFlow } = useContext(TabsContext);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
//create the first flow
|
||||||
|
if (flows.length === 0) {
|
||||||
|
addFlow();
|
||||||
|
console.log("que");
|
||||||
|
}
|
||||||
|
}, [addFlow, flows.length]);
|
||||||
|
|
||||||
|
|
||||||
// Initialize state variable for the list of alerts
|
// Initialize state variable for the list of alerts
|
||||||
const [alertsList, setAlertsList] = useState<
|
const [alertsList, setAlertsList] = useState<
|
||||||
Array<{
|
Array<{
|
||||||
|
|
@ -122,7 +135,12 @@ export default function App() {
|
||||||
}}
|
}}
|
||||||
FallbackComponent={CrashErrorComponent}
|
FallbackComponent={CrashErrorComponent}
|
||||||
>
|
>
|
||||||
<MainPage />
|
{flows.length !== 0 && (
|
||||||
|
<>
|
||||||
|
<Header />
|
||||||
|
<Router />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
<div></div>
|
<div></div>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
114
src/frontend/src/components/headerComponent/index.tsx
Normal file
114
src/frontend/src/components/headerComponent/index.tsx
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import { SunIcon, MoonIcon, BellIcon } from "lucide-react";
|
||||||
|
import { useContext, useState, useEffect } from "react";
|
||||||
|
import { FaGithub } from "react-icons/fa";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { TabsContext } from "../../contexts/tabsContext";
|
||||||
|
import AlertDropdown from "../../alerts/alertDropDown";
|
||||||
|
import { alertContext } from "../../contexts/alertContext";
|
||||||
|
import { darkContext } from "../../contexts/darkContext";
|
||||||
|
import { PopUpContext } from "../../contexts/popUpContext";
|
||||||
|
import { typesContext } from "../../contexts/typesContext";
|
||||||
|
import MenuBar from "../../pages/MainPage/components/menuBar";
|
||||||
|
|
||||||
|
export default function Header(){
|
||||||
|
const {
|
||||||
|
flows,
|
||||||
|
addFlow,
|
||||||
|
removeFlow,
|
||||||
|
tabIndex,
|
||||||
|
setTabIndex,
|
||||||
|
uploadFlow,
|
||||||
|
downloadFlow,
|
||||||
|
} = useContext(TabsContext);
|
||||||
|
const { openPopUp } = useContext(PopUpContext);
|
||||||
|
const { templates } = useContext(typesContext);
|
||||||
|
const AlertWidth = 384;
|
||||||
|
const { dark, setDark } = useContext(darkContext);
|
||||||
|
const [activeTab, setActiveTab] = useState("myflow");
|
||||||
|
const [rename, setRename] = useState(false);
|
||||||
|
const { notificationCenter, setNotificationCenter, setErrorData } =
|
||||||
|
useContext(alertContext);
|
||||||
|
useEffect(() => {
|
||||||
|
//create the first flow
|
||||||
|
if (flows.length === 0 && Object.keys(templates).length > 0) {
|
||||||
|
addFlow();
|
||||||
|
}
|
||||||
|
}, [addFlow, flows.length, templates]);
|
||||||
|
return (
|
||||||
|
<div className="w-full h-16 flex justify-between items-center border-b">
|
||||||
|
<MenuBar
|
||||||
|
activeTab={activeTab}
|
||||||
|
setRename={setRename}
|
||||||
|
rename={rename}
|
||||||
|
flows={flows}
|
||||||
|
tabIndex={tabIndex}
|
||||||
|
/>
|
||||||
|
<div className="flex">
|
||||||
|
<Button>Explore</Button>
|
||||||
|
<Button>My Flows</Button>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end px-2 w-96">
|
||||||
|
<div className="ml-auto mr-2 flex gap-5">
|
||||||
|
<Button
|
||||||
|
asChild
|
||||||
|
variant="outline"
|
||||||
|
className="text-gray-600 dark:text-gray-300 "
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="https://github.com/logspace-ai/langflow"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="flex"
|
||||||
|
>
|
||||||
|
<FaGithub className="h-5 w-5 mr-2" />
|
||||||
|
Join The Community
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
<button
|
||||||
|
className="text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200"
|
||||||
|
onClick={() => {
|
||||||
|
setDark(!dark);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{dark ? (
|
||||||
|
<SunIcon className="h-5 w-5" />
|
||||||
|
) : (
|
||||||
|
<MoonIcon className="h-5 w-5" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200 relative"
|
||||||
|
onClick={(event: React.MouseEvent<HTMLElement>) => {
|
||||||
|
setNotificationCenter(false);
|
||||||
|
const { top, left } = (
|
||||||
|
event.target as Element
|
||||||
|
).getBoundingClientRect();
|
||||||
|
openPopUp(
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className="z-10 absolute"
|
||||||
|
style={{ top: top + 34, left: left - AlertWidth }}
|
||||||
|
>
|
||||||
|
<AlertDropdown />
|
||||||
|
</div>
|
||||||
|
<div className="h-screen w-screen fixed top-0 left-0"></div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{notificationCenter && (
|
||||||
|
<div className="absolute w-1.5 h-1.5 rounded-full bg-destructive right-[3px]"></div>
|
||||||
|
)}
|
||||||
|
<BellIcon className="h-5 w-5" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
<button>
|
||||||
|
<img
|
||||||
|
src="https://github.com/shadcn.png"
|
||||||
|
className="rounded-full w-8"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -5,22 +5,25 @@ import { LocationProvider } from "./locationContext";
|
||||||
import PopUpProvider from "./popUpContext";
|
import PopUpProvider from "./popUpContext";
|
||||||
import { TabsProvider } from "./tabsContext";
|
import { TabsProvider } from "./tabsContext";
|
||||||
import { TypesProvider } from "./typesContext";
|
import { TypesProvider } from "./typesContext";
|
||||||
|
import { ReactFlowProvider } from "reactflow";
|
||||||
|
|
||||||
export default function ContextWrapper({ children }: { children: ReactNode }) {
|
export default function ContextWrapper({ children }: { children: ReactNode }) {
|
||||||
//element to wrap all context
|
//element to wrap all context
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DarkProvider>
|
<ReactFlowProvider>
|
||||||
<TypesProvider>
|
<DarkProvider>
|
||||||
<LocationProvider>
|
<TypesProvider>
|
||||||
<AlertProvider>
|
<LocationProvider>
|
||||||
<TabsProvider>
|
<AlertProvider>
|
||||||
<PopUpProvider>{children}</PopUpProvider>
|
<TabsProvider>
|
||||||
</TabsProvider>
|
<PopUpProvider>{children}</PopUpProvider>
|
||||||
</AlertProvider>
|
</TabsProvider>
|
||||||
</LocationProvider>
|
</AlertProvider>
|
||||||
</TypesProvider>
|
</LocationProvider>
|
||||||
</DarkProvider>
|
</TypesProvider>
|
||||||
|
</DarkProvider>
|
||||||
|
</ReactFlowProvider>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ export default function ExtraSidebar() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="flex flex-col">
|
||||||
<div className="relative mt-2 flex items-center mb-2 mx-2">
|
<div className="relative mt-2 flex items-center mb-2 mx-2">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -128,6 +128,6 @@ export default function ExtraSidebar() {
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import ReactFlow, {
|
||||||
useOnViewportChange,
|
useOnViewportChange,
|
||||||
OnSelectionChangeParams,
|
OnSelectionChangeParams,
|
||||||
OnNodesChange,
|
OnNodesChange,
|
||||||
|
ReactFlowProvider,
|
||||||
} from "reactflow";
|
} from "reactflow";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { locationContext } from "../../contexts/locationContext";
|
import { locationContext } from "../../contexts/locationContext";
|
||||||
|
|
@ -32,12 +33,13 @@ import { FlowType, NodeType } from "../../types/flow";
|
||||||
import { APIClassType } from "../../types/api";
|
import { APIClassType } from "../../types/api";
|
||||||
import { isValidConnection } from "../../utils";
|
import { isValidConnection } from "../../utils";
|
||||||
import useUndoRedo from "./hooks/useUndoRedo";
|
import useUndoRedo from "./hooks/useUndoRedo";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
const nodeTypes = {
|
const nodeTypes = {
|
||||||
genericNode: GenericNode,
|
genericNode: GenericNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function FlowPage({ flow }: { flow: FlowType }) {
|
export default function FlowPage() {
|
||||||
let {
|
let {
|
||||||
updateFlow,
|
updateFlow,
|
||||||
disableCopyPaste,
|
disableCopyPaste,
|
||||||
|
|
@ -46,6 +48,10 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
|
||||||
paste,
|
paste,
|
||||||
lastCopiedSelection,
|
lastCopiedSelection,
|
||||||
setLastCopiedSelection,
|
setLastCopiedSelection,
|
||||||
|
flows,
|
||||||
|
tabIndex,
|
||||||
|
setTabIndex
|
||||||
|
|
||||||
} = useContext(TabsContext);
|
} = useContext(TabsContext);
|
||||||
const { types, reactFlowInstance, setReactFlowInstance, templates } =
|
const { types, reactFlowInstance, setReactFlowInstance, templates } =
|
||||||
useContext(typesContext);
|
useContext(typesContext);
|
||||||
|
|
@ -53,6 +59,18 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
|
||||||
|
|
||||||
const { takeSnapshot } = useUndoRedo();
|
const { takeSnapshot } = useUndoRedo();
|
||||||
|
|
||||||
|
const {id} = useParams();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(flows.length !== 0){
|
||||||
|
console.log(id, "o id é esse");
|
||||||
|
setTabIndex(flows.findIndex((flow) => flow.id === id) == -1 ? 0 : flows.findIndex((flow) => flow.id === id));
|
||||||
|
console.log("setou", flows.findIndex((flow) => flow.id === id))
|
||||||
|
console.log(flows[tabIndex])
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [flows, id])
|
||||||
|
|
||||||
const [position, setPosition] = useState({ x: 0, y: 0 });
|
const [position, setPosition] = useState({ x: 0, y: 0 });
|
||||||
const [lastSelection, setLastSelection] =
|
const [lastSelection, setLastSelection] =
|
||||||
useState<OnSelectionChangeParams>(null);
|
useState<OnSelectionChangeParams>(null);
|
||||||
|
|
@ -111,28 +129,28 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
|
||||||
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
|
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
|
||||||
const { setErrorData } = useContext(alertContext);
|
const { setErrorData } = useContext(alertContext);
|
||||||
const [nodes, setNodes, onNodesChange] = useNodesState(
|
const [nodes, setNodes, onNodesChange] = useNodesState(
|
||||||
flow.data?.nodes ?? []
|
flows[tabIndex].data?.nodes ?? []
|
||||||
);
|
);
|
||||||
const [edges, setEdges, onEdgesChange] = useEdgesState(
|
const [edges, setEdges, onEdgesChange] = useEdgesState(
|
||||||
flow.data?.edges ?? []
|
flows[tabIndex].data?.edges ?? []
|
||||||
);
|
);
|
||||||
const { setViewport } = useReactFlow();
|
const { setViewport } = useReactFlow();
|
||||||
const edgeUpdateSuccessful = useRef(true);
|
const edgeUpdateSuccessful = useRef(true);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (reactFlowInstance && flow) {
|
if (reactFlowInstance && flows[tabIndex]) {
|
||||||
flow.data = reactFlowInstance.toObject();
|
flows[tabIndex].data = reactFlowInstance.toObject();
|
||||||
updateFlow(flow);
|
updateFlow(flows[tabIndex]);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [nodes, edges]);
|
}, [nodes, edges]);
|
||||||
//update flow when tabs change
|
//update flow when tabs change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setNodes(flow?.data?.nodes ?? []);
|
setNodes(flows[tabIndex]?.data?.nodes ?? []);
|
||||||
setEdges(flow?.data?.edges ?? []);
|
setEdges(flows[tabIndex]?.data?.edges ?? []);
|
||||||
if (reactFlowInstance) {
|
if (reactFlowInstance) {
|
||||||
setViewport(flow?.data?.viewport ?? { x: 1, y: 0, zoom: 0.5 });
|
setViewport(flows[tabIndex]?.data?.viewport ?? { x: 1, y: 0, zoom: 0.5 });
|
||||||
}
|
}
|
||||||
}, [flow, reactFlowInstance, setEdges, setNodes, setViewport]);
|
}, [flows[tabIndex], reactFlowInstance, setEdges, setNodes, setViewport]);
|
||||||
//set extra sidebar
|
//set extra sidebar
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setExtraComponent(<ExtraSidebar />);
|
setExtraComponent(<ExtraSidebar />);
|
||||||
|
|
@ -312,55 +330,66 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
|
||||||
const { setDisableCopyPaste } = useContext(TabsContext);
|
const { setDisableCopyPaste } = useContext(TabsContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full" ref={reactFlowWrapper}>
|
<div className="h-full w-full flex basis-auto flex-1 overflow-hidden">
|
||||||
{Object.keys(templates).length > 0 && Object.keys(types).length > 0 ? (
|
<ExtraSidebar />
|
||||||
<>
|
<main className="h-full w-full flex-1 border-t border-gray-200 dark:border-gray-700 flex">
|
||||||
<ReactFlow
|
{/* Primary column */}
|
||||||
nodes={nodes}
|
|
||||||
onMove={() => {
|
<div className="w-full h-full" ref={reactFlowWrapper}>
|
||||||
updateFlow({ ...flow, data: reactFlowInstance.toObject() });
|
{Object.keys(templates).length > 0 &&
|
||||||
}}
|
Object.keys(types).length > 0 ? (
|
||||||
edges={edges}
|
<>
|
||||||
onPaneClick={() => {
|
<ReactFlow
|
||||||
setDisableCopyPaste(false);
|
nodes={nodes}
|
||||||
}}
|
onMove={() => {
|
||||||
onPaneMouseLeave={() => {
|
updateFlow({
|
||||||
setDisableCopyPaste(true);
|
...flows[tabIndex],
|
||||||
}}
|
data: reactFlowInstance.toObject(),
|
||||||
onNodesChange={onNodesChange}
|
});
|
||||||
onEdgesChange={onEdgesChangeMod}
|
}}
|
||||||
onConnect={onConnect}
|
edges={edges}
|
||||||
disableKeyboardA11y={true}
|
onPaneClick={() => {
|
||||||
onLoad={setReactFlowInstance}
|
setDisableCopyPaste(false);
|
||||||
onInit={setReactFlowInstance}
|
}}
|
||||||
nodeTypes={nodeTypes}
|
onPaneMouseLeave={() => {
|
||||||
onEdgeUpdate={onEdgeUpdate}
|
setDisableCopyPaste(true);
|
||||||
onEdgeUpdateStart={onEdgeUpdateStart}
|
}}
|
||||||
onEdgeUpdateEnd={onEdgeUpdateEnd}
|
onNodesChange={onNodesChange}
|
||||||
onNodeDragStart={onNodeDragStart}
|
onEdgesChange={onEdgesChangeMod}
|
||||||
onSelectionDragStart={onSelectionDragStart}
|
onConnect={onConnect}
|
||||||
onSelectionEnd={onSelectionEnd}
|
disableKeyboardA11y={true}
|
||||||
onSelectionStart={onSelectionStart}
|
onLoad={setReactFlowInstance}
|
||||||
onEdgesDelete={onEdgesDelete}
|
onInit={setReactFlowInstance}
|
||||||
connectionLineComponent={ConnectionLineComponent}
|
nodeTypes={nodeTypes}
|
||||||
onDragOver={onDragOver}
|
onEdgeUpdate={onEdgeUpdate}
|
||||||
onDrop={onDrop}
|
onEdgeUpdateStart={onEdgeUpdateStart}
|
||||||
onNodesDelete={onDelete}
|
onEdgeUpdateEnd={onEdgeUpdateEnd}
|
||||||
onSelectionChange={onSelectionChange}
|
onNodeDragStart={onNodeDragStart}
|
||||||
nodesDraggable={!disableCopyPaste}
|
onSelectionDragStart={onSelectionDragStart}
|
||||||
panOnDrag={!disableCopyPaste}
|
onSelectionEnd={onSelectionEnd}
|
||||||
zoomOnDoubleClick={!disableCopyPaste}
|
onSelectionStart={onSelectionStart}
|
||||||
selectNodesOnDrag={false}
|
onEdgesDelete={onEdgesDelete}
|
||||||
className="theme-attribution"
|
connectionLineComponent={ConnectionLineComponent}
|
||||||
>
|
onDragOver={onDragOver}
|
||||||
<Background className="dark:bg-gray-900" />
|
onDrop={onDrop}
|
||||||
<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>
|
onNodesDelete={onDelete}
|
||||||
</ReactFlow>
|
onSelectionChange={onSelectionChange}
|
||||||
<Chat flow={flow} reactFlowInstance={reactFlowInstance} />
|
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={flows[tabIndex]} reactFlowInstance={reactFlowInstance} />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,18 +20,17 @@ import _ from "lodash";
|
||||||
import { TabsContext } from "../../../../contexts/tabsContext";
|
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||||
import { alertContext } from "../../../../contexts/alertContext";
|
import { alertContext } from "../../../../contexts/alertContext";
|
||||||
import { updateFlowInDatabase } from "../../../../controllers/API";
|
import { updateFlowInDatabase } from "../../../../controllers/API";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
export const CardComponent = ({
|
export const CardComponent = ({
|
||||||
flow,
|
flow,
|
||||||
idx,
|
idx,
|
||||||
removeFlow,
|
removeFlow,
|
||||||
setTabIndex,
|
setTabIndex,
|
||||||
setActiveTab,
|
|
||||||
}: {
|
}: {
|
||||||
flow: FlowType;
|
flow: FlowType;
|
||||||
idx: number;
|
idx: number;
|
||||||
removeFlow: (id: string) => void;
|
removeFlow: (id: string) => void;
|
||||||
setTabIndex: (idx: number) => void;
|
setTabIndex: (idx: number) => void;
|
||||||
setActiveTab: (tab: string) => void;
|
|
||||||
}) => {
|
}) => {
|
||||||
const { setErrorData } = useContext(alertContext);
|
const { setErrorData } = useContext(alertContext);
|
||||||
const { updateFlow } = useContext(TabsContext);
|
const { updateFlow } = useContext(TabsContext);
|
||||||
|
|
@ -65,13 +64,15 @@ export const CardComponent = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-5">
|
<div className="flex gap-5">
|
||||||
|
<Link to={`/flow/${flow.id}`}>
|
||||||
<Edit
|
<Edit
|
||||||
className="w-4"
|
className="w-4"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setTabIndex(idx);
|
setTabIndex(idx);
|
||||||
setActiveTab("myflow");
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</Link>
|
||||||
<Trash
|
<Trash
|
||||||
className="w-4"
|
className="w-4"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
||||||
|
|
@ -30,14 +30,11 @@ export default function HomePage() {
|
||||||
removeFlow,
|
removeFlow,
|
||||||
tabIndex,
|
tabIndex,
|
||||||
setTabIndex,
|
setTabIndex,
|
||||||
uploadFlow,
|
|
||||||
downloadFlow,
|
|
||||||
} = useContext(TabsContext);
|
} = useContext(TabsContext);
|
||||||
const { openPopUp } = useContext(PopUpContext);
|
const { openPopUp } = useContext(PopUpContext);
|
||||||
const { templates } = useContext(typesContext);
|
const { templates } = useContext(typesContext);
|
||||||
const AlertWidth = 384;
|
const AlertWidth = 384;
|
||||||
const { dark, setDark } = useContext(darkContext);
|
const { dark, setDark } = useContext(darkContext);
|
||||||
const [activeTab, setActiveTab] = useState("myflow");
|
|
||||||
const [rename, setRename] = useState(false);
|
const [rename, setRename] = useState(false);
|
||||||
const { notificationCenter, setNotificationCenter, setErrorData } =
|
const { notificationCenter, setNotificationCenter, setErrorData } =
|
||||||
useContext(alertContext);
|
useContext(alertContext);
|
||||||
|
|
@ -50,106 +47,9 @@ export default function HomePage() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
flows.length !== 0 && (
|
flows.length !== 0 && (
|
||||||
<Tabs
|
<div
|
||||||
defaultValue="myflow"
|
className="w-full h-full flex flex-col bg-muted"
|
||||||
value={activeTab}
|
|
||||||
onValueChange={setActiveTab}
|
|
||||||
className="w-full h-full flex flex-col"
|
|
||||||
>
|
>
|
||||||
<TabsList className="w-full h-16 flex justify-between items-center border-b">
|
|
||||||
<MenuBar
|
|
||||||
activeTab={activeTab}
|
|
||||||
setRename={setRename}
|
|
||||||
rename={rename}
|
|
||||||
flows={flows}
|
|
||||||
tabIndex={tabIndex}
|
|
||||||
/>
|
|
||||||
<div className="flex">
|
|
||||||
<TabsTrigger value="community">Explore</TabsTrigger>
|
|
||||||
<TabsTrigger value="myflows">My Flows</TabsTrigger>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-end px-2 w-96">
|
|
||||||
<div className="ml-auto mr-2 flex gap-5">
|
|
||||||
<Button
|
|
||||||
asChild
|
|
||||||
variant="outline"
|
|
||||||
className="text-gray-600 dark:text-gray-300 "
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="https://github.com/logspace-ai/langflow"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="flex"
|
|
||||||
>
|
|
||||||
<FaGithub className="h-5 w-5 mr-2" />
|
|
||||||
Join The Community
|
|
||||||
</a>
|
|
||||||
</Button>
|
|
||||||
<button
|
|
||||||
className="text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200"
|
|
||||||
onClick={() => {
|
|
||||||
setDark(!dark);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{dark ? (
|
|
||||||
<SunIcon className="h-5 w-5" />
|
|
||||||
) : (
|
|
||||||
<MoonIcon className="h-5 w-5" />
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200 relative"
|
|
||||||
onClick={(event: React.MouseEvent<HTMLElement>) => {
|
|
||||||
setNotificationCenter(false);
|
|
||||||
const { top, left } = (
|
|
||||||
event.target as Element
|
|
||||||
).getBoundingClientRect();
|
|
||||||
openPopUp(
|
|
||||||
<>
|
|
||||||
<div
|
|
||||||
className="z-10 absolute"
|
|
||||||
style={{ top: top + 34, left: left - AlertWidth }}
|
|
||||||
>
|
|
||||||
<AlertDropdown />
|
|
||||||
</div>
|
|
||||||
<div className="h-screen w-screen fixed top-0 left-0"></div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{notificationCenter && (
|
|
||||||
<div className="absolute w-1.5 h-1.5 rounded-full bg-destructive right-[3px]"></div>
|
|
||||||
)}
|
|
||||||
<BellIcon className="h-5 w-5" aria-hidden="true" />
|
|
||||||
</button>
|
|
||||||
<button>
|
|
||||||
<img
|
|
||||||
src="https://github.com/shadcn.png"
|
|
||||||
className="rounded-full w-8"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TabsList>
|
|
||||||
|
|
||||||
<TabsContent value="myflow" className="w-full h-full">
|
|
||||||
<div className="h-full w-full flex basis-auto flex-1 overflow-hidden">
|
|
||||||
<ExtraSidebar />
|
|
||||||
<main className="h-full w-full flex-1 border-t border-gray-200 dark:border-gray-700 flex">
|
|
||||||
{/* Primary column */}
|
|
||||||
<div className="w-full h-full">
|
|
||||||
<ReactFlowProvider>
|
|
||||||
{flows[tabIndex] ? (
|
|
||||||
<FlowPage flow={flows[tabIndex]}></FlowPage>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</ReactFlowProvider>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</TabsContent>
|
|
||||||
<TabsContent value="myflows" className="w-full h-full bg-muted">
|
|
||||||
<div className="w-full p-4 grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
<div className="w-full p-4 grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||||
{flows.map((flow, idx) => (
|
{flows.map((flow, idx) => (
|
||||||
<CardComponent
|
<CardComponent
|
||||||
|
|
@ -157,12 +57,10 @@ export default function HomePage() {
|
||||||
idx={idx}
|
idx={idx}
|
||||||
removeFlow={removeFlow}
|
removeFlow={removeFlow}
|
||||||
setTabIndex={setTabIndex}
|
setTabIndex={setTabIndex}
|
||||||
setActiveTab={setActiveTab}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</div>
|
||||||
</Tabs>
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
src/frontend/src/routes.tsx
Normal file
16
src/frontend/src/routes.tsx
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { Route, Routes } from "react-router-dom"
|
||||||
|
import HomePage from "./pages/MainPage";
|
||||||
|
import FlowPage from "./pages/FlowPage";
|
||||||
|
|
||||||
|
const Router = () => {
|
||||||
|
return(
|
||||||
|
<Routes>
|
||||||
|
<Route path="/" element={<HomePage/>}/>
|
||||||
|
<Route path="/flow/:id/">
|
||||||
|
<Route path="" element={<FlowPage/>}/>
|
||||||
|
</Route>
|
||||||
|
</Routes>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Router;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue