Merge remote-tracking branch 'origin/dev' into new-style-features
This commit is contained in:
commit
80a73f93fe
129 changed files with 6607 additions and 3026 deletions
|
|
@ -1 +0,0 @@
|
|||
/usr/lib/node_modules/opencommit/out/cli.cjs
|
||||
3623
src/frontend/package-lock.json
generated
3623
src/frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -8,15 +8,16 @@
|
|||
"@headlessui/react": "^1.7.10",
|
||||
"@heroicons/react": "^2.0.15",
|
||||
"@mui/material": "^5.11.9",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||
"@radix-ui/react-menubar": "^1.0.3",
|
||||
"@radix-ui/react-separator": "^1.0.3",
|
||||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-dialog": "^1.0.4",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-menubar": "^1.0.3",
|
||||
"@radix-ui/react-progress": "^1.0.3",
|
||||
"@radix-ui/react-separator": "^1.0.3",
|
||||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@radix-ui/react-switch": "^1.0.3",
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-tooltip": "^1.0.6",
|
||||
"@tabler/icons-react": "^2.18.0",
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
|
|
@ -98,9 +99,10 @@
|
|||
"@types/uuid": "^9.0.1",
|
||||
"@vitejs/plugin-react-swc": "^3.0.0",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"daisyui": "^3.1.1",
|
||||
"postcss": "^8.4.23",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.3.5"
|
||||
"vite": "^4.3.9"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,13 +47,6 @@ export default function App() {
|
|||
}>
|
||||
>([]);
|
||||
|
||||
// Initialize state variable for the version
|
||||
const [version, setVersion] = useState("");
|
||||
useEffect(() => {
|
||||
getVersion().then((data) => {
|
||||
setVersion(data.version);
|
||||
});
|
||||
}, []);
|
||||
// Use effect hook to update alertsList when a new alert is added
|
||||
useEffect(() => {
|
||||
// If there is an error alert open with data, add it to the alertsList
|
||||
|
|
@ -157,14 +150,6 @@ export default function App() {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
<a
|
||||
target={"_blank"}
|
||||
href="https://logspace.ai/"
|
||||
className="absolute left-7 bottom-2 flex h-6 cursor-pointer flex-col items-center justify-start overflow-hidden rounded-lg bg-foreground px-2 text-center font-sans text-xs tracking-wide text-secondary transition-all duration-500 ease-in-out hover:h-12"
|
||||
>
|
||||
{version && <div className="mt-1">⛓️ LangFlow v{version}</div>}
|
||||
<div className={version ? "mt-2" : "mt-1"}>Created by Logspace</div>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
|
||||
import {
|
||||
classNames,
|
||||
getRandomKeyByssmm,
|
||||
groupByFamily,
|
||||
isValidConnection,
|
||||
nodeIconsLucide,
|
||||
} from "../../../../utils";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import InputComponent from "../../../../components/inputComponent";
|
||||
|
|
@ -17,7 +19,7 @@ import InputFileComponent from "../../../../components/inputFileComponent";
|
|||
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||
import IntComponent from "../../../../components/intComponent";
|
||||
import PromptAreaComponent from "../../../../components/promptComponent";
|
||||
import { nodeNames, nodeIcons } from "../../../../utils";
|
||||
import { nodeNames } from "../../../../utils";
|
||||
import React from "react";
|
||||
import { nodeColors } from "../../../../utils";
|
||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
||||
|
|
@ -40,7 +42,7 @@ export default function ParameterComponent({
|
|||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
const [position, setPosition] = useState(0);
|
||||
const { closePopUp } = useContext(PopUpContext);
|
||||
const { setTabsState, tabId } = useContext(TabsContext);
|
||||
const { setTabsState, tabId, save } = useContext(TabsContext);
|
||||
|
||||
useEffect(() => {
|
||||
if (ref.current && ref.current.offsetTop && ref.current.clientHeight) {
|
||||
|
|
@ -82,18 +84,18 @@ export default function ParameterComponent({
|
|||
|
||||
refHtml.current = groupedObj.map((item, i) => (
|
||||
<span
|
||||
key={i}
|
||||
key={getRandomKeyByssmm()}
|
||||
className={classNames(
|
||||
i > 0 ? "items-center flex mt-3" : "items-center flex"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="h-5 w-5"
|
||||
className="h-6 w-6"
|
||||
style={{
|
||||
color: nodeColors[item.family],
|
||||
}}
|
||||
>
|
||||
{React.createElement(nodeIcons[item.family])}
|
||||
{React.createElement(nodeIconsLucide[item.family])}
|
||||
</div>
|
||||
<span className="ps-2 text-gray-950">
|
||||
{nodeNames[item.family] ?? ""}{" "}
|
||||
|
|
@ -102,14 +104,14 @@ export default function ParameterComponent({
|
|||
-
|
||||
{item.type.split(", ").length > 2
|
||||
? item.type.split(", ").map((el, i) => (
|
||||
<>
|
||||
<span key={i}>
|
||||
{i == item.type.split(", ").length - 1
|
||||
<React.Fragment key={el + i}>
|
||||
<span>
|
||||
{i === item.type.split(", ").length - 1
|
||||
? el
|
||||
: (el += `, `)}
|
||||
</span>
|
||||
{i % 2 == 0 && i > 0 && <br></br>}
|
||||
</>
|
||||
{i % 2 === 0 && i > 0 && <br />}
|
||||
</React.Fragment>
|
||||
))
|
||||
: item.type}
|
||||
</span>
|
||||
|
|
@ -239,7 +241,8 @@ export default function ParameterComponent({
|
|||
fileTypes={data.node.template[name].fileTypes}
|
||||
suffixes={data.node.template[name].suffixes}
|
||||
onFileChange={(t: string) => {
|
||||
data.node.template[name].content = t;
|
||||
data.node.template[name].file_path = t;
|
||||
save();
|
||||
}}
|
||||
></InputFileComponent>
|
||||
) : left === true && type === "int" ? (
|
||||
|
|
|
|||
|
|
@ -1,7 +1,21 @@
|
|||
import { classNames, nodeColors, nodeIcons, toTitleCase } from "../../utils";
|
||||
import {
|
||||
classNames,
|
||||
nodeColors,
|
||||
nodeIconsLucide,
|
||||
toTitleCase,
|
||||
} from "../../utils";
|
||||
import ParameterComponent from "./components/parameterComponent";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import { useContext, useState, useEffect, useRef } from "react";
|
||||
import {
|
||||
useContext,
|
||||
useState,
|
||||
useEffect,
|
||||
useRef,
|
||||
ForwardRefExoticComponent,
|
||||
ComponentType,
|
||||
SVGProps,
|
||||
ReactNode,
|
||||
} from "react";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
|
|
@ -12,6 +26,7 @@ import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarCom
|
|||
|
||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||
import { useSSE } from "../../contexts/SSEContext";
|
||||
import { ReactElement } from "react-markdown/lib/react-markdown";
|
||||
|
||||
export default function GenericNode({
|
||||
data,
|
||||
|
|
@ -25,11 +40,12 @@ export default function GenericNode({
|
|||
const { types, deleteNode } = useContext(typesContext);
|
||||
|
||||
const { closePopUp, openPopUp } = useContext(PopUpContext);
|
||||
|
||||
const Icon = nodeIcons[data.type] || nodeIcons[types[data.type]];
|
||||
// any to avoid type conflict
|
||||
const Icon: any =
|
||||
nodeIconsLucide[data.type] || nodeIconsLucide[types[data.type]];
|
||||
const [validationStatus, setValidationStatus] = useState(null);
|
||||
// State for outline color
|
||||
const { sseData } = useSSE();
|
||||
const { sseData, isBuilding } = useSSE();
|
||||
|
||||
// useEffect(() => {
|
||||
// if (reactFlowInstance) {
|
||||
|
|
@ -88,8 +104,13 @@ export default function GenericNode({
|
|||
}}
|
||||
/>
|
||||
<div className="ml-2 truncate">
|
||||
<ShadTooltip delayDuration={1500} content={data.type}>
|
||||
<div className="ml-2 truncate text-foreground">{data.type}</div>
|
||||
<ShadTooltip
|
||||
delayDuration={1500}
|
||||
content={data.node.display_name}
|
||||
>
|
||||
<div className="ml-2 truncate text-gray-800">
|
||||
{data.node.display_name}
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -137,10 +158,10 @@ export default function GenericNode({
|
|||
></div>
|
||||
<div
|
||||
className={classNames(
|
||||
!validationStatus
|
||||
? "w-4 h-4 rounded-full bg-status-yellow opacity-100"
|
||||
: "w-4 h-4 rounded-full bg-ring opacity-0 hidden animate-spin",
|
||||
"absolute w-4 hover:text-ring hover: transition-all ease-in-out duration-200"
|
||||
!validationStatus || isBuilding
|
||||
? "w-4 h-4 rounded-full bg-yellow-500 opacity-100"
|
||||
: "w-4 h-4 rounded-full bg-gray-500 opacity-0 hidden animate-spin",
|
||||
"absolute w-4 hover:text-gray-500 hover:dark:text-gray-300 transition-all ease-in-out duration-200"
|
||||
)}
|
||||
></div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
import {
|
||||
XCircleIcon,
|
||||
XMarkIcon,
|
||||
InformationCircleIcon,
|
||||
CheckCircleIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Transition } from "@headlessui/react";
|
||||
import { useState } from "react";
|
||||
import { SingleAlertComponentType } from "../../../../types/alerts";
|
||||
import { X, CheckCircle2, Info, XCircle } from "lucide-react";
|
||||
|
||||
export default function SingleAlert({
|
||||
dropItem,
|
||||
|
|
@ -34,8 +29,8 @@ export default function SingleAlert({
|
|||
key={dropItem.id}
|
||||
>
|
||||
<div className="flex-shrink-0">
|
||||
<XCircleIcon
|
||||
className="h-5 w-5 text-red-400"
|
||||
<XCircle
|
||||
className="h-5 w-5 text-red-400 dark:text-red-50"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -70,7 +65,7 @@ export default function SingleAlert({
|
|||
className="inline-flex rounded-md bg-red-50 p-1.5 text-red-500"
|
||||
>
|
||||
<span className="sr-only">Dismiss</span>
|
||||
<XMarkIcon className="h-5 w-5" aria-hidden="true" />
|
||||
<X className="h-5 w-5" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -81,8 +76,8 @@ export default function SingleAlert({
|
|||
key={dropItem.id}
|
||||
>
|
||||
<div className="flex-shrink-0">
|
||||
<InformationCircleIcon
|
||||
className="h-5 w-5 text-blue-400 "
|
||||
<Info
|
||||
className="h-5 w-5 text-blue-400 dark:text-blue-50"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -116,7 +111,7 @@ export default function SingleAlert({
|
|||
className="inline-flex rounded-md bg-blue-50 p-1.5 text-blue-500 "
|
||||
>
|
||||
<span className="sr-only">Dismiss</span>
|
||||
<XMarkIcon className="h-5 w-5" aria-hidden="true" />
|
||||
<X className="h-5 w-5" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -127,8 +122,8 @@ export default function SingleAlert({
|
|||
key={dropItem.id}
|
||||
>
|
||||
<div className="flex-shrink-0">
|
||||
<CheckCircleIcon
|
||||
className="h-5 w-5 text-green-400 "
|
||||
<CheckCircle2
|
||||
className="h-5 w-5 text-green-400 dark:text-green-50"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -150,7 +145,7 @@ export default function SingleAlert({
|
|||
className="inline-flex rounded-md bg-green-50 p-1.5 text-green-500 "
|
||||
>
|
||||
<span className="sr-only">Dismiss</span>
|
||||
<XMarkIcon className="h-5 w-5" aria-hidden="true" />
|
||||
<X className="h-5 w-5" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { useContext, useEffect, useRef } from "react";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { XMarkIcon } from "@heroicons/react/24/solid";
|
||||
import { TrashIcon } from "@heroicons/react/24/outline";
|
||||
import SingleAlert from "./components/singleAlertComponent";
|
||||
import { AlertDropdownType } from "../../types/alerts";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { useOnClickOutside } from "../hooks/useOnClickOutside";
|
||||
import { X, Trash2 } from "lucide-react";
|
||||
|
||||
export default function AlertDropdown({}: AlertDropdownType) {
|
||||
const { closePopUp } = useContext(PopUpContext);
|
||||
const componentRef = useRef<HTMLDivElement>(null);
|
||||
|
|
@ -36,13 +36,13 @@ export default function AlertDropdown({}: AlertDropdownType) {
|
|||
setTimeout(clearNotificationList, 100);
|
||||
}}
|
||||
>
|
||||
<TrashIcon className="w-[1.1rem] h-[1.1rem]" />
|
||||
<Trash2 className="w-[1.1rem] h-[1.1rem]" />
|
||||
</button>
|
||||
<button
|
||||
className="text-foreground hover:text-status-red"
|
||||
onClick={closePopUp}
|
||||
>
|
||||
<XMarkIcon className="h-5 w-5" />
|
||||
<X className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Transition } from "@headlessui/react";
|
||||
import { XCircleIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ErrorAlertType } from "../../types/alerts";
|
||||
import { XCircle } from "lucide-react";
|
||||
|
||||
export default function ErrorAlert({
|
||||
title,
|
||||
|
|
@ -43,8 +43,8 @@ export default function ErrorAlert({
|
|||
>
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0">
|
||||
<XCircleIcon
|
||||
className="h-5 w-5 text-error-background"
|
||||
<XCircle
|
||||
className="h-5 w-5 text-red-400 dark:text-red-50"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Transition } from "@headlessui/react";
|
||||
import { InformationCircleIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { NoticeAlertType } from "../../types/alerts";
|
||||
import { Info } from "lucide-react";
|
||||
|
||||
export default function NoticeAlert({
|
||||
title,
|
||||
|
|
@ -40,8 +40,8 @@ export default function NoticeAlert({
|
|||
>
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0">
|
||||
<InformationCircleIcon
|
||||
className="h-5 w-5 text-medium-blue"
|
||||
<Info
|
||||
className="h-5 w-5 text-blue-400 dark:text-blue-50"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Transition } from "@headlessui/react";
|
||||
import { CheckCircleIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||
import { useEffect, useState } from "react";
|
||||
import { SuccessAlertType } from "../../types/alerts";
|
||||
import { CheckCircle2 } from "lucide-react";
|
||||
|
||||
export default function SuccessAlert({
|
||||
title,
|
||||
|
|
@ -38,8 +38,8 @@ export default function SuccessAlert({
|
|||
>
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0">
|
||||
<CheckCircleIcon
|
||||
className="h-5 w-5 text-status-green"
|
||||
<CheckCircle2
|
||||
className="h-5 w-5 text-green-400 dark:text-green-50"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Disclosure } from "@headlessui/react";
|
||||
import { ChevronLeftIcon } from "@heroicons/react/24/outline";
|
||||
import { useContext, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { classNames } from "../../utils";
|
||||
|
|
|
|||
6
src/frontend/src/components/LoadingSpinner/index.tsx
Normal file
6
src/frontend/src/components/LoadingSpinner/index.tsx
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { RadialProgressType } from "../../types/components";
|
||||
|
||||
export default function LoadingSpinner({}) {
|
||||
return <></>;
|
||||
}
|
||||
21
src/frontend/src/components/ProgressBarComponent/index.tsx
Normal file
21
src/frontend/src/components/ProgressBarComponent/index.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { ReactElement, useContext, useEffect, useRef, useState } from "react";
|
||||
import { ProgressBarType } from "../../types/components";
|
||||
import { Progress } from "../../components/ui/progress";
|
||||
import { progressContext } from "../../contexts/ProgressContext";
|
||||
import { setInterval } from "timers/promises";
|
||||
|
||||
export default function ProgressBarComponent({
|
||||
value,
|
||||
children,
|
||||
}: ProgressBarType) {
|
||||
const ref = useRef(0);
|
||||
const reff = useRef();
|
||||
const { progress } = useContext(progressContext);
|
||||
|
||||
useEffect(() => {
|
||||
ref.current = progress * 100;
|
||||
console.log(progress);
|
||||
}, [progress]);
|
||||
|
||||
return <Progress className="h-2.5" value={ref.current} />;
|
||||
}
|
||||
19
src/frontend/src/components/RadialProgress/index.tsx
Normal file
19
src/frontend/src/components/RadialProgress/index.tsx
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { RadialProgressType } from "../../types/components";
|
||||
|
||||
export default function RadialProgressComponent({
|
||||
value,
|
||||
color,
|
||||
}: RadialProgressType) {
|
||||
const style = {
|
||||
"--value": value * 100,
|
||||
"--size": "1.5rem",
|
||||
"--thickness": "2px",
|
||||
} as React.CSSProperties;
|
||||
|
||||
return (
|
||||
<div className={"radial-progress " + color} style={style}>
|
||||
<strong className="text-[8px]">{Math.trunc(value * 100)}%</strong>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -29,13 +29,15 @@ export const CardComponent = ({
|
|||
<Card className="group">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex w-full items-center gap-4">
|
||||
<span
|
||||
className={
|
||||
"rounded-full w-7 h-7 flex items-center justify-center text-2xl " +
|
||||
gradients[parseInt(flow.id.slice(0, 12), 16) % gradients.length]
|
||||
}
|
||||
></span>
|
||||
<span className="flex-1 w-full inline-block truncate-doubleline break-words">{flow.name}</span>
|
||||
<span
|
||||
className={
|
||||
"rounded-full w-7 h-7 flex items-center justify-center text-2xl " +
|
||||
gradients[parseInt(flow.id.slice(0, 12), 16) % gradients.length]
|
||||
}
|
||||
></span>
|
||||
<span className="flex-1 w-full inline-block truncate-doubleline break-words">
|
||||
{flow.name}
|
||||
</span>
|
||||
{onDelete && (
|
||||
<button className="flex self-start" onClick={onDelete}>
|
||||
<Trash2 className="w-4 h-4 text-primary opacity-0 group-hover:opacity-100 transition-all" />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useContext } from "react";
|
||||
import { useContext, useState } from "react";
|
||||
import { Transition } from "@headlessui/react";
|
||||
import { Zap } from "lucide-react";
|
||||
import { validateNodes } from "../../../utils";
|
||||
|
|
@ -10,6 +10,8 @@ import { alertContext } from "../../../contexts/alertContext";
|
|||
import { postBuildInit } from "../../../controllers/API";
|
||||
import ShadTooltip from "../../ShadTooltipComponent";
|
||||
|
||||
import RadialProgressComponent from "../../RadialProgress";
|
||||
|
||||
export default function BuildTrigger({
|
||||
open,
|
||||
flow,
|
||||
|
|
@ -21,11 +23,12 @@ export default function BuildTrigger({
|
|||
setIsBuilt: any;
|
||||
isBuilt: boolean;
|
||||
}) {
|
||||
const [isBuilding, setIsBuilding] = useState(false);
|
||||
|
||||
const { updateSSEData } = useSSE();
|
||||
const { updateSSEData, isBuilding, setIsBuilding, sseData } = useSSE();
|
||||
const { reactFlowInstance } = useContext(typesContext);
|
||||
const { setErrorData } = useContext(alertContext);
|
||||
const { setErrorData, setSuccessData } = useContext(alertContext);
|
||||
const [isIconTouched, setIsIconTouched] = useState(false);
|
||||
const eventClick = isBuilding ? "pointer-events-none" : "";
|
||||
const [progress, setProgress] = useState(0);
|
||||
|
||||
async function handleBuild(flow: FlowType) {
|
||||
try {
|
||||
|
|
@ -47,10 +50,12 @@ export default function BuildTrigger({
|
|||
const allNodesValid = await streamNodeData(flow);
|
||||
await enforceMinimumLoadingTime(startTime, minimumLoadingTime);
|
||||
setIsBuilt(allNodesValid);
|
||||
if(!allNodesValid) {
|
||||
if (!allNodesValid) {
|
||||
setErrorData({
|
||||
title: "Oops! Looks like you missed something",
|
||||
list: ["Check nodes and retry. Hover over 🔴 node for status."],
|
||||
list: [
|
||||
"Check components and retry. Hover over component status icon 🔴 to inspect.",
|
||||
],
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -59,12 +64,10 @@ export default function BuildTrigger({
|
|||
setIsBuilding(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function streamNodeData(flow: FlowType) {
|
||||
// Step 1: Make a POST request to send the flow data and receive a unique session ID
|
||||
const response = await postBuildInit(flow);
|
||||
const { flowId } = response.data;
|
||||
|
||||
// Step 2: Use the session ID to establish an SSE connection using EventSource
|
||||
let validationResults = [];
|
||||
let finished = false;
|
||||
|
|
@ -82,15 +85,25 @@ export default function BuildTrigger({
|
|||
eventSource.close();
|
||||
|
||||
return;
|
||||
} else if (parsedData.log) {
|
||||
// If the event is a log, log it
|
||||
setSuccessData({ title: parsedData.log });
|
||||
} else {
|
||||
// Otherwise, process the data
|
||||
const isValid = processStreamResult(parsedData);
|
||||
setProgress(parsedData.progress);
|
||||
validationResults.push(isValid);
|
||||
}
|
||||
// Otherwise, process the data
|
||||
const isValid = processStreamResult(parsedData);
|
||||
validationResults.push(isValid);
|
||||
};
|
||||
|
||||
eventSource.onerror = (error) => {
|
||||
eventSource.onerror = (error: any) => {
|
||||
console.error("EventSource failed:", error);
|
||||
eventSource.close();
|
||||
if (error.data) {
|
||||
const parsedData = JSON.parse(error.data);
|
||||
setErrorData({ title: parsedData.error });
|
||||
setIsBuilding(false);
|
||||
}
|
||||
};
|
||||
// Step 3: Wait for the stream to finish
|
||||
while (!finished) {
|
||||
|
|
@ -124,6 +137,14 @@ export default function BuildTrigger({
|
|||
}
|
||||
}
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
setIsIconTouched(true);
|
||||
};
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
setIsIconTouched(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Transition
|
||||
show={!open}
|
||||
|
|
@ -136,30 +157,30 @@ export default function BuildTrigger({
|
|||
leaveTo="translate-y-96"
|
||||
>
|
||||
<div className={`fixed right-4` + (isBuilt ? " bottom-20" : " bottom-4")}>
|
||||
<ShadTooltip
|
||||
delayDuration={500}
|
||||
content="Build Flow"
|
||||
side="left"
|
||||
<div
|
||||
className={`${eventClick} flex justify-center align-center py-1 px-3 w-12 h-12 rounded-full shadow-md shadow-[#0000002a] hover:shadow-[#00000032] bg-[#E2E7EE] dark:border-gray-600 cursor-pointer`}
|
||||
onClick={() => {
|
||||
handleBuild(flow);
|
||||
}}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<div
|
||||
className="flex justify-center align-center py-1 px-3 w-12 h-12 rounded-full shadow-md hover:shadow-sm shadow-btn-shadow hover:shadow-btn-shadow
|
||||
bg-buildBackground cursor-pointer"
|
||||
onClick={() => {
|
||||
handleBuild(flow);
|
||||
}}
|
||||
>
|
||||
<button>
|
||||
<div className="flex gap-3 items-center">
|
||||
{isBuilding ? (
|
||||
// Render your loading animation here when isBuilding is true
|
||||
<Loading strokeWidth={1.5} className="text-build" />
|
||||
) : (
|
||||
<Zap className="sh-6 w-6 fill-build stroke-1 stroke-build"/>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
<button>
|
||||
<div className="flex gap-3 items-center">
|
||||
{isBuilding && progress < 1 ? (
|
||||
// Render your loading animation here when isBuilding is true
|
||||
<RadialProgressComponent
|
||||
color={"text-orange-400"}
|
||||
value={progress}
|
||||
></RadialProgressComponent>
|
||||
) : isBuilding ? (
|
||||
<Loading strokeWidth={1.5} style={{ color: "#fb923c" }} />
|
||||
) : (
|
||||
<Zap className="sh-6 w-6 fill-orange-400 stroke-1 stroke-orange-400" />
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
import {
|
||||
ChatBubbleLeftEllipsisIcon,
|
||||
ChatBubbleOvalLeftEllipsisIcon,
|
||||
PlusSmallIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
import { useState } from "react";
|
||||
import { ChatMessageType } from "../../../types/chat";
|
||||
import { nodeColors } from "../../../utils";
|
||||
import Convert from "ansi-to-html";
|
||||
const convert = new Convert({ newline: true });
|
||||
import { MessageCircle } from "lucide-react";
|
||||
|
||||
export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
|
||||
const [hidden, setHidden] = useState(true);
|
||||
|
|
@ -24,7 +20,7 @@ export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
|
|||
onClick={() => setHidden((prev) => !prev)}
|
||||
className="absolute top-2 right-2 cursor-pointer"
|
||||
>
|
||||
<ChatBubbleOvalLeftEllipsisIcon className="w-5 h-5 animate-bounce" />
|
||||
<MessageCircle className="w-5 h-5 animate-bounce" />
|
||||
</div>
|
||||
)}
|
||||
{chat.thought && chat.thought !== "" && !hidden && (
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Transition } from "@headlessui/react";
|
||||
import { MessagesSquare } from "lucide-react";
|
||||
|
||||
import { alertContext } from "../../../contexts/alertContext";
|
||||
import { useContext } from "react";
|
||||
import ShadTooltip from "../../ShadTooltipComponent";
|
||||
|
|
@ -30,26 +31,21 @@ export default function ChatTrigger({ open, setOpen, isBuilt }) {
|
|||
leaveTo="translate-y-96"
|
||||
>
|
||||
<div className="absolute bottom-4 right-3">
|
||||
<ShadTooltip
|
||||
delayDuration={500}
|
||||
content="Chat Interface"
|
||||
side="left"
|
||||
<div
|
||||
className="flex justify-center align-center py-1 px-3 w-12 h-12 rounded-full shadow-md shadow-[#0000002a] hover:shadow-[#00000032]
|
||||
bg-[#E2E7EE] dark:border-gray-600 cursor-pointer"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<div
|
||||
className="border flex justify-center items-center py-1 px-3 w-12 h-12 rounded-full bg-almost-dark-blue cursor-pointer"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<button>
|
||||
<div className="flex gap-3">
|
||||
<MessagesSquare
|
||||
className="h-6 w-6 text-medium-light-blue fill-medium-light-blue"
|
||||
style={{ color: "white" }}
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
<button>
|
||||
<div className="flex gap-3">
|
||||
<MessagesSquare
|
||||
className="pth-6 w-6 fill-[#5c8be1] stroke-1 stroke-[#5c8be1]"
|
||||
style={{ color: "white" }}
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ export default function Chat({ flow }: ChatType) {
|
|||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (
|
||||
(event.key === "K" || event.key === "k") &&
|
||||
(event.metaKey || event.ctrlKey)
|
||||
(event.metaKey || event.ctrlKey) &&
|
||||
isBuilt
|
||||
) {
|
||||
event.preventDefault();
|
||||
setOpen((oldState) => !oldState);
|
||||
|
|
@ -26,7 +27,7 @@ export default function Chat({ flow }: ChatType) {
|
|||
return () => {
|
||||
document.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, []);
|
||||
}, [isBuilt]);
|
||||
|
||||
useEffect(() => {
|
||||
// Define an async function within the useEffect hook
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { ArrowTopRightOnSquareIcon } from "@heroicons/react/24/outline";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import CodeAreaModal from "../../modals/codeAreaModal";
|
||||
import TextAreaModal from "../../modals/textAreaModal";
|
||||
import { TextAreaComponentType } from "../../types/components";
|
||||
import { INPUT_STYLE } from "../../constants";
|
||||
import { ExternalLink } from "lucide-react";
|
||||
|
||||
export default function CodeAreaComponent({
|
||||
value,
|
||||
|
|
@ -69,7 +69,7 @@ export default function CodeAreaComponent({
|
|||
}}
|
||||
>
|
||||
{!editNode && (
|
||||
<ArrowTopRightOnSquareIcon className="w-6 h-6 hover:text-ring" />
|
||||
<ExternalLink className="w-6 h-6 hover:text-ring dark:text-gray-300 ml-3" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { Listbox, Transition } from "@headlessui/react";
|
||||
import { ChevronUpDownIcon, CheckIcon } from "@heroicons/react/24/outline";
|
||||
import { Fragment, useState } from "react";
|
||||
import { Fragment, useEffect, useState } from "react";
|
||||
import { DropDownComponentType } from "../../types/components";
|
||||
import { classNames } from "../../utils";
|
||||
import { INPUT_STYLE } from "../../constants";
|
||||
import { ChevronsUpDown, Check } from "lucide-react";
|
||||
|
||||
export default function Dropdown({
|
||||
value,
|
||||
|
|
@ -15,6 +15,9 @@ export default function Dropdown({
|
|||
let [internalValue, setInternalValue] = useState(
|
||||
value === "" || !value ? "Choose an option" : value
|
||||
);
|
||||
useEffect(() => {
|
||||
setInternalValue(value === "" || !value ? "Choose an option" : value);
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -43,8 +46,8 @@ export default function Dropdown({
|
|||
"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
|
||||
}
|
||||
>
|
||||
<ChevronUpDownIcon
|
||||
className="h-5 w-5 text-ring"
|
||||
<ChevronsUpDown
|
||||
className="h-5 w-5 text-gray-400"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</span>
|
||||
|
|
@ -97,7 +100,7 @@ export default function Dropdown({
|
|||
"absolute inset-y-0 right-0 flex items-center pr-4"
|
||||
)}
|
||||
>
|
||||
<CheckIcon
|
||||
<Check
|
||||
className={
|
||||
active
|
||||
? "h-5 w-5 text-black"
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ 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>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
className="gap-2 flex items-center max-w-[200px]"
|
||||
variant="primary"
|
||||
|
|
@ -64,11 +64,21 @@ export const MenuBar = ({ flows, tabId }) => {
|
|||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-44">
|
||||
<DropdownMenuLabel>Edit</DropdownMenuLabel>
|
||||
<DropdownMenuLabel>Options</DropdownMenuLabel>
|
||||
<DropdownMenuItem
|
||||
onClick={() => {
|
||||
handleAddFlow();
|
||||
}}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
New
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={() => {
|
||||
openPopUp(<FlowSettingsModal />);
|
||||
}}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Settings2 className="w-4 h-4 mr-2 " />
|
||||
Settings
|
||||
|
|
@ -77,6 +87,7 @@ export const MenuBar = ({ flows, tabId }) => {
|
|||
onClick={() => {
|
||||
undo();
|
||||
}}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Undo className="w-4 h-4 mr-2 " />
|
||||
Undo
|
||||
|
|
@ -85,13 +96,14 @@ export const MenuBar = ({ flows, tabId }) => {
|
|||
onClick={() => {
|
||||
redo();
|
||||
}}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Redo className="w-4 h-4 mr-2 " />
|
||||
Redo
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuLabel>Projects</DropdownMenuLabel>
|
||||
<DropdownMenuRadioGroup
|
||||
{/* <DropdownMenuLabel>Projects</DropdownMenuLabel> */}
|
||||
{/* <DropdownMenuRadioGroup className="max-h-full overflow-scroll"
|
||||
value={tabId}
|
||||
onValueChange={(value) => {
|
||||
setTabId(value);
|
||||
|
|
@ -99,22 +111,20 @@ export const MenuBar = ({ flows, tabId }) => {
|
|||
>
|
||||
{flows.map((flow, idx) => {
|
||||
return (
|
||||
<Link to={"/flow/" + flow.id} className="flex w-full items-center">
|
||||
<DropdownMenuRadioItem value={flow.id} className="flex-1 w-full inline-block truncate break-words mr-2">
|
||||
<Link
|
||||
to={"/flow/" + flow.id}
|
||||
className="flex w-full items-center"
|
||||
>
|
||||
<DropdownMenuRadioItem
|
||||
value={flow.id}
|
||||
className="flex-1 w-full inline-block truncate break-words mr-2"
|
||||
>
|
||||
{flow.name}
|
||||
</DropdownMenuRadioItem>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</DropdownMenuRadioGroup>
|
||||
<DropdownMenuItem
|
||||
onClick={() => {
|
||||
handleAddFlow();
|
||||
}}
|
||||
>
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
New Project
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuRadioGroup> */}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { SunIcon, MoonIcon, BellIcon, Home, Users2 } from "lucide-react";
|
||||
import { useContext, useState, useEffect } from "react";
|
||||
import { FaGithub } from "react-icons/fa";
|
||||
import { BellIcon, Home, MoonIcon, SunIcon, Users2 } from "lucide-react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa";
|
||||
import { Button } from "../ui/button";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import AlertDropdown from "../../alerts/alertDropDown";
|
||||
|
|
@ -10,6 +10,10 @@ import { PopUpContext } from "../../contexts/popUpContext";
|
|||
import { typesContext } from "../../contexts/typesContext";
|
||||
import MenuBar from "./components/menuBar";
|
||||
import { Link, useLocation, useParams } from "react-router-dom";
|
||||
import { USER_PROJECTS_HEADER } from "../../constants";
|
||||
import { getRepoStars } from "../../controllers/API";
|
||||
import { Separator } from "../ui/separator";
|
||||
import { Bell } from "lucide-react";
|
||||
|
||||
export default function Header() {
|
||||
const { flows, addFlow, tabId } = useContext(TabsContext);
|
||||
|
|
@ -21,6 +25,16 @@ export default function Header() {
|
|||
const { notificationCenter, setNotificationCenter, setErrorData } =
|
||||
useContext(alertContext);
|
||||
const location = useLocation();
|
||||
|
||||
const [stars, setStars] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchStars() {
|
||||
const starsCount = await getRepoStars("logspace-ai", "langflow");
|
||||
setStars(starsCount);
|
||||
}
|
||||
fetchStars();
|
||||
}, []);
|
||||
return (
|
||||
<div className="w-full h-12 flex justify-between items-center border-b bg-muted">
|
||||
<div className="flex gap-2 justify-start items-center w-96">
|
||||
|
|
@ -39,7 +53,7 @@ export default function Header() {
|
|||
size="sm"
|
||||
>
|
||||
<Home className="w-4 h-4" />
|
||||
<div className="flex-1">My Projects</div>
|
||||
<div className="flex-1">{USER_PROJECTS_HEADER}</div>
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to="/community">
|
||||
|
|
@ -56,24 +70,38 @@ export default function Header() {
|
|||
</Link>
|
||||
</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-muted-foreground "
|
||||
<div className="ml-auto mr-2 flex gap-5 items-center">
|
||||
<a
|
||||
href="https://github.com/logspace-ai/langflow"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-flex shadow-sm items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background text-gray-600 dark:text-gray-300 border border-input hover:bg-accent hover:text-accent-foreground h-9 px-3 pr-0 rounded-md"
|
||||
>
|
||||
<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>
|
||||
<FaGithub className="h-5 w-5 mr-2" />
|
||||
Star
|
||||
<div className="ml-2 flex text-sm bg-background rounded-md rounded-l-none border px-2 h-9 -mr-px items-center justify-center">
|
||||
{stars}
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
href="https://twitter.com/logspace_ai"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
<FaTwitter className="h-5 w-5" />
|
||||
</a>
|
||||
<a
|
||||
href="https://discord.gg/EqksyE2EX9"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
<FaDiscord className="h-5 w-5" />
|
||||
</a>
|
||||
{/* <Separator orientation="vertical" />
|
||||
<button
|
||||
className="text-gray-600 hover:text-gray-500"
|
||||
className="text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200"
|
||||
onClick={() => {
|
||||
setDark(!dark);
|
||||
}}
|
||||
|
|
@ -107,14 +135,8 @@ export default function Header() {
|
|||
{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" />
|
||||
<Bell 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>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { DocumentMagnifyingGlassIcon } from "@heroicons/react/24/outline";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { FileComponentType } from "../../types/components";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { INPUT_STYLE } from "../../constants";
|
||||
import { FileSearch2 } from "lucide-react";
|
||||
import { uploadFile } from "../../controllers/API";
|
||||
|
||||
export default function InputFileComponent({
|
||||
value,
|
||||
|
|
@ -14,7 +16,9 @@ export default function InputFileComponent({
|
|||
editNode = false,
|
||||
}: FileComponentType) {
|
||||
const [myValue, setMyValue] = useState(value);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { setErrorData } = useContext(alertContext);
|
||||
const { tabId } = useContext(TabsContext);
|
||||
useEffect(() => {
|
||||
if (disabled) {
|
||||
setMyValue("");
|
||||
|
|
@ -23,12 +27,6 @@ export default function InputFileComponent({
|
|||
}
|
||||
}, [disabled, onChange]);
|
||||
|
||||
function attachFile(fileReadEvent: ProgressEvent<FileReader>) {
|
||||
fileReadEvent.preventDefault();
|
||||
const file = fileReadEvent.target.result;
|
||||
onFileChange(file as string);
|
||||
}
|
||||
|
||||
function checkFileType(fileName: string): boolean {
|
||||
for (let index = 0; index < suffixes.length; index++) {
|
||||
if (fileName.endsWith(suffixes[index])) {
|
||||
|
|
@ -43,27 +41,54 @@ export default function InputFileComponent({
|
|||
}, [value]);
|
||||
|
||||
const handleButtonClick = () => {
|
||||
// Create a file input element
|
||||
const input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.accept = suffixes.join(",");
|
||||
input.style.display = "none";
|
||||
input.multiple = false;
|
||||
input.style.display = "none"; // Hidden from view
|
||||
input.multiple = false; // Allow only one file selection
|
||||
|
||||
input.onchange = (e: Event) => {
|
||||
setLoading(true);
|
||||
|
||||
// Get the selected file
|
||||
const file = (e.target as HTMLInputElement).files?.[0];
|
||||
const fileData = new FileReader();
|
||||
fileData.onload = attachFile;
|
||||
|
||||
// Check if the file type is correct
|
||||
if (file && checkFileType(file.name)) {
|
||||
fileData.readAsDataURL(file);
|
||||
setMyValue(file.name);
|
||||
onChange(file.name);
|
||||
// Upload the file
|
||||
uploadFile(file, tabId)
|
||||
.then((res) => res.data)
|
||||
.then((data) => {
|
||||
console.log("File uploaded successfully");
|
||||
// Get the file name from the response
|
||||
const { file_path } = data;
|
||||
console.log("File name:", file_path);
|
||||
|
||||
// Update the state and callback with the name of the file
|
||||
// sets the value to the user
|
||||
setMyValue(file.name);
|
||||
onChange(file.name);
|
||||
// sets the value that goes to the backend
|
||||
onFileChange(file_path);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
console.error("Error occurred while uploading file");
|
||||
setLoading(false);
|
||||
});
|
||||
} else {
|
||||
// Show an error if the file type is not allowed
|
||||
setErrorData({
|
||||
title:
|
||||
"Please select a valid file. Only files this files are allowed:",
|
||||
"Please select a valid file. Only these file types are allowed:",
|
||||
list: fileTypes,
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Trigger the file selection dialog
|
||||
input.click();
|
||||
};
|
||||
|
||||
|
|
@ -73,7 +98,7 @@ export default function InputFileComponent({
|
|||
disabled ? "pointer-events-none cursor-not-allowed w-full" : "w-full"
|
||||
}
|
||||
>
|
||||
<div className="w-full flex items-center gap-3">
|
||||
<div className="w-full flex items-center gap-2">
|
||||
<span
|
||||
onClick={handleButtonClick}
|
||||
className={
|
||||
|
|
@ -88,8 +113,11 @@ export default function InputFileComponent({
|
|||
{myValue !== "" ? myValue : "No file"}
|
||||
</span>
|
||||
<button onClick={handleButtonClick}>
|
||||
{!editNode && (
|
||||
<DocumentMagnifyingGlassIcon className="w-8 h-8 hover:text-ring" />
|
||||
{!editNode && !loading && (
|
||||
<FileSearch2 className="w-6 h-6 hover:text-ring" />
|
||||
)}
|
||||
{!editNode && loading && (
|
||||
<span className="loading loading-spinner loading-sm pl-3 h-8 pointer-events-none"></span>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { PlusIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { InputListComponentType } from "../../types/components";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
|
||||
import _ from "lodash";
|
||||
import { INPUT_STYLE } from "../../constants";
|
||||
import { X, Plus } from "lucide-react";
|
||||
|
||||
export default function InputListComponent({
|
||||
value,
|
||||
onChange,
|
||||
|
|
@ -59,7 +60,7 @@ export default function InputListComponent({
|
|||
onChange(inputList);
|
||||
}}
|
||||
>
|
||||
<PlusIcon className={"w-4 h-4 hover:text-ring"} />
|
||||
<Plus className={"w-4 h-4 hover:text-ring"} />
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
|
|
@ -72,7 +73,7 @@ export default function InputListComponent({
|
|||
onChange(inputList);
|
||||
}}
|
||||
>
|
||||
<XMarkIcon className="w-4 h-4 hover:text-destructive" />
|
||||
<X className="w-4 h-4 hover:text-red-600" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { ArrowTopRightOnSquareIcon } from "@heroicons/react/24/outline";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TextAreaComponentType } from "../../types/components";
|
||||
import GenericModal from "../../modals/genericModal";
|
||||
import { TypeModal } from "../../utils";
|
||||
import { INPUT_STYLE } from "../../constants";
|
||||
import { ExternalLink } from "lucide-react";
|
||||
|
||||
export default function PromptAreaComponent({
|
||||
value,
|
||||
|
|
@ -74,7 +74,7 @@ export default function PromptAreaComponent({
|
|||
}}
|
||||
>
|
||||
{!editNode && (
|
||||
<ArrowTopRightOnSquareIcon className="w-6 h-6 hover:text-ring " />
|
||||
<ExternalLink className="w-6 h-6 hover:text-ring dark:text-gray-300" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { ArrowTopRightOnSquareIcon } from "@heroicons/react/24/outline";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TextAreaComponentType } from "../../types/components";
|
||||
import GenericModal from "../../modals/genericModal";
|
||||
import { TypeModal } from "../../utils";
|
||||
import { INPUT_STYLE } from "../../constants";
|
||||
import { ExternalLink } from "lucide-react";
|
||||
|
||||
export default function TextAreaComponent({
|
||||
value,
|
||||
onChange,
|
||||
|
|
@ -76,7 +77,7 @@ export default function TextAreaComponent({
|
|||
}}
|
||||
>
|
||||
{!editNode && (
|
||||
<ArrowTopRightOnSquareIcon className="w-6 h-6 hover:text-ring " />
|
||||
<ExternalLink className="w-6 h-6 hover:text-ring dark:text-gray-300" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ const CardDescription = React.forwardRef<
|
|||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<p
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
|
|
|
|||
27
src/frontend/src/components/ui/progress.tsx
Normal file
27
src/frontend/src/components/ui/progress.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Progress = React.forwardRef<
|
||||
React.ElementRef<typeof ProgressPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
|
||||
>(({ className, value, ...props }, ref) => (
|
||||
<ProgressPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative h-4 w-full overflow-hidden rounded-full bg-secondary",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<ProgressPrimitive.Indicator
|
||||
className="h-full w-full flex-1 bg-primary transition-all"
|
||||
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
||||
/>
|
||||
</ProgressPrimitive.Root>
|
||||
));
|
||||
Progress.displayName = ProgressPrimitive.Root.displayName;
|
||||
|
||||
export { Progress };
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
||||
import { cn } from "../../utils"
|
||||
import * as React from "react";
|
||||
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Tabs = TabsPrimitive.Root
|
||||
const Tabs = TabsPrimitive.Root;
|
||||
|
||||
const TabsList = React.forwardRef<
|
||||
React.ElementRef<typeof TabsPrimitive.List>,
|
||||
|
|
@ -18,8 +18,8 @@ const TabsList = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsList.displayName = TabsPrimitive.List.displayName
|
||||
));
|
||||
TabsList.displayName = TabsPrimitive.List.displayName;
|
||||
|
||||
const TabsTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
||||
|
|
@ -33,8 +33,8 @@ const TabsTrigger = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
|
||||
));
|
||||
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
||||
|
||||
const TabsContent = React.forwardRef<
|
||||
React.ElementRef<typeof TabsPrimitive.Content>,
|
||||
|
|
@ -48,7 +48,7 @@ const TabsContent = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsContent.displayName = TabsPrimitive.Content.displayName
|
||||
));
|
||||
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
||||
|
||||
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
||||
export { Tabs, TabsList, TabsTrigger, TabsContent };
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ export const getPythonApiCode = (flow: FlowType): string => {
|
|||
|
||||
BASE_API_URL = "${window.location.protocol}//${
|
||||
window.location.host
|
||||
}/ap1/v1/predict"
|
||||
}/api/v1/process"
|
||||
FLOW_ID = "${flowId}"
|
||||
# You can tweak the flow by adding a tweaks dictionary
|
||||
# e.g {"OpenAI-XXXXX": {"model_name": "gpt-4"}}
|
||||
|
|
@ -83,7 +83,7 @@ def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
|
|||
"""
|
||||
api_url = f"{BASE_API_URL}/{flow_id}"
|
||||
|
||||
payload = {"message": message}
|
||||
payload = {"inputs": {"input": message}}
|
||||
|
||||
if tweaks:
|
||||
payload["tweaks"] = tweaks
|
||||
|
|
@ -106,9 +106,9 @@ export const getCurlCode = (flow: FlowType): string => {
|
|||
return `curl -X POST \\
|
||||
${window.location.protocol}//${
|
||||
window.location.host
|
||||
}/api/v1/predict/${flowId} \\
|
||||
}/api/v1/process/${flowId} \\
|
||||
-H 'Content-Type: application/json' \\
|
||||
-d '{"message": "Your message", "tweaks": ${JSON.stringify(
|
||||
-d '{"inputs": {"input": message}, "tweaks": ${JSON.stringify(
|
||||
tweaks,
|
||||
null,
|
||||
2
|
||||
|
|
@ -121,11 +121,12 @@ export const getCurlCode = (flow: FlowType): string => {
|
|||
*/
|
||||
export const getPythonCode = (flow: FlowType): string => {
|
||||
const flowName = flow.name;
|
||||
const tweaks = buildTweaks(flow);
|
||||
return `from langflow import load_flow_from_json
|
||||
|
||||
flow = load_flow_from_json("${flowName}.json")
|
||||
# Now you can use it like any chain
|
||||
flow("Hey, have you heard of LangFlow?")`;
|
||||
TWEAKS = ${JSON.stringify(tweaks, null, 2)}
|
||||
flow = load_flow_from_json("${flowName}.json", tweaks=TWEAKS)
|
||||
# Now you can use it like any chain
|
||||
flow("Hey, have you heard of LangFlow?")`;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -170,3 +171,262 @@ export const NAV_DISPLAY_STYLE =
|
|||
*/
|
||||
export const BUTTON_DIV_STYLE =
|
||||
" flex gap-2 ";
|
||||
" focus:ring-1 focus:ring-offset-1 focus:ring-ring focus:outline-none ";
|
||||
|
||||
/**
|
||||
* Default description for the flow
|
||||
* @constant
|
||||
*/
|
||||
export const DESCRIPTIONS: string[] = [
|
||||
"Chain the Words, Master Language!",
|
||||
"Language Architect at Work!",
|
||||
"Empowering Language Engineering.",
|
||||
"Craft Language Connections Here.",
|
||||
"Create, Connect, Converse.",
|
||||
"Smart Chains, Smarter Conversations.",
|
||||
"Bridging Prompts for Brilliance.",
|
||||
"Language Models, Unleashed.",
|
||||
"Your Hub for Text Generation.",
|
||||
"Promptly Ingenious!",
|
||||
"Building Linguistic Labyrinths.",
|
||||
"LangFlow: Create, Chain, Communicate.",
|
||||
"Connect the Dots, Craft Language.",
|
||||
"Interactive Language Weaving.",
|
||||
"Generate, Innovate, Communicate.",
|
||||
"Conversation Catalyst Engine.",
|
||||
"Language Chainlink Master.",
|
||||
"Design Dialogues with LangFlow.",
|
||||
"Nurture NLP Nodes Here.",
|
||||
"Conversational Cartography Unlocked.",
|
||||
"Design, Develop, Dialogize.",
|
||||
];
|
||||
|
||||
/**
|
||||
* Adjectives for the name of the flow
|
||||
* @constant
|
||||
*
|
||||
*/
|
||||
export const ADJECTIVES: string[] = [
|
||||
"admiring",
|
||||
"adoring",
|
||||
"agitated",
|
||||
"amazing",
|
||||
"angry",
|
||||
"awesome",
|
||||
"backstabbing",
|
||||
"berserk",
|
||||
"big",
|
||||
"boring",
|
||||
"clever",
|
||||
"cocky",
|
||||
"compassionate",
|
||||
"condescending",
|
||||
"cranky",
|
||||
"desperate",
|
||||
"determined",
|
||||
"distracted",
|
||||
"dreamy",
|
||||
"drunk",
|
||||
"ecstatic",
|
||||
"elated",
|
||||
"elegant",
|
||||
"evil",
|
||||
"fervent",
|
||||
"focused",
|
||||
"furious",
|
||||
"gigantic",
|
||||
"gloomy",
|
||||
"goofy",
|
||||
"grave",
|
||||
"happy",
|
||||
"high",
|
||||
"hopeful",
|
||||
"hungry",
|
||||
"insane",
|
||||
"jolly",
|
||||
"jovial",
|
||||
"kickass",
|
||||
"lonely",
|
||||
"loving",
|
||||
"mad",
|
||||
"modest",
|
||||
"naughty",
|
||||
"nauseous",
|
||||
"nostalgic",
|
||||
"pedantic",
|
||||
"pensive",
|
||||
"prickly",
|
||||
"reverent",
|
||||
"romantic",
|
||||
"sad",
|
||||
"serene",
|
||||
"sharp",
|
||||
"sick",
|
||||
"silly",
|
||||
"sleepy",
|
||||
"small",
|
||||
"stoic",
|
||||
"stupefied",
|
||||
"suspicious",
|
||||
"tender",
|
||||
"thirsty",
|
||||
"tiny",
|
||||
"trusting",
|
||||
];
|
||||
|
||||
/**
|
||||
* Nouns for the name of the flow
|
||||
* @constant
|
||||
*
|
||||
*/
|
||||
export const NOUNS: string[] = [
|
||||
"albattani",
|
||||
"allen",
|
||||
"almeida",
|
||||
"archimedes",
|
||||
"ardinghelli",
|
||||
"aryabhata",
|
||||
"austin",
|
||||
"babbage",
|
||||
"banach",
|
||||
"bardeen",
|
||||
"bartik",
|
||||
"bassi",
|
||||
"bell",
|
||||
"bhabha",
|
||||
"bhaskara",
|
||||
"blackwell",
|
||||
"bohr",
|
||||
"booth",
|
||||
"borg",
|
||||
"bose",
|
||||
"boyd",
|
||||
"brahmagupta",
|
||||
"brattain",
|
||||
"brown",
|
||||
"carson",
|
||||
"chandrasekhar",
|
||||
"colden",
|
||||
"cori",
|
||||
"cray",
|
||||
"curie",
|
||||
"darwin",
|
||||
"davinci",
|
||||
"dijkstra",
|
||||
"dubinsky",
|
||||
"easley",
|
||||
"einstein",
|
||||
"elion",
|
||||
"engelbart",
|
||||
"euclid",
|
||||
"euler",
|
||||
"fermat",
|
||||
"fermi",
|
||||
"feynman",
|
||||
"franklin",
|
||||
"galileo",
|
||||
"gates",
|
||||
"goldberg",
|
||||
"goldstine",
|
||||
"goldwasser",
|
||||
"golick",
|
||||
"goodall",
|
||||
"hamilton",
|
||||
"hawking",
|
||||
"heisenberg",
|
||||
"heyrovsky",
|
||||
"hodgkin",
|
||||
"hoover",
|
||||
"hopper",
|
||||
"hugle",
|
||||
"hypatia",
|
||||
"jang",
|
||||
"jennings",
|
||||
"jepsen",
|
||||
"joliot",
|
||||
"jones",
|
||||
"kalam",
|
||||
"kare",
|
||||
"keller",
|
||||
"khorana",
|
||||
"kilby",
|
||||
"kirch",
|
||||
"knuth",
|
||||
"kowalevski",
|
||||
"lalande",
|
||||
"lamarr",
|
||||
"leakey",
|
||||
"leavitt",
|
||||
"lichterman",
|
||||
"liskov",
|
||||
"lovelace",
|
||||
"lumiere",
|
||||
"mahavira",
|
||||
"mayer",
|
||||
"mccarthy",
|
||||
"mcclintock",
|
||||
"mclean",
|
||||
"mcnulty",
|
||||
"meitner",
|
||||
"meninsky",
|
||||
"mestorf",
|
||||
"minsky",
|
||||
"mirzakhani",
|
||||
"morse",
|
||||
"murdock",
|
||||
"newton",
|
||||
"nobel",
|
||||
"noether",
|
||||
"northcutt",
|
||||
"noyce",
|
||||
"panini",
|
||||
"pare",
|
||||
"pasteur",
|
||||
"payne",
|
||||
"perlman",
|
||||
"pike",
|
||||
"poincare",
|
||||
"poitras",
|
||||
"ptolemy",
|
||||
"raman",
|
||||
"ramanujan",
|
||||
"ride",
|
||||
"ritchie",
|
||||
"roentgen",
|
||||
"rosalind",
|
||||
"saha",
|
||||
"sammet",
|
||||
"shaw",
|
||||
"shirley",
|
||||
"shockley",
|
||||
"sinoussi",
|
||||
"snyder",
|
||||
"spence",
|
||||
"stallman",
|
||||
"stonebraker",
|
||||
"swanson",
|
||||
"swartz",
|
||||
"swirles",
|
||||
"tesla",
|
||||
"thompson",
|
||||
"torvalds",
|
||||
"turing",
|
||||
"varahamihira",
|
||||
"visvesvaraya",
|
||||
"volhard",
|
||||
"wescoff",
|
||||
"williams",
|
||||
"wilson",
|
||||
"wing",
|
||||
"wozniak",
|
||||
"wright",
|
||||
"yalow",
|
||||
"yonath",
|
||||
];
|
||||
|
||||
/**
|
||||
* Header text for user projects
|
||||
* @constant
|
||||
*
|
||||
*/
|
||||
export const USER_PROJECTS_HEADER = "My Collection";
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import {
|
|||
const initialValue = {
|
||||
updateSSEData: ({}) => {},
|
||||
sseData: {},
|
||||
isBuilding: false,
|
||||
setIsBuilding: (isBuilding: boolean) => {},
|
||||
};
|
||||
|
||||
const SSEContext = createContext(initialValue);
|
||||
|
|
@ -19,6 +21,7 @@ export function useSSE() {
|
|||
|
||||
export function SSEProvider({ children }) {
|
||||
const [sseData, setSSEData] = useState({});
|
||||
const [isBuilding, setIsBuilding] = useState(false);
|
||||
|
||||
const updateSSEData = useCallback((newData: any) => {
|
||||
setSSEData((prevData) => ({
|
||||
|
|
@ -28,7 +31,9 @@ export function SSEProvider({ children }) {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<SSEContext.Provider value={{ sseData, updateSSEData }}>
|
||||
<SSEContext.Provider
|
||||
value={{ sseData, updateSSEData, isBuilding, setIsBuilding }}
|
||||
>
|
||||
{children}
|
||||
</SSEContext.Provider>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ export function AlertProvider({ children }: { children: ReactNode }) {
|
|||
function setErrorData(newState: { title: string; list?: Array<string> }) {
|
||||
setErrorDataState(newState);
|
||||
setErrorOpen(true);
|
||||
if (newState.title) {
|
||||
if (newState.title && newState.title !== "") {
|
||||
setNotificationCenter(true);
|
||||
pushNotificationList({
|
||||
type: "error",
|
||||
|
|
@ -97,7 +97,7 @@ export function AlertProvider({ children }: { children: ReactNode }) {
|
|||
function setNoticeData(newState: { title: string; link?: string }) {
|
||||
setNoticeDataState(newState);
|
||||
setNoticeOpen(true);
|
||||
if (newState.title) {
|
||||
if (newState.title && newState.title !== "") {
|
||||
// Add new notice to notification center
|
||||
setNotificationCenter(true);
|
||||
pushNotificationList({
|
||||
|
|
@ -117,7 +117,7 @@ export function AlertProvider({ children }: { children: ReactNode }) {
|
|||
setSuccessOpen(true); // open the success alert
|
||||
|
||||
// If the new state has a "title" property, add a new success notification to the list
|
||||
if (newState.title) {
|
||||
if (newState.title && newState.title !== "") {
|
||||
setNotificationCenter(true); // show the notification center
|
||||
pushNotificationList({
|
||||
// add the new notification to the list
|
||||
|
|
|
|||
|
|
@ -8,10 +8,15 @@ import {
|
|||
} from "react";
|
||||
import { FlowType, NodeType } from "../types/flow";
|
||||
import { TabsContextType, TabsState } from "../types/tabs";
|
||||
import { updateIds, updateTemplate } from "../utils";
|
||||
import {
|
||||
updateIds,
|
||||
updateTemplate,
|
||||
getRandomDescription,
|
||||
getRandomName,
|
||||
} from "../utils";
|
||||
import { alertContext } from "./alertContext";
|
||||
import { typesContext } from "./typesContext";
|
||||
import { APITemplateType } from "../types/api";
|
||||
import { APIClassType, APITemplateType } from "../types/api";
|
||||
import ShortUniqueId from "short-unique-id";
|
||||
import { addEdge } from "reactflow";
|
||||
import {
|
||||
|
|
@ -40,7 +45,7 @@ const TabsContextInitialValue: TabsContextType = {
|
|||
uploadFlows: () => {},
|
||||
uploadFlow: () => {},
|
||||
hardReset: () => {},
|
||||
saveFlow: async (flow:FlowType) => {},
|
||||
saveFlow: async (flow: FlowType) => {},
|
||||
disableCopyPaste: false,
|
||||
setDisableCopyPaste: (state: boolean) => {},
|
||||
lastCopiedSelection: null,
|
||||
|
|
@ -187,20 +192,26 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
}
|
||||
|
||||
function processFlowEdges(flow) {
|
||||
if(!flow.data || !flow.data.edges) return;
|
||||
flow.data.edges.forEach((edge) => {
|
||||
edge.className = "";
|
||||
edge.style = { stroke: "#555555" };
|
||||
});
|
||||
}
|
||||
function updateDisplay_name(node:NodeType,template:APIClassType) {
|
||||
node.data.node.display_name = template["display_name"]?template["display_name"]:node.data.type;
|
||||
}
|
||||
|
||||
function processFlowNodes(flow) {
|
||||
flow.data.nodes.forEach((node) => {
|
||||
if(!flow.data || !flow.data.nodes) return;
|
||||
flow.data.nodes.forEach((node:NodeType) => {
|
||||
const template = templates[node.data.type];
|
||||
if (!template) {
|
||||
setErrorData({ title: `Unknown node type: ${node.data.type}` });
|
||||
return;
|
||||
}
|
||||
if (Object.keys(template["template"]).length > 0) {
|
||||
updateDisplay_name(node,template);
|
||||
updateNodeBaseClasses(node, template);
|
||||
updateNodeEdges(flow, node, template);
|
||||
updateNodeDescription(node, template);
|
||||
|
|
@ -209,11 +220,11 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
});
|
||||
}
|
||||
|
||||
function updateNodeBaseClasses(node, template) {
|
||||
function updateNodeBaseClasses(node:NodeType,template:APIClassType) {
|
||||
node.data.node.base_classes = template["base_classes"];
|
||||
}
|
||||
|
||||
function updateNodeEdges(flow, node, template) {
|
||||
function updateNodeEdges(flow:FlowType, node:NodeType,template:APIClassType) {
|
||||
flow.data.edges.forEach((edge) => {
|
||||
if (edge.source === node.id) {
|
||||
edge.sourceHandle = edge.sourceHandle
|
||||
|
|
@ -225,11 +236,11 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
});
|
||||
}
|
||||
|
||||
function updateNodeDescription(node, template) {
|
||||
function updateNodeDescription(node:NodeType,template:APIClassType) {
|
||||
node.data.node.description = template["description"];
|
||||
}
|
||||
|
||||
function updateNodeTemplate(node, template) {
|
||||
function updateNodeTemplate(node:NodeType,template:APIClassType) {
|
||||
node.data.node.template = updateTemplate(
|
||||
template["template"] as unknown as APITemplateType,
|
||||
node.data.node.template as APITemplateType
|
||||
|
|
@ -346,7 +357,6 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
*/
|
||||
function removeFlow(id: string) {
|
||||
const index = flows.findIndex((flow) => flow.id === id);
|
||||
console.log(index);
|
||||
if (index >= 0) {
|
||||
deleteFlowFromDatabase(id).then(() => {
|
||||
setFlows(flows.filter((flow) => flow.id !== id));
|
||||
|
|
@ -454,11 +464,13 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
if (newProject) {
|
||||
let flowData = extractDataFromFlow(flow);
|
||||
if (flowData.description == "") {
|
||||
flowData.description = "This is a new flow.";
|
||||
flowData.description = getRandomDescription();
|
||||
}
|
||||
|
||||
// Create a new flow with a default name if no flow is provided.
|
||||
const newFlow = createNewFlow(flowData, flow);
|
||||
processFlowEdges(newFlow);
|
||||
processFlowNodes(newFlow);
|
||||
|
||||
try {
|
||||
const { id } = await saveFlowToDatabase(newFlow);
|
||||
|
|
@ -536,7 +548,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
const createNewFlow = (flowData, flow) => ({
|
||||
description: flowData.description,
|
||||
name: flow?.name ?? "New Flow",
|
||||
name: flow?.name ?? getRandomName(),
|
||||
data: flowData.data,
|
||||
id: "",
|
||||
});
|
||||
|
|
@ -565,10 +577,10 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
}
|
||||
|
||||
async function saveFlow(newFlow: FlowType) {
|
||||
try{
|
||||
try {
|
||||
// updates flow in db
|
||||
const updatedFlow = await updateFlowInDatabase(newFlow);
|
||||
if (updatedFlow){
|
||||
if (updatedFlow) {
|
||||
// updates flow in state
|
||||
setFlows((prevState) => {
|
||||
const newFlows = [...prevState];
|
||||
|
|
@ -590,8 +602,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
catch(err){
|
||||
} catch (err) {
|
||||
setErrorData(err);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,16 +51,21 @@ export function TypesProvider({ children }: { children: ReactNode }) {
|
|||
);
|
||||
// Set the types by reducing over the keys of the result data and updating the accumulator.
|
||||
setTypes(
|
||||
Object.keys(result.data).reduce((acc, curr) => {
|
||||
Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => {
|
||||
acc[c] = curr;
|
||||
// Add the base classes to the accumulator as well.
|
||||
result.data[curr][c].base_classes?.forEach((b) => {
|
||||
acc[b] = curr;
|
||||
});
|
||||
});
|
||||
return acc;
|
||||
}, {})
|
||||
// Reverse the keys so the tool world does not overlap
|
||||
Object.keys(result.data)
|
||||
.reverse()
|
||||
.reduce((acc, curr) => {
|
||||
Object.keys(result.data[curr]).forEach(
|
||||
(c: keyof APIKindType) => {
|
||||
acc[c] = curr;
|
||||
// Add the base classes to the accumulator as well.
|
||||
result.data[curr][c].base_classes?.forEach((b) => {
|
||||
acc[b] = curr;
|
||||
});
|
||||
}
|
||||
);
|
||||
return acc;
|
||||
}, {})
|
||||
);
|
||||
}
|
||||
// Clear the interval if successful.
|
||||
|
|
|
|||
|
|
@ -66,8 +66,6 @@ export function UndoRedoProvider({ children }) {
|
|||
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import {
|
|||
PromptTypeAPI,
|
||||
errorsTypeAPI,
|
||||
InitTypeAPI,
|
||||
UploadFileTypeAPI,
|
||||
} from "./../../types/api/index";
|
||||
import { APIObjectType, sendAllProps } from "../../types/api/index";
|
||||
import axios, { AxiosResponse } from "axios";
|
||||
|
|
@ -18,6 +19,20 @@ export async function getAll(): Promise<AxiosResponse<APIObjectType>> {
|
|||
return await axios.get(`/api/v1/all`);
|
||||
}
|
||||
|
||||
const GITHUB_API_URL = "https://api.github.com";
|
||||
|
||||
export async function getRepoStars(owner, repo) {
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`${GITHUB_API_URL}/repos/${owner}/${repo}`
|
||||
);
|
||||
return response.data.stargazers_count;
|
||||
} catch (error) {
|
||||
console.error("Error fetching repository data:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends data to the API for prediction.
|
||||
*
|
||||
|
|
@ -34,13 +49,6 @@ export async function postValidateCode(
|
|||
return await axios.post("/api/v1/validate/code", { code });
|
||||
}
|
||||
|
||||
export async function postValidateNode(
|
||||
nodeId: string,
|
||||
data: any
|
||||
): Promise<AxiosResponse<string>> {
|
||||
return await axios.post(`/api/v1/validate/node/${nodeId}`, { data });
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the prompt for the code block by sending it to an API endpoint.
|
||||
*
|
||||
|
|
@ -305,3 +313,21 @@ export async function postBuildInit(
|
|||
): Promise<AxiosResponse<InitTypeAPI>> {
|
||||
return await axios.post(`/api/v1/build/init`, flow);
|
||||
}
|
||||
|
||||
// fetch(`/upload/${id}`, {
|
||||
// method: "POST",
|
||||
// body: formData,
|
||||
// });
|
||||
/**
|
||||
* Uploads a file to the server.
|
||||
* @param {File} file - The file to upload.
|
||||
* @param {string} id - The ID of the flow to upload the file to.
|
||||
*/
|
||||
export async function uploadFile(
|
||||
file: File,
|
||||
id: string
|
||||
): Promise<AxiosResponse<UploadFileTypeAPI>> {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
return await axios.post(`/api/v1/upload/${id}`, formData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import React, { forwardRef } from "react";
|
||||
import { ReactComponent as MidjorneySVG } from "./Midjourney_Emblem.svg";
|
||||
import { ReactComponent as MidjourneySVG } from "./Midjourney_Emblem.svg";
|
||||
|
||||
export const MidjorneyIcon = forwardRef<
|
||||
export const MidjourneyIcon = forwardRef<
|
||||
SVGSVGElement,
|
||||
React.PropsWithChildren<{}>
|
||||
>((props, ref) => {
|
||||
return <MidjorneySVG ref={ref} {...props} />;
|
||||
return <MidjourneySVG ref={ref} {...props} />;
|
||||
});
|
||||
|
|
|
|||
9
src/frontend/src/icons/MongoDB/index.tsx
Normal file
9
src/frontend/src/icons/MongoDB/index.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import React, { forwardRef } from "react";
|
||||
import { ReactComponent as MongoDBSVG } from "./mongodb-icon.svg";
|
||||
|
||||
export const MongoDBIcon = forwardRef<
|
||||
SVGSVGElement,
|
||||
React.PropsWithChildren<{}>
|
||||
>((props, ref) => {
|
||||
return <MongoDBSVG ref={ref} {...props} />;
|
||||
});
|
||||
1
src/frontend/src/icons/MongoDB/mongodb-icon.svg
Normal file
1
src/frontend/src/icons/MongoDB/mongodb-icon.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 32 32"><path d="M15.9.087l.854 1.604c.192.296.4.558.645.802.715.715 1.394 1.464 2.004 2.266 1.447 1.9 2.423 4.01 3.12 6.292.418 1.394.645 2.824.662 4.27.07 4.323-1.412 8.035-4.4 11.12-.488.488-1.01.94-1.57 1.342-.296 0-.436-.227-.558-.436-.227-.383-.366-.82-.436-1.255-.105-.523-.174-1.046-.14-1.586v-.244C16.057 24.21 15.796.21 15.9.087z" fill="#599636"/><path d="M15.9.034c-.035-.07-.07-.017-.105.017.017.35-.105.662-.296.96-.21.296-.488.523-.767.767-1.55 1.342-2.77 2.963-3.747 4.776-1.3 2.44-1.97 5.055-2.16 7.808-.087.993.314 4.497.627 5.508.854 2.684 2.388 4.933 4.375 6.885.488.47 1.01.906 1.55 1.325.157 0 .174-.14.21-.244a4.78 4.78 0 0 0 .157-.68l.35-2.614L15.9.034z" fill="#6cac48"/><path d="M16.754 28.845c.035-.4.227-.732.436-1.063-.21-.087-.366-.26-.488-.453-.105-.174-.192-.383-.26-.575-.244-.732-.296-1.5-.366-2.248v-.453c-.087.07-.105.662-.105.75a17.37 17.37 0 0 1-.314 2.353c-.052.314-.087.627-.28.906 0 .035 0 .07.017.122.314.924.4 1.865.453 2.824v.35c0 .418-.017.33.33.47.14.052.296.07.436.174.105 0 .122-.087.122-.157l-.052-.575v-1.604c-.017-.28.035-.558.07-.82z" fill="#c2bfbf"/></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
9
src/frontend/src/icons/Pinecone/index.tsx
Normal file
9
src/frontend/src/icons/Pinecone/index.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import React, { forwardRef } from "react";
|
||||
import { ReactComponent as PineconeSVG } from "./pinecone_logo.svg";
|
||||
|
||||
export const PineconeIcon = forwardRef<
|
||||
SVGSVGElement,
|
||||
React.PropsWithChildren<{}>
|
||||
>((props, ref) => {
|
||||
return <PineconeSVG ref={ref} {...props} />;
|
||||
});
|
||||
21
src/frontend/src/icons/Pinecone/pinecone_logo.svg
Normal file
21
src/frontend/src/icons/Pinecone/pinecone_logo.svg
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<svg width="32" height="35" viewBox="0 0 32 35" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.8555 34.2962C14.9325 34.2962 15.8055 33.4451 15.8055 32.3954C15.8055 31.3456 14.9325 30.4946 13.8555 30.4946C12.7786 30.4946 11.9055 31.3456 11.9055 32.3954C11.9055 33.4451 12.7786 34.2962 13.8555 34.2962Z" fill="black"/>
|
||||
<path d="M18.4138 7.19675L19.2512 2.66005" stroke="black" stroke-width="2.11786" stroke-linecap="square"/>
|
||||
<path d="M22.2656 5.5855L19.3466 2.11099L15.3748 4.37292" stroke="black" stroke-width="2.11786" stroke-linecap="square" stroke-linejoin="round"/>
|
||||
<path d="M14.9202 26.5528L15.7337 22.0169" stroke="black" stroke-width="2.11786" stroke-linecap="square"/>
|
||||
<path d="M18.7729 24.9304L15.83 21.4671L11.8701 23.741" stroke="black" stroke-width="2.11786" stroke-linecap="square" stroke-linejoin="round"/>
|
||||
<path d="M16.6077 17.1996L17.4212 12.6633" stroke="black" stroke-width="2.11786" stroke-linecap="square"/>
|
||||
<path d="M20.4587 15.58L17.5277 12.128L13.5679 14.3904" stroke="black" stroke-width="2.11786" stroke-linecap="square" stroke-linejoin="round"/>
|
||||
<path d="M8.32871 26.1554L4.75171 28.5815" stroke="black" stroke-width="2.01017" stroke-linecap="square"/>
|
||||
<path d="M8.54383 30.0865L4.3208 28.8738L4.63185 24.5944" stroke="black" stroke-width="2.01017" stroke-linecap="square" stroke-linejoin="round"/>
|
||||
<path d="M21.3213 28.4299L23.8096 31.9282" stroke="black" stroke-width="2.01017" stroke-linecap="square"/>
|
||||
<path d="M19.718 32.045L24.1085 32.3365L25.3527 28.2438" stroke="black" stroke-width="2.01017" stroke-linecap="square" stroke-linejoin="round"/>
|
||||
<path d="M25.3999 21.3291L29.7784 22.0996" stroke="black" stroke-width="2.05804" stroke-linecap="square"/>
|
||||
<path d="M26.9072 25.072L30.3048 22.1919L28.1634 18.3557" stroke="black" stroke-width="2.05804" stroke-linecap="square" stroke-linejoin="round"/>
|
||||
<path d="M24.1196 12.8615L28.0197 10.763" stroke="black" stroke-width="2.05804" stroke-linecap="square"/>
|
||||
<path d="M24.3357 8.83965L28.4869 10.5188L27.7093 14.8216" stroke="black" stroke-width="2.05804" stroke-linecap="square" stroke-linejoin="round"/>
|
||||
<path d="M6.91639 18.1572L2.52588 17.4101" stroke="black" stroke-width="2.05804" stroke-linecap="square"/>
|
||||
<path d="M4.17731 21.1645L2 17.328L5.36167 14.436" stroke="black" stroke-width="2.05804" stroke-linecap="square" stroke-linejoin="round"/>
|
||||
<path d="M11.0799 10.6129L8.14893 7.34769" stroke="black" stroke-width="2.05804" stroke-linecap="square"/>
|
||||
<path d="M12.2897 6.77496L7.80349 6.96156L7.01392 11.2649" stroke="black" stroke-width="2.05804" stroke-linecap="square" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
9
src/frontend/src/icons/supabase/index.tsx
Normal file
9
src/frontend/src/icons/supabase/index.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import React, { forwardRef } from "react";
|
||||
import { ReactComponent as SupabaseSvg } from "./supabase-icon.svg";
|
||||
|
||||
export const SupabaseIcon = forwardRef<
|
||||
SVGSVGElement,
|
||||
React.PropsWithChildren<{}>
|
||||
>((props, ref) => {
|
||||
return <SupabaseSvg ref={ref} {...props} />;
|
||||
});
|
||||
99
src/frontend/src/icons/supabase/supabase-icon.svg
Normal file
99
src/frontend/src/icons/supabase/supabase-icon.svg
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg20"
|
||||
sodipodi:docname="supabase-icon.svg"
|
||||
style="fill:none"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||
<metadata
|
||||
id="metadata24">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1687"
|
||||
inkscape:window-height="849"
|
||||
id="namedview22"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.0884956"
|
||||
inkscape:cx="54.5"
|
||||
inkscape:cy="56.5"
|
||||
inkscape:window-x="70"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg20" />
|
||||
<path
|
||||
d="m 37.41219,62.936701 c -1.634985,2.05896 -4.950068,0.93085 -4.989463,-1.69817 L 31.846665,22.786035 h 25.855406 c 4.683108,0 7.294967,5.409033 4.382927,9.07673 z"
|
||||
id="path2"
|
||||
style="fill:url(#paint0_linear);stroke-width:0.57177335"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 37.41219,62.936701 c -1.634985,2.05896 -4.950068,0.93085 -4.989463,-1.69817 L 31.846665,22.786035 h 25.855406 c 4.683108,0 7.294967,5.409033 4.382927,9.07673 z"
|
||||
id="path4"
|
||||
style="fill:url(#paint1_linear);fill-opacity:0.2;stroke-width:0.57177335"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 26.89694,1.0634102 c 1.634986,-2.05918508 4.950125,-0.93090008 4.989521,1.698149 L 32.138899,41.214003 H 6.607076 c -4.6832501,0 -7.29518376,-5.409032 -4.3830007,-9.07673 z"
|
||||
id="path6"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#3ecf8e;stroke-width:0.57177335" />
|
||||
<defs
|
||||
id="defs18">
|
||||
<linearGradient
|
||||
id="paint0_linear"
|
||||
x1="53.973801"
|
||||
y1="54.973999"
|
||||
x2="94.163498"
|
||||
y2="71.829498"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.57177306,0,0,0.57177334,0.98590077,-0.12074988)">
|
||||
<stop
|
||||
stop-color="#249361"
|
||||
id="stop8" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3ECF8E"
|
||||
id="stop10" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint1_linear"
|
||||
x1="36.1558"
|
||||
y1="30.577999"
|
||||
x2="54.484402"
|
||||
y2="65.080597"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.57177306,0,0,0.57177334,0.98590077,-0.12074988)">
|
||||
<stop
|
||||
id="stop13" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
id="stop15" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
|
|
@ -71,35 +71,35 @@
|
|||
--almost-light-blue: #dbeafe; tailwind blue 100 */
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 224 71% 4%; /* hsl(224 71% 4%) */
|
||||
--foreground: 213 31% 91%; /* hsl(213 31% 91%) */
|
||||
.dark {
|
||||
--background: 224 71% 4%; /* hsl(224 71% 4%) */
|
||||
--foreground: 213 31% 91%; /* hsl(213 31% 91%) */
|
||||
|
||||
--muted: 223 47% 11%; /* hsl(223 47% 11%) */
|
||||
--muted-foreground: 215.4 16.3% 56.9%; /* hsl(215 16% 56%) */
|
||||
--muted: 223 47% 11%; /* hsl(223 47% 11%) */
|
||||
--muted-foreground: 215.4 16.3% 56.9%; /* hsl(215 16% 56%) */
|
||||
|
||||
--popover: 224 71% 4%; /* hsl(224 71% 4%) */
|
||||
--popover-foreground: 215 20.2% 65.1%; /* hsl(215 20% 65%) */
|
||||
--popover: 224 71% 4%; /* hsl(224 71% 4%) */
|
||||
--popover-foreground: 215 20.2% 65.1%; /* hsl(215 20% 65%) */
|
||||
|
||||
--card: 224 71% 4%; /* hsl(224 71% 4%) */
|
||||
--card-foreground: 213 31% 91%; /* hsl(213 31% 91%) */
|
||||
--card: 224 71% 4%; /* hsl(224 71% 4%) */
|
||||
--card-foreground: 213 31% 91%; /* hsl(213 31% 91%) */
|
||||
|
||||
--border: 216 34% 17%; /* hsl(216 34% 17%) */
|
||||
--input: 216 34% 17%; /* hsl(216 34% 17%) */
|
||||
--border: 216 34% 17%; /* hsl(216 34% 17%) */
|
||||
--input: 216 34% 17%; /* hsl(216 34% 17%) */
|
||||
|
||||
--primary: 210 40% 98%; /* hsl(210 40% 98%) */
|
||||
--primary-foreground: 222.2 47.4% 1.2%; /* hsl(222 47% 1%) */
|
||||
--primary: 210 40% 98%; /* hsl(210 40% 98%) */
|
||||
--primary-foreground: 222.2 47.4% 1.2%; /* hsl(222 47% 1%) */
|
||||
|
||||
--secondary: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
|
||||
--secondary-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
|
||||
--secondary: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
|
||||
--secondary-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
|
||||
|
||||
--accent: 216 34% 17%; /* hsl(216 34% 17%) */
|
||||
--accent-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
|
||||
--accent: 216 34% 17%; /* hsl(216 34% 17%) */
|
||||
--accent-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
|
||||
|
||||
--destructive: 0 63% 31%; /* hsl(0 63% 31%) */
|
||||
--destructive-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
|
||||
--destructive: 0 63% 31%; /* hsl(0 63% 31%) */
|
||||
--destructive-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
|
||||
|
||||
--ring: 216 34% 17%; /* hsl(216 34% 17%) */
|
||||
--ring: 216 34% 17%; /* hsl(216 34% 17%) */
|
||||
|
||||
--radius: 0.5rem;
|
||||
|
||||
|
|
@ -118,7 +118,7 @@
|
|||
--card-foreground: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
|
||||
--border: 214.3 21.8% 91.4%; /* hsl(214 32% 91%) */
|
||||
--input: 214.3 21.8% 91.4%; /* hsl(214 32% 91%) */
|
||||
--primary: 222.2 27.0% 11.2%; /* hsl(222 27% 18%) */
|
||||
--primary: 222.2 27% 11.2%; /* hsl(222 27% 18%) */
|
||||
--primary-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
|
||||
--secondary: 210 40% 96.1%; /* hsl(210 40% 96%) */
|
||||
--secondary-foreground: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
|
||||
|
|
@ -222,4 +222,4 @@ code {
|
|||
The cursor: default; property value restores the browser's default cursor style for the targeted element. By applying this style, the element will no longer have a custom cursor appearance such as "grab" or any other custom cursor defined elsewhere in the application. Instead, it will revert to the default cursor style determined by the browser, typically an arrow-shaped cursor. */
|
||||
.react-flow__pane {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { CodeBracketSquareIcon } from "@heroicons/react/24/outline";
|
||||
import { useContext, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import "ace-builds/src-noconflict/mode-python";
|
||||
|
|
@ -26,7 +25,7 @@ import {
|
|||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "../../components/ui/tabs";
|
||||
import { Check, Clipboard } from "lucide-react";
|
||||
import { Check, Clipboard, Code2 } from "lucide-react";
|
||||
|
||||
export default function ApiModal({ flow }: { flow: FlowType }) {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
|
@ -88,8 +87,8 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center">
|
||||
<span className="pr-2">Code</span>
|
||||
<CodeBracketSquareIcon
|
||||
className="h-6 w-6 text-foreground pl-1"
|
||||
<Code2
|
||||
className="h-6 w-6 text-gray-800 pl-1 dark:text-white"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</DialogTitle>
|
||||
|
|
@ -104,7 +103,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
<div className="flex items-center justify-between px-2">
|
||||
<TabsList>
|
||||
{tabs.map((tab, index) => (
|
||||
<TabsTrigger value={index.toString()}>{tab.name}</TabsTrigger>
|
||||
<TabsTrigger key={index} value={index.toString()}>{tab.name}</TabsTrigger>
|
||||
))}
|
||||
</TabsList>
|
||||
<div className="float-right">
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import {
|
|||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import ToggleShadComponent from "../../components/toggleShadComponent";
|
||||
import { VariableIcon } from "@heroicons/react/24/outline";
|
||||
import InputListComponent from "../../components/inputListComponent";
|
||||
import TextAreaComponent from "../../components/textAreaComponent";
|
||||
import InputComponent from "../../components/inputComponent";
|
||||
|
|
@ -33,6 +32,7 @@ import {
|
|||
} from "../../components/ui/dialog";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import { Variable } from "lucide-react";
|
||||
|
||||
export default function EditNodeModal({ data }: { data: NodeDataType }) {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
|
@ -79,8 +79,8 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
|
|||
}
|
||||
|
||||
return (
|
||||
<Dialog open={true} onOpenChange={setModalOpen}>
|
||||
<DialogTrigger></DialogTrigger>
|
||||
<Dialog open={true} onOpenChange={setModalOpen} >
|
||||
<DialogTrigger asChild></DialogTrigger>
|
||||
<DialogContent className="lg:max-w-[700px] ">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center">
|
||||
|
|
@ -90,10 +90,8 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
|
|||
<DialogDescription>
|
||||
{data.node?.description}
|
||||
<div className="flex pt-4">
|
||||
<VariableIcon className="w-5 h-5 pe-1 text-foreground stroke-2">
|
||||
|
||||
</VariableIcon>
|
||||
<span className="text-sm font-semibold text-foreground">
|
||||
<Variable className="w-5 h-5 pe-1 text-gray-700 stroke-2 dark:text-slate-200"></Variable>
|
||||
<span className="text-sm font-semibold text-gray-800 dark:text-white">
|
||||
Parameters
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ export default function ModalField({
|
|||
data.node.template[name].value = t;
|
||||
setEnabled(t);
|
||||
}}
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
) : type === "float" ? (
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { XMarkIcon } from "@heroicons/react/24/outline";
|
||||
import { Fragment, useContext, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
|
|
@ -13,6 +12,7 @@ import {
|
|||
} from "../../utils";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import ModalField from "./components/ModalField";
|
||||
import { X } from "lucide-react";
|
||||
|
||||
export default function NodeModal({ data }: { data: NodeDataType }) {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
|
@ -27,7 +27,8 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
|
|||
}, 300);
|
||||
}
|
||||
}
|
||||
const Icon = nodeIcons[types[data.type]];
|
||||
// any to avoid type conflict
|
||||
const Icon: any = nodeIcons[types[data.type]];
|
||||
return (
|
||||
<Transition.Root show={open} appear={true} as={Fragment}>
|
||||
<Dialog
|
||||
|
|
@ -69,7 +70,7 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
|
|||
}}
|
||||
>
|
||||
<span className="sr-only">Close</span>
|
||||
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
|
||||
<X className="h-6 w-6" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="h-full w-full flex flex-col justify-center items-center">
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { LockClosedIcon, PaperAirplaneIcon } from "@heroicons/react/24/outline";
|
||||
import { classNames } from "../../../utils";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { TabsContext } from "../../../contexts/tabsContext";
|
||||
import { INPUT_STYLE } from "../../../constants";
|
||||
import { Lock, Send } from "lucide-react";
|
||||
|
||||
export default function ChatInput({
|
||||
lockChat,
|
||||
chatValue,
|
||||
|
|
@ -10,6 +11,12 @@ export default function ChatInput({
|
|||
setChatValue,
|
||||
inputRef,
|
||||
}) {
|
||||
useEffect(() => {
|
||||
if (!lockChat && inputRef.current) {
|
||||
inputRef.current.focus();
|
||||
}
|
||||
}, [lockChat, inputRef]);
|
||||
|
||||
useEffect(() => {
|
||||
if (inputRef.current) {
|
||||
inputRef.current.style.height = "inherit"; // Reset the height
|
||||
|
|
@ -54,13 +61,13 @@ export default function ChatInput({
|
|||
<div className="absolute bottom-0.5 right-3">
|
||||
<button disabled={lockChat} onClick={() => sendMessage()}>
|
||||
{lockChat ? (
|
||||
<LockClosedIcon
|
||||
className="h-5 w-5 text-ring animate-pulse"
|
||||
<Lock
|
||||
className="h-5 w-5 text-gray-500 dark:hover:text-gray-300 animate-pulse"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
) : (
|
||||
<PaperAirplaneIcon
|
||||
className="h-5 w-5 text-ring hover:text-muted-foreground"
|
||||
<Send
|
||||
className="h-5 w-5 text-gray-500 hover:text-gray-600 dark:hover:text-gray-300"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import { ChatBubbleOvalLeftEllipsisIcon } from "@heroicons/react/24/outline";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { ChatMessageType } from "../../../types/chat";
|
||||
import { classNames } from "../../../utils";
|
||||
import AiIcon from "../../../assets/Gooey Ring-5s-271px.svg";
|
||||
import AiIconStill from "../../../assets/froze-flow.png";
|
||||
import { UserIcon } from "@heroicons/react/24/solid";
|
||||
import FileCard from "../fileComponent";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import rehypeMathjax from "rehype-mathjax";
|
||||
|
|
@ -12,6 +10,7 @@ import remarkGfm from "remark-gfm";
|
|||
import remarkMath from "remark-math";
|
||||
import { CodeBlock } from "./codeBlock";
|
||||
import Convert from "ansi-to-html";
|
||||
import { User2, MessageCircle } from "lucide-react";
|
||||
|
||||
export default function ChatMessage({
|
||||
chat,
|
||||
|
|
@ -62,7 +61,7 @@ export default function ChatMessage({
|
|||
</div>
|
||||
)}
|
||||
{chat.isSend && (
|
||||
<UserIcon className="w-6 h-6 -mb-1 text-foreground " />
|
||||
<User2 className="w-6 h-6 -mb-1 text-gray-800 dark:text-gray-200" />
|
||||
)}
|
||||
</div>
|
||||
{!chat.isSend ? (
|
||||
|
|
@ -73,7 +72,7 @@ export default function ChatMessage({
|
|||
onClick={() => setHidden((prev) => !prev)}
|
||||
className="absolute -top-1 -left-2 cursor-pointer"
|
||||
>
|
||||
<ChatBubbleOvalLeftEllipsisIcon className="w-5 h-5 animate-bounce" />
|
||||
<MessageCircle className="w-5 h-5 animate-bounce dark:text-white" />
|
||||
</div>
|
||||
)}
|
||||
{chat.thought && chat.thought !== "" && !hidden && (
|
||||
|
|
@ -152,7 +151,7 @@ export default function ChatMessage({
|
|||
</div>
|
||||
) : (
|
||||
<div className="w-full flex items-center">
|
||||
<div className="text-start inline-block px-3 text-sm text-muted-foreground">
|
||||
<div className="text-start inline-block px-3 text-gray-600 dark:text-white">
|
||||
<span
|
||||
className="text-muted-foreground "
|
||||
dangerouslySetInnerHTML={{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { CloudArrowDownIcon, DocumentIcon } from "@heroicons/react/24/outline";
|
||||
import * as base64js from "base64-js";
|
||||
import { useState } from "react";
|
||||
import { DownloadCloud, File } from "lucide-react";
|
||||
|
||||
export default function FileCard({ fileName, content, fileType }) {
|
||||
const handleDownload = () => {
|
||||
|
|
@ -43,7 +43,7 @@ export default function FileCard({ fileName, content, fileType }) {
|
|||
className="text-ring py-1 px-2 "
|
||||
onClick={handleDownload}
|
||||
>
|
||||
<CloudArrowDownIcon className="hover:scale-110 w-5 h-5 text-current"></CloudArrowDownIcon>
|
||||
<DownloadCloud className="hover:scale-110 w-5 h-5 text-current" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -65,14 +65,14 @@ export default function FileCard({ fileName, content, fileType }) {
|
|||
className="w-8 h-8"
|
||||
/>
|
||||
) : (
|
||||
<DocumentIcon className="w-8 h-8" />
|
||||
<File className="w-8 h-8" />
|
||||
)}
|
||||
<div className="flex flex-col items-start">
|
||||
{" "}
|
||||
<div className="truncate text-sm text-current">{fileName}</div>
|
||||
<div className="truncate text-xs text-ring">{fileType}</div>
|
||||
</div>
|
||||
<CloudArrowDownIcon className="w-6 h-6 text-current ml-auto" />
|
||||
<DownloadCloud className="w-6 h-6 text-current ml-auto" />
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { ChatBubbleOvalLeftEllipsisIcon } from "@heroicons/react/24/outline";
|
||||
import { Fragment, useContext, useEffect, useRef, useState } from "react";
|
||||
import { FlowType } from "../../types/flow";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { validateNodes } from "../../utils";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import ChatMessage from "./chatMessage";
|
||||
import { FaEraser } from "react-icons/fa";
|
||||
import { HiX } from "react-icons/hi";
|
||||
import { X, MessagesSquare, Eraser } from "lucide-react";
|
||||
import { sendAllProps } from "../../types/api";
|
||||
import { ChatMessageType } from "../../types/chat";
|
||||
import ChatInput from "./chatInput";
|
||||
|
|
@ -352,13 +350,13 @@ export default function ChatModal({
|
|||
onClick={() => clearChat()}
|
||||
className="absolute top-2 right-10 hover:text-status-red text-muted-foreground z-30"
|
||||
>
|
||||
<FaEraser className="w-4 h-4" />
|
||||
<Eraser className="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setModalOpen(false)}
|
||||
className="absolute top-1.5 right-2 hover:text-status-red text-muted-foreground z-30"
|
||||
>
|
||||
<HiX className="w-5 h-5" />
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -387,7 +385,7 @@ export default function ChatModal({
|
|||
<span className="text-base text-ring">
|
||||
Start a conversation and click the agent’s thoughts{" "}
|
||||
<span>
|
||||
<ChatBubbleOvalLeftEllipsisIcon className="w-6 h-6 inline animate-bounce " />
|
||||
<MessagesSquare className="w-5 h-5 inline animate-bounce mx-1 " />
|
||||
</span>{" "}
|
||||
to inspect the chaining process.
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { XMarkIcon, CommandLineIcon } from "@heroicons/react/24/outline";
|
||||
import { Fragment, useContext, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import AceEditor from "react-ace";
|
||||
|
|
@ -22,6 +21,7 @@ import {
|
|||
} from "../../components/ui/dialog";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { CODE_PROMPT_DIALOG_SUBTITLE } from "../../constants";
|
||||
import { TerminalSquare } from "lucide-react";
|
||||
|
||||
export default function CodeAreaModal({
|
||||
value,
|
||||
|
|
@ -51,8 +51,8 @@ export default function CodeAreaModal({
|
|||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center">
|
||||
<span className="pr-2">Edit Code</span>
|
||||
<CommandLineIcon
|
||||
className="h-6 w-6 text-foreground pl-1"
|
||||
<TerminalSquare
|
||||
className="h-6 w-6 text-gray-800 pl-1 dark:text-white"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</DialogTitle>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { ArrowDownTrayIcon } from "@heroicons/react/24/outline";
|
||||
import { useContext, useRef, useState } from "react";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
|
|
@ -34,7 +33,7 @@ export default function ExportModal() {
|
|||
}, 300);
|
||||
}
|
||||
}
|
||||
const [checked, setChecked] = useState(true);
|
||||
const [checked, setChecked] = useState(false);
|
||||
const [name, setName] = useState(flows.find((f) => f.id === tabId).name);
|
||||
const [description, setDescription] = useState(
|
||||
flows.find((f) => f.id === tabId).description
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ export default function FlowSettingsModal() {
|
|||
const { closePopUp } = useContext(PopUpContext);
|
||||
const { setErrorData, setSuccessData } = useContext(alertContext);
|
||||
const ref = useRef();
|
||||
const { flows, tabId, updateFlow, setTabsState, saveFlow } = useContext(TabsContext);
|
||||
const { flows, tabId, updateFlow, setTabsState, saveFlow } =
|
||||
useContext(TabsContext);
|
||||
const maxLength = 50;
|
||||
const [name, setName] = useState(flows.find((f) => f.id === tabId).name);
|
||||
const [description, setDescription] = useState(
|
||||
|
|
@ -36,8 +37,8 @@ export default function FlowSettingsModal() {
|
|||
}, 300);
|
||||
}
|
||||
}
|
||||
function handleClick(){
|
||||
let savedFlow = flows.find((f) => f.id === tabId)
|
||||
function handleClick() {
|
||||
let savedFlow = flows.find((f) => f.id === tabId);
|
||||
savedFlow.name = name;
|
||||
savedFlow.description = description;
|
||||
saveFlow(savedFlow);
|
||||
|
|
@ -67,10 +68,7 @@ export default function FlowSettingsModal() {
|
|||
/>
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
onClick={handleClick}
|
||||
type="submit"
|
||||
>
|
||||
<Button onClick={handleClick} type="submit">
|
||||
Save
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { XMarkIcon, DocumentTextIcon } from "@heroicons/react/24/outline";
|
||||
import { Fragment, useContext, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { darkContext } from "../../contexts/darkContext";
|
||||
|
|
@ -17,6 +16,7 @@ import {
|
|||
import { Button } from "../../components/ui/button";
|
||||
import { Textarea } from "../../components/ui/textarea";
|
||||
import { PROMPT_DIALOG_SUBTITLE, TEXT_DIALOG_SUBTITLE } from "../../constants";
|
||||
import { FileText } from "lucide-react";
|
||||
|
||||
export default function GenericModal({
|
||||
value,
|
||||
|
|
@ -54,8 +54,8 @@ export default function GenericModal({
|
|||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center">
|
||||
<span className="pr-2">{myModalTitle}</span>
|
||||
<DocumentTextIcon
|
||||
className="h-6 w-6 text-foreground pl-1"
|
||||
<FileText
|
||||
className="h-6 w-6 text-gray-800 pl-1 dark:text-white"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</DialogTitle>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import React, { ReactNode, useEffect, useRef, useState } from "react";
|
||||
import { DocumentDuplicateIcon } from "@heroicons/react/solid";
|
||||
import React, { ReactNode } from "react";
|
||||
import { classNames } from "../../../utils";
|
||||
import Tooltip from "../../../components/TooltipComponent";
|
||||
|
||||
export default function ButtonBox({
|
||||
onClick,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,11 @@ export default function CommunityPage() {
|
|||
Community Examples
|
||||
</span>
|
||||
<div className="flex gap-2">
|
||||
<a href="https://github.com/logspace-ai/langflow_examples">
|
||||
<a
|
||||
href="https://github.com/logspace-ai/langflow_examples"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button variant="primary">
|
||||
<GithubIcon className="w-4 mr-2" />
|
||||
Add Your Example
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { ChevronRightIcon } from "@heroicons/react/24/solid";
|
||||
import { Disclosure } from "@headlessui/react";
|
||||
import { DisclosureComponentType } from "../../../../types/components";
|
||||
import { ChevronRight } from "lucide-react";
|
||||
|
||||
export default function DisclosureComponent({
|
||||
button: { title, Icon, buttons = [] },
|
||||
|
|
@ -14,8 +14,8 @@ export default function DisclosureComponent({
|
|||
<div>
|
||||
<Disclosure.Button className="select-none bg-muted w-full flex justify-between items-center -mt-px px-3 py-2 border-y border-y-input">
|
||||
<div className="flex gap-4">
|
||||
<Icon className="w-6 text-foreground" />
|
||||
<span className="flex items-center text-sm text-foreground font-medium">
|
||||
<Icon size={22} className="text-gray-800 dark:text-white/80" />
|
||||
<span className="flex items-center text-sm text-gray-800 dark:text-white/80 font-medium">
|
||||
{title}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -26,7 +26,7 @@ export default function DisclosureComponent({
|
|||
</button>
|
||||
))}
|
||||
<div>
|
||||
<ChevronRightIcon
|
||||
<ChevronRight
|
||||
className={`${
|
||||
open || openDisc ? "rotate-90 transform" : ""
|
||||
} h-4 w-4 text-foreground`}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
tabsState,
|
||||
saveFlow,
|
||||
setTabsState,
|
||||
tabId
|
||||
tabId,
|
||||
} = useContext(TabsContext);
|
||||
const { types, reactFlowInstance, setReactFlowInstance, templates } =
|
||||
useContext(typesContext);
|
||||
|
|
@ -69,7 +69,6 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
!disableCopyPaste
|
||||
) {
|
||||
event.preventDefault();
|
||||
console.log(_.cloneDeep(lastSelection));
|
||||
setLastCopiedSelection(_.cloneDeep(lastSelection));
|
||||
}
|
||||
if (
|
||||
|
|
@ -157,7 +156,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
};
|
||||
});
|
||||
},
|
||||
[onEdgesChange, setNodes,setTabsState,tabId]
|
||||
[onEdgesChange, setNodes, setTabsState, tabId]
|
||||
);
|
||||
|
||||
const onNodesChangeMod = useCallback(
|
||||
|
|
@ -172,7 +171,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
};
|
||||
});
|
||||
},
|
||||
[onNodesChange,setTabsState,tabId]
|
||||
[onNodesChange, setTabsState, tabId]
|
||||
);
|
||||
|
||||
const onConnect = useCallback(
|
||||
|
|
@ -278,14 +277,14 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
// Specify dependencies for useCallback
|
||||
[getNodeId, reactFlowInstance, setErrorData, setNodes, takeSnapshot]
|
||||
);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if(tabsState && tabsState[flow.id]?.isPending) {
|
||||
saveFlow(flow)
|
||||
if (tabsState && tabsState[flow.id]?.isPending) {
|
||||
saveFlow(flow);
|
||||
}
|
||||
}
|
||||
},[])
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onDelete = useCallback(
|
||||
(mynodes) => {
|
||||
|
|
@ -371,6 +370,9 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
onPaneMouseLeave={() => {
|
||||
setDisableCopyPaste(true);
|
||||
}}
|
||||
onPaneMouseEnter={() => {
|
||||
setDisableCopyPaste(false);
|
||||
}}
|
||||
onNodesChange={onNodesChangeMod}
|
||||
onEdgesChange={onEdgesChangeMod}
|
||||
onConnect={onConnect}
|
||||
|
|
@ -396,6 +398,8 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
zoomOnDoubleClick={!disableCopyPaste}
|
||||
selectNodesOnDrag={false}
|
||||
className="theme-attribution"
|
||||
minZoom={0.01}
|
||||
maxZoom={8}
|
||||
>
|
||||
<Background className="" />
|
||||
<Controls className="[&>button]:text-black"></Controls>
|
||||
|
|
|
|||
|
|
@ -1,25 +1,23 @@
|
|||
import { Bars2Icon } from "@heroicons/react/24/outline";
|
||||
import DisclosureComponent from "../DisclosureComponent";
|
||||
import {
|
||||
classNames,
|
||||
nodeColors,
|
||||
nodeIcons,
|
||||
nodeIconsLucide,
|
||||
nodeNames,
|
||||
} from "../../../../utils";
|
||||
import { useContext, useState } from "react";
|
||||
import { typesContext } from "../../../../contexts/typesContext";
|
||||
import { APIClassType, APIObjectType } from "../../../../types/api";
|
||||
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
|
||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
||||
import { Code2, FileDown, FileUp, Save } from "lucide-react";
|
||||
import { Code2, FileDown, FileUp, Save, Search } from "lucide-react";
|
||||
import { PopUpContext } from "../../../../contexts/popUpContext";
|
||||
import ExportModal from "../../../../modals/exportModal";
|
||||
import ApiModal from "../../../../modals/ApiModal";
|
||||
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||
import { alertContext } from "../../../../contexts/alertContext";
|
||||
import { updateFlowInDatabase } from "../../../../controllers/API";
|
||||
import { INPUT_STYLE } from "../../../../constants";
|
||||
import { Separator } from "../../../../components/ui/separator";
|
||||
import { Menu } from "lucide-react";
|
||||
|
||||
export default function ExtraSidebar() {
|
||||
const { data } = useContext(typesContext);
|
||||
|
|
@ -124,7 +122,7 @@ export default function ExtraSidebar() {
|
|||
type="text"
|
||||
name="search"
|
||||
id="search"
|
||||
placeholder="Search Nodes"
|
||||
placeholder="Search"
|
||||
className={
|
||||
INPUT_STYLE +
|
||||
"w-full border-1 rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
|
||||
|
|
@ -135,7 +133,7 @@ export default function ExtraSidebar() {
|
|||
}}
|
||||
/>
|
||||
<div className="absolute inset-y-0 right-0 flex py-1.5 pr-3 items-center">
|
||||
<MagnifyingGlassIcon className="h-5 w-5"></MagnifyingGlassIcon>
|
||||
<Search size={20} color="#000000" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -146,10 +144,10 @@ export default function ExtraSidebar() {
|
|||
Object.keys(dataFilter[d]).length > 0 ? (
|
||||
<DisclosureComponent
|
||||
openDisc={search.length == 0 ? false : true}
|
||||
key={i}
|
||||
key={nodeNames[d]}
|
||||
button={{
|
||||
title: nodeNames[d] ?? nodeNames.unknown,
|
||||
Icon: nodeIcons[d] ?? nodeIcons.unknown,
|
||||
Icon: nodeIconsLucide[d] ?? nodeIconsLucide.unknown,
|
||||
}}
|
||||
>
|
||||
<div className="p-2 flex flex-col gap-2">
|
||||
|
|
@ -157,9 +155,10 @@ export default function ExtraSidebar() {
|
|||
.sort()
|
||||
.map((t: string, k) => (
|
||||
<ShadTooltip
|
||||
content={t}
|
||||
delayDuration={500}
|
||||
content={data[d][t].display_name}
|
||||
delayDuration={1500}
|
||||
side="right"
|
||||
key={data[d][t].display_name}
|
||||
>
|
||||
<div key={k} data-tooltip-id={t}>
|
||||
<div
|
||||
|
|
@ -183,11 +182,11 @@ export default function ExtraSidebar() {
|
|||
);
|
||||
}}
|
||||
>
|
||||
<div className="flex w-full justify-between text-sm px-3 py-1 bg-background items-center border-dashed border-ring border-l-0 rounded-md rounded-l-none border">
|
||||
<span className="text-black w-full pr-1 truncate text-xs">
|
||||
{t}
|
||||
<div className="flex w-full justify-between text-sm px-3 py-1 bg-white dark:bg-gray-800 items-center border-dashed border-gray-400 dark:border-gray-600 border-l-0 rounded-md rounded-l-none border">
|
||||
<span className="text-black dark:text-white w-full pr-1 truncate text-xs">
|
||||
{data[d][t].display_name}
|
||||
</span>
|
||||
<Bars2Icon className="w-4 h-6 text-ring " />
|
||||
<Menu className="w-4 h-6 text-gray-400 dark:text-gray-600" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { useContext, useEffect } from "react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import Page from "./components/PageComponent";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { getVersion } from "../../controllers/API";
|
||||
|
||||
export default function FlowPage() {
|
||||
const { flows, tabId, setTabId } = useContext(TabsContext);
|
||||
|
|
@ -9,6 +10,15 @@ export default function FlowPage() {
|
|||
useEffect(() => {
|
||||
setTabId(id);
|
||||
}, [id]);
|
||||
|
||||
// Initialize state variable for the version
|
||||
const [version, setVersion] = useState("");
|
||||
useEffect(() => {
|
||||
getVersion().then((data) => {
|
||||
setVersion(data.version);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="h-full w-full overflow-hidden">
|
||||
{flows.length > 0 &&
|
||||
|
|
@ -16,6 +26,14 @@ export default function FlowPage() {
|
|||
flows.findIndex((flow) => flow.id === tabId) !== -1 && (
|
||||
<Page flow={flows.find((flow) => flow.id === tabId)} />
|
||||
)}
|
||||
<a
|
||||
target={"_blank"}
|
||||
href="https://logspace.ai/"
|
||||
className="absolute left-7 bottom-2 flex h-6 cursor-pointer flex-col items-center justify-start overflow-hidden rounded-lg bg-foreground px-2 text-center font-sans text-xs tracking-wide text-secondary transition-all duration-500 ease-in-out hover:h-12"
|
||||
>
|
||||
{version && <div className="mt-1">⛓️ LangFlow v{version}</div>}
|
||||
<div className={version ? "mt-2" : "mt-1"}>Created by Logspace</div>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,23 @@
|
|||
import { useContext, useEffect } from "react";
|
||||
import { COLUMN_DIV_STYLE, NAV_DISPLAY_STYLE, BUTTON_DIV_STYLE } from "../../constants";
|
||||
|
||||
import { Download, Upload, Plus, Home, ExternalLink } from "lucide-react";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { CardComponent } from "../../components/cardComponent";
|
||||
export default function HomePage() {
|
||||
const { flows, setTabId, downloadFlows, uploadFlows, addFlow, removeFlow } =
|
||||
import { Download, Upload, Plus, Home, ExternalLink } from "lucide-react";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { CardComponent } from "../../components/cardComponent";
|
||||
import { USER_PROJECTS_HEADER } from "../../constants";
|
||||
export default function HomePage() {
|
||||
const { flows, setTabId, downloadFlows, uploadFlows, addFlow, removeFlow } =
|
||||
useContext(TabsContext);
|
||||
useEffect(() => {
|
||||
setTabId("");
|
||||
}, []);
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<div className={`${ COLUMN_DIV_STYLE }`} >
|
||||
<div className={`${ NAV_DISPLAY_STYLE }`}>
|
||||
<span className=" text-2xl flex items-center justify-center gap-2 font-semibold ">
|
||||
<Home className=" w-6 " />
|
||||
My Projects
|
||||
<div className="w-full h-full flex overflow-auto flex-col bg-muted px-16">
|
||||
<div className="w-full flex justify-between py-12 pb-2 px-6">
|
||||
<span className="text-2xl flex items-center justify-center gap-2 font-semibold">
|
||||
<Home className="w-6" />
|
||||
{USER_PROJECTS_HEADER}
|
||||
</span>
|
||||
<div className={`${ BUTTON_DIV_STYLE }`}>
|
||||
<Button
|
||||
|
|
@ -53,8 +52,7 @@ import { COLUMN_DIV_STYLE, NAV_DISPLAY_STYLE, BUTTON_DIV_STYLE } from "../../con
|
|||
</div>
|
||||
</div>
|
||||
<span className="flex pb-14 px-6 text-muted-foreground w-[60%]">
|
||||
Manage your personal projects. Download or upload your complete project
|
||||
collection.
|
||||
Manage your personal projects. Download or upload your collection.
|
||||
</span>
|
||||
<div className="w-full p-4 grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
{flows.map((flow, idx) => (
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ const Router = () => {
|
|||
<Route path="/flow/:id/">
|
||||
<Route path="" element={<FlowPage />} />
|
||||
</Route>
|
||||
<Route path="*" element={<HomePage/>}/>
|
||||
<Route path="*" element={<HomePage />} />
|
||||
</Routes>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export type APIClassType = {
|
|||
base_classes: Array<string>;
|
||||
description: string;
|
||||
template: APITemplateType;
|
||||
display_name: string;
|
||||
[key: string]: Array<string> | string | APITemplateType;
|
||||
};
|
||||
export type TemplateVariableType = {
|
||||
|
|
@ -46,3 +47,8 @@ export type BuildStatusTypeAPI = {
|
|||
export type InitTypeAPI = {
|
||||
flowId: string;
|
||||
};
|
||||
|
||||
export type UploadFileTypeAPI = {
|
||||
file_path: string;
|
||||
flowId: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import {
|
||||
ComponentType,
|
||||
ForwardRefExoticComponent,
|
||||
ReactElement,
|
||||
ReactFragment,
|
||||
ReactNode,
|
||||
SVGProps,
|
||||
} from "react";
|
||||
|
|
@ -71,7 +71,7 @@ export type DisclosureComponentType = {
|
|||
openDisc: boolean;
|
||||
button: {
|
||||
title: string;
|
||||
Icon: ForwardRefExoticComponent<React.SVGProps<SVGSVGElement>>;
|
||||
Icon: any;
|
||||
buttons?: {
|
||||
Icon: ReactElement;
|
||||
title: string;
|
||||
|
|
@ -104,3 +104,14 @@ export type TooltipComponentType = {
|
|||
| "top-start"
|
||||
| "top";
|
||||
};
|
||||
|
||||
export type ProgressBarType = {
|
||||
children?: ReactElement;
|
||||
value?: number;
|
||||
max?: number;
|
||||
};
|
||||
|
||||
export type RadialProgressType = {
|
||||
value?: number;
|
||||
color?: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import { HomeIcon } from "@heroicons/react/24/outline";
|
||||
|
||||
export type sidebarNavigationItemType = {
|
||||
name: string;
|
||||
href: string;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { ReactFlowInstance } from "reactflow";
|
||||
import { APIClassType } from "../api";
|
||||
|
||||
const types: { [char: string]: string } = {};
|
||||
const template: { [char: string]: string } = {};
|
||||
const template: { [char: string]: APIClassType } = {};
|
||||
const data: { [char: string]: string } = {};
|
||||
|
||||
export type typesContextType = {
|
||||
|
|
|
|||
|
|
@ -33,15 +33,37 @@ import { HackerNewsIcon } from "./icons/hackerNews";
|
|||
import { HugginFaceIcon } from "./icons/HuggingFace";
|
||||
import { IFixIcon } from "./icons/IFixIt";
|
||||
import { MetaIcon } from "./icons/Meta";
|
||||
import { MidjorneyIcon } from "./icons/Midjorney";
|
||||
import { MidjourneyIcon } from "./icons/Midjorney";
|
||||
import { NotionIcon } from "./icons/Notion";
|
||||
import { OpenAiIcon } from "./icons/OpenAi";
|
||||
import { QDrantIcon } from "./icons/QDrant";
|
||||
import { SearxIcon } from "./icons/Searx";
|
||||
import { SlackIcon } from "./icons/Slack";
|
||||
import { PineconeIcon } from "./icons/Pinecone";
|
||||
import clsx, { ClassValue } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { WeaviateIcon } from "./icons/Weaviate";
|
||||
import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "./constants";
|
||||
import { ComponentType, SVGProps } from "react";
|
||||
import {
|
||||
Cpu,
|
||||
Fingerprint,
|
||||
Gift,
|
||||
Hammer,
|
||||
HelpCircle,
|
||||
Laptop2,
|
||||
Layers,
|
||||
Lightbulb,
|
||||
Link,
|
||||
MessageCircle,
|
||||
Paperclip,
|
||||
Rocket,
|
||||
Scissors,
|
||||
TerminalSquare,
|
||||
Wand2,
|
||||
Wrench,
|
||||
} from "lucide-react";
|
||||
import { SupabaseIcon } from "./icons/supabase";
|
||||
import { MongoDBIcon } from "./icons/MongoDB";
|
||||
|
||||
export function classNames(...classes: Array<string>) {
|
||||
return classes.filter(Boolean).join(" ");
|
||||
|
|
@ -165,11 +187,14 @@ export const nodeIcons: {
|
|||
HuggingFaceEmbeddings: HugginFaceIcon,
|
||||
IFixitLoader: IFixIcon,
|
||||
Meta: MetaIcon,
|
||||
Midjorney: MidjorneyIcon,
|
||||
Midjourney: MidjourneyIcon,
|
||||
NotionDirectoryLoader: NotionIcon,
|
||||
ChatOpenAI: OpenAiIcon,
|
||||
OpenAI: OpenAiIcon,
|
||||
OpenAIEmbeddings: OpenAiIcon,
|
||||
Pinecone: PineconeIcon,
|
||||
SupabaseVectorStore: SupabaseIcon,
|
||||
MongoDBAtlasVectorSearch: MongoDBIcon,
|
||||
// UnstructuredPowerPointLoader: PowerPointIcon, // word and powerpoint have differente styles
|
||||
Qdrant: QDrantIcon,
|
||||
// ReadTheDocsLoader: ReadTheDocsIcon, // does not work
|
||||
|
|
@ -198,6 +223,151 @@ export const nodeIcons: {
|
|||
unknown: QuestionMarkCircleIcon,
|
||||
};
|
||||
|
||||
export const nodeIconsLucide: {
|
||||
[char: string]: React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>;
|
||||
} = {
|
||||
Chroma: ChromaIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
AirbyteJSONLoader: AirbyteIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
Anthropic: AnthropicIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
ChatAnthropic: AnthropicIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
BingSearchAPIWrapper: BingIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
BingSearchRun: BingIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
Cohere: CohereIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
CohereEmbeddings: CohereIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
EverNoteLoader: EvernoteIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
FacebookChatLoader: FBIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
GitbookLoader: GitBookIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
GoogleSearchAPIWrapper: GoogleIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
GoogleSearchResults: GoogleIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
GoogleSearchRun: GoogleIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
HNLoader: HackerNewsIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
HuggingFaceHub: HugginFaceIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
HuggingFaceEmbeddings: HugginFaceIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
IFixitLoader: IFixIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
Meta: MetaIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
Midjorney: MidjourneyIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
MongoDBAtlasVectorSearch: MongoDBIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
NotionDirectoryLoader: NotionIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
ChatOpenAI: OpenAiIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
OpenAI: OpenAiIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
OpenAIEmbeddings: OpenAiIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
Pinecone: PineconeIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
Qdrant: QDrantIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
Searx: SearxIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
SlackDirectoryLoader: SlackIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
SupabaseVectorStore: SupabaseIcon as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
agents: Rocket as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
chains: Link as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
memories: Cpu as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
llms: Lightbulb as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
prompts: TerminalSquare as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
tools: Wrench as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
advanced: Laptop2 as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
chat: MessageCircle as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
embeddings: Fingerprint as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
documentloaders: Paperclip as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
vectorstores: Layers as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
toolkits: Hammer as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
textsplitters: Scissors as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
wrappers: Gift as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
utilities: Wand2 as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
unknown: HelpCircle as React.ForwardRefExoticComponent<
|
||||
ComponentType<SVGProps<SVGSVGElement>>
|
||||
>,
|
||||
};
|
||||
|
||||
export const gradients = [
|
||||
"bg-gradient-to-br from-gray-800 via-rose-700 to-violet-900",
|
||||
"bg-gradient-to-br from-green-200 via-green-300 to-blue-500",
|
||||
|
|
@ -420,9 +590,7 @@ export function toFirstUpperCase(str: string) {
|
|||
}
|
||||
|
||||
export function snakeToSpaces(str: string) {
|
||||
let result = str.split("_").join(" ");
|
||||
|
||||
return result;
|
||||
return str.split("_").join(" ");
|
||||
}
|
||||
|
||||
export function toNormalCase(str: string) {
|
||||
|
|
@ -466,10 +634,7 @@ export function roundNumber(x: number, decimals: number) {
|
|||
export function getConnectedNodes(edge: Edge, nodes: Array<Node>): Array<Node> {
|
||||
const sourceId = edge.source;
|
||||
const targetId = edge.target;
|
||||
const connectedNodes = nodes.filter(
|
||||
(node) => node.id === targetId || node.id === sourceId
|
||||
);
|
||||
return connectedNodes;
|
||||
return nodes.filter((node) => node.id === targetId || node.id === sourceId);
|
||||
}
|
||||
|
||||
export function isValidConnection(
|
||||
|
|
@ -508,9 +673,10 @@ export function isValidConnection(
|
|||
|
||||
export function removeApiKeys(flow: FlowType): FlowType {
|
||||
let cleanFLow = _.cloneDeep(flow);
|
||||
console.log(cleanFLow);
|
||||
cleanFLow.data.nodes.forEach((node) => {
|
||||
for (const key in node.data.node.template) {
|
||||
if (key.includes("api")) {
|
||||
if (node.data.node.template[key].password) {
|
||||
node.data.node.template[key].value = "";
|
||||
}
|
||||
}
|
||||
|
|
@ -715,7 +881,7 @@ export function groupByFamily(data, baseClasses) {
|
|||
return foundIndex === index;
|
||||
});
|
||||
|
||||
let groupedObj = groupedBy.reduce((result, item) => {
|
||||
return groupedBy.reduce((result, item) => {
|
||||
const existingGroup = result.find((group) => group.family === item.family);
|
||||
|
||||
if (existingGroup) {
|
||||
|
|
@ -726,8 +892,6 @@ export function groupByFamily(data, baseClasses) {
|
|||
|
||||
return result;
|
||||
}, []);
|
||||
|
||||
return groupedObj;
|
||||
}
|
||||
|
||||
export function buildTweaks(flow) {
|
||||
|
|
@ -768,9 +932,7 @@ export function validateNode(
|
|||
)
|
||||
? [
|
||||
`${type} is missing ${
|
||||
template.display_name
|
||||
? template.display_name
|
||||
: toNormalCase(template[t].name)
|
||||
template.display_name || toNormalCase(template[t].name)
|
||||
}.`,
|
||||
]
|
||||
: []
|
||||
|
|
@ -789,3 +951,49 @@ export function validateNodes(reactFlowInstance: ReactFlowInstance) {
|
|||
.getNodes()
|
||||
.flatMap((n: NodeType) => validateNode(n, reactFlowInstance));
|
||||
}
|
||||
|
||||
export function getRandomElement<T>(array: T[]): T {
|
||||
return array[Math.floor(Math.random() * array.length)];
|
||||
}
|
||||
export function getRandomDescription(): string {
|
||||
return getRandomElement(DESCRIPTIONS);
|
||||
}
|
||||
|
||||
export function getRandomName(
|
||||
retry: number = 0,
|
||||
noSpace: boolean = false,
|
||||
maxRetries: number = 3
|
||||
): string {
|
||||
const left: string[] = ADJECTIVES;
|
||||
const right: string[] = NOUNS;
|
||||
|
||||
const lv = getRandomElement(left);
|
||||
const rv = getRandomElement(right);
|
||||
|
||||
// Condition to avoid "boring wozniak"
|
||||
if (lv === "boring" && rv === "wozniak") {
|
||||
if (retry < maxRetries) {
|
||||
return getRandomName(retry + 1, noSpace, maxRetries);
|
||||
} else {
|
||||
console.warn("Max retries reached, returning as is");
|
||||
}
|
||||
}
|
||||
|
||||
// Append a suffix if retrying and noSpace is true
|
||||
if (retry > 0 && noSpace) {
|
||||
const retrySuffix = Math.floor(Math.random() * 10);
|
||||
return `${lv}_${rv}${retrySuffix}`;
|
||||
}
|
||||
|
||||
// Construct the final name
|
||||
let final_name = noSpace ? `${lv}_${rv}` : `${lv} ${rv}`;
|
||||
// Return title case final name
|
||||
return toTitleCase(final_name);
|
||||
}
|
||||
|
||||
export function getRandomKeyByssmm(): string {
|
||||
const now = new Date();
|
||||
const seconds = String(now.getSeconds()).padStart(2, "0");
|
||||
const milliseconds = String(now.getMilliseconds()).padStart(3, "0");
|
||||
return seconds + milliseconds;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,5 +316,6 @@ module.exports = {
|
|||
});
|
||||
}),
|
||||
require("@tailwindcss/typography"),
|
||||
require("daisyui"),
|
||||
],
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue