refactor: routes and back button (#3600)

* Changed ProtectedRoute to handle refresh token

* Created DashboardWrapperPage to insert header into elements

* Changed routes to be contained by only one ProtectedRoute

* Removed refresh and get version query of App.tsx

* Added loading if user not authenticated in ProtectedAdminRoute

* Changed page layout to not contain header

* Changed AdminPage and FlowPage to not have headers

* Removed unused variables

* Refactored redirectToLastLocation of headerComponent

* Removed unused track last visited path

* changed viewPage to not set onFlowPage since it's used only on header

* Added flow fetching into Playground page

* Fixed back button not working between flows

* Changed duplicate requests to show which request failed

* Refactored useGetBuilds to remove duplicated request

* Re-added get version query and config query

* [autofix.ci] apply automated fixes

* Fix tests that rely on autosave delay

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Lucas Oliveira 2024-08-28 13:52:11 -03:00 • committed by GitHub
commit d6537b724e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 221 additions and 282 deletions

View file

@ -3,10 +3,6 @@ import { Cookies } from "react-cookie";
import { RouterProvider } from "react-router-dom"; import { RouterProvider } from "react-router-dom";
import "reactflow/dist/style.css"; import "reactflow/dist/style.css";
import LoadingComponent from "./components/loadingComponent"; import LoadingComponent from "./components/loadingComponent";
import {
LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS,
LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS_ENV,
} from "./constants/constants";
import { AuthContext } from "./contexts/authContext"; import { AuthContext } from "./contexts/authContext";
import { import {
useAutoLogin, useAutoLogin,
@ -34,8 +30,6 @@ export default function App() {
const { mutate: mutateAutoLogin } = useAutoLogin(); const { mutate: mutateAutoLogin } = useAutoLogin();
useGetVersionQuery();
const { mutate: mutateRefresh } = useRefreshAccessToken(); const { mutate: mutateRefresh } = useRefreshAccessToken();
const isLoginPage = location.pathname.includes("login"); const isLoginPage = location.pathname.includes("login");
@ -79,23 +73,7 @@ export default function App() {
}); });
}, []); }, []);
useEffect(() => { useGetVersionQuery();
const envRefreshTime = LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS_ENV;
const automaticRefreshTime = LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS;
const accessTokenTimer = isNaN(envRefreshTime)
? automaticRefreshTime
: envRefreshTime;
const intervalId = setInterval(() => {
if (isAuthenticated && !isLoginPage) {
mutateRefresh({ refresh_token: refreshToken });
}
}, accessTokenTimer * 1000);
return () => clearInterval(intervalId);
}, [isLoginPage]);
useSaveConfig(); useSaveConfig();
return ( return (

View file

@ -2,17 +2,20 @@ import useAuthStore from "@/stores/authStore";
import { useContext } from "react"; import { useContext } from "react";
import { Navigate } from "react-router-dom"; import { Navigate } from "react-router-dom";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import LoadingComponent from "../loadingComponent";
export const ProtectedAdminRoute = ({ children }) => { export const ProtectedAdminRoute = ({ children }) => {
const { userData } = useContext(AuthContext); const { userData } = useContext(AuthContext);
const isAuthenticated = useAuthStore((state) => state.isAuthenticated); const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
const autoLogin = useAuthStore((state) => state.autoLogin); const autoLogin = useAuthStore((state) => state.autoLogin);
const isAdmin = useAuthStore((state) => state.isAdmin); const isAdmin = useAuthStore((state) => state.isAdmin);
const isLoginPage = location.pathname.includes("login");
const logout = useAuthStore((state) => state.logout);
if (!isAuthenticated && !isLoginPage) { if (!isAuthenticated) {
logout(); return (
<div className="flex h-screen w-screen items-center justify-center">
<LoadingComponent remSize={30} />
</div>
);
} else if ((userData && !isAdmin) || autoLogin) { } else if ((userData && !isAdmin) || autoLogin) {
return <Navigate to="/" replace />; return <Navigate to="/" replace />;
} else { } else {

View file

@ -1,13 +1,40 @@
import { LANGFLOW_AUTO_LOGIN_OPTION } from "@/constants/constants"; import {
LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS,
LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS_ENV,
LANGFLOW_AUTO_LOGIN_OPTION,
} from "@/constants/constants";
import { useRefreshAccessToken } from "@/controllers/API/queries/auth";
import useAuthStore from "@/stores/authStore"; import useAuthStore from "@/stores/authStore";
import { useEffect } from "react";
import { Cookies } from "react-cookie";
export const ProtectedRoute = ({ children }) => { export const ProtectedRoute = ({ children }) => {
const isAuthenticated = useAuthStore((state) => state.isAuthenticated); const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
const hasToken = !!localStorage.getItem(LANGFLOW_AUTO_LOGIN_OPTION); const hasToken = !!localStorage.getItem(LANGFLOW_AUTO_LOGIN_OPTION);
const isLoginPage = location.pathname.includes("login");
const logout = useAuthStore((state) => state.logout); const logout = useAuthStore((state) => state.logout);
if (!isAuthenticated && hasToken && !isLoginPage) { const cookies = new Cookies();
const refreshToken = cookies.get("refresh_token");
const { mutate: mutateRefresh } = useRefreshAccessToken();
useEffect(() => {
const envRefreshTime = LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS_ENV;
const automaticRefreshTime = LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS;
const accessTokenTimer = isNaN(envRefreshTime)
? automaticRefreshTime
: envRefreshTime;
const intervalId = setInterval(() => {
if (isAuthenticated) {
mutateRefresh({ refresh_token: refreshToken });
}
}, accessTokenTimer * 1000);
return () => clearInterval(intervalId);
}, []);
if (!isAuthenticated && hasToken) {
logout(); logout();
} else { } else {
return children; return children;

View file

@ -34,11 +34,6 @@ export const MenuBar = ({}: {}): JSX.Element => {
const addFlow = useAddFlow(); const addFlow = useAddFlow();
const setErrorData = useAlertStore((state) => state.setErrorData); const setErrorData = useAlertStore((state) => state.setErrorData);
const setSuccessData = useAlertStore((state) => state.setSuccessData); const setSuccessData = useAlertStore((state) => state.setSuccessData);
const setLockChat = useFlowStore((state) => state.setLockChat);
const setIsBuilding = useFlowStore((state) => state.setIsBuilding);
const revertBuiltStatusFromBuilding = useFlowStore(
(state) => state.revertBuiltStatusFromBuilding,
);
const undo = useFlowsManagerStore((state) => state.undo); const undo = useFlowsManagerStore((state) => state.undo);
const redo = useFlowsManagerStore((state) => state.redo); const redo = useFlowsManagerStore((state) => state.redo);
const saveLoading = useFlowsManagerStore((state) => state.saveLoading); const saveLoading = useFlowsManagerStore((state) => state.saveLoading);

View file

@ -15,7 +15,6 @@ import { useLogout } from "@/controllers/API/queries/auth";
import useAuthStore from "@/stores/authStore"; import useAuthStore from "@/stores/authStore";
import useAlertStore from "../../stores/alertStore"; import useAlertStore from "../../stores/alertStore";
import { useDarkStore } from "../../stores/darkStore"; import { useDarkStore } from "../../stores/darkStore";
import { useLocationStore } from "../../stores/locationStore";
import { useStoreStore } from "../../stores/storeStore"; import { useStoreStore } from "../../stores/storeStore";
import IconComponent, { ForwardedIconComponent } from "../genericIconComponent"; import IconComponent, { ForwardedIconComponent } from "../genericIconComponent";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
@ -48,29 +47,22 @@ export default function Header(): JSX.Element {
const setDark = useDarkStore((state) => state.setDark); const setDark = useDarkStore((state) => state.setDark);
const stars = useDarkStore((state) => state.stars); const stars = useDarkStore((state) => state.stars);
const routeHistory = useLocationStore((state) => state.routeHistory);
const profileImageUrl = `${BASE_URL_API}files/profile_pictures/${ const profileImageUrl = `${BASE_URL_API}files/profile_pictures/${
userData?.profile_image ?? "Space/046-rocket.svg" userData?.profile_image ?? "Space/046-rocket.svg"
}`; }`;
const redirectToLastLocation = () => { const redirectToLastLocation = () => {
const lastVisitedIndex = routeHistory const canGoBack = location.key !== "default";
.reverse() if (canGoBack) {
.findIndex((path) => path !== location.pathname); navigate(-1);
} else {
const lastFlowVisited = routeHistory[lastVisitedIndex]; navigate("/", { replace: true });
lastFlowVisited ? navigate(lastFlowVisited) : navigate("/all"); }
}; };
const visitedFlowPathBefore = () => { const showArrowReturnIcon = LOCATIONS_TO_RETURN.some((path) =>
const last100VisitedPaths = routeHistory.slice(-99); location.pathname.includes(path),
return last100VisitedPaths.some((path) => path.includes("/flow/")); );
};
const showArrowReturnIcon =
LOCATIONS_TO_RETURN.some((path) => location.pathname.includes(path)) &&
visitedFlowPathBefore();
const handleLogout = () => { const handleLogout = () => {
mutationLogout(undefined, { mutationLogout(undefined, {

View file

@ -1,4 +1,3 @@
import Header from "../headerComponent";
import { Separator } from "../ui/separator"; import { Separator } from "../ui/separator";
export default function PageLayout({ export default function PageLayout({
@ -15,8 +14,6 @@ export default function PageLayout({
betaIcon?: boolean; betaIcon?: boolean;
}) { }) {
return ( return (
<div className="flex h-screen w-full flex-col">
<Header />
<div className="flex h-full w-full flex-col justify-between overflow-auto bg-background px-16"> <div className="flex h-full w-full flex-col justify-between overflow-auto bg-background px-16">
<div className="flex w-full items-center justify-between gap-4 space-y-0.5 py-8 pb-2"> <div className="flex w-full items-center justify-between gap-4 space-y-0.5 py-8 pb-2">
<div className="flex w-full flex-col"> <div className="flex w-full flex-col">
@ -34,6 +31,5 @@ export default function PageLayout({
<Separator className="my-6 flex" /> <Separator className="my-6 flex" />
{children} {children}
</div> </div>
</div>
); );
} }

View file

@ -1,6 +1,5 @@
import { LANGFLOW_ACCESS_TOKEN } from "@/constants/constants"; import { LANGFLOW_ACCESS_TOKEN } from "@/constants/constants";
import useAuthStore from "@/stores/authStore"; import useAuthStore from "@/stores/authStore";
import { useUtilityStore } from "@/stores/utilityStore";
import axios, { AxiosError, AxiosInstance, AxiosRequestConfig } from "axios"; import axios, { AxiosError, AxiosInstance, AxiosRequestConfig } from "axios";
import { useContext, useEffect } from "react"; import { useContext, useEffect } from "react";
import { Cookies } from "react-cookie"; import { Cookies } from "react-cookie";
@ -89,13 +88,13 @@ function ApiInterceptor() {
// Request interceptor to add access token to every request // Request interceptor to add access token to every request
const requestInterceptor = api.interceptors.request.use( const requestInterceptor = api.interceptors.request.use(
(config) => { (config) => {
const checkRequest = checkDuplicateRequestAndStoreRequest(config);
const controller = new AbortController(); const controller = new AbortController();
try {
if (!checkRequest) { checkDuplicateRequestAndStoreRequest(config);
controller.abort("Duplicate Request"); } catch (e) {
console.error("Duplicate Request"); const error = e as Error;
controller.abort(error.message);
console.error(error.message);
} }
const accessToken = cookies.get(LANGFLOW_ACCESS_TOKEN); const accessToken = cookies.get(LANGFLOW_ACCESS_TOKEN);

View file

@ -21,13 +21,11 @@ export function checkDuplicateRequestAndStoreRequest(config) {
currentTime - parseInt(lastRequestTime, 10) < 300 && currentTime - parseInt(lastRequestTime, 10) < 300 &&
lastCurrentUrl === currentUrl lastCurrentUrl === currentUrl
) { ) {
return false; throw new Error("Duplicate request: " + lastUrl);
} }
localStorage.setItem("lastUrlCalled", config.url ?? ""); localStorage.setItem("lastUrlCalled", config.url ?? "");
localStorage.setItem("lastMethodCalled", config.method ?? ""); localStorage.setItem("lastMethodCalled", config.method ?? "");
localStorage.setItem("lastRequestTime", currentTime.toString()); localStorage.setItem("lastRequestTime", currentTime.toString());
localStorage.setItem("lastCurrentUrl", currentUrl); localStorage.setItem("lastCurrentUrl", currentUrl);
return true;
} }

View file

@ -9,35 +9,22 @@ import { UseRequestProcessor } from "../../services/request-processor";
interface BuildsQueryParams { interface BuildsQueryParams {
flowId?: string; flowId?: string;
nodeId?: string;
} }
export const useGetBuildsQuery: useQueryFunctionType< export const useGetBuildsQuery: useQueryFunctionType<
BuildsQueryParams, BuildsQueryParams,
AxiosResponse<{ vertex_builds: FlowPoolType }> AxiosResponse<{ vertex_builds: FlowPoolType }>
> = ({}) => { > = (params) => {
const { query } = UseRequestProcessor(); const { query } = UseRequestProcessor();
const setFlowPool = useFlowStore((state) => state.setFlowPool); const setFlowPool = useFlowStore((state) => state.setFlowPool);
const currentFlow = useFlowStore((state) => state.currentFlow); const currentFlow = useFlowStore((state) => state.currentFlow);
const getBuildsFn = async ( const responseFn = async () => {
params: BuildsQueryParams,
): Promise<AxiosResponse<{ vertex_builds: FlowPoolType }>> => {
const config = {}; const config = {};
config["params"] = { flow_id: params.flowId }; config["params"] = { flow_id: params.flowId };
if (params.nodeId) { const response = await api.get<any>(`${getURL("BUILDS")}`, config);
config["params"] = { nodeId: params.nodeId };
}
return await api.get<any>(`${getURL("BUILDS")}`, config);
};
const responseFn = async () => {
const response = await getBuildsFn({
flowId: currentFlow!.id,
});
if (currentFlow) { if (currentFlow) {
const flowPool = response.data.vertex_builds; const flowPool = response.data.vertex_builds;
@ -47,10 +34,14 @@ export const useGetBuildsQuery: useQueryFunctionType<
return response; return response;
}; };
const queryResult = query(["useGetBuildsQuery"], responseFn, { const queryResult = query(
["useGetBuildsQuery", { key: params.flowId }],
responseFn,
{
placeholderData: keepPreviousData, placeholderData: keepPreviousData,
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
}); },
);
return queryResult; return queryResult;
}; };

View file

@ -1,14 +0,0 @@
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
import { useLocationStore } from "../stores/locationStore";
function useTrackLastVisitedPath() {
const location = useLocation();
const setHistory = useLocationStore((state) => state.setRouteHistory);
useEffect(() => {
setHistory(location.pathname);
}, [location]);
}
export default useTrackLastVisitedPath;

View file

@ -7,7 +7,6 @@ import {
import { cloneDeep } from "lodash"; import { cloneDeep } from "lodash";
import { useContext, useEffect, useRef, useState } from "react"; import { useContext, useEffect, useRef, useState } from "react";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import Header from "../../components/headerComponent";
import LoadingComponent from "../../components/loadingComponent"; import LoadingComponent from "../../components/loadingComponent";
import PaginatorComponent from "../../components/paginatorComponent"; import PaginatorComponent from "../../components/paginatorComponent";
import ShadTooltip from "../../components/shadTooltipComponent"; import ShadTooltip from "../../components/shadTooltipComponent";
@ -246,7 +245,6 @@ export default function AdminPage() {
return ( return (
<> <>
<Header />
{userData && ( {userData && (
<div className="admin-page-panel flex h-full flex-col pb-8"> <div className="admin-page-panel flex h-full flex-col pb-8">
<div className="main-page-nav-arrangement"> <div className="main-page-nav-arrangement">

View file

@ -10,7 +10,6 @@ import {
TIMEOUT_ERROR_MESSAGE, TIMEOUT_ERROR_MESSAGE,
} from "@/constants/constants"; } from "@/constants/constants";
import { useGetHealthQuery } from "@/controllers/API/queries/health"; import { useGetHealthQuery } from "@/controllers/API/queries/health";
import useTrackLastVisitedPath from "@/hooks/use-track-last-visited-path";
import useFlowsManagerStore from "@/stores/flowsManagerStore"; import useFlowsManagerStore from "@/stores/flowsManagerStore";
import { useUtilityStore } from "@/stores/utilityStore"; import { useUtilityStore } from "@/stores/utilityStore";
import { cn } from "@/utils/utils"; import { cn } from "@/utils/utils";
@ -20,8 +19,6 @@ import { ErrorBoundary } from "react-error-boundary";
import { Outlet } from "react-router-dom"; import { Outlet } from "react-router-dom";
export function AppWrapperPage() { export function AppWrapperPage() {
useTrackLastVisitedPath();
const isLoading = useFlowsManagerStore((state) => state.isLoading); const isLoading = useFlowsManagerStore((state) => state.isLoading);
const healthCheckMaxRetries = useFlowsManagerStore( const healthCheckMaxRetries = useFlowsManagerStore(

View file

@ -0,0 +1,11 @@
import Header from "@/components/headerComponent";
import { Outlet } from "react-router-dom";
export function DashboardWrapperPage() {
return (
<div className="flex h-screen w-full flex-col">
<Header />
<Outlet />
</div>
);
}

View file

@ -143,7 +143,7 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
}; };
}, [lastCopiedSelection, lastSelection, takeSnapshot, selectionMenuVisible]); }, [lastCopiedSelection, lastSelection, takeSnapshot, selectionMenuVisible]);
const { isFetching, refetch } = useGetBuildsQuery({}); const { isFetching } = useGetBuildsQuery({ flowId: currentFlowId });
const showCanvas = const showCanvas =
Object.keys(templates).length > 0 && Object.keys(templates).length > 0 &&
@ -151,8 +151,6 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
!isFetching; !isFetching;
useEffect(() => { useEffect(() => {
refetch();
useFlowStore.setState({ autoSaveFlow });
if (checkOldComponents({ nodes })) { if (checkOldComponents({ nodes })) {
setNoticeData({ setNoticeData({
title: title:
@ -161,6 +159,10 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
} }
}, [currentFlowId]); }, [currentFlowId]);
useEffect(() => {
useFlowStore.setState({ autoSaveFlow });
});
function handleUndo(e: KeyboardEvent) { function handleUndo(e: KeyboardEvent) {
if (!isWrappedWithClass(e, "noflow")) { if (!isWrappedWithClass(e, "noflow")) {
e.preventDefault(); e.preventDefault();

View file

@ -8,7 +8,6 @@ import { customStringify } from "@/utils/reactflowUtils";
import { useEffect } from "react"; import { useEffect } from "react";
import { useBlocker, useNavigate, useParams } from "react-router-dom"; import { useBlocker, useNavigate, useParams } from "react-router-dom";
import FlowToolbar from "../../components/chatComponent"; import FlowToolbar from "../../components/chatComponent";
import Header from "../../components/headerComponent";
import { useDarkStore } from "../../stores/darkStore"; import { useDarkStore } from "../../stores/darkStore";
import useFlowStore from "../../stores/flowStore"; import useFlowStore from "../../stores/flowStore";
import useFlowsManagerStore from "../../stores/flowsManagerStore"; import useFlowsManagerStore from "../../stores/flowsManagerStore";
@ -81,7 +80,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
} }
}; };
awaitgetTypes(); awaitgetTypes();
}, [id, flows]); }, [id, flows, currentFlowId]);
useEffect(() => { useEffect(() => {
setOnFlowPage(true); setOnFlowPage(true);
@ -94,7 +93,6 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
return ( return (
<> <>
<Header />
<div className="flow-page-positioning"> <div className="flow-page-positioning">
{currentFlow && ( {currentFlow && (
<div className="flex h-full overflow-hidden"> <div className="flex h-full overflow-hidden">

View file

@ -1,6 +1,9 @@
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
import { useStoreStore } from "@/stores/storeStore"; import { useStoreStore } from "@/stores/storeStore";
import { useTypesStore } from "@/stores/typesStore";
import { useEffect } from "react"; import { useEffect } from "react";
import { useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import LoadingComponent from "../../components/loadingComponent"; import LoadingComponent from "../../components/loadingComponent";
import { getComponent } from "../../controllers/API"; import { getComponent } from "../../controllers/API";
import IOModal from "../../modals/IOModal"; import IOModal from "../../modals/IOModal";
@ -8,7 +11,6 @@ import useFlowsManagerStore from "../../stores/flowsManagerStore";
import cloneFLowWithParent from "../../utils/storeUtils"; import cloneFLowWithParent from "../../utils/storeUtils";
export default function PlaygroundPage() { export default function PlaygroundPage() {
const getFlowById = useFlowsManagerStore((state) => state.getFlowById);
const flows = useFlowsManagerStore((state) => state.flows); const flows = useFlowsManagerStore((state) => state.flows);
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow); const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
const currentSavedFlow = useFlowsManagerStore((state) => state.currentFlow); const currentSavedFlow = useFlowsManagerStore((state) => state.currentFlow);
@ -21,19 +23,38 @@ export default function PlaygroundPage() {
return newFlow; return newFlow;
} }
const navigate = useNavigate();
useGetGlobalVariables();
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
const { mutateAsync: refreshFlows } = useGetRefreshFlows();
const setIsLoading = useFlowsManagerStore((state) => state.setIsLoading);
const getTypes = useTypesStore((state) => state.getTypes);
// Set flow tab id // Set flow tab id
useEffect(() => { useEffect(() => {
if (flows) { const awaitgetTypes = async () => {
const flow = getFlowById(id!); if (flows && currentFlowId === "") {
if (flow) { const isAnExistingFlow = flows.find((flow) => flow.id === id);
setCurrentFlow(flow);
} else { if (!isAnExistingFlow) {
if (validApiKey) if (validApiKey) {
getFlowData().then((flow) => { getFlowData().then((flow) => {
setCurrentFlow(flow); setCurrentFlow(flow);
}); });
} else {
navigate("/");
} }
} }
setCurrentFlow(isAnExistingFlow);
} else if (!flows) {
setIsLoading(true);
await refreshFlows(undefined);
await getTypes();
setIsLoading(false);
}
};
awaitgetTypes();
}, [id, flows, validApiKey]); }, [id, flows, validApiKey]);
return ( return (

View file

@ -1,6 +1,5 @@
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows"; import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
import { useGetGlobalVariables } from "@/controllers/API/queries/variables"; import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
import useFlowStore from "@/stores/flowStore";
import { useTypesStore } from "@/stores/typesStore"; import { useTypesStore } from "@/stores/typesStore";
import { useEffect } from "react"; import { useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
@ -10,7 +9,6 @@ import Page from "../FlowPage/components/PageComponent";
export default function ViewPage() { export default function ViewPage() {
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow); const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
const setOnFlowPage = useFlowStore((state) => state.setOnFlowPage);
const { id } = useParams(); const { id } = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
useGetGlobalVariables(); useGetGlobalVariables();
@ -43,15 +41,6 @@ export default function ViewPage() {
awaitgetTypes(); awaitgetTypes();
}, [id, flows]); }, [id, flows]);
useEffect(() => {
setOnFlowPage(true);
return () => {
setOnFlowPage(false);
setCurrentFlow(undefined);
};
}, [id]);
return ( return (
<div className="flow-page-positioning"> <div className="flow-page-positioning">
<Page view /> <Page view />

View file

@ -1,17 +1,18 @@
import React, { lazy } from "react"; import { lazy } from "react";
import { import {
createBrowserRouter, createBrowserRouter,
createRoutesFromElements, createRoutesFromElements,
Navigate, Navigate,
Outlet,
Route, Route,
} from "react-router-dom"; } from "react-router-dom";
import { ProtectedAdminRoute } from "./components/authAdminGuard"; import { ProtectedAdminRoute } from "./components/authAdminGuard";
import { ProtectedRoute } from "./components/authGuard"; import { ProtectedRoute } from "./components/authGuard";
import { ProtectedLoginRoute } from "./components/authLoginGuard"; import { ProtectedLoginRoute } from "./components/authLoginGuard";
import { AuthSettingsGuard } from "./components/authSettingsGuard"; import { AuthSettingsGuard } from "./components/authSettingsGuard";
import { CatchAllRoute } from "./components/catchAllRoutes";
import { StoreGuard } from "./components/storeGuard"; import { StoreGuard } from "./components/storeGuard";
import { AppWrapperPage } from "./pages/AppWrapperPage"; import { AppWrapperPage } from "./pages/AppWrapperPage";
import { DashboardWrapperPage } from "./pages/DashboardWrapperPage";
import FlowPage from "./pages/FlowPage"; import FlowPage from "./pages/FlowPage";
import LoginPage from "./pages/LoginPage"; import LoginPage from "./pages/LoginPage";
import MyCollectionComponent from "./pages/MainPage/components/myCollectionComponent"; import MyCollectionComponent from "./pages/MainPage/components/myCollectionComponent";
@ -34,15 +35,17 @@ const PlaygroundPage = lazy(() => import("./pages/Playground"));
const SignUp = lazy(() => import("./pages/SignUpPage")); const SignUp = lazy(() => import("./pages/SignUpPage"));
const router = createBrowserRouter( const router = createBrowserRouter(
createRoutesFromElements([ createRoutesFromElements([
<Route path="" element={<AppWrapperPage />}> <Route path="/" element={<AppWrapperPage />}>
<Route <Route
path="/" path=""
element={ element={
<ProtectedRoute> <ProtectedRoute>
<HomePage /> <Outlet />
</ProtectedRoute> </ProtectedRoute>
} }
> >
<Route path="" element={<DashboardWrapperPage />}>
<Route path="" element={<HomePage />}>
<Route index element={<Navigate replace to={"all"} />} /> <Route index element={<Navigate replace to={"all"} />} />
<Route <Route
path="flows/" path="flows/"
@ -55,7 +58,9 @@ const router = createBrowserRouter(
</Route> </Route>
<Route <Route
path="components/" path="components/"
element={<MyCollectionComponent key="components" type="component" />} element={
<MyCollectionComponent key="components" type="component" />
}
> >
<Route <Route
path="folder/:folderId" path="folder/:folderId"
@ -74,14 +79,7 @@ const router = createBrowserRouter(
/> />
</Route> </Route>
</Route> </Route>
<Route <Route path="/settings" element={<SettingsPage />}>
path="/settings"
element={
<ProtectedRoute>
<SettingsPage />
</ProtectedRoute>
}
>
<Route index element={<Navigate replace to={"general"} />} /> <Route index element={<Navigate replace to={"general"} />} />
<Route path="global-variables" element={<GlobalVariablesPage />} /> <Route path="global-variables" element={<GlobalVariablesPage />} />
<Route path="api-keys" element={<ApiKeysPage />} /> <Route path="api-keys" element={<ApiKeysPage />} />
@ -99,67 +97,42 @@ const router = createBrowserRouter(
<Route <Route
path="/store" path="/store"
element={ element={
<ProtectedRoute>
<StoreGuard> <StoreGuard>
<StorePage /> <StorePage />
</StoreGuard> </StoreGuard>
</ProtectedRoute>
} }
/> />
<Route <Route
path="/store/:id/" path="/store/:id/"
element={ element={
<ProtectedRoute>
<StoreGuard> <StoreGuard>
<StorePage /> <StorePage />
</StoreGuard> </StoreGuard>
</ProtectedRoute>
} }
/> />
<Route path="/playground/:id/"> <Route path="/account">
<Route path="delete" element={<DeleteAccountPage />}></Route>
</Route>
<Route <Route
path="" path="/admin"
element={ element={
<ProtectedRoute> <ProtectedAdminRoute>
<PlaygroundPage /> <AdminPage />
</ProtectedRoute> </ProtectedAdminRoute>
} }
/> />
</Route> </Route>
<Route path="/flow/:id/"> <Route path="/flow/:id/">
<Route <Route path="" element={<DashboardWrapperPage />}>
path="folder/:folderId/" <Route path="folder/:folderId/" element={<FlowPage />} />
element={ <Route path="" element={<FlowPage />} />
<ProtectedRoute> </Route>
<FlowPage /> <Route path="view" element={<ViewPage />} />
</ProtectedRoute> </Route>
} <Route path="/playground/:id/">
/> <Route path="" element={<PlaygroundPage />} />
<Route </Route>
path=""
element={
<ProtectedRoute>
<FlowPage />
</ProtectedRoute>
}
/>
<Route
path="view"
element={
<ProtectedRoute>
<ViewPage />
</ProtectedRoute>
}
/>
</Route> </Route>
<Route
path="*"
element={
<ProtectedRoute>
<CatchAllRoute />
</ProtectedRoute>
}
/>
<Route <Route
path="/login" path="/login"
element={ element={
@ -184,24 +157,7 @@ const router = createBrowserRouter(
</ProtectedLoginRoute> </ProtectedLoginRoute>
} }
/> />
<Route <Route path="*" element={<Navigate replace to="/" />} />
path="/admin"
element={
<ProtectedAdminRoute>
<AdminPage />
</ProtectedAdminRoute>
}
/>
<Route path="/account">
<Route
path="delete"
element={
<ProtectedRoute>
<DeleteAccountPage />
</ProtectedRoute>
}
></Route>
</Route>
</Route>, </Route>,
]), ]),
); );

View file

@ -1,4 +1,4 @@
import { expect, test } from "@playwright/test"; import { test } from "@playwright/test";
import * as dotenv from "dotenv"; import * as dotenv from "dotenv";
import path from "path"; import path from "path";
@ -70,6 +70,8 @@ test("should delete rows from table message", async ({ page }) => {
timeout: 30000, timeout: 30000,
}); });
await page.waitForTimeout(2000);
await page.getByTestId("user-profile-settings").last().click(); await page.getByTestId("user-profile-settings").last().click();
await page.getByText("Settings").last().click(); await page.getByText("Settings").last().click();
await page.getByText("Messages").last().click(); await page.getByText("Messages").last().click();