diff --git a/src/backend/langflow/api/v1/login.py b/src/backend/langflow/api/v1/login.py
index 9021b40b6..b8fa48577 100644
--- a/src/backend/langflow/api/v1/login.py
+++ b/src/backend/langflow/api/v1/login.py
@@ -1,4 +1,4 @@
-from fastapi import APIRouter, Depends, HTTPException, status
+from fastapi import Request, Response, APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from sqlmodel import Session
@@ -16,6 +16,7 @@ router = APIRouter(tags=["Login"])
@router.post("/login", response_model=Token)
async def login_to_get_access_token(
+ response: Response,
form_data: OAuth2PasswordRequestForm = Depends(),
db: Session = Depends(get_session),
# _: Session = Depends(get_current_active_user)
@@ -31,7 +32,10 @@ async def login_to_get_access_token(
) from exc
if user:
- return create_user_tokens(user_id=user.id, db=db, update_last_login=True)
+ tokens = create_user_tokens(user_id=user.id, db=db, update_last_login=True)
+ response.set_cookie("refresh_token_lf", tokens["refresh_token"], httponly=True, secure=True, samesite="strict")
+ response.set_cookie("access_token_lf", tokens["access_token"], httponly=False, secure=True, samesite="strict")
+ return tokens
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
@@ -41,9 +45,13 @@ async def login_to_get_access_token(
@router.get("/auto_login")
-async def auto_login(db: Session = Depends(get_session), settings_service=Depends(get_settings_service)):
+async def auto_login(
+ response: Response, db: Session = Depends(get_session), settings_service=Depends(get_settings_service)
+):
if settings_service.auth_settings.AUTO_LOGIN:
- return create_user_longterm_token(db)
+ tokens = create_user_longterm_token(db)
+ response.set_cookie("access_token_lf", tokens["access_token"], httponly=False, secure=True, samesite="strict")
+ return tokens
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
@@ -55,12 +63,23 @@ async def auto_login(db: Session = Depends(get_session), settings_service=Depend
@router.post("/refresh")
-async def refresh_token(token: str):
+async def refresh_token(request: Request, response: Response):
+ token = request.cookies.get("refresh_token_lf")
if token:
- return create_refresh_token(token)
+ tokens = create_refresh_token(token)
+ response.set_cookie("refresh_token_lf", tokens["refresh_token"], httponly=True, secure=True, samesite="strict")
+ response.set_cookie("access_token_lf", tokens["access_token"], httponly=False, secure=True, samesite="strict")
+ return tokens
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid refresh token",
headers={"WWW-Authenticate": "Bearer"},
)
+
+
+@router.post("/logout")
+async def logout(response: Response):
+ response.delete_cookie("refresh_token_lf")
+ response.delete_cookie("access_token_lf")
+ return {"message": "Logout successful"}
diff --git a/src/backend/langflow/components/retrievers/VectaraSelfQueryRetriver.py b/src/backend/langflow/components/retrievers/VectaraSelfQueryRetriver.py
index bc8d78909..26afd765c 100644
--- a/src/backend/langflow/components/retrievers/VectaraSelfQueryRetriver.py
+++ b/src/backend/langflow/components/retrievers/VectaraSelfQueryRetriver.py
@@ -15,29 +15,21 @@ class VectaraSelfQueryRetriverComponent(CustomComponent):
display_name: str = "Vectara Self Query Retriever for Vectara Vector Store"
description: str = "Implementation of Vectara Self Query Retriever"
- documentation = (
- "https://python.langchain.com/docs/integrations/retrievers/self_query/vectara_self_query"
- )
+ documentation = "https://python.langchain.com/docs/integrations/retrievers/self_query/vectara_self_query"
beta = True
field_config = {
"code": {"show": True},
- "vectorstore": {
- "display_name": "Vector Store",
- "info": "Input Vectara Vectore Store"
- },
- "llm": {
- "display_name": "LLM",
- "info": "For self query retriever"
- },
- "document_content_description":{
- "display_name": "Document Content Description",
+ "vectorstore": {"display_name": "Vector Store", "info": "Input Vectara Vectore Store"},
+ "llm": {"display_name": "LLM", "info": "For self query retriever"},
+ "document_content_description": {
+ "display_name": "Document Content Description",
"info": "For self query retriever",
- },
+ },
"metadata_field_info": {
- "display_name": "Metadata Field Info",
- "info": "Each metadata field info is a string in the form of key value pair dictionary containing additional search metadata.\nExample input: {\"name\":\"speech\",\"description\":\"what name of the speech\",\"type\":\"string or list[string]\"}.\nThe keys should remain constant(name, description, type)",
- },
+ "display_name": "Metadata Field Info",
+ "info": 'Each metadata field info is a string in the form of key value pair dictionary containing additional search metadata.\nExample input: {"name":"speech","description":"what name of the speech","type":"string or list[string]"}.\nThe keys should remain constant(name, description, type)',
+ },
}
def build(
@@ -47,24 +39,19 @@ class VectaraSelfQueryRetriverComponent(CustomComponent):
llm: BaseLanguageModel,
metadata_field_info: List[str],
) -> BaseRetriever:
-
metadata_field_obj = []
for meta in metadata_field_info:
meta_obj = json.loads(meta)
- if 'name' not in meta_obj or 'description' not in meta_obj or 'type' not in meta_obj :
- raise Exception('Incorrect metadata field info format.')
+ if "name" not in meta_obj or "description" not in meta_obj or "type" not in meta_obj:
+ raise Exception("Incorrect metadata field info format.")
attribute_info = AttributeInfo(
- name = meta_obj['name'],
- description = meta_obj['description'],
- type = meta_obj['type'],
+ name=meta_obj["name"],
+ description=meta_obj["description"],
+ type=meta_obj["type"],
)
metadata_field_obj.append(attribute_info)
return SelfQueryRetriever.from_llm(
- llm,
- vectorstore,
- document_content_description,
- metadata_field_obj,
- verbose=True
- )
\ No newline at end of file
+ llm, vectorstore, document_content_description, metadata_field_obj, verbose=True
+ )
diff --git a/src/frontend/harFiles/backend_12112023.har b/src/frontend/harFiles/backend_12112023.har
index 5021c7da5..63dbde94a 100644
--- a/src/frontend/harFiles/backend_12112023.har
+++ b/src/frontend/harFiles/backend_12112023.har
@@ -284,7 +284,7 @@
{ "name": "Accept-Language", "value": "en-US,en;q=0.9" },
{ "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" },
{ "name": "Connection", "value": "keep-alive" },
- { "name": "Cookie", "value": "access_tkn_lflw=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
+ { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
{ "name": "Host", "value": "localhost:3000" },
{ "name": "Referer", "value": "http://localhost:3000/flows" },
{ "name": "Sec-Fetch-Dest", "value": "empty" },
@@ -338,7 +338,7 @@
{ "name": "Accept-Language", "value": "en-US,en;q=0.9" },
{ "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" },
{ "name": "Connection", "value": "keep-alive" },
- { "name": "Cookie", "value": "access_tkn_lflw=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
+ { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
{ "name": "Host", "value": "localhost:3000" },
{ "name": "Referer", "value": "http://localhost:3000/flows" },
{ "name": "Sec-Fetch-Dest", "value": "empty" },
@@ -392,7 +392,7 @@
{ "name": "Accept-Language", "value": "en-US,en;q=0.9" },
{ "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" },
{ "name": "Connection", "value": "keep-alive" },
- { "name": "Cookie", "value": "access_tkn_lflw=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
+ { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
{ "name": "Host", "value": "localhost:3000" },
{ "name": "Referer", "value": "http://localhost:3000/flows" },
{ "name": "Sec-Fetch-Dest", "value": "empty" },
@@ -446,7 +446,7 @@
{ "name": "Accept-Language", "value": "en-US,en;q=0.9" },
{ "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" },
{ "name": "Connection", "value": "keep-alive" },
- { "name": "Cookie", "value": "access_tkn_lflw=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
+ { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
{ "name": "Host", "value": "localhost:3000" },
{ "name": "Referer", "value": "http://localhost:3000/flow/2920dde2-5c24-4fe0-9c06-ef86b5a16a99" },
{ "name": "Sec-Fetch-Dest", "value": "empty" },
@@ -500,7 +500,7 @@
{ "name": "Accept-Language", "value": "en-US,en;q=0.9" },
{ "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" },
{ "name": "Connection", "value": "keep-alive" },
- { "name": "Cookie", "value": "access_tkn_lflw=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
+ { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
{ "name": "Host", "value": "localhost:3000" },
{ "name": "Referer", "value": "http://localhost:3000/flow/2920dde2-5c24-4fe0-9c06-ef86b5a16a99" },
{ "name": "Sec-Fetch-Dest", "value": "empty" },
@@ -554,7 +554,7 @@
{ "name": "Accept-Language", "value": "en-US,en;q=0.9" },
{ "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" },
{ "name": "Connection", "value": "keep-alive" },
- { "name": "Cookie", "value": "access_tkn_lflw=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
+ { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" },
{ "name": "Host", "value": "localhost:3000" },
{ "name": "Referer", "value": "http://localhost:3000/flow/2920dde2-5c24-4fe0-9c06-ef86b5a16a99" },
{ "name": "Sec-Fetch-Dest", "value": "empty" },
diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json
index 94319da10..8ef4b20ce 100644
--- a/src/frontend/package-lock.json
+++ b/src/frontend/package-lock.json
@@ -13,6 +13,7 @@
"@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.0.18",
"@mui/material": "^5.14.7",
+ "@preact/signals-react": "^2.0.0",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.4",
@@ -71,7 +72,8 @@
"tailwindcss-animate": "^1.0.7",
"uuid": "^9.0.0",
"vite-plugin-svgr": "^3.2.0",
- "web-vitals": "^2.1.4"
+ "web-vitals": "^2.1.4",
+ "zustand": "^4.4.7"
},
"devDependencies": {
"@playwright/test": "^1.38.0",
@@ -1465,6 +1467,31 @@
"url": "https://opencollective.com/popperjs"
}
},
+ "node_modules/@preact/signals-core": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.5.1.tgz",
+ "integrity": "sha512-dE6f+WCX5ZUDwXzUIWNMhhglmuLpqJhuy3X3xHrhZYI0Hm2LyQwOu0l9mdPiWrVNsE+Q7txOnJPgtIqHCYoBVA==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
+ },
+ "node_modules/@preact/signals-react": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@preact/signals-react/-/signals-react-2.0.0.tgz",
+ "integrity": "sha512-tMVi2SXFXlojaiPNWa8dlYaidR/XvEgMSp+iymKJgMssBM/QVtUQrodKZek1BJju+dkVHiyeuQHmkuLOI9oyNw==",
+ "dependencies": {
+ "@preact/signals-core": "^1.5.1",
+ "use-sync-external-store": "^1.2.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ },
+ "peerDependencies": {
+ "react": "^16.14.0 || 17.x || 18.x"
+ }
+ },
"node_modules/@radix-ui/number": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz",
@@ -11719,9 +11746,9 @@
}
},
"node_modules/zustand": {
- "version": "4.4.6",
- "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.6.tgz",
- "integrity": "sha512-Rb16eW55gqL4W2XZpJh0fnrATxYEG3Apl2gfHTyDSE965x/zxslTikpNch0JgNjJA9zK6gEFW8Fl6d1rTZaqgg==",
+ "version": "4.4.7",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.7.tgz",
+ "integrity": "sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==",
"dependencies": {
"use-sync-external-store": "1.2.0"
},
@@ -12606,6 +12633,20 @@
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
},
+ "@preact/signals-core": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.5.1.tgz",
+ "integrity": "sha512-dE6f+WCX5ZUDwXzUIWNMhhglmuLpqJhuy3X3xHrhZYI0Hm2LyQwOu0l9mdPiWrVNsE+Q7txOnJPgtIqHCYoBVA=="
+ },
+ "@preact/signals-react": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@preact/signals-react/-/signals-react-2.0.0.tgz",
+ "integrity": "sha512-tMVi2SXFXlojaiPNWa8dlYaidR/XvEgMSp+iymKJgMssBM/QVtUQrodKZek1BJju+dkVHiyeuQHmkuLOI9oyNw==",
+ "requires": {
+ "@preact/signals-core": "^1.5.1",
+ "use-sync-external-store": "^1.2.0"
+ }
+ },
"@radix-ui/number": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz",
@@ -19291,9 +19332,9 @@
"integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg=="
},
"zustand": {
- "version": "4.4.6",
- "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.6.tgz",
- "integrity": "sha512-Rb16eW55gqL4W2XZpJh0fnrATxYEG3Apl2gfHTyDSE965x/zxslTikpNch0JgNjJA9zK6gEFW8Fl6d1rTZaqgg==",
+ "version": "4.4.7",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.7.tgz",
+ "integrity": "sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==",
"requires": {
"use-sync-external-store": "1.2.0"
}
diff --git a/src/frontend/package.json b/src/frontend/package.json
index d411b70eb..015b6d9a2 100644
--- a/src/frontend/package.json
+++ b/src/frontend/package.json
@@ -8,6 +8,7 @@
"@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.0.18",
"@mui/material": "^5.14.7",
+ "@preact/signals-react": "^2.0.0",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.4",
@@ -66,7 +67,8 @@
"tailwindcss-animate": "^1.0.7",
"uuid": "^9.0.0",
"vite-plugin-svgr": "^3.2.0",
- "web-vitals": "^2.1.4"
+ "web-vitals": "^2.1.4",
+ "zustand": "^4.4.7"
},
"scripts": {
"dev:docker": "vite --host 0.0.0.0",
diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx
index 0898ad58d..3b88ee14c 100644
--- a/src/frontend/src/App.tsx
+++ b/src/frontend/src/App.tsx
@@ -1,6 +1,5 @@
import _ from "lodash";
import { useContext, useEffect, useState } from "react";
-import { useLocation, useNavigate } from "react-router-dom";
import "reactflow/dist/style.css";
import "./App.css";
@@ -15,37 +14,27 @@ import {
FETCH_ERROR_DESCRIPION,
FETCH_ERROR_MESSAGE,
} from "./constants/constants";
-import { alertContext } from "./contexts/alertContext";
-import { FlowsContext } from "./contexts/flowsContext";
-import { locationContext } from "./contexts/locationContext";
-import { typesContext } from "./contexts/typesContext";
+import { AuthContext } from "./contexts/authContext";
+import { getHealth } from "./controllers/API";
import Router from "./routes";
+import useAlertStore from "./stores/alertStore";
+import { useDarkStore } from "./stores/darkStore";
+import useFlowsManagerStore from "./stores/flowsManagerStore";
+import { useTypesStore } from "./stores/typesStore";
export default function App() {
- let { setCurrent, setShowSideBar, setIsStackedOpen } =
- useContext(locationContext);
- let location = useLocation();
- useEffect(() => {
- setCurrent(location.pathname.replace(/\/$/g, "").split("/"));
- setShowSideBar(true);
- setIsStackedOpen(true);
- }, [location.pathname, setCurrent, setIsStackedOpen, setShowSideBar]);
- const { hardReset } = useContext(FlowsContext);
- const {
- errorData,
- errorOpen,
- setErrorOpen,
- noticeData,
- noticeOpen,
- setNoticeOpen,
- successData,
- successOpen,
- setSuccessOpen,
- loading,
- } = useContext(alertContext);
- const navigate = useNavigate();
- const { fetchError } = useContext(typesContext);
+ const errorData = useAlertStore((state) => state.errorData);
+ const errorOpen = useAlertStore((state) => state.errorOpen);
+ const setErrorOpen = useAlertStore((state) => state.setErrorOpen);
+ const noticeData = useAlertStore((state) => state.noticeData);
+ const noticeOpen = useAlertStore((state) => state.noticeOpen);
+ const setNoticeOpen = useAlertStore((state) => state.setNoticeOpen);
+ const successData = useAlertStore((state) => state.successData);
+ const successOpen = useAlertStore((state) => state.successOpen);
+ const setSuccessOpen = useAlertStore((state) => state.setSuccessOpen);
+ const loading = useAlertStore((state) => state.loading);
+ const [fetchError, setFetchError] = useState(false);
// Initialize state variable for the list of alerts
const [alertsList, setAlertsList] = useState<
@@ -131,28 +120,60 @@ export default function App() {
);
};
+ const { isAuthenticated } = useContext(AuthContext);
+ const refreshFlows = useFlowsManagerStore((state) => state.refreshFlows);
+ const getTypes = useTypesStore((state) => state.getTypes);
+ const refreshVersion = useDarkStore((state) => state.refreshVersion);
+ const refreshStars = useDarkStore((state) => state.refreshStars);
+
+ useEffect(() => {
+ refreshStars();
+ refreshVersion();
+
+ // If the user is authenticated, fetch the types. This code is important to check if the user is auth because of the execution order of the useEffect hooks.
+ if (isAuthenticated === true) {
+ // get data from db
+ getTypes().then(() => {
+ refreshFlows();
+ });
+ }
+ }, [isAuthenticated]);
+
+ useEffect(() => {
+ // Timer to call getHealth every 5 seconds
+ const timer = setInterval(() => {
+ getHealth()
+ .then(() => {
+ if (fetchError) setFetchError(false);
+ })
+ .catch(() => {
+ setFetchError(true);
+ });
+ }, 5000);
+
+ // Clean up the timer on component unmount
+ return () => {
+ clearInterval(timer);
+ };
+ }, []);
+
return (
//need parent component with width and height
{
- window.localStorage.removeItem("tabsData");
- window.localStorage.clear();
- hardReset();
- window.location.href = window.location.href;
+ // any reset function
}}
FallbackComponent={CrashErrorComponent}
>
- {loading ? (
+ {fetchError ? (
+
+ ) : loading ? (
- {fetchError ? (
-
- ) : (
-
- )}
+
) : (
<>
diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx
index 4c81e29a5..a76a15d17 100644
--- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx
+++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx
@@ -1,12 +1,6 @@
import { cloneDeep } from "lodash";
-import React, {
- ReactNode,
- useContext,
- useEffect,
- useRef,
- useState,
-} from "react";
-import { Handle, Position, useUpdateNodeInternals } from "reactflow";
+import React, { ReactNode, useEffect, useRef, useState } from "react";
+import { Handle, Position } from "reactflow";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
import CodeAreaComponent from "../../../../components/codeAreaComponent";
import DictComponent from "../../../../components/dictComponent";
@@ -26,16 +20,15 @@ import {
LANGFLOW_SUPPORTED_TYPES,
TOOLTIP_EMPTY,
} from "../../../../constants/constants";
-import { alertContext } from "../../../../contexts/alertContext";
-import { FlowsContext } from "../../../../contexts/flowsContext";
-import { typesContext } from "../../../../contexts/typesContext";
-import { undoRedoContext } from "../../../../contexts/undoRedoContext";
import { postCustomComponentUpdate } from "../../../../controllers/API";
+import useAlertStore from "../../../../stores/alertStore";
+import useFlowStore from "../../../../stores/flowStore";
+import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
+import { useTypesStore } from "../../../../stores/typesStore";
import { APIClassType } from "../../../../types/api";
import { ParameterComponentType } from "../../../../types/components";
import { NodeDataType } from "../../../../types/flow";
import {
- cleanEdges,
convertObjToArray,
convertValuesToNumbers,
hasDuplicateKeys,
@@ -68,47 +61,27 @@ export default function ParameterComponent({
const ref = useRef(null);
const refHtml = useRef(null);
const infoHtml = useRef(null);
- const { setErrorData, modalContextOpen } = useContext(alertContext);
- const updateNodeInternals = useUpdateNodeInternals();
- const [position, setPosition] = useState(0);
- const { setTabsState, tabId, flows, tabsState, updateFlow } =
- useContext(FlowsContext);
+ const setErrorData = useAlertStore((state) => state.setErrorData);
+ const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
+ const nodes = useFlowStore((state) => state.nodes);
+ const edges = useFlowStore((state) => state.edges);
+ const setNode = useFlowStore((state) => state.setNode);
- const [dataRef, setDataRef] = useState(data);
-
- const flow = flows.find((flow) => flow.id === tabId)?.data?.nodes ?? null;
-
- // Update component position
- useEffect(() => {
- if (ref.current && ref.current.offsetTop && ref.current.clientHeight) {
- setPosition(ref.current.offsetTop + ref.current.clientHeight / 2);
- updateNodeInternals(data.id);
- }
- }, [data.id, ref, ref.current, ref.current?.offsetTop, updateNodeInternals]);
-
- useEffect(() => {
- updateNodeInternals(data.id);
- }, [data.id, position, updateNodeInternals]);
+ const flow = currentFlow?.data?.nodes ?? null;
const groupedEdge = useRef(null);
- useEffect(() => {
- setDataRef(data);
- }, [modalContextOpen]);
+ const setFilterEdge = useTypesStore((state) => state.setFilterEdge);
- const { reactFlowInstance, setFilterEdge } = useContext(typesContext);
let disabled =
- reactFlowInstance
- ?.getEdges()
- .some(
- (edge) =>
- edge.targetHandle ===
- scapedJSONStringfy(proxy ? { ...id, proxy } : id)
- ) ?? false;
+ edges.some(
+ (edge) =>
+ edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id)
+ ) ?? false;
- const { data: myData } = useContext(typesContext);
+ const myData = useTypesStore((state) => state.data);
- const { takeSnapshot } = useContext(undoRedoContext);
+ const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
const handleUpdateValues = async (name: string, data: NodeDataType) => {
const code = data.node?.template["code"]?.value;
@@ -133,68 +106,46 @@ export default function ParameterComponent({
if (data.node!.template[name].value !== newValue) {
takeSnapshot();
}
- data.node!.template[name].value = newValue;
- updateNodeInternals(data.id);
- setDataRef((old) => {
- let newData = cloneDeep(old);
- newData.node!.template[name].value = newValue;
- return newData;
+ data.node!.template[name].value = newValue; // necessary to enable ctrl+z inside the input
+
+ setNode(data.id, (oldNode) => {
+ let newNode = cloneDeep(oldNode);
+
+ newNode.data = {
+ ...newNode.data,
+ };
+
+ newNode.data.node.template[name].value = newValue;
+
+ return newNode;
});
- // Set state to pending
- //@ts-ignore
- if (data.node!.template[name].value !== newValue) {
- const tabs = cloneDeep(tabsState);
- tabs[tabId].isPending = false;
- tabs[tabId].formKeysData = tabsState[tabId].formKeysData;
- setTabsState({
- ...tabs,
- });
- }
renderTooltips();
};
const handleNodeClass = (newNodeClass: APIClassType, code?: string): void => {
if (!data.node) return;
- if (data.node!.template[name].value !== newNodeClass.template[name].value) {
+ if (data.node!.template[name].value !== code) {
takeSnapshot();
}
- data.node! = {
- ...newNodeClass,
- description: newNodeClass.description ?? data.node!.description,
- display_name: newNodeClass.display_name ?? data.node!.display_name,
- };
- data.node!.template[name].value = code;
- updateNodeInternals(data.id);
- // Set state to pending
- //@ts-ignore
- if (data.node!.template[name].value !== code) {
- const tabs = cloneDeep(tabsState);
- tabs[tabId].isPending = false;
- tabs[tabId].formKeysData = tabsState[tabId].formKeysData;
- setTabsState({
- ...tabs,
- });
- }
+
+ 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;
+ });
+
renderTooltips();
- let flow = flows.find((flow) => flow.id === tabId);
- setTimeout(() => {
- //timeout necessary because ReactFlow updates are not async
- if (reactFlowInstance && flow && flow.data) {
- cleanEdges({
- flow: {
- edges: flow.data!.edges,
- nodes: flow.data!.nodes,
- },
- updateEdge: (edge) => {
- reactFlowInstance.setEdges(edge);
- updateNodeInternals(data.id);
- },
- });
- updateFlow(flow);
- }
- }, 50);
};
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
@@ -323,7 +274,7 @@ export default function ParameterComponent({
: scapedJSONStringfy(id)
}
isValidConnection={(connection) =>
- isValidConnection(connection, reactFlowInstance!)
+ isValidConnection(connection, nodes, edges)
}
className={classNames(
left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ",
@@ -331,7 +282,6 @@ export default function ParameterComponent({
)}
style={{
borderColor: color,
- top: position,
}}
onClick={() => {
setFilterEdge(groupedEdge.current);
@@ -344,7 +294,7 @@ export default function ParameterComponent({
) : (
<>
- isValidConnection(connection, reactFlowInstance!)
+ isValidConnection(connection, nodes, edges)
}
className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ",
@@ -404,7 +354,6 @@ export default function ParameterComponent({
)}
style={{
borderColor: color,
- top: position,
}}
onClick={() => {
setFilterEdge(groupedEdge.current);
@@ -454,9 +403,7 @@ export default function ParameterComponent({
id={"toggle-" + index}
disabled={disabled}
enabled={data.node?.template[name].value ?? false}
- setEnabled={(isEnabled) => {
- handleOnNewValue(isEnabled);
- }}
+ setEnabled={handleOnNewValue}
size="large"
/>
@@ -558,10 +505,7 @@ export default function ParameterComponent({
}
: data.node!.template[name].value
}
- onChange={(newValue) => {
- data.node!.template[name].value = newValue;
- handleOnNewValue(newValue);
- }}
+ onChange={handleOnNewValue}
id="div-dict-input"
/>
@@ -571,15 +515,14 @@ export default function ParameterComponent({
disabled={disabled}
editNode={false}
value={
- dataRef.node!.template[name].value?.length === 0 ||
- !dataRef.node!.template[name].value
+ data.node!.template[name].value?.length === 0 ||
+ !data.node!.template[name].value
? [{ "": "" }]
- : convertObjToArray(dataRef.node!.template[name].value)
+ : convertObjToArray(data.node!.template[name].value)
}
duplicateKey={errorDuplicateKey}
onChange={(newValue) => {
const valueToNumbers = convertValuesToNumbers(newValue);
- data.node!.template[name].value = valueToNumbers;
setErrorDuplicateKey(hasDuplicateKeys(valueToNumbers));
handleOnNewValue(valueToNumbers);
}}
diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx
index ca92a74cf..30110fdfe 100644
--- a/src/frontend/src/CustomNodes/GenericNode/index.tsx
+++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx
@@ -1,17 +1,15 @@
-import { useContext, useEffect, useState } from "react";
-import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
+import { useEffect, useState } from "react";
+import { NodeToolbar } from "reactflow";
import ShadTooltip from "../../components/ShadTooltipComponent";
import Tooltip from "../../components/TooltipComponent";
import IconComponent from "../../components/genericIconComponent";
import InputComponent from "../../components/inputComponent";
import { Textarea } from "../../components/ui/textarea";
import { priorityFields } from "../../constants/constants";
-import { useSSE } from "../../contexts/SSEContext";
-import { alertContext } from "../../contexts/alertContext";
-import { FlowsContext } from "../../contexts/flowsContext";
-import { typesContext } from "../../contexts/typesContext";
-import { undoRedoContext } from "../../contexts/undoRedoContext";
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
+import useFlowStore from "../../stores/flowStore";
+import useFlowsManagerStore from "../../stores/flowsManagerStore";
+import { useTypesStore } from "../../stores/typesStore";
import { validationStatusType } from "../../types/components";
import { NodeDataType } from "../../types/flow";
import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils";
@@ -30,11 +28,9 @@ export default function GenericNode({
xPos: number;
yPos: number;
}): JSX.Element {
- const { updateFlow, flows, tabId, saveCurrentFlow } =
- useContext(FlowsContext);
- const updateNodeInternals = useUpdateNodeInternals();
- const { types, deleteNode, reactFlowInstance, setFilterEdge, getFilterEdge } =
- useContext(typesContext);
+ const types = useTypesStore((state) => state.types);
+ const deleteNode = useFlowStore((state) => state.deleteNode);
+ const setNode = useFlowStore((state) => state.setNode);
const name = nodeIconsLucide[data.type] ? data.type : types[data.type];
const [inputName, setInputName] = useState(false);
const [nodeName, setNodeName] = useState(data.node!.display_name);
@@ -46,9 +42,8 @@ export default function GenericNode({
useState(null);
const [handles, setHandles] = useState([]);
let numberOfInputs: boolean[] = [];
- const { modalContextOpen } = useContext(alertContext);
- const { takeSnapshot } = useContext(undoRedoContext);
+ const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
function countHandles(): void {
numberOfInputs = Object.keys(data.node!.template)
@@ -84,7 +79,8 @@ export default function GenericNode({
}, [data, data.node]);
// State for outline color
- const { sseData, isBuilding } = useSSE();
+ const sseData = useFlowStore((state) => state.sseData);
+ const isBuilding = useFlowStore((state) => state.isBuilding);
useEffect(() => {
setNodeDescription(data.node!.description);
@@ -118,10 +114,12 @@ export default function GenericNode({
deleteNode={(id) => {
takeSnapshot();
deleteNode(id);
- saveCurrentFlow();
}}
setShowNode={(show: boolean) => {
- data.showNode = show;
+ setNode(data.id, (old) => ({
+ ...old,
+ data: { ...old.data, showNode: show },
+ }));
}}
numberOfHandles={handles}
showNode={showNode}
@@ -173,8 +171,16 @@ export default function GenericNode({
setInputName(false);
if (nodeName.trim() !== "") {
setNodeName(nodeName);
- data.node!.display_name = nodeName;
- updateNodeInternals(data.id);
+ setNode(data.id, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ node: {
+ ...old.data.node,
+ display_name: nodeName,
+ },
+ },
+ }));
} else {
setNodeName(data.node!.display_name);
}
@@ -380,8 +386,16 @@ export default function GenericNode({
onBlur={() => {
setInputDescription(false);
setNodeDescription(nodeDescription);
- data.node!.description = nodeDescription;
- updateNodeInternals(data.id);
+ setNode(data.id, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ node: {
+ ...old.data.node,
+ description: nodeDescription,
+ },
+ },
+ }));
}}
value={nodeDescription}
onChange={(e) => setNodeDescription(e.target.value)}
@@ -395,8 +409,16 @@ export default function GenericNode({
) {
setInputDescription(false);
setNodeDescription(nodeDescription);
- data.node!.description = nodeDescription;
- updateNodeInternals(data.id);
+ setNode(data.id, (old) => ({
+ ...old,
+ data: {
+ ...old.data,
+ node: {
+ ...old.data.node,
+ description: nodeDescription,
+ },
+ },
+ }));
}
}}
/>
diff --git a/src/frontend/src/alerts/alertDropDown/index.tsx b/src/frontend/src/alerts/alertDropDown/index.tsx
index 92d9df46f..967d82174 100644
--- a/src/frontend/src/alerts/alertDropDown/index.tsx
+++ b/src/frontend/src/alerts/alertDropDown/index.tsx
@@ -1,23 +1,27 @@
-import { useContext, useState } from "react";
+import { useState } from "react";
import IconComponent from "../../components/genericIconComponent";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "../../components/ui/popover";
-import { alertContext } from "../../contexts/alertContext";
+import useAlertStore from "../../stores/alertStore";
import { AlertDropdownType } from "../../types/alerts";
import SingleAlert from "./components/singleAlertComponent";
export default function AlertDropdown({
children,
}: AlertDropdownType): JSX.Element {
- const {
- notificationList,
- clearNotificationList,
- removeFromNotificationList,
- setNotificationCenter,
- } = useContext(alertContext);
+ const notificationList = useAlertStore((state) => state.notificationList);
+ const clearNotificationList = useAlertStore(
+ (state) => state.clearNotificationList
+ );
+ const removeFromNotificationList = useAlertStore(
+ (state) => state.removeFromNotificationList
+ );
+ const setNotificationCenter = useAlertStore(
+ (state) => state.setNotificationCenter
+ );
const [open, setOpen] = useState(false);
diff --git a/src/frontend/src/components/authAdminGuard/index.tsx b/src/frontend/src/components/authAdminGuard/index.tsx
index 724d39f5a..96c404af3 100644
--- a/src/frontend/src/components/authAdminGuard/index.tsx
+++ b/src/frontend/src/components/authAdminGuard/index.tsx
@@ -1,30 +1,16 @@
-import { useContext, useEffect } from "react";
+import { useContext } from "react";
import { Navigate } from "react-router-dom";
import { AuthContext } from "../../contexts/authContext";
export const ProtectedAdminRoute = ({ children }) => {
- const {
- isAdmin,
- isAuthenticated,
- logout,
- getAuthentication,
- userData,
- autoLogin,
- } = useContext(AuthContext);
- useEffect(() => {
- if (!isAuthenticated && !getAuthentication()) {
- window.location.replace("/login");
- logout();
- }
- }, [isAuthenticated, getAuthentication, logout, userData]);
+ const { isAdmin, isAuthenticated, logout, userData, autoLogin } =
+ useContext(AuthContext);
- if (!isAuthenticated && !getAuthentication()) {
- return ;
- }
-
- if ((userData && !isAdmin) || autoLogin) {
+ if (!isAuthenticated) {
+ logout();
+ } else if ((userData && !isAdmin) || autoLogin) {
return ;
+ } else {
+ return children;
}
-
- return children;
};
diff --git a/src/frontend/src/components/authGuard/index.tsx b/src/frontend/src/components/authGuard/index.tsx
index 9b21a1c9f..8450248a9 100644
--- a/src/frontend/src/components/authGuard/index.tsx
+++ b/src/frontend/src/components/authGuard/index.tsx
@@ -1,14 +1,11 @@
import { useContext } from "react";
-import { Navigate } from "react-router-dom";
import { AuthContext } from "../../contexts/authContext";
export const ProtectedRoute = ({ children }) => {
- const { isAuthenticated, logout, getAuthentication } =
- useContext(AuthContext);
- if (!isAuthenticated && !getAuthentication()) {
+ const { isAuthenticated, logout } = useContext(AuthContext);
+ if (!isAuthenticated) {
logout();
- return ;
+ } else {
+ return children;
}
-
- return children;
};
diff --git a/src/frontend/src/components/authLoginGuard/index.tsx b/src/frontend/src/components/authLoginGuard/index.tsx
index 980528023..ed12d0f54 100644
--- a/src/frontend/src/components/authLoginGuard/index.tsx
+++ b/src/frontend/src/components/authLoginGuard/index.tsx
@@ -3,14 +3,14 @@ import { Navigate } from "react-router-dom";
import { AuthContext } from "../../contexts/authContext";
export const ProtectedLoginRoute = ({ children }) => {
- const { getAuthentication, autoLogin } = useContext(AuthContext);
+ const { isAuthenticated, autoLogin } = useContext(AuthContext);
if (autoLogin === true) {
window.location.replace("/");
return ;
}
- if (getAuthentication()) {
+ if (isAuthenticated) {
window.location.replace("/");
return ;
}
diff --git a/src/frontend/src/components/cardComponent/index.tsx b/src/frontend/src/components/cardComponent/index.tsx
index 5417f58ce..a253f1f5e 100644
--- a/src/frontend/src/components/cardComponent/index.tsx
+++ b/src/frontend/src/components/cardComponent/index.tsx
@@ -1,9 +1,9 @@
-import { useContext, useEffect, useState } from "react";
-import { alertContext } from "../../contexts/alertContext";
-import { FlowsContext } from "../../contexts/flowsContext";
-import { StoreContext } from "../../contexts/storeContext";
+import { useEffect, useState } from "react";
import { getComponent, postLikeComponent } from "../../controllers/API";
import DeleteConfirmationModal from "../../modals/DeleteConfirmationModal";
+import useAlertStore from "../../stores/alertStore";
+import useFlowsManagerStore from "../../stores/flowsManagerStore";
+import { useStoreStore } from "../../stores/storeStore";
import { storeComponent } from "../../types/store";
import cloneFLowWithParent from "../../utils/storeUtils";
import { cn } from "../../utils/utils";
@@ -32,9 +32,10 @@ export default function CollectionCardComponent({
button?: JSX.Element;
onDelete?: () => void;
}) {
- const { addFlow } = useContext(FlowsContext);
- const { setSuccessData, setErrorData } = useContext(alertContext);
- const { setValidApiKey } = useContext(StoreContext);
+ const addFlow = useFlowsManagerStore((state) => state.addFlow);
+ const setSuccessData = useAlertStore((state) => state.setSuccessData);
+ const setErrorData = useAlertStore((state) => state.setErrorData);
+ const setValidApiKey = useStoreStore((state) => state.updateValidApiKey);
const isStore = false;
const [loading, setLoading] = useState(false);
const [loadingLike, setLoadingLike] = useState(false);
diff --git a/src/frontend/src/components/chatComponent/buildTrigger/index.tsx b/src/frontend/src/components/chatComponent/buildTrigger/index.tsx
index f1e374a03..546f8a529 100644
--- a/src/frontend/src/components/chatComponent/buildTrigger/index.tsx
+++ b/src/frontend/src/components/chatComponent/buildTrigger/index.tsx
@@ -1,15 +1,12 @@
import { Transition } from "@headlessui/react";
-import { useContext, useState } from "react";
+import { useState } from "react";
import Loading from "../../../components/ui/loading";
-import { useSSE } from "../../../contexts/SSEContext";
-import { alertContext } from "../../../contexts/alertContext";
-import { typesContext } from "../../../contexts/typesContext";
import { postBuildInit } from "../../../controllers/API";
import { FlowType } from "../../../types/flow";
-import { FlowsContext } from "../../../contexts/flowsContext";
+import useAlertStore from "../../../stores/alertStore";
+import useFlowStore from "../../../stores/flowStore";
import { parsedDataType } from "../../../types/components";
-import { FlowsState } from "../../../types/tabs";
import { validateNodes } from "../../../utils/reactflowUtils";
import RadialProgressComponent from "../../RadialProgress";
import IconComponent from "../../genericIconComponent";
@@ -24,11 +21,15 @@ export default function BuildTrigger({
setIsBuilt: any;
isBuilt: boolean;
}): JSX.Element {
- const { updateSSEData, isBuilding, setIsBuilding, sseData } = useSSE();
- const { reactFlowInstance } = useContext(typesContext);
- const { setTabsState, saveFlow } = useContext(FlowsContext);
- const { setErrorData, setSuccessData } = useContext(alertContext);
- const [isIconTouched, setIsIconTouched] = useState(false);
+ const updateSSEData = useFlowStore((state) => state.updateSSEData);
+ const isBuilding = useFlowStore((state) => state.isBuilding);
+ const setIsBuilding = useFlowStore((state) => state.setIsBuilding);
+ const nodes = useFlowStore((state) => state.nodes);
+ const edges = useFlowStore((state) => state.edges);
+ const setErrorData = useAlertStore((state) => state.setErrorData);
+ const setSuccessData = useAlertStore((state) => state.setSuccessData);
+ const setFlowState = useFlowStore((state) => state.setFlowState);
+
const eventClick = isBuilding ? "pointer-events-none" : "";
const [progress, setProgress] = useState(0);
@@ -37,10 +38,7 @@ export default function BuildTrigger({
if (isBuilding) {
return;
}
- const errors = validateNodes(
- reactFlowInstance!.getNodes(),
- reactFlowInstance!.getEdges()
- );
+ const errors = validateNodes(nodes, edges);
if (errors.length > 0) {
setErrorData({
title: "Oops! Looks like you missed something",
@@ -76,7 +74,6 @@ export default function BuildTrigger({
}
async function streamNodeData(flow: FlowType) {
// Step 1: Make a POST request to send the flow data and receive a unique session ID
- const id = saveFlow(flow, true);
const response = await postBuildInit(flow);
const { flowId } = response.data;
// Step 2: Use the session ID to establish an SSE connection using EventSource
@@ -99,16 +96,7 @@ export default function BuildTrigger({
// If the event is a log, log it
setSuccessData({ title: parsedData.log });
} else if (parsedData.input_keys !== undefined) {
- //@ts-ignore
- setTabsState((old: FlowsState) => {
- return {
- ...old,
- [flowId]: {
- ...old[flowId],
- formKeysData: parsedData,
- },
- };
- });
+ setFlowState(parsedData);
} else {
// Otherwise, process the data
const isValid = processStreamResult(parsedData);
@@ -154,14 +142,6 @@ export default function BuildTrigger({
}
}
- const handleMouseEnter = () => {
- setIsIconTouched(true);
- };
-
- const handleMouseLeave = () => {
- setIsIconTouched(false);
- };
-
return (
{
handleBuild(flow);
}}
- onMouseEnter={handleMouseEnter}
- onMouseLeave={handleMouseLeave}
>