From cc776b31967d43f95f2a01d1bf05913de2f4d8b0 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 5 Jan 2024 13:14:00 -0300 Subject: [PATCH] Implemented Zustand Alert and changed all the usages --- src/frontend/src/App.tsx | 23 +++-- .../components/parameterComponent/index.tsx | 4 +- .../src/alerts/alertDropDown/index.tsx | 19 ++-- .../src/components/cardComponent/index.tsx | 4 +- .../chatComponent/buildTrigger/index.tsx | 5 +- .../chatComponent/chatTrigger/index.tsx | 3 +- .../components/menuBar/index.tsx | 3 +- .../src/components/headerComponent/index.tsx | 3 +- .../components/inputFileComponent/index.tsx | 4 +- src/frontend/src/contexts/alertContext.tsx | 1 - src/frontend/src/contexts/authContext.tsx | 3 +- src/frontend/src/contexts/flowsContext.tsx | 6 +- src/frontend/src/contexts/typesContext.tsx | 3 +- src/frontend/src/controllers/API/api.tsx | 4 +- .../src/modals/EditNodeModal/index.tsx | 3 - .../src/modals/SecretKeyModal/index.tsx | 3 +- .../src/modals/StoreApiKeyModal/index.tsx | 4 +- .../src/modals/codeAreaModal/index.tsx | 5 +- src/frontend/src/modals/exportModal/index.tsx | 3 +- src/frontend/src/modals/formModal/index.tsx | 4 +- .../src/modals/genericModal/index.tsx | 10 +- src/frontend/src/modals/shareModal/index.tsx | 5 +- .../src/pages/AdminPage/LoginPage/index.tsx | 4 +- src/frontend/src/pages/AdminPage/index.tsx | 4 +- src/frontend/src/pages/ApiKeysPage/index.tsx | 5 +- .../components/PageComponent/index.tsx | 10 +- .../extraSidebarComponent/index.tsx | 3 +- .../MainPage/components/components/index.tsx | 5 +- src/frontend/src/pages/MainPage/index.tsx | 5 +- .../src/pages/ProfileSettingsPage/index.tsx | 4 +- src/frontend/src/pages/StorePage/index.tsx | 3 +- src/frontend/src/pages/loginPage/index.tsx | 4 +- src/frontend/src/pages/signUpPage/index.tsx | 4 +- src/frontend/src/stores/alertStore.ts | 95 +++++++++++++++++++ src/frontend/src/types/zustand/alert/index.ts | 23 +++++ 35 files changed, 219 insertions(+), 72 deletions(-) create mode 100644 src/frontend/src/stores/alertStore.ts create mode 100644 src/frontend/src/types/zustand/alert/index.ts diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 3dee06b4d..7f15c8fe8 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -22,6 +22,7 @@ import Router from "./routes"; import { AuthContext } from "./contexts/authContext"; import { FlowsContext } from "./contexts/flowsContext"; import { getVersion } from "./controllers/API"; +import useAlertStore from "./stores/alertStore"; export default function App() { let { setCurrent, setShowSideBar, setIsStackedOpen } = @@ -33,18 +34,16 @@ export default function App() { setIsStackedOpen(true); }, [location.pathname, setCurrent, setIsStackedOpen, setShowSideBar]); - const { - errorData, - errorOpen, - setErrorOpen, - noticeData, - noticeOpen, - setNoticeOpen, - successData, - successOpen, - setSuccessOpen, - loading, - } = useContext(alertContext); + 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 } = useContext(typesContext); diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 3cc59f83f..3d2fe05b8 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -48,6 +48,7 @@ import { nodeNames, } from "../../../../utils/styleUtils"; import { classNames, groupByFamily } from "../../../../utils/utils"; +import useAlertStore from "../../../../stores/alertStore"; export default function ParameterComponent({ left, @@ -68,8 +69,7 @@ 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 setErrorData = useAlertStore((state) => state.setErrorData); const updateNodeInternals = useUpdateNodeInternals(); const [position, setPosition] = useState(0); const { tabId, flows } = useContext(FlowsContext); const nodes = useFlowStore((state) => state.nodes); diff --git a/src/frontend/src/alerts/alertDropDown/index.tsx b/src/frontend/src/alerts/alertDropDown/index.tsx index 92d9df46f..7fc68dbe1 100644 --- a/src/frontend/src/alerts/alertDropDown/index.tsx +++ b/src/frontend/src/alerts/alertDropDown/index.tsx @@ -8,16 +8,23 @@ import { import { alertContext } from "../../contexts/alertContext"; import { AlertDropdownType } from "../../types/alerts"; import SingleAlert from "./components/singleAlertComponent"; +import useAlertStore from "../../stores/alertStore"; 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/cardComponent/index.tsx b/src/frontend/src/components/cardComponent/index.tsx index 9365064ba..d67e68a02 100644 --- a/src/frontend/src/components/cardComponent/index.tsx +++ b/src/frontend/src/components/cardComponent/index.tsx @@ -18,6 +18,7 @@ import { CardHeader, CardTitle, } from "../ui/card"; +import useAlertStore from "../../stores/alertStore"; export default function CollectionCardComponent({ data, @@ -33,7 +34,8 @@ export default function CollectionCardComponent({ onDelete?: () => void; }) { const { addFlow } = useContext(FlowsContext); - const { setSuccessData, setErrorData } = useContext(alertContext); + 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); diff --git a/src/frontend/src/components/chatComponent/buildTrigger/index.tsx b/src/frontend/src/components/chatComponent/buildTrigger/index.tsx index 9a1ffa9d0..705babf83 100644 --- a/src/frontend/src/components/chatComponent/buildTrigger/index.tsx +++ b/src/frontend/src/components/chatComponent/buildTrigger/index.tsx @@ -13,6 +13,7 @@ import { validateNodes } from "../../../utils/reactflowUtils"; import RadialProgressComponent from "../../RadialProgress"; import IconComponent from "../../genericIconComponent"; import useFlowStore from "../../../stores/flowStore"; +import useAlertStore from "../../../stores/alertStore"; export default function BuildTrigger({ open, @@ -28,7 +29,9 @@ export default function BuildTrigger({ const { setTabsState, saveFlow } = useContext(FlowsContext); const nodes = useFlowStore((state) => state.nodes); const edges = useFlowStore((state) => state.edges); - const { setErrorData, setSuccessData } = useContext(alertContext); + const setErrorData = useAlertStore((state) => state.setErrorData); + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const [isIconTouched, setIsIconTouched] = useState(false); const eventClick = isBuilding ? "pointer-events-none" : ""; const [progress, setProgress] = useState(0); diff --git a/src/frontend/src/components/chatComponent/chatTrigger/index.tsx b/src/frontend/src/components/chatComponent/chatTrigger/index.tsx index a390da8d2..4d76c6179 100644 --- a/src/frontend/src/components/chatComponent/chatTrigger/index.tsx +++ b/src/frontend/src/components/chatComponent/chatTrigger/index.tsx @@ -10,6 +10,7 @@ import { import { alertContext } from "../../../contexts/alertContext"; import { chatTriggerPropType } from "../../../types/components"; import IconComponent from "../../genericIconComponent"; +import useAlertStore from "../../../stores/alertStore"; export default function ChatTrigger({ open, @@ -17,7 +18,7 @@ export default function ChatTrigger({ isBuilt, canOpen, }: chatTriggerPropType): JSX.Element { - const { setErrorData } = useContext(alertContext); + const setErrorData = useAlertStore((state) => state.setErrorData); function handleClick(): void { if (isBuilt) { diff --git a/src/frontend/src/components/headerComponent/components/menuBar/index.tsx b/src/frontend/src/components/headerComponent/components/menuBar/index.tsx index 6d471fc10..ef7a3ceec 100644 --- a/src/frontend/src/components/headerComponent/components/menuBar/index.tsx +++ b/src/frontend/src/components/headerComponent/components/menuBar/index.tsx @@ -15,10 +15,11 @@ import FlowSettingsModal from "../../../../modals/flowSettingsModal"; import { menuBarPropsType } from "../../../../types/components"; import IconComponent from "../../../genericIconComponent"; import { Button } from "../../../ui/button"; +import useAlertStore from "../../../../stores/alertStore"; export const MenuBar = ({ flows, tabId }: menuBarPropsType): JSX.Element => { const { addFlow } = useContext(FlowsContext); - const { setErrorData } = useContext(alertContext); + const setErrorData = useAlertStore((state) => state.setErrorData); const { undo, redo } = useContext(undoRedoContext); const [openSettings, setOpenSettings] = useState(false); diff --git a/src/frontend/src/components/headerComponent/index.tsx b/src/frontend/src/components/headerComponent/index.tsx index 26619837f..4070225b7 100644 --- a/src/frontend/src/components/headerComponent/index.tsx +++ b/src/frontend/src/components/headerComponent/index.tsx @@ -22,10 +22,11 @@ import { } from "../ui/dropdown-menu"; import { Separator } from "../ui/separator"; import MenuBar from "./components/menuBar"; +import useAlertStore from "../../stores/alertStore"; export default function Header(): JSX.Element { const { flows, tabId } = useContext(FlowsContext); - const { notificationCenter } = useContext(alertContext); + const notificationCenter = useAlertStore((state) => state.notificationCenter); const location = useLocation(); const { logout, autoLogin, isAdmin, userData } = useContext(AuthContext); const navigate = useNavigate(); diff --git a/src/frontend/src/components/inputFileComponent/index.tsx b/src/frontend/src/components/inputFileComponent/index.tsx index b87e5e5f5..9e589ca8b 100644 --- a/src/frontend/src/components/inputFileComponent/index.tsx +++ b/src/frontend/src/components/inputFileComponent/index.tsx @@ -4,6 +4,7 @@ import { FlowsContext } from "../../contexts/flowsContext"; import { uploadFile } from "../../controllers/API"; import { FileComponentType } from "../../types/components"; import IconComponent from "../genericIconComponent"; +import useAlertStore from "../../stores/alertStore"; export default function InputFileComponent({ value, @@ -15,8 +16,7 @@ export default function InputFileComponent({ }: FileComponentType): JSX.Element { const [myValue, setMyValue] = useState(value); const [loading, setLoading] = useState(false); - const { setErrorData } = useContext(alertContext); - const { tabId } = useContext(FlowsContext); + const setErrorData = useAlertStore((state) => state.setErrorData); const { tabId } = useContext(FlowsContext); // Clear component state useEffect(() => { diff --git a/src/frontend/src/contexts/alertContext.tsx b/src/frontend/src/contexts/alertContext.tsx index 30932f21b..171177d5b 100644 --- a/src/frontend/src/contexts/alertContext.tsx +++ b/src/frontend/src/contexts/alertContext.tsx @@ -50,7 +50,6 @@ export function AlertProvider({ children }: { children: ReactNode }) { const [successOpen, setSuccessOpen] = useState(false); const [notificationCenter, setNotificationCenter] = useState(false); const [notificationList, setNotificationList] = useState([]); - const [isTweakPage, setIsTweakPage] = useState(false); const [modalContextOpen, setModalContextOpen] = useState(false); const pushNotificationList = (notification: AlertItemType) => { setNotificationList((old) => { diff --git a/src/frontend/src/contexts/authContext.tsx b/src/frontend/src/contexts/authContext.tsx index 3d4bd28e9..e69e021d2 100644 --- a/src/frontend/src/contexts/authContext.tsx +++ b/src/frontend/src/contexts/authContext.tsx @@ -4,6 +4,7 @@ import { autoLogin as autoLoginApi, getLoggedUser } from "../controllers/API"; import { Users } from "../types/api"; import { AuthContextType } from "../types/contexts/auth"; import { alertContext } from "./alertContext"; +import useAlertStore from "../stores/alertStore"; const initialValue: AuthContextType = { isAdmin: false, @@ -38,7 +39,7 @@ export function AuthProvider({ children }): React.ReactElement { const [isAdmin, setIsAdmin] = useState(false); const [userData, setUserData] = useState(null); const [autoLogin, setAutoLogin] = useState(false); - const { setLoading } = useContext(alertContext); + const setLoading = useAlertStore((state) => state.setLoading); const [apiKey, setApiKey] = useState( cookies.get("apikey_tkn_lflw") ); diff --git a/src/frontend/src/contexts/flowsContext.tsx b/src/frontend/src/contexts/flowsContext.tsx index cbb1d4f54..9891d7833 100644 --- a/src/frontend/src/contexts/flowsContext.tsx +++ b/src/frontend/src/contexts/flowsContext.tsx @@ -62,6 +62,7 @@ import { alertContext } from "./alertContext"; import { AuthContext } from "./authContext"; import { typesContext } from "./typesContext"; import useFlowStore from "../stores/flowStore"; +import useAlertStore from "../stores/alertStore"; const uid = new ShortUniqueId({ length: 5 }); @@ -96,9 +97,8 @@ export const FlowsContext = createContext( ); export function FlowsProvider({ children }: { children: ReactNode }) { - const { setErrorData, setSuccessData } = useContext(alertContext); - const { getAuthentication, isAuthenticated } = useContext(AuthContext); - + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setErrorData = useAlertStore((state) => state.setErrorData); const [tabId, setTabId] = useState(""); const [isLoading, setIsLoading] = useState(false); const [flows, setFlows] = useState>([]); diff --git a/src/frontend/src/contexts/typesContext.tsx b/src/frontend/src/contexts/typesContext.tsx index 2abaf5275..a4a9e2965 100644 --- a/src/frontend/src/contexts/typesContext.tsx +++ b/src/frontend/src/contexts/typesContext.tsx @@ -12,6 +12,7 @@ import { APIKindType } from "../types/api"; import { typesContextType } from "../types/typesContext"; import { alertContext } from "./alertContext"; import { AuthContext } from "./authContext"; +import useAlertStore from "../stores/alertStore"; //context to share types adn functions from nodes to flow @@ -35,7 +36,7 @@ export function TypesProvider({ children }: { children: ReactNode }) { const [templates, setTemplates] = useState({}); const [data, setData] = useState({}); const [fetchError, setFetchError] = useState(false); - const { setLoading } = useContext(alertContext); + const setLoading = useAlertStore((state) => state.setLoading); const { getAuthentication } = useContext(AuthContext); const [getFilterEdge, setFilterEdge] = useState([]); diff --git a/src/frontend/src/controllers/API/api.tsx b/src/frontend/src/controllers/API/api.tsx index 2847fe8b0..8ec489f4d 100644 --- a/src/frontend/src/controllers/API/api.tsx +++ b/src/frontend/src/controllers/API/api.tsx @@ -3,8 +3,8 @@ import { useContext, useEffect } from "react"; import { Cookies } from "react-cookie"; import { useNavigate } from "react-router-dom"; import { renewAccessToken } from "."; -import { alertContext } from "../../contexts/alertContext"; import { AuthContext } from "../../contexts/authContext"; +import useAlertStore from "../../stores/alertStore"; // Create a new Axios instance const api: AxiosInstance = axios.create({ @@ -12,7 +12,7 @@ const api: AxiosInstance = axios.create({ }); function ApiInterceptor() { - const { setErrorData } = useContext(alertContext); + const setErrorData = useAlertStore((state) => state.setErrorData); let { accessToken, login, logout, authenticationErrorCount } = useContext(AuthContext); const navigate = useNavigate(); diff --git a/src/frontend/src/modals/EditNodeModal/index.tsx b/src/frontend/src/modals/EditNodeModal/index.tsx index 7fa7c1703..ff899158a 100644 --- a/src/frontend/src/modals/EditNodeModal/index.tsx +++ b/src/frontend/src/modals/EditNodeModal/index.tsx @@ -61,8 +61,6 @@ const EditNodeModal = forwardRef( const edges = useFlowStore((state) => state.edges); const setNode = useFlowStore((state) => state.setNode); - const { setModalContextOpen } = useContext(alertContext); - function changeAdvanced(n) { setMyData((old) => { let newData = cloneDeep(old); @@ -84,7 +82,6 @@ const EditNodeModal = forwardRef( if (open) { setMyData(data); // reset data to what it is on node when opening modal } - setModalContextOpen(open); }, [open]); const [errorDuplicateKey, setErrorDuplicateKey] = useState(false); diff --git a/src/frontend/src/modals/SecretKeyModal/index.tsx b/src/frontend/src/modals/SecretKeyModal/index.tsx index 29f7a529b..f9b6d9732 100644 --- a/src/frontend/src/modals/SecretKeyModal/index.tsx +++ b/src/frontend/src/modals/SecretKeyModal/index.tsx @@ -8,6 +8,7 @@ import { createApiKey } from "../../controllers/API"; import { ApiKeyType } from "../../types/components"; import { nodeIconsLucide } from "../../utils/styleUtils"; import BaseModal from "../baseModal"; +import useAlertStore from "../../stores/alertStore"; export default function SecretKeyModal({ title, @@ -24,7 +25,7 @@ export default function SecretKeyModal({ const [apiKeyValue, setApiKeyValue] = useState(""); const [renderKey, setRenderKey] = useState(false); const [textCopied, setTextCopied] = useState(true); - const { setSuccessData } = useContext(alertContext); + const setSuccessData = useAlertStore((state) => state.setSuccessData); const inputRef = useRef(null); useEffect(() => { diff --git a/src/frontend/src/modals/StoreApiKeyModal/index.tsx b/src/frontend/src/modals/StoreApiKeyModal/index.tsx index bb16e12ff..2dbc2ff4b 100644 --- a/src/frontend/src/modals/StoreApiKeyModal/index.tsx +++ b/src/frontend/src/modals/StoreApiKeyModal/index.tsx @@ -9,6 +9,7 @@ import { addApiKeyStore } from "../../controllers/API"; import { useStoreStore } from "../../stores/storeStore"; import { StoreApiKeyType } from "../../types/components"; import BaseModal from "../baseModal"; +import useAlertStore from "../../stores/alertStore"; export default function StoreApiKeyModal({ children, @@ -16,7 +17,8 @@ export default function StoreApiKeyModal({ }: StoreApiKeyType) { if (disabled) return <>{children}; const [open, setOpen] = useState(false); - const { setSuccessData, setErrorData } = useContext(alertContext); + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setErrorData = useAlertStore((state) => state.setErrorData); const { storeApiKey } = useContext(AuthContext); const [apiKeyValue, setApiKeyValue] = useState(""); diff --git a/src/frontend/src/modals/codeAreaModal/index.tsx b/src/frontend/src/modals/codeAreaModal/index.tsx index cba033acd..df33e54b5 100644 --- a/src/frontend/src/modals/codeAreaModal/index.tsx +++ b/src/frontend/src/modals/codeAreaModal/index.tsx @@ -15,6 +15,7 @@ import { postCustomComponent, postValidateCode } from "../../controllers/API"; import { useDarkStore } from "../../stores/darkStore"; import { codeAreaModalPropsType } from "../../types/components"; import BaseModal from "../baseModal"; +import useAlertStore from "../../stores/alertStore"; export default function CodeAreaModal({ value, @@ -29,8 +30,8 @@ export default function CodeAreaModal({ const dark = useDarkStore((state) => state.dark); const [height, setHeight] = useState(null); - const { setErrorData, setSuccessData } = useContext(alertContext); - const [error, setError] = useState<{ + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setErrorData = useAlertStore((state) => state.setErrorData); const [error, setError] = useState<{ detail: { error: string | undefined; traceback: string | undefined }; } | null>(null); diff --git a/src/frontend/src/modals/exportModal/index.tsx b/src/frontend/src/modals/exportModal/index.tsx index 89bd0593a..180e3db8b 100644 --- a/src/frontend/src/modals/exportModal/index.tsx +++ b/src/frontend/src/modals/exportModal/index.tsx @@ -8,11 +8,12 @@ import { alertContext } from "../../contexts/alertContext"; import { FlowsContext } from "../../contexts/flowsContext"; import { removeApiKeys } from "../../utils/reactflowUtils"; import BaseModal from "../baseModal"; +import useAlertStore from "../../stores/alertStore"; const ExportModal = forwardRef( (props: { children: ReactNode }, ref): JSX.Element => { const { flows, tabId, downloadFlow, version } = useContext(FlowsContext); - const { setNoticeData } = useContext(alertContext); + const setNoticeData = useAlertStore((state) => state.setNoticeData); const [checked, setChecked] = useState(true); const flow = flows.find((f) => f.id === tabId); useEffect(() => { diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index e508ef6ae..6ac62689a 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -28,6 +28,7 @@ import { getBuildStatus } from "../../controllers/API"; import useFlowStore from "../../stores/flowStore"; import { FlowsState } from "../../types/tabs"; import { validateNodes } from "../../utils/reactflowUtils"; +import useAlertStore from "../../stores/alertStore"; export default function FormModal({ flow, @@ -65,8 +66,7 @@ export default function FormModal({ const [chatHistory, setChatHistory] = useState([]); const template = useRef(tabsState[flow.id].formKeysData.template); const { accessToken } = useContext(AuthContext); - const { setErrorData } = useContext(alertContext); - const ws = useRef(null); + const setErrorData = useAlertStore((state) => state.setErrorData); const ws = useRef(null); const [lockChat, setLockChat] = useState(false); const isOpen = useRef(open); const messagesRef = useRef(null); diff --git a/src/frontend/src/modals/genericModal/index.tsx b/src/frontend/src/modals/genericModal/index.tsx index dbc955802..f57ffef4d 100644 --- a/src/frontend/src/modals/genericModal/index.tsx +++ b/src/frontend/src/modals/genericModal/index.tsx @@ -19,6 +19,7 @@ import { genericModalPropsType } from "../../types/components"; import { handleKeyDown } from "../../utils/reactflowUtils"; import { classNames, varHighlightHTML } from "../../utils/utils"; import BaseModal from "../baseModal"; +import useAlertStore from "../../stores/alertStore"; export default function GenericModal({ field_name = "", @@ -40,8 +41,9 @@ export default function GenericModal({ const [inputValue, setInputValue] = useState(value); const [isEdit, setIsEdit] = useState(true); const [wordsHighlight, setWordsHighlight] = useState([]); - const { setErrorData, setSuccessData, setNoticeData, setModalContextOpen } = - useContext(alertContext); + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setErrorData = useAlertStore((state) => state.setErrorData); + const setNoticeData = useAlertStore((state) => state.setNoticeData); const textRef = useRef(null); const divRef = useRef(null); const divRefPrompt = useRef(null); @@ -155,10 +157,6 @@ export default function GenericModal({ }); } - useEffect(() => { - setModalContextOpen(modalOpen); - }, [modalOpen]); - return ( {}} diff --git a/src/frontend/src/modals/shareModal/index.tsx b/src/frontend/src/modals/shareModal/index.tsx index bd2e4aaca..ad75bc142 100644 --- a/src/frontend/src/modals/shareModal/index.tsx +++ b/src/frontend/src/modals/shareModal/index.tsx @@ -23,6 +23,7 @@ import { import { getTagsIds } from "../../utils/storeUtils"; import ConfirmationModal from "../ConfirmationModal"; import BaseModal from "../baseModal"; +import useAlertStore from "../../stores/alertStore"; export default function ShareModal({ component, @@ -43,8 +44,8 @@ export default function ShareModal({ const hasStore = useStoreStore((state) => state.hasStore); const hasApiKey = useStoreStore((state) => state.hasApiKey); - const { setSuccessData, setErrorData } = useContext(alertContext); - const [internalOpen, internalSetOpen] = useState(children ? false : true); + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setErrorData = useAlertStore((state) => state.setErrorData); const [internalOpen, internalSetOpen] = useState(children ? false : true); const [openConfirmationModal, setOpenConfirmationModal] = useState(false); const nameComponent = is_component ? "component" : "flow"; diff --git a/src/frontend/src/pages/AdminPage/LoginPage/index.tsx b/src/frontend/src/pages/AdminPage/LoginPage/index.tsx index 4f2f51b05..d2a077771 100644 --- a/src/frontend/src/pages/AdminPage/LoginPage/index.tsx +++ b/src/frontend/src/pages/AdminPage/LoginPage/index.tsx @@ -11,6 +11,7 @@ import { inputHandlerEventType, loginInputStateType, } from "../../../types/components"; +import useAlertStore from "../../../stores/alertStore"; export default function LoginAdminPage() { const navigate = useNavigate(); @@ -20,8 +21,7 @@ export default function LoginAdminPage() { const { login, getAuthentication, setUserData } = useContext(AuthContext); const { password, username } = inputState; - const { setErrorData } = useContext(alertContext); - + const setErrorData = useAlertStore((state) => state.setErrorData); function handleInput({ target: { name, value }, }: inputHandlerEventType): void { diff --git a/src/frontend/src/pages/AdminPage/index.tsx b/src/frontend/src/pages/AdminPage/index.tsx index 39a36544c..fa59e29bc 100644 --- a/src/frontend/src/pages/AdminPage/index.tsx +++ b/src/frontend/src/pages/AdminPage/index.tsx @@ -33,6 +33,7 @@ import ConfirmationModal from "../../modals/ConfirmationModal"; import UserManagementModal from "../../modals/UserManagementModal"; import { Users } from "../../types/api"; import { UserInputType } from "../../types/components"; +import useAlertStore from "../../stores/alertStore"; export default function AdminPage() { const [inputValue, setInputValue] = useState(""); @@ -40,7 +41,8 @@ export default function AdminPage() { const [size, setPageSize] = useState(10); const [index, setPageIndex] = useState(1); const [loadingUsers, setLoadingUsers] = useState(true); - const { setErrorData, setSuccessData } = useContext(alertContext); + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setErrorData = useAlertStore((state) => state.setErrorData); const { userData } = useContext(AuthContext); const [totalRowsCount, setTotalRowsCount] = useState(0); diff --git a/src/frontend/src/pages/ApiKeysPage/index.tsx b/src/frontend/src/pages/ApiKeysPage/index.tsx index 01aff0f36..09d402711 100644 --- a/src/frontend/src/pages/ApiKeysPage/index.tsx +++ b/src/frontend/src/pages/ApiKeysPage/index.tsx @@ -26,11 +26,12 @@ import { LAST_USED_SPAN_2, } from "../../constants/constants"; import { ApiKey } from "../../types/components"; +import useAlertStore from "../../stores/alertStore"; export default function ApiKeysPage() { const [loadingKeys, setLoadingKeys] = useState(true); - const { setErrorData, setSuccessData } = useContext(alertContext); - const { userData } = useContext(AuthContext); + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setErrorData = useAlertStore((state) => state.setErrorData); const { userData } = useContext(AuthContext); const [userId, setUserId] = useState(""); const keysList = useRef([]); diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index 5f1ada5cd..ce034ed64 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -21,11 +21,11 @@ import ReactFlow, { import GenericNode from "../../../../CustomNodes/GenericNode"; import Chat from "../../../../components/chatComponent"; import Loading from "../../../../components/ui/loading"; -import { alertContext } from "../../../../contexts/alertContext"; import { FlowsContext } from "../../../../contexts/flowsContext"; import { locationContext } from "../../../../contexts/locationContext"; import { typesContext } from "../../../../contexts/typesContext"; import { undoRedoContext } from "../../../../contexts/undoRedoContext"; +import useAlertStore from "../../../../stores/alertStore"; import useFlowStore from "../../../../stores/flowStore"; import { APIClassType } from "../../../../types/api"; import { FlowType, NodeType } from "../../../../types/flow"; @@ -64,7 +64,9 @@ export default function Page({ const { takeSnapshot } = useContext(undoRedoContext); const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance); - const setReactFlowInstance = useFlowStore((state) => state.setReactFlowInstance); + const setReactFlowInstance = useFlowStore( + (state) => state.setReactFlowInstance + ); const nodes = useFlowStore((state) => state.nodes); const edges = useFlowStore((state) => state.edges); const onNodesChange = useFlowStore((state) => state.onNodesChange); @@ -145,7 +147,7 @@ export default function Page({ const [selectionMenuVisible, setSelectionMenuVisible] = useState(false); const { setExtraComponent, setExtraNavigation } = useContext(locationContext); - const { setErrorData } = useContext(alertContext); + const setErrorData = useAlertStore((state) => state.setErrorData); const edgeUpdateSuccessful = useRef(true); @@ -350,7 +352,7 @@ export default function Page({ const onMove = useCallback(() => { if (!isPending) setPending(true); }, [setPending]); - + return (
{!view && } diff --git a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx index 78f369e96..a8a5787e8 100644 --- a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx @@ -25,6 +25,7 @@ import { } from "../../../../utils/utils"; import DisclosureComponent from "../DisclosureComponent"; import SidebarDraggableComponent from "./sideBarDraggableComponent"; +import useAlertStore from "../../../../stores/alertStore"; export default function ExtraSidebar(): JSX.Element { const { data, templates, getFilterEdge, setFilterEdge } = @@ -37,7 +38,7 @@ export default function ExtraSidebar(): JSX.Element { const isBuilt = useFlowStore((state) => state.isBuilt); const isPending = useFlowStore((state) => state.isPending); - const { setErrorData } = useContext(alertContext); + const setErrorData = useAlertStore((state) => state.setErrorData); const [dataFilter, setFilterData] = useState(data); const [search, setSearch] = useState(""); function onDragStart( diff --git a/src/frontend/src/pages/MainPage/components/components/index.tsx b/src/frontend/src/pages/MainPage/components/components/index.tsx index 78c5cf538..5f65609be 100644 --- a/src/frontend/src/pages/MainPage/components/components/index.tsx +++ b/src/frontend/src/pages/MainPage/components/components/index.tsx @@ -6,8 +6,8 @@ import CardsWrapComponent from "../../../../components/cardsWrapComponent"; import IconComponent from "../../../../components/genericIconComponent"; import { SkeletonCardComponent } from "../../../../components/skeletonCardComponent"; import { Button } from "../../../../components/ui/button"; -import { alertContext } from "../../../../contexts/alertContext"; import { FlowsContext } from "../../../../contexts/flowsContext"; +import useAlertStore from "../../../../stores/alertStore"; import { FlowType } from "../../../../types/flow"; export default function ComponentsComponent({ @@ -17,7 +17,8 @@ export default function ComponentsComponent({ }) { const { flows, removeFlow, uploadFlow, addFlow, isLoading } = useContext(FlowsContext); - const { setErrorData, setSuccessData } = useContext(alertContext); + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setErrorData = useAlertStore((state) => state.setErrorData); const [pageSize, setPageSize] = useState(10); const [pageIndex, setPageIndex] = useState(1); const [loadingScreen, setLoadingScreen] = useState(true); diff --git a/src/frontend/src/pages/MainPage/index.tsx b/src/frontend/src/pages/MainPage/index.tsx index 1cf02f65b..f974c3336 100644 --- a/src/frontend/src/pages/MainPage/index.tsx +++ b/src/frontend/src/pages/MainPage/index.tsx @@ -7,12 +7,13 @@ import PageLayout from "../../components/pageLayout"; import SidebarNav from "../../components/sidebarComponent"; import { Button } from "../../components/ui/button"; import { USER_PROJECTS_HEADER } from "../../constants/constants"; -import { alertContext } from "../../contexts/alertContext"; import { FlowsContext } from "../../contexts/flowsContext"; +import useAlertStore from "../../stores/alertStore"; export default function HomePage(): JSX.Element { const { setTabId, downloadFlows, uploadFlows, addFlow, uploadFlow } = useContext(FlowsContext); - const { setErrorData, setSuccessData } = useContext(alertContext); + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setErrorData = useAlertStore((state) => state.setErrorData); const location = useLocation(); const pathname = location.pathname; const is_component = pathname === "/components"; diff --git a/src/frontend/src/pages/ProfileSettingsPage/index.tsx b/src/frontend/src/pages/ProfileSettingsPage/index.tsx index 395b7bdf4..90c762eea 100644 --- a/src/frontend/src/pages/ProfileSettingsPage/index.tsx +++ b/src/frontend/src/pages/ProfileSettingsPage/index.tsx @@ -16,6 +16,7 @@ import { patchUserInputStateType, } from "../../types/components"; import { gradients } from "../../utils/styleUtils"; +import useAlertStore from "../../stores/alertStore"; export default function ProfileSettingsPage(): JSX.Element { const { setTabId } = useContext(FlowsContext); @@ -27,7 +28,8 @@ export default function ProfileSettingsPage(): JSX.Element { useEffect(() => { setTabId(""); }, []); - const { setErrorData, setSuccessData } = useContext(alertContext); + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setErrorData = useAlertStore((state) => state.setErrorData); const { userData, setUserData } = useContext(AuthContext); const { password, cnfPassword, gradient } = inputState; diff --git a/src/frontend/src/pages/StorePage/index.tsx b/src/frontend/src/pages/StorePage/index.tsx index 11122f945..5b07461f9 100644 --- a/src/frontend/src/pages/StorePage/index.tsx +++ b/src/frontend/src/pages/StorePage/index.tsx @@ -32,6 +32,7 @@ import StoreApiKeyModal from "../../modals/StoreApiKeyModal"; import { useStoreStore } from "../../stores/storeStore"; import { storeComponent } from "../../types/store"; import { cn } from "../../utils/utils"; +import useAlertStore from "../../stores/alertStore"; export default function StorePage(): JSX.Element { const hasApiKey = useStoreStore((state) => state.hasApiKey); @@ -44,7 +45,7 @@ export default function StorePage(): JSX.Element { const { apiKey } = useContext(AuthContext); - const { setErrorData } = useContext(alertContext); + const setErrorData = useAlertStore((state) => state.setErrorData); const { setTabId } = useContext(FlowsContext); const [loading, setLoading] = useState(true); const [loadingTags, setLoadingTags] = useState(true); diff --git a/src/frontend/src/pages/loginPage/index.tsx b/src/frontend/src/pages/loginPage/index.tsx index 7628dd08a..bc781011e 100644 --- a/src/frontend/src/pages/loginPage/index.tsx +++ b/src/frontend/src/pages/loginPage/index.tsx @@ -5,9 +5,9 @@ import InputComponent from "../../components/inputComponent"; import { Button } from "../../components/ui/button"; import { Input } from "../../components/ui/input"; import { CONTROL_LOGIN_STATE } from "../../constants/constants"; -import { alertContext } from "../../contexts/alertContext"; import { AuthContext } from "../../contexts/authContext"; import { getLoggedUser, onLogin } from "../../controllers/API"; +import useAlertStore from "../../stores/alertStore"; import { LoginType } from "../../types/api"; import { inputHandlerEventType, @@ -22,7 +22,7 @@ export default function LoginPage(): JSX.Element { const { login, getAuthentication, setUserData, setIsAdmin } = useContext(AuthContext); const navigate = useNavigate(); - const { setErrorData } = useContext(alertContext); + const setErrorData = useAlertStore((state) => state.setErrorData); function handleInput({ target: { name, value }, diff --git a/src/frontend/src/pages/signUpPage/index.tsx b/src/frontend/src/pages/signUpPage/index.tsx index d153dc522..93900f15d 100644 --- a/src/frontend/src/pages/signUpPage/index.tsx +++ b/src/frontend/src/pages/signUpPage/index.tsx @@ -15,6 +15,7 @@ import { inputHandlerEventType, signUpInputStateType, } from "../../types/components"; +import useAlertStore from "../../stores/alertStore"; export default function SignUp(): JSX.Element { const [inputState, setInputState] = @@ -23,7 +24,8 @@ export default function SignUp(): JSX.Element { const [isDisabled, setDisableBtn] = useState(true); const { password, cnfPassword, username } = inputState; - const { setErrorData, setSuccessData } = useContext(alertContext); + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setErrorData = useAlertStore((state) => state.setErrorData); const navigate = useNavigate(); function handleInput({ diff --git a/src/frontend/src/stores/alertStore.ts b/src/frontend/src/stores/alertStore.ts new file mode 100644 index 000000000..63c58e28c --- /dev/null +++ b/src/frontend/src/stores/alertStore.ts @@ -0,0 +1,95 @@ +import { uniqueId } from "lodash"; +import { create } from "zustand"; +import { AlertItemType } from "../types/alerts"; +import { AlertStoreType } from "../types/zustand/alert"; + +const pushNotificationList = ( + list: AlertItemType[], + notification: AlertItemType +) => { + list.unshift(notification); + return list; +}; + +const useAlertStore = create((set, get) => ({ + errorData: { title: "", list: [] }, + errorOpen: false, + noticeData: { title: "", link: "" }, + noticeOpen: false, + successData: { title: "" }, + successOpen: false, + notificationCenter: false, + notificationList: [], + loading: true, + setErrorData: (newState: { title: string; list?: Array }) => { + if (newState.title && newState.title !== "") { + set({ + errorData: newState, + errorOpen: true, + notificationCenter: true, + notificationList: pushNotificationList(get().notificationList, { + type: "error", + title: newState.title, + list: newState.list, + id: uniqueId(), + }), + }); + } + }, + setErrorOpen: (newState: boolean) => { + set({ errorOpen: newState }); + }, + setNoticeData: (newState: { title: string; link?: string }) => { + if (newState.title && newState.title !== "") { + set({ + noticeData: newState, + noticeOpen: true, + notificationCenter: true, + notificationList: pushNotificationList(get().notificationList, { + type: "notice", + title: newState.title, + link: newState.link, + id: uniqueId(), + }), + }); + } + }, + setNoticeOpen: (newState: boolean) => { + set({ noticeOpen: newState }); + }, + setSuccessData: (newState: { title: string }) => { + if (newState.title && newState.title !== "") { + set({ + successData: newState, + successOpen: true, + notificationCenter: true, + notificationList: pushNotificationList(get().notificationList, { + type: "success", + title: newState.title, + id: uniqueId(), + }), + }); + } + }, + setSuccessOpen: (newState: boolean) => { + set({ successOpen: newState }); + }, + setNotificationCenter: (newState: boolean) => { + set({ notificationCenter: newState }); + }, + clearNotificationList: () => { + set({ notificationList: [] }); + }, + removeFromNotificationList: (index: string) => { + set({ + notificationList: get().notificationList.filter( + (item) => item.id !== index + ), + }); + }, + setLoading: (newState: boolean) => { + set({ loading: newState }); + }, +})); + +export default useAlertStore; diff --git a/src/frontend/src/types/zustand/alert/index.ts b/src/frontend/src/types/zustand/alert/index.ts new file mode 100644 index 000000000..1e273cc4e --- /dev/null +++ b/src/frontend/src/types/zustand/alert/index.ts @@ -0,0 +1,23 @@ +import { AlertItemType } from "../../alerts"; + +export type AlertStoreType = { + errorData: { title: string; list?: Array }; + setErrorData: (newState: { title: string; list?: Array }) => void; + errorOpen: boolean; + setErrorOpen: (newState: boolean) => void; + noticeData: { title: string; link?: string }; + setNoticeData: (newState: { title: string; link?: string }) => void; + noticeOpen: boolean; + setNoticeOpen: (newState: boolean) => void; + successData: { title: string }; + setSuccessData: (newState: { title: string }) => void; + successOpen: boolean; + setSuccessOpen: (newState: boolean) => void; + notificationCenter: boolean; + setNotificationCenter: (newState: boolean) => void; + notificationList: Array; + clearNotificationList: () => void; + removeFromNotificationList: (index: string) => void; + loading: boolean; + setLoading: (newState: boolean) => void; +};