Merge branch 'dev' into two_edges_dev

This commit is contained in:
italojohnny 2024-06-13 15:58:33 -03:00
commit f0630ec870
63 changed files with 1977 additions and 2717 deletions

File diff suppressed because it is too large Load diff

View file

@ -85,9 +85,6 @@
"format": "npx prettier --write \"{tests,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore",
"type-check": "tsc --noEmit --pretty --project tsconfig.json && vite"
},
"simple-git-hooks": {
"pre-commit": "npx pretty-quick --staged"
},
"eslintConfig": {
"extends": [
"react-app",
@ -130,7 +127,6 @@
"prettier": "^2.8.8",
"prettier-plugin-organize-imports": "^3.2.3",
"prettier-plugin-tailwindcss": "^0.3.0",
"pretty-quick": "^3.1.3",
"simple-git-hooks": "^2.11.1",
"tailwindcss": "^3.3.3",
"tailwindcss-dotted-background": "^1.1.0",
@ -138,4 +134,4 @@
"ua-parser-js": "^1.0.37",
"vite": "^4.5.2"
}
}
}

View file

@ -80,7 +80,6 @@ export default function App() {
login(user["access_token"]);
setUserData(user);
setAutoLogin(true);
setLoading(false);
fetchAllData();
}
})

View file

@ -1,6 +1,5 @@
import { cloneDeep } from "lodash";
import { ReactNode, useEffect, useRef, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
import CodeAreaComponent from "../../../../components/codeAreaComponent";
import DictComponent from "../../../../components/dictComponent";
@ -18,7 +17,10 @@ import TextAreaComponent from "../../../../components/textAreaComponent";
import ToggleShadComponent from "../../../../components/toggleShadComponent";
import { Button } from "../../../../components/ui/button";
import { RefreshButton } from "../../../../components/ui/refreshButton";
import { LANGFLOW_SUPPORTED_TYPES } from "../../../../constants/constants";
import {
LANGFLOW_SUPPORTED_TYPES,
TOOLTIP_EMPTY,
} from "../../../../constants/constants";
import { Case } from "../../../../shared/components/caseComponent";
import useFlowStore from "../../../../stores/flowStore";
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
@ -49,8 +51,10 @@ import useHandleNodeClass from "../../../hooks/use-handle-node-class";
import useHandleRefreshButtonPress from "../../../hooks/use-handle-refresh-buttons";
import HandleTooltips from "../HandleTooltipComponent";
import OutputComponent from "../OutputComponent";
import OutputModal from "../outputModal";
import TooltipRenderComponent from "../tooltipRenderComponent";
import { TEXT_FIELD_TYPES } from "./constants";
import OutputModal from "../outputModal";
import { useHotkeys } from "react-hotkeys-hook";
export default function ParameterComponent({
left,
@ -71,6 +75,8 @@ export default function ParameterComponent({
selected,
outputProxy,
}: ParameterComponentType): JSX.Element {
const ref = useRef<HTMLDivElement>(null);
const refHtml = useRef<HTMLDivElement & ReactNode>(null);
const infoHtml = useRef<HTMLDivElement & ReactNode>(null);
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
const nodes = useFlowStore((state) => state.nodes);
@ -81,13 +87,16 @@ export default function ParameterComponent({
const [isLoading, setIsLoading] = useState(false);
const updateNodeInternals = useUpdateNodeInternals();
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
const flow = currentFlow?.data?.nodes ?? null;
const groupedEdge = useRef(null);
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
const [openOutputModal, setOpenOutputModal] = useState(false);
const flowPool = useFlowStore((state) => state.flowPool);
const isValid =
const displayOutputPreview =
!!flowPool[data.id] &&
flowPool[data.id][flowPool[data.id].length - 1]?.valid;
flowPool[data.id][flowPool[data.id].length - 1]?.valid &&
flowPool[data.id][flowPool[data.id].length - 1]?.data?.logs[0]?.message;
const flowPoolNode = (flowPool[data.id] ?? [])[
(flowPool[data.id]?.length ?? 1) - 1
@ -96,7 +105,6 @@ export default function ParameterComponent({
if (flowPoolNode?.data?.logs && outputName) {
hasOutputs = flowPoolNode?.data?.logs[outputName] ?? null;
}
const displayOutputPreview = isValid && hasOutputs;
const unknownOutput = !!(
flowPool[data.id] &&
flowPool[data.id][flowPool[data.id].length - 1]?.data?.logs[0]?.type ===
@ -157,7 +165,7 @@ export default function ParameterComponent({
const handleOnNewValue = async (
newValue: string | string[] | boolean | Object[],
skipSnapshot: boolean | undefined = false
skipSnapshot: boolean | undefined = false,
): Promise<void> => {
handleOnNewValueHook(newValue, skipSnapshot);
};
@ -270,7 +278,7 @@ export default function ParameterComponent({
className={classNames(
left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ",
"h-3 w-3 rounded-full border-2 bg-background",
!showNode ? "mt-0" : ""
!showNode ? "mt-0" : "",
)}
style={{
borderColor: color ?? nodeColors.unknown,
@ -287,6 +295,7 @@ export default function ParameterComponent({
)
) : (
<div
ref={ref}
className={
"relative mt-1 flex w-full flex-wrap items-center justify-between bg-muted px-5 py-2" +
((name === "code" && type === "code") ||

View file

@ -458,10 +458,11 @@ export default function GenericNode({
.filter((templateField) => templateField.charAt(0) !== "_")
.map(
(templateField: string, idx) =>
data.node!.template[templateField].show &&
!data.node!.template[templateField].advanced && (
data.node!.template[templateField]?.show &&
!data.node!.template[templateField]?.advanced && (
<ParameterComponent
index={idx}
selected={selected}
index={idx.toString()}
key={scapedJSONStringfy({
inputTypes:
data.node!.template[templateField].input_types,
@ -545,7 +546,7 @@ export default function GenericNode({
title={
data.node?.output_types &&
data.node.output_types.length > 0
? data.node.output_types.join("|")
? data.node.output_types.join(" | ")
: data.type
}
tooltipTitle={data.node?.base_classes.join("\n")}
@ -718,10 +719,11 @@ export default function GenericNode({
.sort((a, b) => sortFields(a, b, data.node?.field_order ?? []))
.map((templateField: string, idx) => (
<div key={idx}>
{data.node!.template[templateField].show &&
!data.node!.template[templateField].advanced ? (
{data.node!.template[templateField]?.show &&
!data.node!.template[templateField]?.advanced ? (
<ParameterComponent
index={idx}
selected={selected}
index={idx.toString()}
key={scapedJSONStringfy({
inputTypes:
data.node!.template[templateField].input_types,

View file

@ -5,9 +5,9 @@ export function countHandlesFn(data: NodeDataType): number {
.filter((templateField) => templateField.charAt(0) !== "_")
.map((templateCamp) => {
const { template } = data.node!;
if (template[templateCamp].input_types) return true;
if (!template[templateCamp].show) return false;
switch (template[templateCamp].type) {
if (template[templateCamp]?.input_types) return true;
if (!template[templateCamp]?.show) return false;
switch (template[templateCamp]?.type) {
case "str":
case "bool":
case "float":

View file

@ -1,5 +1,9 @@
import { cloneDeep } from "lodash";
import { useEffect } from "react";
import {
ERROR_UPDATING_COMPONENT,
TITLE_ERROR_UPDATING_COMPONENT,
} from "../../constants/constants";
import useAlertStore from "../../stores/alertStore";
import { ResponseErrorDetailAPI } from "../../types/api";
@ -38,8 +42,10 @@ const useFetchDataOnMount = (
let responseError = error as ResponseErrorDetailAPI;
setErrorData({
title: "Error while updating the Component",
list: [responseError?.response?.data?.detail ?? "Unknown error"],
title: TITLE_ERROR_UPDATING_COMPONENT,
list: [
responseError?.response?.data?.detail ?? ERROR_UPDATING_COMPONENT,
],
});
}
setIsLoading(false);

View file

@ -1,4 +1,8 @@
import { cloneDeep } from "lodash";
import {
ERROR_UPDATING_COMPONENT,
TITLE_ERROR_UPDATING_COMPONENT,
} from "../../constants/constants";
import useAlertStore from "../../stores/alertStore";
import { ResponseErrorTypeAPI } from "../../types/api";
@ -42,9 +46,10 @@ const useHandleOnNewValue = (
} catch (error) {
let responseError = error as ResponseErrorTypeAPI;
setErrorData({
title: "Error while updating the Component",
title: TITLE_ERROR_UPDATING_COMPONENT,
list: [
responseError?.response?.data?.detail.error ?? "Unknown error",
responseError?.response?.data?.detail.error ??
ERROR_UPDATING_COMPONENT,
],
});
}

View file

@ -1,4 +1,8 @@
import { cloneDeep } from "lodash";
import {
ERROR_UPDATING_COMPONENT,
TITLE_ERROR_UPDATING_COMPONENT,
} from "../../constants/constants";
import useAlertStore from "../../stores/alertStore";
import { ResponseErrorDetailAPI } from "../../types/api";
import { handleUpdateValues } from "../../utils/parameterUtils";
@ -25,8 +29,10 @@ const useHandleRefreshButtonPress = (setIsLoading, setNode) => {
let responseError = error as ResponseErrorDetailAPI;
setErrorData({
title: "Error while updating the Component",
list: [responseError?.response?.data?.detail ?? "Unknown error"],
title: TITLE_ERROR_UPDATING_COMPONENT,
list: [
responseError?.response?.data?.detail ?? ERROR_UPDATING_COMPONENT,
],
});
}
setIsLoading(false);

View file

@ -70,7 +70,10 @@ export default function AddNewVariableButton({
let responseError = error as ResponseErrorDetailAPI;
setErrorData({
title: "Error creating variable",
list: [responseError?.response?.data?.detail ?? "Unknown error"],
list: [
responseError?.response?.data?.detail ??
"An unexpected error occurred while adding a new variable. Please try again.",
],
});
});
}

View file

@ -36,6 +36,7 @@ export default function Header(): JSX.Element {
const location = useLocation();
const { logout, autoLogin, isAdmin, userData } = useContext(AuthContext);
const navigate = useNavigate();
const removeFlow = useFlowsManagerStore((store) => store.removeFlow);
const hasStore = useStoreStore((state) => state.hasStore);
@ -208,7 +209,7 @@ export default function Header(): JSX.Element {
0,
BACKEND_URL.length - 1
)}${BASE_URL_API}files/profile_pictures/${
userData?.profile_image ?? "Space/046-rocket.png"
userData?.profile_image ?? "Space/046-rocket.svg"
}` ?? profileCircle
}
className="h-7 w-7 shrink-0 focus-visible:outline-0"
@ -226,7 +227,7 @@ export default function Header(): JSX.Element {
0,
BACKEND_URL.length - 1
)}${BASE_URL_API}files/profile_pictures/${
userData?.profile_image
userData?.profile_image ?? "Space/046-rocket.svg"
}` ?? profileCircle
}
className="h-5 w-5 focus-visible:outline-0 "

View file

@ -31,7 +31,7 @@ export default function InputListComponent({
<div
className={classNames(
value.length > 1 && editNode ? "my-1" : "",
"flex flex-col gap-3",
"flex flex-col gap-3"
)}
>
{value.map((singleValue, idx) => {

View file

@ -853,3 +853,8 @@ export const ALLOWED_IMAGE_INPUT_EXTENSIONS = ["png", "jpg", "jpeg"];
export const FS_ERROR_TEXT =
"Please ensure your file has one of the following extensions:";
export const SN_ERROR_TEXT = ALLOWED_IMAGE_INPUT_EXTENSIONS.join(", ");
export const ERROR_UPDATING_COMPONENT =
"An unexpected error occurred while updating the Component. Please try again.";
export const TITLE_ERROR_UPDATING_COMPONENT =
"Error while updating the Component";

View file

@ -42,6 +42,7 @@ export function AuthProvider({ children }): React.ReactElement {
const [apiKey, setApiKey] = useState<string | null>(
cookies.get("apikey_tkn_lflw")
);
// const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
useEffect(() => {
const storedAccessToken = cookies.get("access_token_lf");
@ -59,11 +60,11 @@ export function AuthProvider({ children }): React.ReactElement {
function getUser() {
getLoggedUser()
.then((user) => {
.then(async (user) => {
setUserData(user);
setLoading(false);
const isSuperUser = user!.is_superuser;
setIsAdmin(isSuperUser);
// await getFoldersApi(true);
})
.catch((error) => {
setLoading(false);

View file

@ -5,6 +5,7 @@ import CsvOutputComponent from "../../../../components/csvOutputComponent";
import DataOutputComponent from "../../../../components/dataOutputComponent";
import InputListComponent from "../../../../components/inputListComponent";
import PdfViewer from "../../../../components/pdfViewer";
import RecordsOutputComponent from "../../../../components/recordsOutputComponent";
import { Textarea } from "../../../../components/ui/textarea";
import { PDFViewConstant } from "../../../../constants/constants";
import { InputOutput } from "../../../../constants/enums";
@ -253,7 +254,7 @@ export default function IOFieldView({
rows={
Array.isArray(flowPoolNode?.data?.artifacts)
? flowPoolNode?.data?.artifacts?.map(
(artifact) => artifact.data
(artifact) => artifact.data,
) ?? []
: [flowPoolNode?.data?.artifacts]
}

View file

@ -18,7 +18,7 @@ export default function SessionView({ rows }: { rows: Array<any> }) {
setSelectedRows,
setSuccessData,
setErrorData,
selectedRows,
selectedRows
);
const { handleUpdate } = useUpdateMessage(setSuccessData, setErrorData);

View file

@ -36,12 +36,6 @@ export default function ChatView({
const outputTypes = outputs.map((obj) => obj.type);
const updateFlowPool = useFlowStore((state) => state.updateFlowPool);
// useEffect(() => {
// if (!outputTypes.includes("ChatOutput")) {
// setNoticeData({ title: NOCHATOUTPUT_NOTICE_ALERT });
// }
// }, []);
//build chat history
useEffect(() => {
const chatOutputResponses: VertexBuildTypeAPI[] = [];
@ -62,14 +56,24 @@ export default function ChatView({
const chatMessages: ChatMessageType[] = chatOutputResponses
.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp))
//
.filter((output) => output.data.message)
.filter(
(output) =>
output.data.message || (!output.data.message && output.artifacts)
)
.map((output, index) => {
try {
console.log("output:", output);
const messageOutput = output.data.message;
const hasMessageValue =
messageOutput?.message ||
messageOutput?.message === "" ||
(messageOutput?.files ?? []).length > 0 ||
messageOutput?.stream_url;
const { sender, message, sender_name, stream_url, files } =
output.data.message;
console.log("output.data.message:", output.data.message);
console.log("output.data.message.files:", output.data.message.files);
hasMessageValue ? output.data.message : output.artifacts;
const is_ai =
sender === "Machine" || sender === null || sender === undefined;
return {
@ -136,26 +140,12 @@ export default function ChatView({
message: string,
stream_url?: string
) {
// if (message === "") return;
chat.message = message;
// chat is one of the chatHistory
updateFlowPool(chat.componentId, {
message,
sender_name: chat.sender_name ?? "Bot",
sender: chat.isSend ? "User" : "Machine",
});
// setChatHistory((oldChatHistory) => {
// const index = oldChatHistory.findIndex((ch) => ch.id === chat.id);
// if (index === -1) return oldChatHistory;
// let newChatHistory = _.cloneDeep(oldChatHistory);
// newChatHistory = [
// ...newChatHistory.slice(0, index),
// chat,
// ...newChatHistory.slice(index + 1),
// ];
// console.log("newChatHistory:", newChatHistory);
// return newChatHistory;
// });
}
const [files, setFiles] = useState<FilePreviewType[]>([]);
const [isDragging, setIsDragging] = useState(false);
@ -190,44 +180,6 @@ export default function ChatView({
aria-hidden="true"
/>
</Button>
{/* <Select
onValueChange={handleSelectChange}
value=""
disabled={lockChat}
>
<SelectTrigger className="">
<button className="flex gap-1">
<IconComponent
name="Eraser"
className={classNames(
"h-5 w-5 transition-all duration-100",
lockChat ? "animate-pulse text-primary" : "text-primary",
)}
aria-hidden="true"
/>
</button>
</SelectTrigger>
<SelectContent className="right-[9.5em]">
<SelectItem value="builds" className="cursor-pointer">
<div className="flex">
<IconComponent
name={"Trash2"}
className={`relative top-0.5 mr-2 h-4 w-4`}
/>
<span className="">Clear Builds</span>
</div>
</SelectItem>
<SelectItem value="buildsNSession" className="cursor-pointer">
<div className="flex">
<IconComponent
name={"Trash2"}
className={`relative top-0.5 mr-2 h-4 w-4`}
/>
<span className="">Clear Builds & Session</span>
</div>
</SelectItem>
</SelectContent>
</Select> */}
</div>
<div ref={messagesRef} className="chat-message-div">
{chatHistory?.length > 0 ? (

View file

@ -10,7 +10,7 @@ import IconComponent from "../../components/genericIconComponent";
import { EXPORT_CODE_DIALOG } from "../../constants/constants";
import { AuthContext } from "../../contexts/authContext";
import { useTweaksStore } from "../../stores/tweaksStore";
import { InputFieldType } from "../../types/api";
import { TemplateVariableType } from "../../types/api";
import { uniqueTweakType } from "../../types/components";
import { FlowType } from "../../types/flow/index";
import BaseModal from "../baseModal";
@ -39,7 +39,7 @@ const ApiModal = forwardRef(
open?: boolean;
setOpen?: (a: boolean | ((o?: boolean) => boolean)) => void;
},
ref
ref,
) => {
const tweak = useTweaksStore((state) => state.tweak);
const addTweaks = useTweaksStore((state) => state.setTweak);
@ -57,18 +57,18 @@ const ApiModal = forwardRef(
flow?.id,
autoLogin,
tweak,
flow?.endpoint_name
flow?.endpoint_name,
);
const curl_run_code = getCurlRunCode(
flow?.id,
autoLogin,
tweak,
flow?.endpoint_name
flow?.endpoint_name,
);
const curl_webhook_code = getCurlWebhookCode(
flow?.id,
autoLogin,
flow?.endpoint_name
flow?.endpoint_name,
);
const pythonCode = getPythonCode(flow?.name, tweak);
const widgetCode = getWidgetCode(flow?.id, flow?.name, autoLogin);
@ -83,7 +83,7 @@ const ApiModal = forwardRef(
pythonCode,
];
const [tabs, setTabs] = useState(
createTabsArray(codesArray, includeWebhook)
createTabsArray(codesArray, includeWebhook),
);
const canShowTweaks =
@ -132,7 +132,7 @@ const ApiModal = forwardRef(
buildTweakObject(
nodeId,
element.data.node.template[templateField].value,
element.data.node.template[templateField]
element.data.node.template[templateField],
);
}
});
@ -149,7 +149,7 @@ const ApiModal = forwardRef(
async function buildTweakObject(
tw: string,
changes: string | string[] | boolean | number | Object[] | Object,
template: InputFieldType
template: TemplateVariableType,
) {
changes = getChangesType(changes, template);
@ -191,7 +191,7 @@ const ApiModal = forwardRef(
flow?.id,
autoLogin,
cloneTweak,
flow?.endpoint_name
flow?.endpoint_name,
);
const pythonCode = getPythonCode(flow?.name, cloneTweak);
const widgetCode = getWidgetCode(flow?.id, flow?.name, autoLogin);
@ -235,7 +235,7 @@ const ApiModal = forwardRef(
</BaseModal.Content>
</BaseModal>
);
}
},
);
export default ApiModal;

View file

@ -1,9 +1,9 @@
import { InputFieldType } from "../../../types/api";
import { TemplateVariableType } from "../../../types/api";
import { convertArrayToObj } from "../../../utils/reactflowUtils";
export const getChangesType = (
changes: string | string[] | boolean | number | Object[] | Object,
template: InputFieldType
template: TemplateVariableType,
) => {
if (typeof changes === "string" && template.type === "float") {
changes = parseFloat(changes);

View file

@ -11,10 +11,10 @@ export const getNodesWithDefaultValue = (flow) => {
.filter(
(templateField) =>
templateField.charAt(0) !== "_" &&
node.data.node.template[templateField].show &&
node.data.node.template[templateField]?.show &&
LANGFLOW_SUPPORTED_TYPES.has(
node.data.node.template[templateField].type
)
node.data.node.template[templateField].type,
),
)
.map((n, i) => {
arrNodesWithValues.push(node["id"]);

View file

@ -1,11 +1,11 @@
import { InputFieldType } from "../../../types/api";
import { TemplateVariableType } from "../../../types/api";
import { NodeType } from "../../../types/flow";
export const getValue = (
value: string,
node: NodeType,
template: InputFieldType,
tweak: Object[]
template: TemplateVariableType,
tweak: Object[],
) => {
let returnValue = value ?? "";

View file

@ -18,7 +18,7 @@ export default function FlowSettingsModal({
useEffect(() => {
setName(currentFlow!.name);
setDescription(currentFlow!.description);
}, [currentFlow!.name, currentFlow!.description, open]);
}, [currentFlow?.name, currentFlow?.description, open]);
const [name, setName] = useState(currentFlow!.name);
const [description, setDescription] = useState(currentFlow!.description);
@ -40,6 +40,7 @@ export default function FlowSettingsModal({
list: [err?.response?.data.detail ?? ""],
});
console.error(err);
setIsSaving(false);
});
}

View file

@ -38,6 +38,7 @@ import {
generateNodeFromFlow,
getNodeId,
isValidConnection,
reconnectEdges,
scapeJSONParse,
updateIds,
validateSelection,
@ -61,19 +62,19 @@ export default function Page({
const preventDefault = true;
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
const autoSaveCurrentFlow = useFlowsManagerStore(
(state) => state.autoSaveCurrentFlow
(state) => state.autoSaveCurrentFlow,
);
const types = useTypesStore((state) => state.types);
const templates = useTypesStore((state) => state.templates);
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
const reactFlowWrapper = useRef<HTMLDivElement>(null);
const [showCanvas, setSHowCanvas] = useState(
Object.keys(templates).length > 0 && Object.keys(types).length > 0
Object.keys(templates).length > 0 && Object.keys(types).length > 0,
);
const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance);
const setReactFlowInstance = useFlowStore(
(state) => state.setReactFlowInstance
(state) => state.setReactFlowInstance,
);
const nodes = useFlowStore((state) => state.nodes);
const edges = useFlowStore((state) => state.edges);
@ -90,10 +91,10 @@ export default function Page({
const paste = useFlowStore((state) => state.paste);
const resetFlow = useFlowStore((state) => state.resetFlow);
const lastCopiedSelection = useFlowStore(
(state) => state.lastCopiedSelection
(state) => state.lastCopiedSelection,
);
const setLastCopiedSelection = useFlowStore(
(state) => state.setLastCopiedSelection
(state) => state.setLastCopiedSelection,
);
const onConnect = useFlowStore((state) => state.onConnect);
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
@ -116,7 +117,7 @@ export default function Page({
clonedSelection!,
clonedNodes,
clonedEdges,
getRandomName()
getRandomName(),
);
const newGroupNode = generateNodeFromFlow(newFlow, getNodeId);
// const newEdges = reconnectEdges(newGroupNode, removedEdges);
@ -124,8 +125,8 @@ export default function Page({
...clonedNodes.filter(
(oldNodes) =>
!clonedSelection?.nodes.some(
(selectionNode) => selectionNode.id === oldNodes.id
)
(selectionNode) => selectionNode.id === oldNodes.id,
),
),
newGroupNode,
]);
@ -212,7 +213,7 @@ export default function Page({
{
x: position.current.x,
y: position.current.y,
}
},
);
}
}
@ -296,7 +297,7 @@ export default function Page({
useEffect(() => {
setSHowCanvas(
Object.keys(templates).length > 0 && Object.keys(types).length > 0
Object.keys(templates).length > 0 && Object.keys(types).length > 0,
);
}, [templates, types]);
@ -305,7 +306,7 @@ export default function Page({
takeSnapshot();
onConnect(params);
},
[takeSnapshot, onConnect]
[takeSnapshot, onConnect],
);
const onNodeDragStart: NodeDragHandler = useCallback(() => {
@ -346,7 +347,7 @@ export default function Page({
// Extract the data from the drag event and parse it as a JSON object
const data: { type: string; node?: APIClassType } = JSON.parse(
event.dataTransfer.getData("nodedata")
event.dataTransfer.getData("nodedata"),
);
const newId = getNodeId(data.type);
@ -362,7 +363,7 @@ export default function Page({
};
paste(
{ nodes: [newNode], edges: [] },
{ x: event.clientX, y: event.clientY }
{ x: event.clientX, y: event.clientY },
);
} else if (event.dataTransfer.types.some((types) => types === "Files")) {
takeSnapshot();
@ -391,7 +392,7 @@ export default function Page({
}
},
// Specify dependencies for useCallback
[getNodeId, setNodes, takeSnapshot, paste]
[getNodeId, setNodes, takeSnapshot, paste],
);
const onEdgeUpdateStart = useCallback(() => {
@ -407,7 +408,7 @@ export default function Page({
setEdges((els) => updateEdge(oldEdge, newConnection, els));
}
},
[setEdges]
[setEdges],
);
const onEdgeUpdateEnd = useCallback((_, edge: Edge): void => {
@ -440,7 +441,7 @@ export default function Page({
(flow: OnSelectionChangeParams): void => {
setLastSelection(flow);
},
[]
[],
);
const onPaneClick = useCallback((flow) => {

View file

@ -57,17 +57,17 @@ export default function NodeToolbarComponent({
const nodeLength = Object.keys(data.node!.template).filter(
(templateField) =>
templateField.charAt(0) !== "_" &&
data.node?.template[templateField].show &&
(data.node.template[templateField].type === "str" ||
data.node.template[templateField].type === "bool" ||
data.node.template[templateField].type === "float" ||
data.node.template[templateField].type === "code" ||
data.node.template[templateField].type === "prompt" ||
data.node.template[templateField].type === "file" ||
data.node.template[templateField].type === "Any" ||
data.node.template[templateField].type === "int" ||
data.node.template[templateField].type === "dict" ||
data.node.template[templateField].type === "NestedDict")
data.node?.template[templateField]?.show &&
(data.node.template[templateField]?.type === "str" ||
data.node.template[templateField]?.type === "bool" ||
data.node.template[templateField]?.type === "float" ||
data.node.template[templateField]?.type === "code" ||
data.node.template[templateField]?.type === "prompt" ||
data.node.template[templateField]?.type === "file" ||
data.node.template[templateField]?.type === "Any" ||
data.node.template[templateField]?.type === "int" ||
data.node.template[templateField]?.type === "dict" ||
data.node.template[templateField]?.type === "NestedDict")
).length;
const hasStore = useStoreStore((state) => state.hasStore);
@ -626,7 +626,7 @@ export default function NodeToolbarComponent({
/>
</SelectItem>
)}
{(!hasStore || !hasApiKey || !validApiKey) && (
{/* {(!hasStore || !hasApiKey || !validApiKey) && (
<SelectItem value={"Download"}>
<ToolbarSelectItem
shortcut={
@ -638,7 +638,7 @@ export default function NodeToolbarComponent({
dataTestId="Download-button-modal"
/>
</SelectItem>
)}
)} */}
<SelectItem
value={"documentation"}
disabled={data.node?.documentation === ""}
@ -688,16 +688,19 @@ export default function NodeToolbarComponent({
style={`${frozen ? " text-ice" : ""} transition-all`}
/>
</SelectItem>
<SelectItem value="Download">
<ToolbarSelectItem
shortcut={
shortcuts.find((obj) => obj.name === "Download")?.shortcut!
}
value={"Download"}
icon={"Download"}
dataTestId="download-button-modal"
/>
</SelectItem>
{(!hasStore || !hasApiKey || !validApiKey) && (
<SelectItem value="Download">
<ToolbarSelectItem
shortcut={
shortcuts.find((obj) => obj.name === "Download")
?.shortcut!
}
value={"Download"}
icon={"Download"}
dataTestId="download-button-modal"
/>
</SelectItem>
)}
<SelectItem
value={"delete"}
className="focus:bg-red-400/[.20]"

View file

@ -20,8 +20,7 @@ export default function LoginPage(): JSX.Element {
useState<loginInputStateType>(CONTROL_LOGIN_STATE);
const { password, username } = inputState;
const { login, isAuthenticated, setUserData, setIsAdmin } =
useContext(AuthContext);
const { login } = useContext(AuthContext);
const navigate = useNavigate();
const setErrorData = useAlertStore((state) => state.setErrorData);

View file

@ -45,9 +45,9 @@ const ProfilePictureFormComponent = ({
} else {
prev[folder] = [path];
}
setLoading(false);
return prev;
});
setLoading(false);
});
}
})

View file

@ -27,7 +27,7 @@ export default function MessagesPage() {
setSelectedRows,
setSuccessData,
setErrorData,
selectedRows,
selectedRows
);
const { handleUpdate } = useUpdateMessage(setSuccessData, setErrorData);
@ -61,7 +61,7 @@ export default function MessagesPage() {
overlayNoRowsTemplate="No data available"
onSelectionChanged={(event: SelectionChangedEvent) => {
setSelectedRows(
event.api.getSelectedRows().map((row) => row.index),
event.api.getSelectedRows().map((row) => row.index)
);
}}
rowSelection="multiple"

View file

@ -177,6 +177,7 @@ export type VertexBuildTypeAPI = {
timestamp: string;
params: any;
messages: ChatOutputType[] | ChatInputType[];
artifacts: any | ChatOutputType | ChatInputType;
};
export type LogType = {

View file

@ -75,7 +75,7 @@ export type ParameterComponentType = {
info?: string;
proxy?: { field: string; id: string };
showNode?: boolean;
index: number;
index?: string;
onCloseModal?: (close: boolean) => void;
outputName?: string;
outputProxy?: OutputFieldProxyType;
@ -511,7 +511,7 @@ export type ChatInputType = {
isDragging: boolean;
files: FilePreviewType[];
setFiles: (
files: FilePreviewType[] | ((prev: FilePreviewType[]) => FilePreviewType[])
files: FilePreviewType[] | ((prev: FilePreviewType[]) => FilePreviewType[]),
) => void;
chatValue: string;
inputRef: {
@ -614,7 +614,7 @@ export type chatMessagePropsType = {
updateChat: (
chat: ChatMessageType,
message: string,
stream_url?: string
stream_url?: string,
) => void;
};

View file

@ -17,7 +17,7 @@ type BuildVerticesParams = {
onBuildUpdate?: (
data: VertexBuildTypeAPI,
status: BuildStatus,
buildId: string
buildId: string,
) => void; // Replace any with the actual type if it's not any
onBuildComplete?: (allNodesValid: boolean) => void;
onBuildError?: (title, list, idList: VertexLayerElementType[]) => void;
@ -55,7 +55,7 @@ export async function updateVerticesOrder(
startNodeId?: string | null,
stopNodeId?: string | null,
nodes?: Node[],
edges?: Edge[]
edges?: Edge[],
): Promise<{
verticesLayers: VertexLayerElementType[][];
verticesIds: string[];
@ -71,7 +71,7 @@ export async function updateVerticesOrder(
startNodeId,
stopNodeId,
nodes,
edges
edges,
);
} catch (error: any) {
setErrorData({
@ -128,7 +128,7 @@ export async function buildVertices({
startNodeId,
stopNodeId,
nodes,
edges
edges,
);
if (onValidateNodes) {
try {
@ -162,7 +162,6 @@ export async function buildVertices({
const currentLayer =
useFlowStore.getState().verticesBuild?.verticesLayers![currentLayerIndex];
// If there are no more layers, we are done
console.log("currentLayer", currentLayer);
if (!currentLayer) {
if (onBuildComplete) {
const allNodesValid = buildResults.every((result) => result);
@ -191,14 +190,14 @@ export async function buildVertices({
onBuildUpdate(
getInactiveVertexData(element.id),
BuildStatus.INACTIVE,
runId
runId,
);
}
if (element.reference) {
onBuildUpdate(
getInactiveVertexData(element.reference),
BuildStatus.INACTIVE,
runId
runId,
);
}
buildResults.push(false);
@ -224,7 +223,7 @@ export async function buildVertices({
if (stop) {
return;
}
})
}),
);
// Once the current layer is built, move to the next layer
currentLayerIndex += 1;
@ -289,7 +288,10 @@ async function buildVertex({
console.error(error);
onBuildError!(
"Error Building Component",
[(error as AxiosError<any>).response?.data?.detail ?? "Unknown Error"],
[
(error as AxiosError<any>).response?.data?.detail ??
"An unexpected error occurred while building the Component. Please try again.",
],
verticesIds.map((id) => ({ id }))
);
stopBuild();

View file

@ -237,13 +237,13 @@ export function groupByFamily(
const checkBaseClass = (template: InputFieldType) => {
return (
template.type &&
template.show &&
template?.type &&
template?.show &&
((!excludeTypes.has(template.type) &&
baseClassesSet.has(template.type)) ||
(template.input_types &&
template.input_types.some((inputType) =>
baseClassesSet.has(inputType),
(template?.input_types &&
template?.input_types.some((inputType) =>
baseClassesSet.has(inputType)
)))
);
};

View file

@ -24,31 +24,59 @@ test("chat_io_teste", async ({ page }) => {
const jsonContent = readFileSync(
"src/frontend/tests/end-to-end/assets/ChatTest.json",
"utf-8"
"utf-8",
);
await page.getByTestId("blank-flow").click();
await page.waitForTimeout(2000);
await page.waitForTimeout(3000);
await page.getByTestId("extended-disclosure").click();
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("chat output");
await page.waitForTimeout(1000);
// Create the DataTransfer and File
const dataTransfer = await page.evaluateHandle((data) => {
const dt = new DataTransfer();
// Convert the buffer to a hex array
const file = new File([data], "ChatTest.json", {
type: "application/json",
});
dt.items.add(file);
return dt;
}, jsonContent);
await page
.getByTestId("outputsChat Output")
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.getByPlaceholder("Search").click();
await page.getByPlaceholder("Search").fill("chat input");
await page.waitForTimeout(1000);
await page
.getByTestId("inputsChat Input")
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.getByTitle("fit view").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
// Click and hold on the first element
await page
.locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[10]/button/div/div'
)
.hover();
await page.mouse.down();
// Move to the second element
await page
.locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[4]/div/button/div/div'
)
.hover();
// Release the mouse
await page.mouse.up();
// Now dispatch
await page.dispatchEvent(
'//*[@id="react-flow-id"]/div[1]/div[1]/div',
"drop",
{
dataTransfer,
}
);
await page.getByLabel("fit view").click();
await page.getByText("Playground", { exact: true }).click();
await page.getByPlaceholder("Send a message...").click();

View file

@ -58,8 +58,13 @@ test("user must interact with chat with Input/Output", async ({ page }) => {
.fill(
"testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!"
);
await page.getByText("Playground", { exact: true }).last().click();
await page.getByTestId("icon-LucideSend").click();
await page.getByText("Close", { exact: true }).click();
await page.getByText("Chat Input", { exact: true }).click();
await page.getByTestId("advanced-button-modal").click();
await page.getByTestId("showsender_name").click();
await page.getByText("Save Changes", { exact: true }).click();
await page
.getByTestId("popover-anchor-input-sender_name")

View file

@ -40,6 +40,7 @@ test("CodeAreaModalComponent", async ({ page }) => {
await page.getByTitle("zoom out").click();
await page.getByTitle("zoom out").click();
await page.getByTestId("div-generic-node").click();
await page.getByTestId("code-button-modal").click();
const wCode =

View file

@ -71,22 +71,12 @@ test("FloatComponent", async ({ page }) => {
await page.getByTestId("showmirostat").click();
expect(
await page.locator('//*[@id="showmirostat"]').isChecked()
await page.locator('//*[@id="showmirostat"]').isChecked(),
).toBeTruthy();
await page.getByTestId("showmirostat_eta").click();
expect(
await page.locator('//*[@id="showmirostat"]').isChecked()
).toBeTruthy();
await page.getByTestId("showmirostat_eta").click();
expect(
await page.locator('//*[@id="showmirostat"]').isChecked()
).toBeTruthy();
await page.getByTestId("showmirostat_eta").click();
expect(
await page.locator('//*[@id="showmirostat_eta"]').isChecked()
await page.locator('//*[@id="showmirostat_eta"]').isChecked(),
).toBeTruthy();
await page.getByTestId("showmirostat_eta").click();
@ -96,12 +86,12 @@ test("FloatComponent", async ({ page }) => {
await page.getByTestId("showmirostat_tau").click();
expect(
await page.locator('//*[@id="showmirostat_tau"]').isChecked()
await page.locator('//*[@id="showmirostat_tau"]').isChecked(),
).toBeTruthy();
await page.getByTestId("showmirostat_tau").click();
expect(
await page.locator('//*[@id="showmirostat_tau"]').isChecked()
await page.locator('//*[@id="showmirostat_tau"]').isChecked(),
).toBeFalsy();
await page.getByTestId("showmodel").click();
@ -124,22 +114,22 @@ test("FloatComponent", async ({ page }) => {
await page.getByTestId("shownum_thread").click();
expect(
await page.locator('//*[@id="shownum_thread"]').isChecked()
await page.locator('//*[@id="shownum_thread"]').isChecked(),
).toBeTruthy();
await page.getByTestId("shownum_thread").click();
expect(
await page.locator('//*[@id="shownum_thread"]').isChecked()
await page.locator('//*[@id="shownum_thread"]').isChecked(),
).toBeFalsy();
await page.getByTestId("showrepeat_last_n").click();
expect(
await page.locator('//*[@id="showrepeat_last_n"]').isChecked()
await page.locator('//*[@id="showrepeat_last_n"]').isChecked(),
).toBeTruthy();
await page.getByTestId("showrepeat_last_n").click();
expect(
await page.locator('//*[@id="showrepeat_last_n"]').isChecked()
await page.locator('//*[@id="showrepeat_last_n"]').isChecked(),
).toBeFalsy();
await page.getByText("Save Changes", { exact: true }).click();
@ -155,7 +145,7 @@ test("FloatComponent", async ({ page }) => {
// showtemperature
await page.locator('//*[@id="showtemperature"]').click();
expect(
await page.locator('//*[@id="showtemperature"]').isChecked()
await page.locator('//*[@id="showtemperature"]').isChecked(),
).toBeTruthy();
await page.getByText("Save Changes", { exact: true }).click();