Merge branch 'db' into merge/mp

This commit is contained in:
Cristhian Zanforlin Lousa 2023-06-14 21:47:53 -03:00
commit 3d69d76c6f
63 changed files with 833 additions and 646 deletions

View file

@ -53,6 +53,7 @@
"remark-gfm": "^3.0.1",
"remark-math": "^5.1.1",
"shadcn-ui": "^0.1.3",
"short-unique-id": "^4.4.4",
"switch": "^0.0.0",
"table": "^6.8.1",
"tailwind-merge": "^1.13.0",
@ -8642,6 +8643,15 @@
"node": ">=8"
}
},
"node_modules/short-unique-id": {
"version": "4.4.4",
"resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-4.4.4.tgz",
"integrity": "sha512-oLF1NCmtbiTWl2SqdXZQbo5KM1b7axdp0RgQLq8qCBBLoq+o3A5wmLrNM6bZIh54/a8BJ3l69kTXuxwZ+XCYuw==",
"bin": {
"short-unique-id": "bin/short-unique-id",
"suid": "bin/short-unique-id"
}
},
"node_modules/side-channel": {
"version": "1.0.4",
"dev": true,

View file

@ -48,6 +48,7 @@
"remark-gfm": "^3.0.1",
"remark-math": "^5.1.1",
"shadcn-ui": "^0.1.3",
"short-unique-id": "^4.4.4",
"switch": "^0.0.0",
"table": "^6.8.1",
"tailwind-merge": "^1.13.0",

View file

@ -25,6 +25,7 @@ import React from "react";
import { nodeColors } from "../../../../utils";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
import { PopUpContext } from "../../../../contexts/popUpContext";
import ToggleShadComponent from "../../../../components/toggleShadComponent";
export default function ParameterComponent({
left,
@ -39,7 +40,6 @@ export default function ParameterComponent({
}: ParameterComponentType) {
const ref = useRef(null);
const refHtml = useRef(null);
const refData = useRef(null);
const updateNodeInternals = useUpdateNodeInternals();
const [position, setPosition] = useState(0);
const { closePopUp } = useContext(PopUpContext);
@ -64,11 +64,11 @@ export default function ParameterComponent({
const { reactFlowInstance } = useContext(typesContext);
let disabled =
reactFlowInstance?.getEdges().some((e) => e.targetHandle === id) ?? false;
const [myData, setMyData] = useState(useContext(typesContext).data);
useEffect(() => {
const groupedObj = groupByFamily(myData, tooltipTitle);
refHtml.current = groupedObj.map((item, i) => (
<span
key={i}
@ -108,169 +108,166 @@ export default function ParameterComponent({
}, [tooltipTitle]);
return (
<>
<div
ref={ref}
className="w-full flex flex-wrap justify-between items-center bg-muted dark:bg-gray-800 dark:text-white mt-1 px-5 py-2"
>
<>
<div
className={"text-sm truncate w-full " + (left ? "" : "text-end")}
<div
ref={ref}
className="w-full flex flex-wrap justify-between items-center bg-muted dark:bg-gray-800 dark:text-white mt-1 px-5 py-2"
>
<>
<div className={"text-sm truncate w-full " + (left ? "" : "text-end")}>
{title}
<span className="text-red-600">{required ? " *" : ""}</span>
</div>
{left &&
(type === "str" ||
type === "bool" ||
type === "float" ||
type === "code" ||
type === "prompt" ||
type === "file" ||
type === "int") ? (
<></>
) : (
<ShadTooltip
delayDuration={0}
content={refHtml.current}
side={left ? "left" : "right"}
open={refHtml?.current?.length > 0}
>
{title}
<span className="text-red-600">{required ? " *" : ""}</span>
</div>
{left &&
(type === "str" ||
type === "bool" ||
type === "float" ||
type === "code" ||
type === "prompt" ||
type === "file" ||
type === "int") ? (
<></>
) : (
<ShadTooltip
delayDuration={0}
content={refHtml.current}
side={left ? "left" : "right"}
open={refHtml?.current?.length > 0}
>
<Handle
type={left ? "target" : "source"}
position={left ? Position.Left : Position.Right}
id={id}
isValidConnection={(connection) =>
isValidConnection(connection, reactFlowInstance)
}
className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ",
"w-3 h-3 rounded-full border-2 bg-white dark:bg-gray-800"
)}
style={{
borderColor: color,
top: position,
}}
></Handle>
</ShadTooltip>
)}
{left === true &&
type === "str" &&
!data.node.template[name].options ? (
<div className="mt-2 w-full">
{data.node.template[name].list ? (
<InputListComponent
disabled={disabled}
value={
!data.node.template[name].value ||
data.node.template[name].value === ""
? [""]
: data.node.template[name].value
}
onChange={(t: string[]) => {
data.node.template[name].value = t;
}}
/>
) : data.node.template[name].multiline ? (
<TextAreaComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
) : (
<InputComponent
disabled={disabled}
disableCopyPaste={true}
password={data.node.template[name].password ?? false}
value={data.node.template[name].value ?? ""}
onChange={(t) => {
data.node.template[name].value = t;
}}
/>
<Handle
type={left ? "target" : "source"}
position={left ? Position.Left : Position.Right}
id={id}
isValidConnection={(connection) =>
isValidConnection(connection, reactFlowInstance)
}
className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ",
"w-3 h-3 rounded-full border-2 bg-white dark:bg-gray-800"
)}
</div>
) : left === true && type === "bool" ? (
<div className="mt-2">
<ToggleComponent
style={{
borderColor: color,
top: position,
}}
></Handle>
</ShadTooltip>
)}
{left === true &&
type === "str" &&
!data.node.template[name].options ? (
<div className="mt-2 w-full">
{data.node.template[name].list ? (
<InputListComponent
disabled={disabled}
enabled={enabled}
setEnabled={(t) => {
data.node.template[name].value = t;
setEnabled(t);
}}
/>
</div>
) : left === true && type === "float" ? (
<div className="mt-2 w-full">
<FloatComponent
disabled={disabled}
disableCopyPaste={true}
value={data.node.template[name].value ?? ""}
onChange={(t) => {
data.node.template[name].value = t;
}}
/>
</div>
) : left === true &&
type === "str" &&
data.node.template[name].options ? (
<div className="w-full">
<Dropdown
options={data.node.template[name].options}
onSelect={(newValue) =>
(data.node.template[name].value = newValue)
value={
!data.node.template[name].value ||
data.node.template[name].value === ""
? [""]
: data.node.template[name].value
}
value={data.node.template[name].value ?? "Choose an option"}
></Dropdown>
</div>
) : left === true && type === "code" ? (
<CodeAreaComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
) : left === true && type === "file" ? (
<InputFileComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
fileTypes={data.node.template[name].fileTypes}
suffixes={data.node.template[name].suffixes}
onFileChange={(t: string) => {
data.node.template[name].content = t;
}}
></InputFileComponent>
) : left === true && type === "int" ? (
<div className="mt-2 w-full">
<IntComponent
onChange={(t: string[]) => {
data.node.template[name].value = t;
}}
/>
) : data.node.template[name].multiline ? (
<TextAreaComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
) : (
<InputComponent
disabled={disabled}
disableCopyPaste={true}
password={data.node.template[name].password ?? false}
value={data.node.template[name].value ?? ""}
onChange={(t) => {
data.node.template[name].value = t;
}}
/>
</div>
) : left === true && type === "prompt" ? (
<PromptAreaComponent
)}
</div>
) : left === true && type === "bool" ? (
<div className="mt-2">
<ToggleShadComponent
disabled={disabled}
enabled={enabled}
setEnabled={(t) => {
data.node.template[name].value = t;
setEnabled(t);
}}
size="large"
/>
</div>
) : left === true && type === "float" ? (
<div className="mt-2 w-full">
<FloatComponent
disabled={disabled}
disableCopyPaste={true}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
onChange={(t) => {
data.node.template[name].value = t;
}}
/>
) : (
<></>
)}
</>
</div>
</>
</div>
) : left === true &&
type === "str" &&
data.node.template[name].options ? (
<div className="w-full">
<Dropdown
options={data.node.template[name].options}
onSelect={(newValue) =>
(data.node.template[name].value = newValue)
}
value={data.node.template[name].value ?? "Choose an option"}
></Dropdown>
</div>
) : left === true && type === "code" ? (
<CodeAreaComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
) : left === true && type === "file" ? (
<InputFileComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
fileTypes={data.node.template[name].fileTypes}
suffixes={data.node.template[name].suffixes}
onFileChange={(t: string) => {
data.node.template[name].content = t;
}}
></InputFileComponent>
) : left === true && type === "int" ? (
<div className="mt-2 w-full">
<IntComponent
disabled={disabled}
disableCopyPaste={true}
value={data.node.template[name].value ?? ""}
onChange={(t) => {
data.node.template[name].value = t;
}}
/>
</div>
) : left === true && type === "prompt" ? (
<PromptAreaComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {
data.node.template[name].value = t;
}}
/>
) : (
<></>
)}
</>
</div>
);
}

View file

@ -1,16 +1,3 @@
import {
BugAntIcon,
Cog6ToothIcon,
InformationCircleIcon,
TrashIcon,
} from "@heroicons/react/24/outline";
import {
CheckCircleIcon,
EllipsisHorizontalCircleIcon,
ExclamationCircleIcon,
} from "@heroicons/react/24/solid";
import {
classNames,
nodeColors,
@ -33,6 +20,7 @@ import { NodeToolbar } from "reactflow";
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
import ShadTooltip from "../../components/ShadTooltipComponent";
import { postValidateNode } from "../../controllers/API";
export default function GenericNode({
data,
selected,
@ -62,17 +50,13 @@ export default function GenericNode({
const validateNode = useCallback(
debounce(async () => {
try {
const response = await fetch(`/validate/node/${data.id}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(reactFlowInstance.toObject()),
});
const response = await postValidateNode(
data.id,
reactFlowInstance.toObject()
);
if (response.status === 200) {
let jsonResponse = await response.json();
let jsonResponseParsed = await JSON.parse(jsonResponse);
let jsonResponseParsed = await JSON.parse(response.data);
setValidationStatus(jsonResponseParsed);
}
} catch (error) {
@ -150,11 +134,10 @@ export default function GenericNode({
"Validating..."
) : (
<div className="max-h-96 overflow-auto">
{validationStatus.params
.split("\n")
.map((line, index) => (
<div key={index}>{line}</div>
))}
{validationStatus.params ||
""
.split("\n")
.map((line, index) => <div key={index}>{line}</div>)}
</div>
)
}
@ -191,7 +174,7 @@ export default function GenericNode({
</div>
<div className="h-full w-full py-5 text-gray-800">
<div className="w-full px-5 pb-3 text-sm text-gray-500 dark:text-gray-300">
<div className="w-full px-5 pb-3 text-sm text-muted-foreground">
{data.node.description}
</div>

View file

@ -1,7 +1,7 @@
import React, { useState, ChangeEvent } from "react";
import { Textarea } from "../ui/textarea";
import { Label } from "../ui/label";
import { Input } from "../ui/input";
import { Textarea } from "../../components/ui/textarea";
import { Label } from "../../components/ui/label";
import { Input } from "../../components/ui/input";
type InputProps = {
name: string | null;
@ -62,7 +62,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
)}
</div>
<Input
className="mt-2"
className="mt-2 font-normal"
onChange={handleNameChange}
type="text"
name="name"
@ -80,7 +80,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
onChange={handleDescriptionChange}
value={description ?? ""}
placeholder="Flow description"
className="max-h-[100px] mt-2"
className="max-h-[100px] mt-2 font-normal"
rows={3}
/>
</Label>

View file

@ -40,7 +40,7 @@ export const CardComponent = ({
</div>
{onDelete && (
<button onClick={onDelete}>
<Trash2 className="w-5 text-primary opacity-0 group-hover:opacity-100 transition-all" />
<Trash2 className="w-4 h-4 text-primary opacity-0 group-hover:opacity-100 transition-all" />
</button>
)}
</CardTitle>

View file

@ -70,7 +70,7 @@ export default function Dropdown({
className={({ active }) =>
classNames(
active
? "text-white bg-slate-400 dark:bg-white dark:text-gray-500"
? " bg-accent dark:bg-white dark:text-gray-500"
: "",
editNode
? "relative cursor-default select-none py-0.5 pl-3 pr-12 dark:text-gray-300 dark:bg-gray-800"

View file

@ -45,7 +45,7 @@ export const MenuBar = ({ flows, tabId }) => {
return (
<div className="flex gap-2 items-center">
<Link to="/">
<ChevronLeft className="w-5" />
<ChevronLeft className="w-4" />
</Link>
<div className="flex items-center font-medium text-sm rounded-md py-1 px-1.5 gap-0.5">
<DropdownMenu>
@ -62,7 +62,7 @@ export const MenuBar = ({ flows, tabId }) => {
openPopUp(<FlowSettingsModal />);
}}
>
<Settings2 className="w-4 h-4 mr-2" />
<Settings2 className="w-4 h-4 mr-2 dark:text-gray-300" />
Settings
</DropdownMenuItem>
<DropdownMenuItem
@ -70,7 +70,7 @@ export const MenuBar = ({ flows, tabId }) => {
undo();
}}
>
<Undo className="w-4 h-4 mr-2" />
<Undo className="w-4 h-4 mr-2 dark:text-gray-300" />
Undo
</DropdownMenuItem>
<DropdownMenuItem
@ -78,7 +78,7 @@ export const MenuBar = ({ flows, tabId }) => {
redo();
}}
>
<Redo className="w-4 h-4 mr-2" />
<Redo className="w-4 h-4 mr-2 dark:text-gray-300" />
Redo
</DropdownMenuItem>
<DropdownMenuSeparator />

View file

@ -72,7 +72,7 @@ export default function Header() {
Join The Community
</a>
</Button>
<button
{/* <button
className="text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200"
onClick={() => {
setDark(!dark);
@ -83,7 +83,7 @@ export default function Header() {
) : (
<MoonIcon className="h-5 w-5" />
)}
</button>
</button> */}
<button
className="text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200 relative"
onClick={(event: React.MouseEvent<HTMLElement>) => {

View file

@ -41,7 +41,7 @@ export default function IntComponent({
if (disableCopyPaste) setDisableCopyPaste(false);
}}
onKeyDown={(event) => {
console.log(event);
// console.log(event);
if (
event.key !== "Backspace" &&
event.key !== "Enter" &&

View file

@ -1,4 +1,3 @@
import { classNames } from "../../utils";
import { useEffect } from "react";
import { ToggleComponentType } from "../../types/components";
import { Switch } from "../ui/switch";
@ -7,17 +6,36 @@ export default function ToggleShadComponent({
enabled,
setEnabled,
disabled,
size,
}: ToggleComponentType) {
useEffect(() => {
if (disabled) {
setEnabled(false);
}
}, [disabled, setEnabled]);
let scaleX, scaleY;
switch (size) {
case "small":
scaleX = 0.6;
scaleY = 0.6;
break;
case "medium":
scaleX = 0.8;
scaleY = 0.8;
break;
case "large":
scaleX = 1;
scaleY = 1;
break;
default:
scaleX = 1;
scaleY = 1;
}
return (
<div className={disabled ? "pointer-events-none cursor-not-allowed" : ""}>
<Switch
style={{
transform: "scaleX(0.6) scaleY(0.6)",
transform: `scaleX(${scaleX}) scaleY(${scaleY})`,
}}
className="data-[state=unchecked]:bg-slate-500"
checked={enabled}

View file

@ -1,5 +1,8 @@
// src/constants.tsx
import { FlowType } from "./types/flow";
import { buildTweaks } from "./utils";
/**
* The base text for subtitle of Export Dialog (Toolbar)
* @constant
@ -51,10 +54,21 @@ export const TEXT_DIALOG_SUBTITLE = "Edit your text.";
* @param {string} flowId - The id of the flow
* @returns {string} - The python code
*/
export const getPythonApiCode = (flowId: string): string => {
export const getPythonApiCode = (flow: FlowType): string => {
const flowId = flow.id;
// create a dictionary of node ids and the values is an empty dictionary
// flow.data.nodes.forEach((node) => {
// node.data.id
// }
const tweaks = buildTweaks(flow);
return `import requests
BASE_API_URL = "${window.location.protocol}//${window.location.host}/predict"
BASE_API_URL = "${window.location.protocol}//${
window.location.host
}/ap1/v1/predict"
FLOW_ID = "${flowId}"
TWEAKS = ${JSON.stringify(tweaks, null, 2)}
def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
"""
@ -76,32 +90,35 @@ def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
return response.json()
# Setup any tweaks you want to apply to the flow
tweaks = {} # {"nodeId": {"key": "value"}, "nodeId2": {"key": "value"}}
FLOW_ID = "${flowId}"
print(run_flow("Your message", flow_id=FLOW_ID, tweaks=tweaks))`;
print(run_flow("Your message", flow_id=FLOW_ID, tweaks=TWEAKS))`;
};
/**
* Function to get the curl code for the API
* @param {string} flowId - The id of the flow
* @returns {string} - The curl code
*/
export const getCurlCode = (flowId: string): string => {
export const getCurlCode = (flow: FlowType): string => {
const flowId = flow.id;
const tweaks = buildTweaks(flow);
return `curl -X POST \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer ${flowId}" \\
-d '{"message": "Your message"}' \\
${window.location.protocol}//${window.location.host}/predict`;
${window.location.protocol}//${
window.location.host
}/api/v1/predict/${flowId} \\
-H 'Content-Type: application/json' \\
-d '{"message": "Your message", "tweaks": ${JSON.stringify(
tweaks,
null,
2
)}}'`;
};
/**
* Function to get the python code for the API
* @param {string} flowName - The name of the flow
* @returns {string} - The python code
*/
export const getPythonCode = (flowName: string): string => {
export const getPythonCode = (flow: FlowType): string => {
const flowName = flow.name;
return `from langflow import load_flow_from_json
flow = load_flow_from_json("${flowName}.json")

View file

@ -12,7 +12,7 @@ import { updateIds, updateTemplate } from "../utils";
import { alertContext } from "./alertContext";
import { typesContext } from "./typesContext";
import { APITemplateType } from "../types/api";
import { v4 as uuidv4 } from "uuid";
import ShortUniqueId from "short-unique-id";
import { addEdge } from "reactflow";
import {
readFlowsFromDatabase,
@ -23,14 +23,17 @@ import {
} from "../controllers/API";
import _ from "lodash";
const uid = new ShortUniqueId({ length: 5 });
const TabsContextInitialValue: TabsContextType = {
save: () => {},
tabId: "",
setTabId: (index: string) => {},
flows: [],
removeFlow: (id: string) => {},
addFlow: async (flowData?: any) => "",
updateFlow: (newFlow: FlowType) => {},
incrementNodeId: () => uuidv4(),
incrementNodeId: () => uid(),
downloadFlow: (flow: FlowType) => {},
downloadFlows: () => {},
uploadFlows: () => {},
@ -41,7 +44,7 @@ const TabsContextInitialValue: TabsContextType = {
lastCopiedSelection: null,
setLastCopiedSelection: (selection: any) => {},
getNodeId: () => "",
getNodeId: (nodeType: string) => "",
paste: (
selection: { nodes: any; edges: any },
position: { x: number; y: number; paneX?: number; paneY?: number }
@ -54,18 +57,46 @@ export const TabsContext = createContext<TabsContextType>(
export function TabsProvider({ children }: { children: ReactNode }) {
const { setErrorData, setNoticeData } = useContext(alertContext);
const [tabId, setTabId] = useState("");
const [flows, setFlows] = useState([]);
const [id, setId] = useState(uuidv4());
const [flows, setFlows] = useState<Array<FlowType>>([]);
const [id, setId] = useState(uid());
const { templates, reactFlowInstance } = useContext(typesContext);
const [lastCopiedSelection, setLastCopiedSelection] = useState(null);
const newNodeId = useRef(uuidv4());
const newNodeId = useRef(uid());
function incrementNodeId() {
newNodeId.current = uuidv4();
newNodeId.current = uid();
return newNodeId.current;
}
function save() {
// added clone deep to avoid mutating the original object
let Saveflows = _.cloneDeep(flows);
if (Saveflows.length !== 0) {
Saveflows.forEach((flow) => {
if (flow.data && flow.data?.nodes)
flow.data?.nodes.forEach((node) => {
// console.log(node.data.type);
//looking for file fields to prevent saving the content and breaking the flow for exceeding the the data limite for local storage
Object.keys(node.data.node.template).forEach((key) => {
// console.log(node.data.node.template[key].type);
if (node.data.node.template[key].type === "file") {
// console.log(node.data.node.template[key]);
node.data.node.template[key].content = null;
node.data.node.template[key].value = "";
}
});
});
});
window.localStorage.setItem(
"tabsData",
JSON.stringify({ tabId, flows: Saveflows, id })
);
}
}
// function loadCookie(cookie: string) {
// if (cookie && Object.keys(templates).length > 0) {
// let cookieObject: LangFlowState = JSON.parse(cookie);
@ -206,10 +237,11 @@ export function TabsProvider({ children }: { children: ReactNode }) {
}
function hardReset() {
newNodeId.current = uuidv4();
newNodeId.current = uid();
setTabId("");
setFlows([]);
setId(uuidv4());
setId(uid());
}
/**
@ -249,8 +281,8 @@ export function TabsProvider({ children }: { children: ReactNode }) {
});
}
function getNodeId() {
return `dndnode_` + incrementNodeId();
function getNodeId(nodeType: string) {
return nodeType + "-" + incrementNodeId();
}
/**
@ -262,6 +294,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
// create a file input
const input = document.createElement("input");
input.type = "file";
input.accept = ".json";
// add a change event listener to the file input
input.onchange = (e: Event) => {
// check if the file type is application/json
@ -343,9 +376,9 @@ export function TabsProvider({ children }: { children: ReactNode }) {
? { x: position.paneX + position.x, y: position.paneY + position.y }
: reactFlowInstance.project({ x: position.x, y: position.y });
selectionInstance.nodes.forEach((n) => {
selectionInstance.nodes.forEach((n: NodeType) => {
// Generate a unique node ID
let newId = getNodeId();
let newId = getNodeId(n.data.type);
idsMap[n.id] = newId;
// Create a new node object
@ -500,7 +533,6 @@ export function TabsProvider({ children }: { children: ReactNode }) {
const createNewFlow = (flowData, flow) => ({
description: flowData.description,
name: flow?.name ?? "New Flow",
id: uuidv4(),
data: flowData.data,
});
@ -540,6 +572,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
tabId,
setTabId,
flows,
save,
incrementNodeId,
removeFlow,
addFlow,

View file

@ -2,6 +2,7 @@ import { PromptTypeAPI, errorsTypeAPI } from "./../../types/api/index";
import { APIObjectType, sendAllProps } from "../../types/api/index";
import axios, { AxiosResponse } from "axios";
import { FlowStyleType, FlowType } from "../../types/flow";
import { ReactFlowJsonObject } from "reactflow";
/**
* Fetches all objects from the API endpoint.
@ -22,18 +23,19 @@ export async function sendAll(data: sendAllProps) {
return await axios.post(`/api/v1/predict`, data);
}
/**
* Validates code by sending it to an API endpoint.
*
* @param {string} code - The code to validate.
* @returns {Promise<AxiosResponse<errorsTypeAPI>>} A promise that resolves to an AxiosResponse containing the validation results.
*/
export async function checkCode(
export async function postValidateCode(
code: string
): Promise<AxiosResponse<errorsTypeAPI>> {
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.
*
@ -75,7 +77,13 @@ export async function getExamples(): Promise<FlowType[]> {
* @returns {Promise<any>} The saved flow data.
* @throws Will throw an error if saving fails.
*/
export async function saveFlowToDatabase(newFlow: FlowType): Promise<FlowType> {
export async function saveFlowToDatabase(newFlow: {
name: string;
id: string;
data: ReactFlowJsonObject;
description: string;
style?: FlowStyleType;
}): Promise<FlowType> {
try {
const response = await axios.post("/api/v1/flows/", {
name: newFlow.name,

View file

@ -72,47 +72,85 @@
:root {
--background: 0 0% 100%;
/* hsl(0 0% 100%) */
--foreground: 222.2 47.4% 11.2%;
--muted: 210 30% 98.5%;
/* hsl(222 47% 11%) */
--muted: 210 40% 98%;
/* hsl(210 40% 98%) */
--muted-foreground: 215.4 16.3% 46.9%;
/* hsl(215 16% 46%) */
--popover: 0 0% 100%;
/* hsl(0 0% 100%) */
--popover-foreground: 222.2 47.4% 11.2%;
/* hsl(222 47% 11%) */
--card: 0 0% 100%;
/* hsl(0 0% 100%) */
--card-foreground: 222.2 47.4% 11.2%;
--border: 214.3 31.8% 93.4%;
/* hsl(222 47% 11%) */
--border: 214.3 31.8% 91.4%;
/* hsl(214 32% 91%) */
--input: 214.3 31.8% 91.4%;
--primary: 222.2 37.4% 18%;
/* hsl(214 32% 91%) */
--primary: 222.2 47.4% 18%;
/* hsl(222 47% 18%) */
--primary-foreground: 210 40% 98%;
--secondary: 210 30% 96.1%;
/* hsl(210 40% 98%) */
--secondary: 210 40% 96.1%;
/* hsl(210 40% 96%) */
--secondary-foreground: 222.2 47.4% 11.2%;
--accent: 210 30% 96.1%;
--accent-foreground: 222.2 37.4% 11.2%;
/* hsl(222 47% 11%) */
--accent: 210 40% 96.1%;
/* hsl(210 40% 96%) */
--accent-foreground: 222.2 47.4% 11.2%;
/* hsl(222 47% 11%) */
--destructive: 0 100% 50%;
/* hsl(0 100% 50%) */
--destructive-foreground: 210 40% 98%;
/* hsl(210 40% 98%) */
--ring: 215 20.2% 65.1%;
/* hsl(215 20% 65%) */
--radius: 0.5rem;
}
.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%) */
-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%) */
-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%) */
-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%) */
-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%) */
-radius: 0.5rem;
}

View file

@ -1,10 +1,6 @@
import { IconCheck, IconClipboard, IconDownload } from "@tabler/icons-react";
import {
XMarkIcon,
CommandLineIcon,
CodeBracketSquareIcon,
} from "@heroicons/react/24/outline";
import { Fragment, useContext, useRef, useState } from "react";
import { IconCheck, IconClipboard } from "@tabler/icons-react";
import { CodeBracketSquareIcon } from "@heroicons/react/24/outline";
import { useContext, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import "ace-builds/src-noconflict/mode-python";
import "ace-builds/src-noconflict/theme-github";
@ -18,13 +14,11 @@ import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Button } from "../../components/ui/button";
import { FlowType } from "../../types/flow";
import { FlowType } from "../../types/flow/index";
import { getCurlCode, getPythonApiCode, getPythonCode } from "../../constants";
import { EXPORT_CODE_DIALOG } from "../../constants";
@ -55,10 +49,10 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
}
}
const pythonApiCode = getPythonApiCode(flow.id);
const pythonApiCode = getPythonApiCode(flow);
const curl_code = getCurlCode(flow.id);
const pythonCode = getPythonCode(flow.name);
const curl_code = getCurlCode(flow);
const pythonCode = getPythonCode(flow);
const tabs = [
{
@ -96,8 +90,8 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
<DialogDescription>{EXPORT_CODE_DIALOG}</DialogDescription>
</DialogHeader>
<div className="flex flex-col h-full w-full ">
<div className="flex px-5 z-10">
<div className="flex flex-col h-full w-full overflow-hidden">
<div className="flex px-5 z-10 w-full">
{tabs.map((tab, index) => (
<button
key={index}
@ -117,7 +111,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
))}
</div>
<div className=" overflow-hidden px-4 sm:p-4 sm:pb-0 sm:pt-0 w-full h-full rounded-lg border-gray-200 border-[1px] bg-muted dark:bg-gray-800">
<div className="items-center mb-2">
<div className="items-center mb-2 w-full">
<div className="float-right">
<button
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-500 dark:text-gray-300"
@ -133,7 +127,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
</div>
</div>
<SyntaxHighlighter
className="h-[350px] w-full"
className="h-[350px] w-full overflow-auto"
language={tabs[activeTab].mode}
style={oneDark}
customStyle={{ margin: 0 }}

View file

@ -1,30 +1,21 @@
import {
ChevronDoubleLeftIcon,
ChevronDoubleRightIcon,
PencilSquareIcon,
XMarkIcon,
} from "@heroicons/react/24/outline";
import { Fragment, useContext, useEffect, useRef, useState } from "react";
import { useContext, useEffect, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { NodeDataType } from "../../types/flow";
import { classNames, limitScrollFieldsModal, nodeIcons } from "../../utils";
import { classNames, limitScrollFieldsModal } from "../../utils";
import { typesContext } from "../../contexts/typesContext";
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "../../components/ui/table";
import { Switch } from "../../components/ui/switch";
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";
import ToggleComponent from "../../components/toggleComponent";
import FloatComponent from "../../components/floatComponent";
import Dropdown from "../../components/dropdownComponent";
import IntComponent from "../../components/intComponent";
@ -42,8 +33,8 @@ import {
DialogTrigger,
} from "../../components/ui/dialog";
import { Button } from "../../components/ui/button";
import { EDIT_DIALOG_SUBTITLE } from "../../constants";
import { Edit } from "lucide-react";
import { Badge } from "../../components/ui/badge";
export default function EditNodeModal({ data }: { data: NodeDataType }) {
const [open, setOpen] = useState(true);
@ -95,14 +86,11 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
<DialogContent className="lg:max-w-[700px] ">
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">Edit Node</span>
<Edit
className="h-5 w-5 text-gray-800 pl-1 dark:text-white"
aria-hidden="true"
/>
<span className="pr-2">{data.type}</span>
<Badge variant="secondary">ID: {data.id}</Badge>
</DialogTitle>
<DialogDescription>
{EDIT_DIALOG_SUBTITLE}
{data.node?.description}
<div className="flex pt-4">
<VariableIcon className="w-5 h-5 pe-1 text-gray-700 stroke-2 dark:text-slate-200">
&nbsp;
@ -151,7 +139,7 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
)
.map((n, i) => (
<TableRow key={i} className="h-10 dark:border-b-muted">
<TableCell className="p-0 text-center text-gray-900 text-xs dark:text-gray-300 text-sm">
<TableCell className="p-0 text-center text-gray-900 dark:text-gray-300 text-sm">
{data.node.template[n].name
? data.node.template[n].name
: data.node.template[n].display_name}
@ -206,6 +194,7 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
data.node.template[n].value = e;
setEnabled(e);
}}
size="small"
disabled={false}
/>
</div>
@ -299,6 +288,7 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
changeAdvanced(data.node.template[n])
}
disabled={false}
size="small"
/>
</div>
</TableCell>
@ -319,7 +309,7 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
}}
type="submit"
>
Save changes
Save Changes
</Button>
</DialogFooter>
</DialogContent>

View file

@ -44,7 +44,7 @@ export default function ChatInput({
}}
className={classNames(
lockChat
? " bg-gray-300 text-black dark:bg-gray-700 dark:text-gray-300"
? " bg-input text-black dark:bg-gray-700 dark:text-gray-300"
: " bg-white-200 text-black dark:bg-gray-900 dark:text-gray-300",
"form-input block w-full custom-scroll rounded-md border-gray-300 dark:border-gray-600 pr-10 sm:text-sm" +
INPUT_STYLE

View file

@ -34,8 +34,8 @@ export default function ChatMessage({
className={classNames(
"w-full py-2 pl-2 flex",
chat.isSend
? "bg-white dark:bg-gray-900 "
: "bg-gray-200 dark:bg-gray-800"
? "bg-background dark:bg-gray-900 "
: "bg-input dark:bg-gray-800"
)}
>
<div

View file

@ -8,7 +8,7 @@ import "ace-builds/src-noconflict/theme-twilight";
import "ace-builds/src-noconflict/ext-language_tools";
// import "ace-builds/webpack-resolver";
import { darkContext } from "../../contexts/darkContext";
import { checkCode } from "../../controllers/API";
import { postValidateCode } from "../../controllers/API";
import { alertContext } from "../../contexts/alertContext";
import { TabsContext } from "../../contexts/tabsContext";
import {
@ -81,7 +81,7 @@ export default function CodeAreaModal({
<Button
className="mt-3"
onClick={() => {
checkCode(code)
postValidateCode(code)
.then((apiReturn) => {
if (apiReturn.data) {
let importsErrors = apiReturn.data.imports.errors;

View file

@ -16,11 +16,8 @@ import {
import { Button } from "../../components/ui/button";
import { Checkbox } from "../../components/ui/checkbox";
import { EXPORT_DIALOG_SUBTITLE } from "../../constants";
import EditFlowSettings from "../../components/nameInputComponent";
import { Label } from "../../components/ui/label";
import { Input } from "../../components/ui/input";
import { Textarea } from "../../components/ui/textarea";
import { Download } from "lucide-react";
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
export default function ExportModal() {
const [open, setOpen] = useState(true);
@ -57,44 +54,15 @@ export default function ExportModal() {
<DialogDescription>{EXPORT_DIALOG_SUBTITLE}</DialogDescription>
</DialogHeader>
<Label>
<span className="font-medium">Name</span>
<Input
className="mt-2 focus-visible:ring-1"
onChange={(event) => {
if (event.target.value != "") {
let newFlow = flows.find((f) => f.id === tabId);
newFlow.name = event.target.value;
setName(event.target.value);
updateFlow(newFlow);
} else {
setName(event.target.value);
}
}}
type="text"
name="name"
value={name ?? null}
placeholder="File name"
id="name"
/>
</Label>
<Label>
<span className="font-medium">Description (optional)</span>
<Textarea
name="description"
id="description"
onChange={(event) => {
let newFlow = flows.find((f) => f.id === tabId);
newFlow.description = event.target.value;
updateFlow(newFlow);
}}
value={flows.find((f) => f.id === tabId).description ?? null}
placeholder="Flow description"
className="max-h-[100px] mt-2 focus-visible:ring-1"
rows={3}
/>
</Label>
<EditFlowSettings
name={name}
description={description}
flows={flows}
tabId={tabId}
setName={setName}
setDescription={setDescription}
updateFlow={updateFlow}
/>
<div className="flex items-center space-x-2">
<Checkbox
id="terms"

View file

@ -15,7 +15,7 @@ import {
import { Button } from "../../components/ui/button";
import { SETTINGS_DIALOG_SUBTITLE } from "../../constants";
import { updateFlowInDatabase } from "../../controllers/API";
import EditFlowSettings from "../../components/nameInputComponent";
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
export default function FlowSettingsModal() {
const [open, setOpen] = useState(true);
@ -52,10 +52,6 @@ export default function FlowSettingsModal() {
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">Settings</span>
<ArrowDownTrayIcon
className="h-6 w-6 text-gray-800 pl-1 dark:text-white"
aria-hidden="true"
/>
</DialogTitle>
<DialogDescription>{SETTINGS_DIALOG_SUBTITLE}</DialogDescription>
</DialogHeader>

View file

@ -43,7 +43,7 @@ export default function PromptAreaModal({
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-500 dark:bg-gray-600 dark:bg-opacity-75 bg-opacity-75 transition-opacity" />
<div className="fixed inset-0 bg-ring dark:bg-gray-600 dark:bg-opacity-75 bg-opacity-75 transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
@ -87,7 +87,7 @@ export default function PromptAreaModal({
</Dialog.Title>
</div>
</div>
<div className="h-full w-full bg-gray-200 overflow-auto dark:bg-gray-900 p-4 gap-4 flex flex-row justify-center items-center">
<div className="h-full w-full bg-accent overflow-auto dark:bg-gray-900 p-4 gap-4 flex flex-row justify-center items-center">
<div className="flex h-full w-full">
<div className="overflow-hidden px-4 py-5 sm:p-6 w-full h-full rounded-lg bg-white dark:bg-gray-800 shadow">
<textarea

View file

@ -1,42 +1,10 @@
import {
Tabs,
TabsList,
TabsTrigger,
TabsContent,
} from "../../components/ui/tabs";
import ExtraSidebar from "../../components/ExtraSidebarComponent";
import { ReactFlowProvider } from "reactflow";
import FlowPage from "../FlowPage";
import { useContext, useEffect, useState } from "react";
import {
SunIcon,
MoonIcon,
BellIcon,
GithubIcon,
Download,
Upload,
Plus,
Home,
Users2,
GitFork,
} from "lucide-react";
import { GithubIcon, Users2, GitFork } from "lucide-react";
import { TabsContext } from "../../contexts/tabsContext";
import AlertDropdown from "../../alerts/alertDropDown";
import { alertContext } from "../../contexts/alertContext";
import { darkContext } from "../../contexts/darkContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { typesContext } from "../../contexts/typesContext";
import { Button } from "../../components/ui/button";
import { FaGithub } from "react-icons/fa";
import _ from "lodash";
import {
getExamples,
updateFlowInDatabase,
uploadFlowsToDatabase,
} from "../../controllers/API";
import { MenuBar } from "../../components/headerComponent/components/menuBar";
import { getExamples } from "../../controllers/API";
import { FlowType } from "../../types/flow";
import { CardComponent } from "../../components/cardComponent";
import { useNavigate } from "react-router-dom";

View file

@ -127,6 +127,7 @@ export default function Page({ flow }: { flow: FlowType }) {
setEdges(flow?.data?.edges ?? []);
if (reactFlowInstance) {
setViewport(flow?.data?.viewport ?? { x: 1, y: 0, zoom: 0.5 });
reactFlowInstance.fitView();
}
}, [flow, reactFlowInstance, setEdges, setNodes, setViewport]);
//set extra sidebar
@ -213,7 +214,8 @@ export default function Page({ flow }: { flow: FlowType }) {
});
// Generate a unique node ID
let newId = getNodeId();
let { type } = data;
let newId = getNodeId(type);
let newNode: NodeType;
if (data.type !== "groupNode") {

View file

@ -1,9 +1,4 @@
import {
Bars2Icon,
PencilSquareIcon,
Square2StackIcon,
TrashIcon,
} from "@heroicons/react/24/outline";
import { Bars2Icon } from "@heroicons/react/24/outline";
import DisclosureComponent from "../DisclosureComponent";
import {
classNames,
@ -11,26 +6,27 @@ import {
nodeIcons,
nodeNames,
} from "../../../../utils";
import { useContext, useEffect, useState, useRef } from "react";
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 { Code, Code2, FileDown, FileUp, Import, Save } from "lucide-react";
import { Code2, FileDown, FileUp, Save } from "lucide-react";
import { PopUpContext } from "../../../../contexts/popUpContext";
import ImportModal from "../../../../modals/importModal";
import ExportModal from "../../../../modals/exportModal";
import ApiModal from "../../../../modals/ApiModal";
import { TabsContext } from "../../../../contexts/tabsContext";
import { Separator } from "../../../../components/ui/separator";
import { alertContext } from "../../../../contexts/alertContext";
import { updateFlowInDatabase } from "../../../../controllers/API";
import { INPUT_STYLE } from "../../../../constants";
import { Input } from "../../../../components/ui/input";
import { Separator } from "../../../../components/ui/separator";
export default function ExtraSidebar() {
const { data } = useContext(typesContext);
const { openPopUp } = useContext(PopUpContext);
const { flows, tabId } = useContext(TabsContext);
const { flows, tabId, uploadFlow } = useContext(TabsContext);
const { setSuccessData, setErrorData } = useContext(alertContext);
const [dataFilter, setFilterData] = useState(data);
const [search, setSearch] = useState("");
@ -82,7 +78,8 @@ export default function ExtraSidebar() {
<button
className="hover:dark:hover:bg-[#242f47] text-gray-700 w-full justify-center shadow-sm transition-all duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 relative inline-flex items-center rounded-md bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
onClick={() => {
openPopUp(<ImportModal />);
// openPopUp(<ImportModal />);
uploadFlow();
}}
>
<FileUp className="w-5 h-5 dark:text-gray-300"></FileUp>
@ -132,7 +129,7 @@ export default function ExtraSidebar() {
type="text"
name="search"
id="search"
placeholder="Search nodes"
placeholder="Search Nodes"
className={
INPUT_STYLE +
"border-1 dark:border-slate-600 dark:border-0.5 dark:ring-0 focus-visible:dark:ring-0 focus-visible:dark:ring-offset-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"

View file

@ -1,21 +1,9 @@
import React, { useContext, useState } from "react";
import { Menu, Transition } from "@headlessui/react";
import { EllipsisVerticalIcon } from "@heroicons/react/20/solid";
import {
Cog6ToothIcon,
TrashIcon,
PencilSquareIcon,
DocumentDuplicateIcon,
DocumentPlusIcon,
Square2StackIcon,
} from "@heroicons/react/24/outline";
import { useContext, useState } from "react";
import { Settings2, Copy, Trash2 } from "lucide-react";
import { classNames } from "../../../../utils";
import { Fragment } from "react";
import NodeModal from "../../../../modals/NodeModal";
import { TabsContext } from "../../../../contexts/tabsContext";
import { useReactFlow } from "reactflow";
import EditNodeModal from "../../../../modals/EditNodeModal";
import TooltipReact from "../../../../components/ReactTooltipComponent";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
const NodeToolbarComponent = (props) => {
@ -48,7 +36,7 @@ const NodeToolbarComponent = (props) => {
props.deleteNode(props.data.id);
}}
>
<TrashIcon className="w-5 h-5 dark:text-gray-300"></TrashIcon>
<Trash2 className="w-4 h-4 dark:text-gray-300"></Trash2>
</button>
</ShadTooltip>
@ -61,7 +49,7 @@ const NodeToolbarComponent = (props) => {
)}
onClick={(event) => {
event.preventDefault();
console.log(reactFlowInstance.getNode(props.data.id));
// console.log(reactFlowInstance.getNode(props.data.id));
paste(
{
nodes: [reactFlowInstance.getNode(props.data.id)],
@ -76,7 +64,7 @@ const NodeToolbarComponent = (props) => {
);
}}
>
<Square2StackIcon className="w-5 h-5 dark:text-gray-300"></Square2StackIcon>
<Copy className="w-4 h-4 dark:text-gray-300"></Copy>
</button>
</ShadTooltip>
@ -89,12 +77,12 @@ const NodeToolbarComponent = (props) => {
props.openPopUp(<EditNodeModal data={props.data} />);
}}
>
<PencilSquareIcon className="w-5 h-5 dark:text-gray-300"></PencilSquareIcon>
<Settings2 className="w-4 h-4 dark:text-gray-300"></Settings2>
</button>
</ShadTooltip>
)}
{/*
{/*
<Menu as="div" className="relative inline-block text-left z-100">
<button className="hover:dark:hover:bg-[#242f47] text-gray-700 transition-all duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 shadow-md relative -ml-px inline-flex items-center bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-muted focus:z-10 rounded-r-md">
<div>
@ -133,7 +121,7 @@ const NodeToolbarComponent = (props) => {
"w-full group flex items-center px-4 py-2 text-sm"
)}
>
<PencilSquareIcon
<Settings
className="mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-500"
aria-hidden="true"
/>

View file

@ -26,7 +26,7 @@ export default function HomePage() {
}}
>
<Download className="w-4 mr-2" />
Download Database
Download Collection
</Button>
<Button
variant="primary"
@ -35,7 +35,7 @@ export default function HomePage() {
}}
>
<Upload className="w-4 mr-2" />
Upload Database
Upload Collection
</Button>
<Button
variant="primary"

View file

@ -21,6 +21,7 @@ export type ToggleComponentType = {
enabled: boolean;
setEnabled: (state: boolean) => void;
disabled: boolean;
size: "small" | "medium" | "large";
};
export type DropDownComponentType = {
value: string;

View file

@ -1,6 +1,7 @@
import { FlowType } from "../flow";
export type TabsContextType = {
save: () => void;
tabId: string;
setTabId: (index: string) => void;
flows: Array<FlowType>;
@ -16,7 +17,7 @@ export type TabsContextType = {
//disable CopyPaste
disableCopyPaste: boolean;
setDisableCopyPaste: (value: boolean) => void;
getNodeId: () => string;
getNodeId: (nodeType: string) => string;
paste: (
selection: { nodes: any; edges: any },
position: { x: number; y: number; paneX?: number; paneY?: number }

View file

@ -16,14 +16,13 @@ import {
Squares2X2Icon,
Bars3CenterLeftIcon,
} from "@heroicons/react/24/outline";
import { Connection, Edge, Node, ReactFlowInstance, addEdge } from "reactflow";
import { FlowType, NodeType } from "./types/flow";
import { APITemplateType, TemplateVariableType } from "./types/api";
import { Connection, Edge, Node, ReactFlowInstance } from "reactflow";
import { FlowType, NodeDataType, NodeType } from "./types/flow";
import { APITemplateType } from "./types/api";
import _ from "lodash";
import { ChromaIcon } from "./icons/ChromaIcon";
import { AnthropicIcon } from "./icons/Anthropic";
import { AirbyteIcon } from "./icons/Airbyte";
import { AzIcon } from "./icons/AzLogo";
import { BingIcon } from "./icons/Bing";
import { CohereIcon } from "./icons/Cohere";
import { EvernoteIcon } from "./icons/Evernote";
@ -37,17 +36,9 @@ import { MetaIcon } from "./icons/Meta";
import { MidjorneyIcon } from "./icons/Midjorney";
import { NotionIcon } from "./icons/Notion";
import { OpenAiIcon } from "./icons/OpenAi";
import { PowerPointIcon } from "./icons/PowerPoint";
import { QDrantIcon } from "./icons/QDrant";
import { ReadTheDocsIcon } from "./icons/ReadTheDocs";
import { SearxIcon } from "./icons/Searx";
import { SlackIcon } from "./icons/Slack";
import { WeaviateIcon } from "./icons/Weaviate";
import { WikipediaIcon } from "./icons/Wikipedia";
import { WolframIcon } from "./icons/Wolfram";
import { WordIcon } from "./icons/Word";
import { SerperIcon } from "./icons/Serper";
import { v4 as uuidv4 } from "uuid";
import clsx, { ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
@ -634,9 +625,9 @@ export function checkUpperWords(str: string) {
export function updateIds(newFlow, getNodeId) {
let idsMap = {};
newFlow.nodes.forEach((n) => {
newFlow.nodes.forEach((n: NodeType) => {
// Generate a unique node ID
let newId = getNodeId();
let newId = getNodeId(n.data.type);
idsMap[n.id] = newId;
n.id = newId;
n.data.id = newId;
@ -720,3 +711,10 @@ export function groupByFamily(data, baseClasses) {
return groupedObj;
}
export function buildTweaks(flow) {
return flow.data.nodes.reduce((acc, node) => {
acc[node.data.id] = {};
return acc;
}, {});
}

View file

@ -1,7 +1,7 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import svgr from "vite-plugin-svgr";
const apiRoutes = ["^/api/v1/"];
const apiRoutes = ["^/api/v1/", "/health"];
// Use environment variable to determine the target.
const target = process.env.VITE_PROXY_TARGET || "http://127.0.0.1:7860";