mirror of
https://github.com/fosrl/pangolin.git
synced 2026-07-06 12:19:50 +00:00
✨ remember last used idp in dashboard login form
This commit is contained in:
@@ -30,10 +30,7 @@ import Link from "next/link";
|
|||||||
import { GenerateOidcUrlResponse } from "@server/routers/idp";
|
import { GenerateOidcUrlResponse } from "@server/routers/idp";
|
||||||
import { Separator } from "./ui/separator";
|
import { Separator } from "./ui/separator";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import {
|
import { generateOidcUrlProxy, loginProxy } from "@app/actions/server";
|
||||||
generateOidcUrlProxy,
|
|
||||||
loginProxy
|
|
||||||
} from "@app/actions/server";
|
|
||||||
import { redirect as redirectTo } from "next/navigation";
|
import { redirect as redirectTo } from "next/navigation";
|
||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
import IdpTypeIcon from "@app/components/IdpTypeIcon";
|
import IdpTypeIcon from "@app/components/IdpTypeIcon";
|
||||||
@@ -41,6 +38,7 @@ import IdpTypeIcon from "@app/components/IdpTypeIcon";
|
|||||||
import { loadReoScript } from "reodotdev";
|
import { loadReoScript } from "reodotdev";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import MfaInputForm from "@app/components/MfaInputForm";
|
import MfaInputForm from "@app/components/MfaInputForm";
|
||||||
|
import { useLocalStorage } from "@app/hooks/useLocalStorage";
|
||||||
|
|
||||||
export type LoginFormIDP = {
|
export type LoginFormIDP = {
|
||||||
idpId: number;
|
idpId: number;
|
||||||
@@ -105,7 +103,6 @@ export default function LoginForm({
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
email: z.string().email({ message: t("emailInvalid") }),
|
email: z.string().email({ message: t("emailInvalid") }),
|
||||||
password: z.string().min(8, { message: t("passwordRequirementsChars") })
|
password: z.string().min(8, { message: t("passwordRequirementsChars") })
|
||||||
@@ -130,6 +127,10 @@ export default function LoginForm({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [lastUsedIdpId, setLastUsedIdpId] = useLocalStorage<string | null>(
|
||||||
|
"login:last-used-idp",
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
async function onSubmit(values: any) {
|
async function onSubmit(values: any) {
|
||||||
const { email, password } = form.getValues();
|
const { email, password } = form.getValues();
|
||||||
@@ -179,8 +180,7 @@ export default function LoginForm({
|
|||||||
if (data.useSecurityKey) {
|
if (data.useSecurityKey) {
|
||||||
setError(
|
setError(
|
||||||
t("securityKeyRequired", {
|
t("securityKeyRequired", {
|
||||||
defaultValue:
|
defaultValue: "Please use your security key to sign in."
|
||||||
"Please use your security key to sign in."
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -242,6 +242,8 @@ export default function LoginForm({
|
|||||||
|
|
||||||
async function loginWithIdp(idpId: number) {
|
async function loginWithIdp(idpId: number) {
|
||||||
let redirectUrl: string | undefined;
|
let redirectUrl: string | undefined;
|
||||||
|
|
||||||
|
setLastUsedIdpId(idpId.toString());
|
||||||
try {
|
try {
|
||||||
const data = await generateOidcUrlProxy(
|
const data = await generateOidcUrlProxy(
|
||||||
idpId,
|
idpId,
|
||||||
@@ -356,7 +358,6 @@ export default function LoginForm({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
|
||||||
{!mfaRequested && (
|
{!mfaRequested && (
|
||||||
<>
|
<>
|
||||||
<SecurityKeyAuthButton
|
<SecurityKeyAuthButton
|
||||||
@@ -385,25 +386,41 @@ export default function LoginForm({
|
|||||||
idp.variant || idp.name.toLowerCase();
|
idp.variant || idp.name.toLowerCase();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<div
|
||||||
|
className="w-full relative"
|
||||||
key={idp.idpId}
|
key={idp.idpId}
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
className="w-full inline-flex items-center space-x-2"
|
|
||||||
onClick={() => {
|
|
||||||
loginWithIdp(idp.idpId);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<IdpTypeIcon type={effectiveType} size={16} />
|
<Button
|
||||||
<span>{idp.name}</span>
|
key={idp.idpId}
|
||||||
</Button>
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
className="w-full inline-flex items-center space-x-2 after:absolute after:inset-0 after:z-10"
|
||||||
|
onClick={() => {
|
||||||
|
loginWithIdp(idp.idpId);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IdpTypeIcon
|
||||||
|
type={effectiveType}
|
||||||
|
size={16}
|
||||||
|
/>
|
||||||
|
<span>{idp.name}</span>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{lastUsedIdpId ===
|
||||||
|
idp.idpId.toString() && (
|
||||||
|
<div className="absolute inset-0">
|
||||||
|
<span className="absolute top-0 right-0 text-xs bg-primary text-primary-foreground rounded-bl-sm rounded-tr-sm px-2 py-0.5">
|
||||||
|
{t("idpLastUsed")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user