mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-01 01:33:14 +00:00
* fix: preserve dashboard redirect after login Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com> * test: cover plan login redirect in e2e Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com> --------- Co-authored-by: Ramon Nogueira <270434257+ramon-langchain@users.noreply.github.com> Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com> (cherry picked from commit bc7ce59169b5350da7286164afb83a7b037b528d)
88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import { createFileRoute } from "@tanstack/react-router";
|
|
import { useEffect, useMemo } from "react";
|
|
|
|
import { buttonVariants } from "@/components/ui/button";
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
import { loginUrl } from "@/lib/api";
|
|
import {
|
|
DEFAULT_AUTH_REDIRECT,
|
|
authRedirectUrl,
|
|
consumeAuthRedirect,
|
|
getRememberedAuthRedirect,
|
|
rememberAuthRedirect,
|
|
} from "@/lib/auth-redirect";
|
|
import { useSession } from "@/lib/session";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
type LoginSearch = { redirect?: string };
|
|
|
|
export const Route = createFileRoute("/login")({
|
|
validateSearch: (search: Record<string, unknown>): LoginSearch => ({
|
|
redirect: typeof search.redirect === "string" ? search.redirect : undefined,
|
|
}),
|
|
component: Login,
|
|
});
|
|
|
|
function Login() {
|
|
const session = useSession();
|
|
const search = Route.useSearch();
|
|
const redirectParam = search.redirect;
|
|
const intendedPath = useMemo(
|
|
() =>
|
|
redirectParam
|
|
? rememberAuthRedirect(redirectParam)
|
|
: getRememberedAuthRedirect() ?? DEFAULT_AUTH_REDIRECT,
|
|
[redirectParam]
|
|
);
|
|
const authenticatedRedirect = useMemo(
|
|
() => (session.data ? consumeAuthRedirect(redirectParam) : null),
|
|
[redirectParam, session.data]
|
|
);
|
|
|
|
if (session.isLoading) {
|
|
return (
|
|
<main className="flex min-h-svh items-center justify-center p-6">
|
|
<Skeleton className="h-40 w-80" />
|
|
</main>
|
|
);
|
|
}
|
|
|
|
if (authenticatedRedirect) {
|
|
return <ClientRedirect path={authenticatedRedirect} />;
|
|
}
|
|
|
|
return (
|
|
<main className="flex min-h-svh items-center justify-center p-6">
|
|
<Card className="w-full max-w-md">
|
|
<CardHeader>
|
|
<CardTitle>Sign in to open-swe</CardTitle>
|
|
<CardDescription>
|
|
Use your GitHub account. We'll configure your default model, reasoning effort, and
|
|
default repo for Slack/Linear/GitHub triggered runs.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<a
|
|
href={loginUrl(authRedirectUrl(intendedPath))}
|
|
className={cn(buttonVariants({ size: "lg" }), "w-full")}
|
|
>
|
|
Continue with GitHub
|
|
</a>
|
|
</CardContent>
|
|
</Card>
|
|
</main>
|
|
);
|
|
}
|
|
|
|
function ClientRedirect({ path }: { path: string }) {
|
|
useEffect(() => {
|
|
if (typeof window !== "undefined") window.location.replace(path);
|
|
}, [path]);
|
|
|
|
return (
|
|
<main className="flex min-h-svh items-center justify-center p-6">
|
|
<Skeleton className="h-40 w-80" />
|
|
</main>
|
|
);
|
|
}
|