Skip to content

Commit

Permalink
Login page is almost done
Browse files Browse the repository at this point in the history
  • Loading branch information
nima70 committed Sep 15, 2024
1 parent 3b46e8b commit f2a38ef
Show file tree
Hide file tree
Showing 29 changed files with 2,590 additions and 114 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,25 @@ With the integration of Tailwind CSS, you get access to utility-first CSS for ra
- Login Idp Link Email
- Login Oauth Grant
- Login Otp
- Login Page Expired
- Login Password
- Login Reset Otp
- Login Updatte Password
- Login Update Profile
- Login Username
- Login Verify Email
- Login x509 Info
- Logout Confirm
- Saml Post Form
- Select Authenticator
- Update Email
- Web Authn Authenticate
- Web Authn Error
- Web Authn Register
- Web Authn Error
- Login Oauth2 Device Verify User Code
- Login Recovery Authn Code Config
- Login Recovery Authn Code input

Stay tuned as more pages are upgraded with Tailwind CSS and ShadCN UI components!

Expand Down
79 changes: 79 additions & 0 deletions src/login/KcPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ import LoginX509Info from "./pages/LoginX509Info";
import LogoutConfirm from "./pages/LogoutConfirm";
import SamlPostForm from "./pages/SamlPostForm";
import SelectAuthenticator from "./pages/SelectAuthenticator";
import UpdateEmail from "./pages/UpdateEmail";
import WebauthnAuthenticate from "./pages/WebauthnAuthenticate";
import WebauthnError from "./pages/WebauthnError";
import WebauthnRegister from "./pages/WebauthnRegister";
import LoginOauth2DeviceVerifyUserCode from "./pages/LoginOauth2DeviceVerifyUserCode";
import LoginRecoveryAuthnCodeConfig from "./pages/LoginRecoveryAuthnCodeConfig";
import LoginRecoveryAuthnCodeInput from "./pages/LoginRecoveryAuthnCodeInput";
const UserProfileFormFields = lazy(() => import("./UserProfileFormFields"));

// Base component to render DefaultPage
Expand Down Expand Up @@ -67,6 +74,78 @@ export default function KcPage(props: { kcContext: KcContext }) {
<Suspense>
{(() => {
switch (kcContext.pageId) {
case "login-recovery-authn-code-input.ftl":
return (
<LoginRecoveryAuthnCodeInput
kcContext={kcContext}
i18n={i18n}
classes={classescustom}
Template={CustomTemplate}
doUseDefaultCss={true}
/>
);
case "login-recovery-authn-code-config.ftl":
return (
<LoginRecoveryAuthnCodeConfig
kcContext={kcContext}
i18n={i18n}
classes={classescustom}
Template={CustomTemplate}
doUseDefaultCss={true}
/>
);
case "login-oauth2-device-verify-user-code.ftl":
return (
<LoginOauth2DeviceVerifyUserCode
kcContext={kcContext}
i18n={i18n}
classes={classescustom}
Template={CustomTemplate}
doUseDefaultCss={true}
/>
);
case "webauthn-register.ftl":
return (
<WebauthnRegister
kcContext={kcContext}
i18n={i18n}
classes={classescustom}
Template={CustomTemplate}
doUseDefaultCss={true}
/>
);
case "webauthn-error.ftl":
return (
<WebauthnError
kcContext={kcContext}
i18n={i18n}
classes={classescustom}
Template={CustomTemplate}
doUseDefaultCss={true}
/>
);
case "webauthn-authenticate.ftl":
return (
<WebauthnAuthenticate
kcContext={kcContext}
i18n={i18n}
classes={classescustom}
Template={CustomTemplate}
doUseDefaultCss={true}
/>
);
case "update-email.ftl":
return (
<UpdateEmail
kcContext={kcContext}
i18n={i18n}
classes={classescustom}
Template={CustomTemplate}
doUseDefaultCss={true}
UserProfileFormFields={UserProfileFormFields} // Pass the required UserProfileFormFields prop
doMakeUserConfirmPassword={true} // or false, depending on your requirement
/>
);
case "select-authenticator.ftl":
return (
<SelectAuthenticator
Expand Down
17 changes: 17 additions & 0 deletions src/login/pages/LoginOauth2DeviceVerifyUserCode.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Meta, StoryObj } from "@storybook/react";
import { createKcPageStory } from "../KcPageStory";

const { KcPageStory } = createKcPageStory({ pageId: "login-oauth2-device-verify-user-code.ftl" });

const meta = {
title: "login/login-oauth2-device-verify-user-code.ftl",
component: KcPageStory
} satisfies Meta<typeof KcPageStory>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
render: () => <KcPageStory />
};
73 changes: 73 additions & 0 deletions src/login/pages/LoginOauth2DeviceVerifyUserCode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
import { PageProps } from "keycloakify/login/pages/PageProps";
import { KcContext } from "../KcContext";
import type { I18n } from "../i18n";
import { buttonVariants } from "../../components/ui/button";
import { Input } from "../../components/ui/input";
import { cn } from "../../lib/utils";
export default function LoginOauth2DeviceVerifyUserCode(
props: PageProps<Extract<KcContext, { pageId: "login-oauth2-device-verify-user-code.ftl" }>, I18n>
) {
const { kcContext, i18n, doUseDefaultCss, classes, Template } = props;
const { url } = kcContext;

const { msg, msgStr } = i18n;

const { kcClsx } = getKcClsx({
doUseDefaultCss,
classes
});

return (
<Template
kcContext={kcContext}
i18n={i18n}
doUseDefaultCss={doUseDefaultCss}
classes={classes}
headerNode={msg("oauth2DeviceVerificationTitle")}
>
<form
id="kc-user-verify-device-user-code-form"
className={kcClsx("kcFormClass")}
action={url.oauth2DeviceVerificationAction}
method="post"
>
<div className={kcClsx("kcFormGroupClass")}>
<div className={kcClsx("kcLabelWrapperClass")}>
<label htmlFor="device-user-code" className={kcClsx("kcLabelClass")}>
{msg("verifyOAuth2DeviceUserCode")}
</label>
</div>

<div className={kcClsx("kcInputWrapperClass")}>
<Input
id="device-user-code"
name="device_user_code"
autoComplete="off"
type="text"
className={kcClsx("kcInputClass")}
autoFocus
/>
</div>
</div>

<div className={kcClsx("kcFormGroupClass")}>
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
<div className={kcClsx("kcFormOptionsWrapperClass")}></div>
</div>

<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
<div className={kcClsx("kcFormButtonsWrapperClass")}>
<input
// className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
className={cn(buttonVariants(), "w-full")}
type="submit"
value={msgStr("doSubmit")}
/>
</div>
</div>
</div>
</form>
</Template>
);
}
2 changes: 1 addition & 1 deletion src/login/pages/LoginOauthGrant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getKcClsx } from "keycloakify/login/lib/kcClsx";
import { PageProps } from "keycloakify/login/pages/PageProps";
import { KcContext } from "../KcContext";
import type { I18n } from "../i18n";
import { buttonVariants } from "@/components/ui/button";
import { buttonVariants } from "../../components/ui/button";
export default function LoginOauthGrant(props: PageProps<Extract<KcContext, { pageId: "login-oauth-grant.ftl" }>, I18n>) {
const { kcContext, i18n, doUseDefaultCss, classes, Template } = props;
const { url, oauth, client } = kcContext;
Expand Down
2 changes: 1 addition & 1 deletion src/login/pages/LoginPageExpired.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { PageProps } from "keycloakify/login/pages/PageProps";
import type { KcContext } from "../KcContext";
import type { I18n } from "../i18n";
import { buttonVariants } from "@/components/ui/button";
import { buttonVariants } from "../../components/ui/button";
import { cn } from "../../lib/utils";

export default function LoginPageExpired(props: PageProps<Extract<KcContext, { pageId: "login-page-expired.ftl" }>, I18n>) {
Expand Down
2 changes: 1 addition & 1 deletion src/login/pages/LoginPassword.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { I18n } from "../i18n";
import { PasswordWrapper } from "../../components/ui/PasswordWrapper";
import { buttonVariants } from "../../components/ui/button";
import { cn } from "../../lib/utils";
import { Input } from "@/components/ui/input";
import { Input } from "../../components/ui/input";
export default function LoginPassword(props: PageProps<Extract<KcContext, { pageId: "login-password.ftl" }>, I18n>) {
const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;

Expand Down
26 changes: 26 additions & 0 deletions src/login/pages/LoginRecoveryAuthnCodeConfig.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { Meta, StoryObj } from "@storybook/react";
import { createKcPageStory } from "../KcPageStory";

const { KcPageStory } = createKcPageStory({ pageId: "login-recovery-authn-code-config.ftl" });

const meta = {
title: "login/login-recovery-authn-code-config.ftl",
component: KcPageStory
} satisfies Meta<typeof KcPageStory>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
render: () => <KcPageStory />
};
export const WithAppInitiatedAction: Story = {
render: () => (
<KcPageStory
kcContext={{
isAppInitiatedAction: true
}}
/>
)
};
Loading

0 comments on commit f2a38ef

Please sign in to comment.