Merge branch 'dev' into uiImprovements

This commit is contained in:
anovazzi1 2023-05-02 22:52:57 -03:00
commit e2c8dfab2f
21 changed files with 598 additions and 564 deletions

View file

@ -1,235 +1,235 @@
import {
createContext,
useEffect,
useState,
useRef,
ReactNode,
useContext,
createContext,
useEffect,
useState,
useRef,
ReactNode,
useContext,
} from "react";
import { FlowType } from "../types/flow";
import { LangFlowState, TabsContextType } from "../types/tabs";
import { normalCaseToSnakeCase, updateObject } from "../utils";
import { normalCaseToSnakeCase, updateObject, updateTemplate } from "../utils";
import { alertContext } from "./alertContext";
import { typesContext } from "./typesContext";
import { TemplateVariableType } from "../types/api";
import { APITemplateType, TemplateVariableType } from "../types/api";
const { v4: uuidv4 } = require("uuid");
const TabsContextInitialValue: TabsContextType = {
save: () => {},
tabIndex: 0,
setTabIndex: (index: number) => {},
flows: [],
removeFlow: (id: string) => {},
addFlow: (flowData?: any) => {},
updateFlow: (newFlow: FlowType) => {},
incrementNodeId: () => 0,
downloadFlow: (flow: FlowType) => {},
uploadFlow: () => {},
hardReset: () => {},
save: () => {},
tabIndex: 0,
setTabIndex: (index: number) => {},
flows: [],
removeFlow: (id: string) => {},
addFlow: (flowData?: any) => {},
updateFlow: (newFlow: FlowType) => {},
incrementNodeId: () => 0,
downloadFlow: (flow: FlowType) => {},
uploadFlow: () => {},
hardReset: () => {},
};
export const TabsContext = createContext<TabsContextType>(
TabsContextInitialValue
TabsContextInitialValue
);
export function TabsProvider({ children }: { children: ReactNode }) {
const { setNoticeData } = useContext(alertContext);
const [tabIndex, setTabIndex] = useState(0);
const [flows, setFlows] = useState<Array<FlowType>>([]);
const [id, setId] = useState("");
const { templates } = useContext(typesContext);
const { setNoticeData } = useContext(alertContext);
const [tabIndex, setTabIndex] = useState(0);
const [flows, setFlows] = useState<Array<FlowType>>([]);
const [id, setId] = useState("");
const { templates } = useContext(typesContext);
const newNodeId = useRef(0);
function incrementNodeId() {
newNodeId.current = newNodeId.current + 1;
return newNodeId.current;
}
function save() {
if (flows.length !== 0)
window.localStorage.setItem(
"tabsData",
JSON.stringify({ tabIndex, flows, id, nodeId: newNodeId.current })
);
}
useEffect(() => {
//save tabs locally
save();
}, [flows, id, tabIndex, newNodeId]);
const newNodeId = useRef(0);
function incrementNodeId() {
newNodeId.current = newNodeId.current + 1;
return newNodeId.current;
}
function save() {
if (flows.length !== 0)
window.localStorage.setItem(
"tabsData",
JSON.stringify({ tabIndex, flows, id, nodeId: newNodeId.current })
);
}
useEffect(() => {
//save tabs locally
save();
}, [flows, id, tabIndex, newNodeId]);
useEffect(() => {
//get tabs locally saved
let cookie = window.localStorage.getItem("tabsData");
if (cookie && Object.keys(templates).length > 0) {
let cookieObject: LangFlowState = JSON.parse(cookie);
cookieObject.flows.forEach((flow) => {
flow.data.nodes.forEach((node) => {
if (Object.keys(templates[node.data.type]["template"]).length > 0) {
node.data.node.template = updateObject(
templates[node.data.type][
"template"
] as unknown as TemplateVariableType,
useEffect(() => {
//get tabs locally saved
let cookie = window.localStorage.getItem("tabsData");
if (cookie && Object.keys(templates).length > 0) {
let cookieObject: LangFlowState = JSON.parse(cookie);
cookieObject.flows.forEach((flow) => {
flow.data.nodes.forEach((node) => {
if (Object.keys(templates[node.data.type]["template"]).length > 0) {
node.data.node.template = updateTemplate(
templates[node.data.type][
"template"
] as unknown as APITemplateType,
node.data.node.template as TemplateVariableType
);
}
});
});
setTabIndex(cookieObject.tabIndex);
setFlows(cookieObject.flows);
setId(cookieObject.id);
newNodeId.current = cookieObject.nodeId;
}
}, [templates]);
function hardReset() {
newNodeId.current = 0;
setTabIndex(0);
setFlows([]);
setId("");
}
node.data.node.template as APITemplateType
);
}
});
});
setTabIndex(cookieObject.tabIndex);
setFlows(cookieObject.flows);
setId(cookieObject.id);
newNodeId.current = cookieObject.nodeId;
}
}, [templates]);
function hardReset() {
newNodeId.current = 0;
setTabIndex(0);
setFlows([]);
setId("");
}
/**
* Downloads the current flow as a JSON file
*/
function downloadFlow(flow: FlowType) {
// create a data URI with the current flow data
const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent(
JSON.stringify(flow)
)}`;
/**
* Downloads the current flow as a JSON file
*/
function downloadFlow(flow: FlowType) {
// create a data URI with the current flow data
const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent(
JSON.stringify(flow)
)}`;
// create a link element and set its properties
const link = document.createElement("a");
link.href = jsonString;
link.download = `${normalCaseToSnakeCase(flows[tabIndex].name)}.json`;
// create a link element and set its properties
const link = document.createElement("a");
link.href = jsonString;
link.download = `${normalCaseToSnakeCase(flows[tabIndex].name)}.json`;
// simulate a click on the link element to trigger the download
link.click();
setNoticeData({
title: "Warning: Critical data,JSON file may including API keys.",
});
}
// simulate a click on the link element to trigger the download
link.click();
setNoticeData({
title: "Warning: Critical data,JSON file may including API keys.",
});
}
/**
* Creates a file input and listens to a change event to upload a JSON flow file.
* If the file type is application/json, the file is read and parsed into a JSON object.
* The resulting JSON object is passed to the addFlow function.
*/
function uploadFlow() {
// create a file input
const input = document.createElement("input");
input.type = "file";
// add a change event listener to the file input
input.onchange = (e: Event) => {
// check if the file type is application/json
if ((e.target as HTMLInputElement).files[0].type === "application/json") {
// get the file from the file input
const file = (e.target as HTMLInputElement).files[0];
// read the file as text
file.text().then((text) => {
// parse the text into a JSON object
let flow: FlowType = JSON.parse(text);
flow.data.nodes.forEach((node) => {
if (Object.keys(templates[node.data.type]["template"]).length > 0) {
node.data.node.template = updateObject(
templates[node.data.type][
"template"
] as unknown as TemplateVariableType,
node.data.node.template as TemplateVariableType
);
}
});
/**
* Creates a file input and listens to a change event to upload a JSON flow file.
* If the file type is application/json, the file is read and parsed into a JSON object.
* The resulting JSON object is passed to the addFlow function.
*/
function uploadFlow() {
// create a file input
const input = document.createElement("input");
input.type = "file";
// add a change event listener to the file input
input.onchange = (e: Event) => {
// check if the file type is application/json
if ((e.target as HTMLInputElement).files[0].type === "application/json") {
// get the file from the file input
const file = (e.target as HTMLInputElement).files[0];
// read the file as text
file.text().then((text) => {
// parse the text into a JSON object
let flow: FlowType = JSON.parse(text);
addFlow(flow);
});
}
};
// trigger the file input click event to open the file dialog
input.click();
}
/**
* Removes a flow from an array of flows based on its id.
* Updates the state of flows and tabIndex using setFlows and setTabIndex hooks.
* @param {string} id - The id of the flow to remove.
*/
function removeFlow(id: string) {
setFlows((prevState) => {
const newFlows = [...prevState];
const index = newFlows.findIndex((flow) => flow.id === id);
if (index >= 0) {
if (index === tabIndex) {
setTabIndex(flows.length - 2);
newFlows.splice(index, 1);
} else {
let flowId = flows[tabIndex].id;
newFlows.splice(index, 1);
setTabIndex(newFlows.findIndex((flow) => flow.id === flowId));
}
}
return newFlows;
});
}
/**
* Add a new flow to the list of flows.
* @param flow Optional flow to add.
*/
function addFlow(flow?: FlowType) {
// Get data from the flow or set it to null if there's no flow provided.
const data = flow?.data ? flow.data : null;
const description = flow?.description ? flow.description : "";
addFlow(flow);
});
}
};
// trigger the file input click event to open the file dialog
input.click();
}
/**
* Removes a flow from an array of flows based on its id.
* Updates the state of flows and tabIndex using setFlows and setTabIndex hooks.
* @param {string} id - The id of the flow to remove.
*/
function removeFlow(id: string) {
setFlows((prevState) => {
const newFlows = [...prevState];
const index = newFlows.findIndex((flow) => flow.id === id);
if (index >= 0) {
if (index === tabIndex) {
setTabIndex(flows.length - 2);
newFlows.splice(index, 1);
} else {
let flowId = flows[tabIndex].id;
newFlows.splice(index, 1);
setTabIndex(newFlows.findIndex((flow) => flow.id === flowId));
}
}
return newFlows;
});
}
/**
* Add a new flow to the list of flows.
* @param flow Optional flow to add.
*/
function addFlow(flow?: FlowType) {
// Get data from the flow or set it to null if there's no flow provided.
const data = flow?.data ? flow.data : null;
const description = flow?.description ? flow.description : "";
// Create a new flow with a default name if no flow is provided.
let newFlow: FlowType = {
description,
name: flow?.name ?? "New Flow",
id: id.toString(),
data,
};
if (data) {
data.nodes.forEach((node) => {
if (Object.keys(templates[node.data.type]["template"]).length > 0) {
node.data.node.template = updateTemplate(
templates[node.data.type]["template"] as unknown as APITemplateType,
node.data.node.template as APITemplateType
);
}
});
}
// Create a new flow with a default name if no flow is provided.
let newFlow: FlowType = {
description,
name: flow?.name ?? "New Flow",
id: id.toString(),
data,
};
// Increment the ID counter.
setId(uuidv4());
// Increment the ID counter.
setId(uuidv4());
// Add the new flow to the list of flows.
setFlows((prevState) => {
const newFlows = [...prevState, newFlow];
return newFlows;
});
// Add the new flow to the list of flows.
setFlows((prevState) => {
const newFlows = [...prevState, newFlow];
return newFlows;
});
// Set the tab index to the new flow.
setTabIndex(flows.length);
}
/**
* Updates an existing flow with new data
* @param newFlow - The new flow object containing the updated data
*/
function updateFlow(newFlow: FlowType) {
setFlows((prevState) => {
const newFlows = [...prevState];
const index = newFlows.findIndex((flow) => flow.id === newFlow.id);
if (index !== -1) {
newFlows[index].description = newFlow.description ?? "";
newFlows[index].data = newFlow.data;
newFlows[index].name = newFlow.name;
}
return newFlows;
});
}
// Set the tab index to the new flow.
setTabIndex(flows.length);
}
/**
* Updates an existing flow with new data
* @param newFlow - The new flow object containing the updated data
*/
function updateFlow(newFlow: FlowType) {
setFlows((prevState) => {
const newFlows = [...prevState];
const index = newFlows.findIndex((flow) => flow.id === newFlow.id);
if (index !== -1) {
newFlows[index].description = newFlow.description ?? "";
newFlows[index].data = newFlow.data;
newFlows[index].name = newFlow.name;
}
return newFlows;
});
}
return (
<TabsContext.Provider
value={{
save,
hardReset,
tabIndex,
setTabIndex,
flows,
incrementNodeId,
removeFlow,
addFlow,
updateFlow,
downloadFlow,
uploadFlow,
}}
>
{children}
</TabsContext.Provider>
);
return (
<TabsContext.Provider
value={{
save,
hardReset,
tabIndex,
setTabIndex,
flows,
incrementNodeId,
removeFlow,
addFlow,
updateFlow,
downloadFlow,
uploadFlow,
}}
>
{children}
</TabsContext.Provider>
);
}

View file

@ -1,318 +1,319 @@
import {
RocketLaunchIcon,
LinkIcon,
CpuChipIcon,
LightBulbIcon,
CommandLineIcon,
WrenchScrewdriverIcon,
WrenchIcon,
ComputerDesktopIcon,
Bars3CenterLeftIcon,
GiftIcon,
PaperClipIcon,
QuestionMarkCircleIcon,
FingerPrintIcon,
ScissorsIcon,
CircleStackIcon,
Squares2X2Icon,
RocketLaunchIcon,
LinkIcon,
CpuChipIcon,
LightBulbIcon,
CommandLineIcon,
WrenchScrewdriverIcon,
WrenchIcon,
ComputerDesktopIcon,
Bars3CenterLeftIcon,
GiftIcon,
PaperClipIcon,
QuestionMarkCircleIcon,
FingerPrintIcon,
ScissorsIcon,
CircleStackIcon,
Squares2X2Icon,
} from "@heroicons/react/24/outline";
import { Connection, Edge, Node, ReactFlowInstance } from "reactflow";
import { FlowType } from "./types/flow";
import { APITemplateType, TemplateVariableType } from "./types/api";
var _ = require("lodash");
export function classNames(...classes: Array<string>) {
return classes.filter(Boolean).join(" ");
return classes.filter(Boolean).join(" ");
}
export const textColors = {
white: "text-white",
red: "text-red-700",
orange: "text-orange-700",
amber: "text-amber-700",
yellow: "text-yellow-700",
lime: "text-lime-700",
green: "text-green-700",
emerald: "text-emerald-700",
teal: "text-teal-700",
cyan: "text-cyan-700",
sky: "text-sky-700",
blue: "text-blue-700",
indigo: "text-indigo-700",
violet: "text-violet-700",
purple: "text-purple-700",
fuchsia: "text-fuchsia-700",
pink: "text-pink-700",
rose: "text-rose-700",
black: "text-black-700",
gray: "text-gray-700",
white: "text-white",
red: "text-red-700",
orange: "text-orange-700",
amber: "text-amber-700",
yellow: "text-yellow-700",
lime: "text-lime-700",
green: "text-green-700",
emerald: "text-emerald-700",
teal: "text-teal-700",
cyan: "text-cyan-700",
sky: "text-sky-700",
blue: "text-blue-700",
indigo: "text-indigo-700",
violet: "text-violet-700",
purple: "text-purple-700",
fuchsia: "text-fuchsia-700",
pink: "text-pink-700",
rose: "text-rose-700",
black: "text-black-700",
gray: "text-gray-700",
};
export const borderLColors = {
white: "border-l-white",
red: "border-l-red-500",
orange: "border-l-orange-500",
amber: "border-l-amber-500",
yellow: "border-l-yellow-500",
lime: "border-l-lime-500",
green: "border-l-green-500",
emerald: "border-l-emerald-500",
teal: "border-l-teal-500",
cyan: "border-l-cyan-500",
sky: "border-l-sky-500",
blue: "border-l-blue-500",
indigo: "border-l-indigo-500",
violet: "border-l-violet-500",
purple: "border-l-purple-500",
fuchsia: "border-l-fuchsia-500",
pink: "border-l-pink-500",
rose: "border-l-rose-500",
black: "border-l-black-500",
gray: "border-l-gray-500",
white: "border-l-white",
red: "border-l-red-500",
orange: "border-l-orange-500",
amber: "border-l-amber-500",
yellow: "border-l-yellow-500",
lime: "border-l-lime-500",
green: "border-l-green-500",
emerald: "border-l-emerald-500",
teal: "border-l-teal-500",
cyan: "border-l-cyan-500",
sky: "border-l-sky-500",
blue: "border-l-blue-500",
indigo: "border-l-indigo-500",
violet: "border-l-violet-500",
purple: "border-l-purple-500",
fuchsia: "border-l-fuchsia-500",
pink: "border-l-pink-500",
rose: "border-l-rose-500",
black: "border-l-black-500",
gray: "border-l-gray-500",
};
export const nodeColors: { [char: string]: string } = {
prompts: "#4367BF",
llms: "#6344BE",
chains: "#FE7500",
agents: "#903BBE",
tools: "#FF3434",
memories: "#F5B85A",
advanced: "#000000",
chat: "#198BF6",
thought: "#272541",
embeddings: "#42BAA7",
documentloaders: "#7AAE42",
vectorstores: "#AA8742",
textsplitters: "#B47CB5",
toolkits: "#DB2C2C",
wrappers: "#E6277A",
utilities: "#31A3CC",
unknown: "#9CA3AF",
prompts: "#4367BF",
llms: "#6344BE",
chains: "#FE7500",
agents: "#903BBE",
tools: "#FF3434",
memories: "#F5B85A",
advanced: "#000000",
chat: "#198BF6",
thought: "#272541",
embeddings: "#42BAA7",
documentloaders: "#7AAE42",
vectorstores: "#AA8742",
textsplitters: "#B47CB5",
toolkits: "#DB2C2C",
wrappers: "#E6277A",
utilities: "#31A3CC",
unknown: "#9CA3AF",
};
export const nodeNames: { [char: string]: string } = {
prompts: "Prompts",
llms: "LLMs",
chains: "Chains",
agents: "Agents",
tools: "Tools",
memories: "Memories",
advanced: "Advanced",
chat: "Chat",
embeddings: "Embeddings",
documentloaders: "Document Loaders",
vectorstores: "Vector Stores",
toolkits: "Toolkits",
wrappers: "Wrappers",
textsplitters: "Text Splitters",
utilities: "Utilities",
unknown: "Unknown",
prompts: "Prompts",
llms: "LLMs",
chains: "Chains",
agents: "Agents",
tools: "Tools",
memories: "Memories",
advanced: "Advanced",
chat: "Chat",
embeddings: "Embeddings",
documentloaders: "Document Loaders",
vectorstores: "Vector Stores",
toolkits: "Toolkits",
wrappers: "Wrappers",
textsplitters: "Text Splitters",
utilities: "Utilities",
unknown: "Unknown",
};
export const nodeIcons: {
[char: string]: React.ForwardRefExoticComponent<
React.SVGProps<SVGSVGElement>
>;
[char: string]: React.ForwardRefExoticComponent<
React.SVGProps<SVGSVGElement>
>;
} = {
agents: RocketLaunchIcon,
chains: LinkIcon,
memories: CpuChipIcon,
llms: LightBulbIcon,
prompts: CommandLineIcon,
tools: WrenchIcon,
advanced: ComputerDesktopIcon,
chat: Bars3CenterLeftIcon,
embeddings: FingerPrintIcon,
documentloaders: PaperClipIcon,
vectorstores: CircleStackIcon,
toolkits: WrenchScrewdriverIcon,
textsplitters: ScissorsIcon,
wrappers: GiftIcon,
utilities: Squares2X2Icon,
unknown: QuestionMarkCircleIcon,
agents: RocketLaunchIcon,
chains: LinkIcon,
memories: CpuChipIcon,
llms: LightBulbIcon,
prompts: CommandLineIcon,
tools: WrenchIcon,
advanced: ComputerDesktopIcon,
chat: Bars3CenterLeftIcon,
embeddings: FingerPrintIcon,
documentloaders: PaperClipIcon,
vectorstores: CircleStackIcon,
toolkits: WrenchScrewdriverIcon,
textsplitters: ScissorsIcon,
wrappers: GiftIcon,
utilities: Squares2X2Icon,
unknown: QuestionMarkCircleIcon,
};
export const bgColors = {
white: "bg-white",
red: "bg-red-100",
orange: "bg-orange-100",
amber: "bg-amber-100",
yellow: "bg-yellow-100",
lime: "bg-lime-100",
green: "bg-green-100",
emerald: "bg-emerald-100",
teal: "bg-teal-100",
cyan: "bg-cyan-100",
sky: "bg-sky-100",
blue: "bg-blue-100",
indigo: "bg-indigo-100",
violet: "bg-violet-100",
purple: "bg-purple-100",
fuchsia: "bg-fuchsia-100",
pink: "bg-pink-100",
rose: "bg-rose-100",
black: "bg-black-100",
gray: "bg-gray-100",
white: "bg-white",
red: "bg-red-100",
orange: "bg-orange-100",
amber: "bg-amber-100",
yellow: "bg-yellow-100",
lime: "bg-lime-100",
green: "bg-green-100",
emerald: "bg-emerald-100",
teal: "bg-teal-100",
cyan: "bg-cyan-100",
sky: "bg-sky-100",
blue: "bg-blue-100",
indigo: "bg-indigo-100",
violet: "bg-violet-100",
purple: "bg-purple-100",
fuchsia: "bg-fuchsia-100",
pink: "bg-pink-100",
rose: "bg-rose-100",
black: "bg-black-100",
gray: "bg-gray-100",
};
export const bgColorsHover = {
white: "hover:bg-white",
black: "hover:bg-black-50",
gray: "hover:bg-gray-50",
red: "hover:bg-red-50",
orange: "hover:bg-orange-50",
amber: "hover:bg-amber-50",
yellow: "hover:bg-yellow-50",
lime: "hover:bg-lime-50",
green: "hover:bg-green-50",
emerald: "hover:bg-emerald-50",
teal: "hover:bg-teal-50",
cyan: "hover:bg-cyan-50",
sky: "hover:bg-sky-50",
blue: "hover:bg-blue-50",
indigo: "hover:bg-indigo-50",
violet: "hover:bg-violet-50",
purple: "hover:bg-purple-50",
fuchsia: "hover:bg-fuchsia-50",
pink: "hover:bg-pink-50",
rose: "hover:bg-rose-50",
white: "hover:bg-white",
black: "hover:bg-black-50",
gray: "hover:bg-gray-50",
red: "hover:bg-red-50",
orange: "hover:bg-orange-50",
amber: "hover:bg-amber-50",
yellow: "hover:bg-yellow-50",
lime: "hover:bg-lime-50",
green: "hover:bg-green-50",
emerald: "hover:bg-emerald-50",
teal: "hover:bg-teal-50",
cyan: "hover:bg-cyan-50",
sky: "hover:bg-sky-50",
blue: "hover:bg-blue-50",
indigo: "hover:bg-indigo-50",
violet: "hover:bg-violet-50",
purple: "hover:bg-purple-50",
fuchsia: "hover:bg-fuchsia-50",
pink: "hover:bg-pink-50",
rose: "hover:bg-rose-50",
};
export const textColorsHex = {
red: "rgb(185 28 28)",
orange: "rgb(194 65 12)",
amber: "rgb(180 83 9)",
yellow: "rgb(161 98 7)",
lime: "rgb(77 124 15)",
green: "rgb(21 128 61)",
emerald: "rgb(4 120 87)",
teal: "rgb(15 118 110)",
cyan: "rgb(14 116 144)",
sky: "rgb(3 105 161)",
blue: "rgb(29 78 216)",
indigo: "rgb(67 56 202)",
violet: "rgb(109 40 217)",
purple: "rgb(126 34 206)",
fuchsia: "rgb(162 28 175)",
pink: "rgb(190 24 93)",
rose: "rgb(190 18 60)",
red: "rgb(185 28 28)",
orange: "rgb(194 65 12)",
amber: "rgb(180 83 9)",
yellow: "rgb(161 98 7)",
lime: "rgb(77 124 15)",
green: "rgb(21 128 61)",
emerald: "rgb(4 120 87)",
teal: "rgb(15 118 110)",
cyan: "rgb(14 116 144)",
sky: "rgb(3 105 161)",
blue: "rgb(29 78 216)",
indigo: "rgb(67 56 202)",
violet: "rgb(109 40 217)",
purple: "rgb(126 34 206)",
fuchsia: "rgb(162 28 175)",
pink: "rgb(190 24 93)",
rose: "rgb(190 18 60)",
};
export const bgColorsHex = {
red: "rgb(254 226 226)",
orange: "rgb(255 237 213)",
amber: "rgb(254 243 199)",
yellow: "rgb(254 249 195)",
lime: "rgb(236 252 203)",
green: "rgb(220 252 231)",
emerald: "rgb(209 250 229)",
teal: "rgb(204 251 241)",
cyan: "rgb(207 250 254)",
sky: "rgb(224 242 254)",
blue: "rgb(219 234 254)",
indigo: "rgb(224 231 255)",
violet: "rgb(237 233 254)",
purple: "rgb(243 232 255)",
fuchsia: "rgb(250 232 255)",
pink: "rgb(252 231 243)",
rose: "rgb(255 228 230)",
red: "rgb(254 226 226)",
orange: "rgb(255 237 213)",
amber: "rgb(254 243 199)",
yellow: "rgb(254 249 195)",
lime: "rgb(236 252 203)",
green: "rgb(220 252 231)",
emerald: "rgb(209 250 229)",
teal: "rgb(204 251 241)",
cyan: "rgb(207 250 254)",
sky: "rgb(224 242 254)",
blue: "rgb(219 234 254)",
indigo: "rgb(224 231 255)",
violet: "rgb(237 233 254)",
purple: "rgb(243 232 255)",
fuchsia: "rgb(250 232 255)",
pink: "rgb(252 231 243)",
rose: "rgb(255 228 230)",
};
export const taskTypeMap: { [key: string]: string } = {
MULTICLASS_CLASSIFICATION: "Multiclass Classification",
MULTICLASS_CLASSIFICATION: "Multiclass Classification",
};
const charWidths: { [char: string]: number } = {
" ": 0.2,
"!": 0.2,
'"': 0.3,
"#": 0.5,
$: 0.5,
"%": 0.5,
"&": 0.5,
"(": 0.2,
")": 0.2,
"*": 0.5,
"+": 0.5,
",": 0.2,
"-": 0.2,
".": 0.1,
"/": 0.5,
":": 0.2,
";": 0.2,
"<": 0.5,
"=": 0.5,
">": 0.5,
"?": 0.2,
"@": 0.5,
"[": 0.2,
"\\": 0.5,
"]": 0.2,
"^": 0.5,
_: 0.2,
"`": 0.5,
"{": 0.2,
"|": 0.2,
"}": 0.2,
"~": 0.5,
" ": 0.2,
"!": 0.2,
'"': 0.3,
"#": 0.5,
$: 0.5,
"%": 0.5,
"&": 0.5,
"(": 0.2,
")": 0.2,
"*": 0.5,
"+": 0.5,
",": 0.2,
"-": 0.2,
".": 0.1,
"/": 0.5,
":": 0.2,
";": 0.2,
"<": 0.5,
"=": 0.5,
">": 0.5,
"?": 0.2,
"@": 0.5,
"[": 0.2,
"\\": 0.5,
"]": 0.2,
"^": 0.5,
_: 0.2,
"`": 0.5,
"{": 0.2,
"|": 0.2,
"}": 0.2,
"~": 0.5,
};
for (let i = 65; i <= 90; i++) {
charWidths[String.fromCharCode(i)] = 0.6;
charWidths[String.fromCharCode(i)] = 0.6;
}
for (let i = 97; i <= 122; i++) {
charWidths[String.fromCharCode(i)] = 0.5;
charWidths[String.fromCharCode(i)] = 0.5;
}
export function measureTextWidth(text: string, fontSize: number) {
let wordWidth = 0;
for (let j = 0; j < text.length; j++) {
let char = text[j];
let charWidth = charWidths[char] || 0.5;
wordWidth += charWidth * fontSize;
}
return wordWidth;
let wordWidth = 0;
for (let j = 0; j < text.length; j++) {
let char = text[j];
let charWidth = charWidths[char] || 0.5;
wordWidth += charWidth * fontSize;
}
return wordWidth;
}
export function measureTextHeight(
text: string,
width: number,
fontSize: number
text: string,
width: number,
fontSize: number
) {
const charHeight = fontSize;
const lineHeight = charHeight * 1.5;
const words = text.split(" ");
let lineWidth = 0;
let totalHeight = 0;
for (let i = 0; i < words.length; i++) {
let word = words[i];
let wordWidth = measureTextWidth(word, fontSize);
if (lineWidth + wordWidth + charWidths[" "] * fontSize <= width) {
lineWidth += wordWidth + charWidths[" "] * fontSize;
} else {
totalHeight += lineHeight;
lineWidth = wordWidth;
}
}
totalHeight += lineHeight;
return totalHeight;
const charHeight = fontSize;
const lineHeight = charHeight * 1.5;
const words = text.split(" ");
let lineWidth = 0;
let totalHeight = 0;
for (let i = 0; i < words.length; i++) {
let word = words[i];
let wordWidth = measureTextWidth(word, fontSize);
if (lineWidth + wordWidth + charWidths[" "] * fontSize <= width) {
lineWidth += wordWidth + charWidths[" "] * fontSize;
} else {
totalHeight += lineHeight;
lineWidth = wordWidth;
}
}
totalHeight += lineHeight;
return totalHeight;
}
export function toCamelCase(str: string) {
return str
.split(" ")
.map((word, index) =>
index === 0
? word.toLowerCase()
: word[0].toUpperCase() + word.slice(1).toLowerCase()
)
.join("");
return str
.split(" ")
.map((word, index) =>
index === 0
? word.toLowerCase()
: word[0].toUpperCase() + word.slice(1).toLowerCase()
)
.join("");
}
export function toFirstUpperCase(str: string) {
return str
.split(" ")
.map((word, index) => word[0].toUpperCase() + word.slice(1).toLowerCase())
.join("");
return str
.split(" ")
.map((word, index) => word[0].toUpperCase() + word.slice(1).toLowerCase())
.join("");
}
export function toNormalCase(str: string) {
@ -337,62 +338,62 @@ export function toNormalCase(str: string) {
}
export function normalCaseToSnakeCase(str: string) {
return str
.split(" ")
.map((word, index) => {
if (index === 0) {
return word[0].toUpperCase() + word.slice(1).toLowerCase();
}
return word.toLowerCase();
})
.join("_");
return str
.split(" ")
.map((word, index) => {
if (index === 0) {
return word[0].toUpperCase() + word.slice(1).toLowerCase();
}
return word.toLowerCase();
})
.join("_");
}
export function roundNumber(x: number, decimals: number) {
return Math.round(x * Math.pow(10, decimals)) / Math.pow(10, decimals);
return Math.round(x * Math.pow(10, decimals)) / Math.pow(10, decimals);
}
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;
const sourceId = edge.source;
const targetId = edge.target;
const connectedNodes = nodes.filter(
(node) => node.id === targetId || node.id === sourceId
);
return connectedNodes;
}
export function isValidConnection(
{ source, target, sourceHandle, targetHandle }: Connection,
reactFlowInstance: ReactFlowInstance
{ source, target, sourceHandle, targetHandle }: Connection,
reactFlowInstance: ReactFlowInstance
) {
if (
sourceHandle.split("|")[0] === targetHandle.split("|")[0] ||
sourceHandle
.split("|")
.slice(2)
.some((t) => t === targetHandle.split("|")[0]) ||
targetHandle.split("|")[0] === "str"
) {
let targetNode = reactFlowInstance.getNode(target).data.node;
if (!targetNode) {
if (
!reactFlowInstance
.getEdges()
.find((e) => e.targetHandle === targetHandle)
) {
return true;
}
} else if (
(!targetNode.template[targetHandle.split("|")[1]].list &&
!reactFlowInstance
.getEdges()
.find((e) => e.targetHandle === targetHandle)) ||
targetNode.template[targetHandle.split("|")[1]].list
) {
return true;
}
}
return false;
if (
sourceHandle.split("|")[0] === targetHandle.split("|")[0] ||
sourceHandle
.split("|")
.slice(2)
.some((t) => t === targetHandle.split("|")[0]) ||
targetHandle.split("|")[0] === "str"
) {
let targetNode = reactFlowInstance.getNode(target).data.node;
if (!targetNode) {
if (
!reactFlowInstance
.getEdges()
.find((e) => e.targetHandle === targetHandle)
) {
return true;
}
} else if (
(!targetNode.template[targetHandle.split("|")[1]].list &&
!reactFlowInstance
.getEdges()
.find((e) => e.targetHandle === targetHandle)) ||
targetNode.template[targetHandle.split("|")[1]].list
) {
return true;
}
}
return false;
}
export function removeApiKeys(flow: FlowType): FlowType {
@ -408,32 +409,48 @@ export function removeApiKeys(flow: FlowType): FlowType {
}
export function updateObject<T extends Record<string, any>>(
reference: T,
objectToUpdate: T
reference: T,
objectToUpdate: T
): T {
let clonedObject = _.cloneDeep(objectToUpdate);
// Loop through each key in the object to update
for (const key in clonedObject) {
// If the key is not in the reference object, delete it
if (!(key in reference)) {
delete clonedObject[key];
}
}
// Loop through each key in the reference object
for (const key in reference) {
// If the key is not in the object to update, add it
if (!(key in clonedObject)) {
clonedObject[key] = reference[key];
}
}
return clonedObject;
let clonedObject = _.cloneDeep(objectToUpdate);
// Loop through each key in the object to update
for (const key in clonedObject) {
// If the key is not in the reference object, delete it
if (!(key in reference)) {
delete clonedObject[key];
}
}
// Loop through each key in the reference object
for (const key in reference) {
// If the key is not in the object to update, add it
if (!(key in clonedObject)) {
clonedObject[key] = reference[key];
}
}
return clonedObject;
}
export function debounce(func, wait) {
let timeout;
return function (...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
let timeout;
return function (...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
export function updateTemplate(
reference: APITemplateType,
objectToUpdate: APITemplateType
): APITemplateType {
let clonedObject:APITemplateType = _.cloneDeep(reference);
// Loop through each key in the reference object
for (const key in clonedObject) {
// If the key is not in the object to update, add it
if (objectToUpdate[key] && objectToUpdate[key].value) {
clonedObject[key].value = objectToUpdate[key].value;
}
}
return clonedObject;
}