Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 31 additions & 21 deletions src/new-landingpage/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useAuth } from "@clerk/clerk-react";
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import type { PropsWithChildren } from "react";
import { LANDING_BASENAME } from "./landingRoutes";
import NewLandingPageLogin from "./NewLandingPageLogin";
import OrganizationOnboarding from "./OrganizationOnboarding";
import "./App.css";
import DashboardPage from "./DashboardPage";
import { useCookies } from "react-cookie";
import LandingPage from "./LandingPage";
import {
Expand All @@ -13,25 +12,23 @@ import {
LANGFLOW_REFRESH_TOKEN,
} from "./session";

function RootRoute() {
const { isSignedIn } = useAuth();
function SessionRedirect({ children }: PropsWithChildren) {
const [cookies] = useCookies([LANGFLOW_ACCESS_TOKEN, LANGFLOW_REFRESH_TOKEN]);
const workspaceReady = hasWorkspaceSession(cookies);

console.log("[App] RootRoute render", { isSignedIn });

if (isSignedIn) {
const workspaceReady = hasWorkspaceSession(cookies);
const destination = workspaceReady ? "/dashboard" : "/organization";

console.log("[App] Redirecting signed-in user from root", {
workspaceReady,
destination,
});

return <Navigate to={destination} replace />;
if (workspaceReady) {
console.log("[App] SessionRedirect detected workspace; sending to /flows");
window.location.assign("/flows");
return null;
}

return <LandingPage />;
return <>{children}</>;
}

function FlowsRedirect() {
console.log("[App] Redirecting to /flows");
window.location.assign("/flows");
return null;
}

export default function App() {
Expand All @@ -40,10 +37,23 @@ export default function App() {
return (
<BrowserRouter basename={LANDING_BASENAME}>
<Routes>
<Route path="/" element={<RootRoute />} />
<Route path="/login" element={<NewLandingPageLogin />} />
<Route path="/organization" element={<OrganizationOnboarding />} />
<Route path="/dashboard" element={<DashboardPage />} />
<Route path="/" element={<LandingPage />} />
<Route
path="/login"
element={
<SessionRedirect>
<NewLandingPageLogin />
</SessionRedirect>
}
/>
<Route
path="/organization"
element={
<SessionRedirect>
<OrganizationOnboarding />
</SessionRedirect>
}
/>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</BrowserRouter>
Expand Down
7 changes: 6 additions & 1 deletion src/new-landingpage/src/NewLandingPageLogin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,18 @@ export default function NewLandingPageLogin() {
useEffect(() => {
if (isLoaded && isSignedIn) {
const workspaceReady = hasWorkspaceSession(cookies);
const destination = workspaceReady ? "/dashboard" : "/organization";
const destination = workspaceReady ? "/flows" : "/organization";

console.log(
"[NewLandingPageLogin] User signed in, redirecting based on session",
{ workspaceReady, destination },
);

if (workspaceReady) {
window.location.assign("/flows");
return;
}

navigate(destination, { replace: true });
}
}, [cookies, isLoaded, isSignedIn, navigate]);
Expand Down
51 changes: 28 additions & 23 deletions src/new-landingpage/src/OrganizationOnboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import {
} from "react";
import {
Navigate,
useLocation,
useNavigate,
useSearchParams,
} from "react-router-dom";
import { useCookies } from "react-cookie";
Expand Down Expand Up @@ -100,10 +98,22 @@ async function requestJson(
});

const text = expectJson ? await response.text() : null;
const data = text ? (JSON.parse(text) as Record<string, any>) : null;
let data: Record<string, any> | null = null;

if (text) {
try {
data = JSON.parse(text) as Record<string, any>;
} catch {
// Non-JSON response (e.g., HTML error page); keep text for fallback messaging
data = null;
}
}

if (!response.ok) {
const detail = (data?.detail as string) ?? response.statusText;
const detail =
(data?.detail as string) ??
(text ? text.slice(0, 200) : null) ??
response.statusText;
throw new HttpError(response.status, detail || "Request failed", data);
}

Expand Down Expand Up @@ -228,8 +238,6 @@ export default function OrganizationOnboarding() {
organizationId: organization?.id,
});

const location = useLocation();
const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams();

const [cookies, setCookie, removeCookie] = useCookies([
Expand All @@ -241,7 +249,6 @@ export default function OrganizationOnboarding() {
const [error, setError] = useState<string | null>(null);
const [status, setStatus] = useState<string | null>(null);
const [isBootstrapping, setIsBootstrapping] = useState(false);
const [shouldGoToDashboard, setShouldGoToDashboard] = useState(false);

const bootstrappedRef = useRef(false);
const processedOrgRef = useRef<string | null>(null);
Expand Down Expand Up @@ -319,13 +326,18 @@ export default function OrganizationOnboarding() {
}
}, [removeCookie, signOut]);

const goToFlows = useCallback(() => {
console.log("[OrganizationOnboarding] Redirecting to /flows");
window.location.assign("/flows");
}, []);

/**
* Core bootstrap flow:
* - createOrganisation
* - ensureLangflowUser
* - backendLogin
* - persist cookies + storage
* - redirect to /dashboard
* - redirect to /flows
*/
const bootstrapSession = useCallback(async () => {
if (!isSignedIn || !organization?.id || bootstrappedRef.current) return;
Expand Down Expand Up @@ -367,13 +379,12 @@ export default function OrganizationOnboarding() {

persistSession(orgToken, (tokens as any)?.refresh_token ?? null, activeOrgId);

setStatus("Redirecting to dashboard...");
setStatus("Redirecting to workspace...");
console.log(
"[OrganizationOnboarding] Redirecting to dashboard with org",
"[OrganizationOnboarding] Redirecting to workspace with org",
activeOrgId,
);
setShouldGoToDashboard(true);
navigate("/dashboard", { replace: true });
goToFlows();
} catch (err: any) {
console.error("[OrganizationOnboarding] Failed to bootstrap", err);
const msg =
Expand All @@ -391,10 +402,10 @@ export default function OrganizationOnboarding() {
clearSession,
getToken,
isSignedIn,
navigate,
organization?.id,
persistSession,
user,
goToFlows,
]);

useEffect(() => {
Expand Down Expand Up @@ -422,17 +433,16 @@ export default function OrganizationOnboarding() {
const hasAccessToken = Boolean(cookies[LANGFLOW_ACCESS_TOKEN]);

if (orgSelected && activeOrgId && hasAccessToken) {
console.log("[OrganizationOnboarding] Session already present; routing to /dashboard", {
console.log("[OrganizationOnboarding] Session already present; routing to /flows", {
activeOrgId,
});
setShouldGoToDashboard(true);
navigate("/dashboard", { replace: true });
goToFlows();
}
}, [cookies, isLoaded, isSignedIn, navigate]);
}, [cookies, goToFlows, isLoaded, isSignedIn]);

/**
* When Clerk redirects back with ?selected=true,
* create org + bootstrap session, then go to /dashboard.
* create org + bootstrap session, then go to /flows.
*/
useEffect(() => {
if (!isLoaded || !isSignedIn) return;
Expand Down Expand Up @@ -495,11 +505,6 @@ export default function OrganizationOnboarding() {
return <Navigate to="/login" replace />;
}

if (shouldGoToDashboard) {
console.log("[OrganizationOnboarding] Local redirect flag set; sending to /dashboard");
return <Navigate to="/dashboard" replace />;
}

return (
<>
{showLoadingOverlay && (
Expand Down
Loading