Merge remote-tracking branch 'origin/dev' into update_lc

This commit is contained in:
Gabriel Luiz Freitas Almeida 2024-01-24 19:22:22 -03:00
commit 87d2db11ac
44 changed files with 1654 additions and 1098 deletions

View file

@ -23,7 +23,6 @@ import useFlowsManagerStore from "./stores/flowsManagerStore";
import { useTypesStore } from "./stores/typesStore";
export default function App() {
const errorData = useAlertStore((state) => state.errorData);
const errorOpen = useAlertStore((state) => state.errorOpen);
const setErrorOpen = useAlertStore((state) => state.setErrorOpen);

View file

@ -57,6 +57,7 @@ export default function ParameterComponent({
proxy,
showNode,
index = "",
isMinimized,
}: ParameterComponentType): JSX.Element {
const ref = useRef<HTMLDivElement>(null);
const refHtml = useRef<HTMLDivElement & ReactNode>(null);
@ -131,25 +132,24 @@ export default function ParameterComponent({
if (data.node!.template[name].value !== code) {
takeSnapshot();
}
setNode(data.id, (oldNode) => {
let newNode = cloneDeep(oldNode);
newNode.data = {
...newNode.data,
node: newNodeClass,
description: newNodeClass.description ?? data.node!.description,
display_name: newNodeClass.display_name ?? data.node!.display_name,
};
newNode.data.node.template[name].value = code;
return newNode;
});
updateNodeInternals(data.id);
renderTooltips();
};
@ -273,9 +273,11 @@ export default function ParameterComponent({
<Handle
type={left ? "target" : "source"}
position={left ? Position.Left : Position.Right}
key={proxy
? scapedJSONStringfy({ ...id, proxy })
: scapedJSONStringfy(id)}
key={
proxy
? scapedJSONStringfy({ ...id, proxy })
: scapedJSONStringfy(id)
}
id={
proxy
? scapedJSONStringfy({ ...id, proxy })
@ -286,7 +288,8 @@ 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"
"h-3 w-3 rounded-full border-2 bg-background",
isMinimized ? "mt-0" : ""
)}
style={{
borderColor: color,
@ -348,9 +351,11 @@ export default function ParameterComponent({
<Handle
type={left ? "target" : "source"}
position={left ? Position.Left : Position.Right}
key={proxy
? scapedJSONStringfy({ ...id, proxy })
: scapedJSONStringfy(id)}
key={
proxy
? scapedJSONStringfy({ ...id, proxy })
: scapedJSONStringfy(id)
}
id={
proxy
? scapedJSONStringfy({ ...id, proxy })
@ -395,8 +400,8 @@ export default function ParameterComponent({
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={handleOnNewValue}
id={"textarea-" + index}
data-testid={"textarea-" + index}
id={"textarea-" + data.node.template[name].name}
data-testid={"textarea-" + data.node.template[name].name}
/>
) : (
<InputComponent

View file

@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
import { NodeToolbar } from "reactflow";
import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
import ShadTooltip from "../../components/ShadTooltipComponent";
import Tooltip from "../../components/TooltipComponent";
import IconComponent from "../../components/genericIconComponent";
@ -41,7 +41,9 @@ export default function GenericNode({
const [validationStatus, setValidationStatus] =
useState<validationStatusType | null>(null);
const [handles, setHandles] = useState<boolean[] | []>([]);
const [isMinimized, setIsMinimized] = useState<boolean>(false);
let numberOfInputs: boolean[] = [];
const updateNodeInternals = useUpdateNodeInternals();
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
@ -105,6 +107,10 @@ export default function GenericNode({
const nameEditable = data.node?.flow || data.type === "CustomComponent";
useEffect(() => {
updateNodeInternals(data.id);
}, [isMinimized]);
return (
<>
<NodeToolbar>
@ -123,6 +129,7 @@ export default function GenericNode({
}}
numberOfHandles={handles}
showNode={showNode}
setIsMinimized={setIsMinimized}
></NodeToolbarComponent>
</NodeToolbar>
@ -276,6 +283,7 @@ export default function GenericNode({
}
proxy={data.node?.template[templateField].proxy}
showNode={showNode}
isMinimized={isMinimized}
/>
)
)}
@ -302,6 +310,7 @@ export default function GenericNode({
type={data.node?.base_classes.join("|")}
left={false}
showNode={showNode}
isMinimized={isMinimized}
/>
</>
)}
@ -506,6 +515,7 @@ export default function GenericNode({
}
proxy={data.node?.template[templateField].proxy}
showNode={showNode}
isMinimized={isMinimized}
/>
) : (
<></>
@ -549,6 +559,7 @@ export default function GenericNode({
type={data.node?.base_classes.join("|")}
left={false}
showNode={showNode}
isMinimized={isMinimized}
/>
)}
</>

View file

@ -5,7 +5,6 @@ import BuildTrigger from "./buildTrigger";
import ChatTrigger from "./chatTrigger";
import * as _ from "lodash";
import { getBuildStatus } from "../../controllers/API";
import FormModal from "../../modals/formModal";
import useFlowStore from "../../stores/flowStore";
import { NodeType } from "../../types/flow";
@ -32,17 +31,6 @@ export default function Chat({ flow }: ChatType): JSX.Element {
};
}, [isBuilt]);
useEffect(() => {
// Define an async function within the useEffect hook
const fetchBuildStatus = async () => {
const response = await getBuildStatus(flow.id);
setIsBuilt(response.data.built);
};
// Call the async function
fetchBuildStatus();
}, [flow]);
const prevNodesRef = useRef<any[] | undefined>();
const nodes: NodeType[] = useNodes();
useEffect(() => {

View file

@ -35,7 +35,6 @@ import {
convertObjToArray,
convertValuesToNumbers,
hasDuplicateKeys,
unselectAllNodes,
} from "../../utils/reactflowUtils";
import { classNames } from "../../utils/utils";
import DictComponent from "../dictComponent";
@ -54,6 +53,7 @@ export default function CodeTabsComponent({
const [data, setData] = useState(flow ? flow["data"]!["nodes"] : null);
const [openAccordion, setOpenAccordion] = useState<string[]>([]);
const dark = useDarkStore((state) => state.dark);
const unselectAll = useFlowStore((state) => state.unselectAll);
const setNodes = useFlowStore((state) => state.setNodes);
@ -67,12 +67,7 @@ export default function CodeTabsComponent({
useEffect(() => {
if (tweaks && data) {
unselectAllNodes({
data,
updateNodes: (nodes) => {
setNodes(nodes);
},
});
unselectAll();
}
}, []);
@ -593,14 +588,7 @@ export default function CodeTabsComponent({
].type === "prompt" ? (
<div className="mx-auto">
<PromptAreaComponent
readonly={
node.data.node?.flow &&
node.data.node.template[
templateField
].dynamic
? true
: false
}
readonly={true}
editNode={true}
disabled={false}
value={
@ -643,14 +631,7 @@ export default function CodeTabsComponent({
<CodeAreaComponent
disabled={false}
editNode={true}
readonly={
node.data.node?.flow &&
node.data.node.template[
templateField
].dynamic
? true
: false
}
readonly={true}
value={
!node.data.node.template[
templateField

View file

@ -216,8 +216,16 @@ const EditNodeModal = forwardRef(
) : myData.node.template[templateParam]
.multiline ? (
<TextAreaComponent
id={"textarea-edit-" + index}
data-testid={"textarea-edit-" + index}
id={
"textarea-edit-" +
myData.node.template[templateParam]
.name
}
data-testid={
"textarea-edit-" +
myData.node.template[templateParam]
.name
}
disabled={disabled}
editNode={true}
value={
@ -448,9 +456,13 @@ const EditNodeModal = forwardRef(
onChange={(value: string | string[]) => {
handleOnNewValue(value, templateParam);
}}
id={"prompt-area-edit" + index}
id={
"prompt-area-edit-" +
myData.node.template[templateParam].name
}
data-testid={
"modal-prompt-input-" + index
"modal-prompt-input-" +
myData.node.template[templateParam].name
}
/>
</div>

View file

@ -126,7 +126,8 @@ export default function GenericModal({
if (
JSON.stringify(apiReturn.data?.frontend_node) !== JSON.stringify({})
) {
setNodeClass!(apiReturn.data?.frontend_node, inputValue);
if (setNodeClass)
setNodeClass(apiReturn.data?.frontend_node, inputValue);
setModalOpen(closeModal);
setIsEdit(false);
}

View file

@ -9,7 +9,6 @@ import ReactFlow, {
OnMove,
OnSelectionChangeParams,
SelectionDragHandler,
addEdge,
updateEdge,
} from "reactflow";
import GenericNode from "../../../../CustomNodes/GenericNode";
@ -19,13 +18,12 @@ import useFlowStore from "../../../../stores/flowStore";
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
import { useTypesStore } from "../../../../stores/typesStore";
import { APIClassType } from "../../../../types/api";
import { FlowType, NodeType, targetHandleType } from "../../../../types/flow";
import { FlowType, NodeType } from "../../../../types/flow";
import {
generateFlow,
generateNodeFromFlow,
getNodeId,
isValidConnection,
scapeJSONParse,
validateSelection,
} from "../../../../utils/reactflowUtils";
import { getRandomName, isWrappedWithClass } from "../../../../utils/utils";
@ -175,8 +173,8 @@ export default function Page({
useEffect(() => {
return () => {
cleanFlow();
}
}, [])
};
}, []);
const onConnectMod = useCallback(
(params: Connection) => {
@ -332,7 +330,7 @@ export default function Page({
<div className="h-full w-full">
<div className="h-full w-full" ref={reactFlowWrapper}>
{Object.keys(templates).length > 0 &&
Object.keys(types).length > 0 ? (
Object.keys(types).length > 0 ? (
<div id="react-flow-id" className="h-full w-full">
<ReactFlow
nodes={nodes}

View file

@ -4,7 +4,7 @@ import {
Select,
SelectContent,
SelectItem,
SelectTrigger
SelectTrigger,
} from "../../../../../components/ui/select-custom";
import { useDarkStore } from "../../../../../stores/darkStore";
import useFlowsManagerStore from "../../../../../stores/flowsManagerStore";

View file

@ -32,6 +32,7 @@ export default function NodeToolbarComponent({
setShowNode,
numberOfHandles,
showNode,
setIsMinimized,
}: nodeToolbarPropsType): JSX.Element {
const nodeLength = Object.keys(data.node!.template).filter(
(templateField) =>
@ -97,6 +98,10 @@ export default function NodeToolbarComponent({
showconfirmShare,
]);
useEffect(() => {
setIsMinimized(!showNode);
}, [showNode]);
const handleSelectChange = (event) => {
switch (event) {
case "advanced":

View file

@ -201,7 +201,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
.map((node) => ({ ...node, selected: false }))
.concat({ ...newNode, selected: false });
});
set({ nodes: newNodes });
get().setNodes(newNodes);
selection.edges.forEach((edge: Edge) => {
let source = idsMap[edge.source];
@ -245,7 +245,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
newEdges.map((edge) => ({ ...edge, selected: false }))
);
});
set({ edges: newEdges });
get().setEdges(newEdges);
},
setLastCopiedSelection: (newSelection) => {
set({ lastCopiedSelection: newSelection });
@ -265,7 +265,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
},
getFilterEdge: [],
onConnect: (connection) => {
let newEdges: Edge[] = []
let newEdges: Edge[] = [];
get().setEdges((oldEdges) => {
newEdges = addEdge(
{
@ -287,8 +287,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
oldEdges
);
return newEdges;
})
});
useFlowsManagerStore
.getState()
.autoSaveCurrentFlow(
@ -297,6 +296,17 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 }
);
},
unselectAll: () => {
let newNodes = cloneDeep(get().nodes);
newNodes.forEach((node) => {
node.selected = false;
let newEdges = cleanEdges(newNodes, get().edges);
set({
nodes: newNodes,
edges: newEdges,
});
});
},
}));
export default useFlowStore;

View file

@ -43,5 +43,4 @@ export const useTypesStore = create<TypesStoreType>((set, get) => ({
let newChange = typeof change === "function" ? change(get().data) : change;
set({ data: newChange });
},
}));

View file

@ -53,6 +53,7 @@ export type ParameterComponentType = {
showNode?: boolean;
index?: string;
onCloseModal?: (close: boolean) => void;
isMinimized?: boolean;
};
export type InputListComponentType = {
value: string[];
@ -479,6 +480,7 @@ export type nodeToolbarPropsType = {
setShowNode: (boolean: any) => void;
numberOfHandles: boolean[] | [];
showNode: boolean;
setIsMinimized: (boolean: boolean) => void;
};
export type parsedDataType = {

View file

@ -54,4 +54,5 @@ export type FlowStoreType = {
setFilterEdge: (newState) => void;
getFilterEdge: any[];
onConnect: (connection: Connection) => void;
unselectAll: () => void;
};

View file

@ -475,7 +475,7 @@ export function convertArrayToObj(arrayOfObjects) {
export function hasDuplicateKeys(array) {
const keys = {};
// Transforms an empty object into an object array without opening the 'editNode' modal to prevent the flow build from breaking.
if (!Array.isArray(array)) array = [{"": ""}];
if (!Array.isArray(array)) array = [{ "": "" }];
for (const obj of array) {
for (const key in obj) {
if (keys[key]) {

View file

@ -44,7 +44,7 @@ test("PromptTemplateComponent", async ({ page }) => {
await page.getByTestId("genericModalBtnSave").click();
await page.getByTestId("div-textarea-5").click();
await page.getByTestId("div-textarea-prompt").click();
await page.getByTestId("text-area-modal").fill("prompt_value_!@#!@#");
value = await page.getByTestId("text-area-modal").inputValue();
@ -55,7 +55,7 @@ test("PromptTemplateComponent", async ({ page }) => {
await page.getByTestId("genericModalBtnSave").click();
await page.getByTestId("div-textarea-6").click();
await page.getByTestId("div-textarea-prompt1").click();
await page
.getByTestId("text-area-modal")
.fill("prompt_name_test_123123!@#!@#");
@ -77,29 +77,31 @@ test("PromptTemplateComponent", async ({ page }) => {
await page.getByTestId("more-options-modal").click();
await page.getByTestId("edit-button-modal").click();
value = await page.locator('//*[@id="textarea-edit-1"]').inputValue();
value = await page.locator('//*[@id="textarea-edit-prompt"]').inputValue();
if (value != "prompt_value_!@#!@#") {
expect(false).toBeTruthy();
}
value = await page.locator('//*[@id="textarea-edit-2"]').inputValue();
value = await page.locator('//*[@id="textarea-edit-prompt1"]').inputValue();
if (value != "prompt_name_test_123123!@#!@#") {
expect(false).toBeTruthy();
}
value = await page.locator('//*[@id="prompt-area-edit0"]').innerText();
value = await page
.locator('//*[@id="prompt-area-edit-template"]')
.innerText();
if (value != "{prompt} example {prompt1}") {
expect(false).toBeTruthy();
}
await page
.locator('//*[@id="textarea-edit-2"]')
.locator('//*[@id="textarea-edit-prompt1"]')
.fill("prompt_edit_test_12312312321!@#$");
await page
.locator('//*[@id="textarea-edit-1"]')
.locator('//*[@id="textarea-edit-prompt"]')
.fill("prompt_edit_test_44444444444!@#$");
await page.locator('//*[@id="showtemplate"]').click();
@ -141,35 +143,29 @@ test("PromptTemplateComponent", async ({ page }) => {
await page.locator('//*[@id="saveChangesBtn"]').click();
const plusButtonLocator = page.locator('//*[@id="textarea-8"]');
const elementCount = await plusButtonLocator.count();
if (elementCount === 0) {
expect(true).toBeTruthy();
await page.getByTestId("more-options-modal").click();
await page.getByTestId("edit-button-modal").click();
await page.getByTestId("more-options-modal").click();
await page.getByTestId("edit-button-modal").click();
await page.locator('//*[@id="showprompt1"]').click();
expect(await page.locator('//*[@id="showprompt1"]').isChecked()).toBeTruthy();
await page.locator('//*[@id="showprompt1"]').click();
expect(
await page.locator('//*[@id="showprompt1"]').isChecked()
).toBeTruthy();
value = await page.locator('//*[@id="textarea-edit-prompt"]').inputValue();
value = await page.locator('//*[@id="textarea-edit-1"]').inputValue();
if (value != "prompt_edit_test_44444444444!@#$") {
expect(false).toBeTruthy();
}
if (value != "prompt_edit_test_44444444444!@#$") {
expect(false).toBeTruthy();
}
value = await page.locator('//*[@id="textarea-edit-prompt1"]').inputValue();
value = await page.locator('//*[@id="textarea-edit-2"]').inputValue();
if (value != "prompt_edit_test_12312312321!@#$") {
expect(false).toBeTruthy();
}
if (value != "prompt_edit_test_12312312321!@#$") {
expect(false).toBeTruthy();
}
value = await page
.locator('//*[@id="prompt-area-edit-template"]')
.innerText();
value = await page.locator('//*[@id="prompt-area-edit0"]').innerText();
if (value != "{prompt} example {prompt1}") {
expect(false).toBeTruthy();
}
if (value != "{prompt} example {prompt1}") {
expect(false).toBeTruthy();
}
});

View file

@ -67,7 +67,7 @@ test.describe("group node test", () => {
await page.getByRole("button", { name: "Group" }).click();
const textArea = page.getByTestId("div-textarea-2");
const textArea = page.getByTestId("div-textarea-description");
const elementCountText = await textArea.count();
if (elementCountText > 0) {
expect(true).toBeTruthy();

View file

@ -26,8 +26,7 @@ test("NestedComponent", async ({ page }) => {
.getByTestId("vectorstoresPinecone")
.first()
.dragTo(page.locator('//*[@id="react-flow-id"]'));
await page.mouse.up();
await page.mouse.down();
await page.click('//*[@id="react-flow-id"]');
await page.getByTestId("more-options-modal").click();
await page.getByTestId("edit-button-modal").click();

View file

@ -74,7 +74,7 @@ test.describe("save component tests", () => {
await page.getByRole("button", { name: "Group" }).click();
let textArea = page.getByTestId("div-textarea-2");
let textArea = page.getByTestId("div-textarea-description");
let elementCountText = await textArea.count();
if (elementCountText > 0) {
expect(true).toBeTruthy();
@ -102,7 +102,7 @@ test.describe("save component tests", () => {
await page.mouse.up();
await page.mouse.down();
textArea = page.getByTestId("div-textarea-2");
textArea = page.getByTestId("div-textarea-description");
elementCountText = await textArea.count();
if (elementCountText > 0) {
expect(true).toBeTruthy();