Skip to content

Commit

Permalink
feat(auth): customise IdpProfile page, to add same acceptance button …
Browse files Browse the repository at this point in the history
…used on main registration form (#2294)

* add page

* update
  • Loading branch information
theosanderson authored Jul 23, 2024
1 parent de4cb8f commit c10dde4
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 34 deletions.
9 changes: 9 additions & 0 deletions keycloak/keycloakify/src/login/KcApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Template from "./Template";

const Login = lazy(() => import("./pages/Login"));
// If you can, favor register-user-profile.ftl over register.ftl, see: https://docs.keycloakify.dev/realtime-input-validation
const IdpReviewUserProfile = lazy(() => import("./pages/IdpReviewUserProfile"));
const RegisterUserProfile = lazy(() => import("./pages/RegisterUserProfile"));
const Terms = lazy(() => import("./pages/Terms"));
const Info = lazy(() => import("keycloakify/login/pages/Info"));
Expand Down Expand Up @@ -69,6 +70,14 @@ export default function KcApp(props: { kcContext: KcContext }) {
doUseDefaultCss={true}
/>
);

case "idp-review-user-profile.ftl":
return (
<IdpReviewUserProfile
{...{ kcContext, i18n, Template, classes }}
doUseDefaultCss={true}
/>
);
// We choose to use the default Template for the Info page and to download the theme resources.
// This is just an example to show you what is possible. You likely don't want to keep this as is.
case "info.ftl":
Expand Down
26 changes: 26 additions & 0 deletions keycloak/keycloakify/src/login/pages/AcceptanceOfTerms.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';

interface AcceptanceOfTermsProps {
termsMessage: string;
onAgreeChange: (agreed: boolean) => void;
}

const AcceptanceOfTerms: React.FC<AcceptanceOfTermsProps> = ({ termsMessage, onAgreeChange }) => {
return (
<div style={{ marginLeft: "1.5em", marginRight: "1.5em" }}>
<div dangerouslySetInnerHTML={{ __html: termsMessage }}></div>
<div>
<label>
<input
type="checkbox"
id="terms"
name="terms"
onChange={(e) => onAgreeChange(e.target.checked)}
/> I agree
</label>
</div>
</div>
);
};

export default AcceptanceOfTerms;
59 changes: 59 additions & 0 deletions keycloak/keycloakify/src/login/pages/IdpReviewUserProfile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { useState } from "react";
import { clsx } from "keycloakify/tools/clsx";
import { UserProfileFormFields } from "keycloakify/login/pages/shared/UserProfileFormFields";
import type { PageProps } from "keycloakify/login/pages/PageProps";
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
import type { KcContext } from "../kcContext";
import type { I18n } from "../i18n";
import AcceptanceOfTerms from "./AcceptanceOfTerms";

export default function IdpReviewUserProfile(props: PageProps<Extract<KcContext, { pageId: "idp-review-user-profile.ftl" }>, I18n>) {
const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;

const { getClassName } = useGetClassName({
doUseDefaultCss,
classes
});

const { msg, msgStr } = i18n;

const { url } = kcContext;

const [isFormSubmittable, setIsFormSubmittable] = useState(false);
const [didAgree, setDidAgree] = useState(false);

return (
<Template {...{ kcContext, i18n, doUseDefaultCss, classes }} headerNode={msg("loginIdpReviewProfileTitle")}>
<form id="kc-idp-review-profile-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
<UserProfileFormFields
kcContext={kcContext}
onIsFormSubmittableValueChange={setIsFormSubmittable}
i18n={i18n}
getClassName={getClassName}
/>
<div className={getClassName("kcFormGroupClass")}>
<AcceptanceOfTerms
termsMessage={kcContext.properties.REGISTRATION_TERMS_MESSAGE || ''}
onAgreeChange={setDidAgree}
/>
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
<div className={getClassName("kcFormOptionsWrapperClass")} />
</div>
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
<input
className={clsx(
getClassName("kcButtonClass"),
getClassName("kcButtonPrimaryClass"),
getClassName("kcButtonBlockClass"),
getClassName("kcButtonLargeClass")
)}
type="submit"
value={msgStr("doSubmit")}
disabled={!isFormSubmittable || !didAgree}
/>
</div>
</div>
</form>
</Template>
);
}
43 changes: 9 additions & 34 deletions keycloak/keycloakify/src/login/pages/RegisterUserProfile.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// ejected using 'npx eject-keycloak-page'
import { useState } from "react";
import { clsx } from "keycloakify/tools/clsx";
import { UserProfileFormFields } from "./shared/UserProfileFormFields";
Expand All @@ -7,6 +6,7 @@ import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
import type { KcContext } from "../kcContext";
import type { I18n } from "../i18n";
import orcidLogoUrl from "../assets/orcid-logo.png";
import AcceptanceOfTerms from "./AcceptanceOfTerms";

export default function RegisterUserProfile(props: PageProps<Extract<KcContext, { pageId: "register-user-profile.ftl" }>, I18n>) {
const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;
Expand All @@ -30,11 +30,8 @@ export default function RegisterUserProfile(props: PageProps<Extract<KcContext,
headerNode={msg("registerTitle")}
>
<form id="kc-register-form" className={getClassName("kcFormClass")} action={url.registrationAction} method="post">
{social.providers !== undefined && (
<div
id="kc-social-providers"

>
{social.providers !== undefined && (
<div id="kc-social-providers">
<ul
className={clsx(
getClassName("kcFormSocialAccountListClass"),
Expand Down Expand Up @@ -68,33 +65,11 @@ export default function RegisterUserProfile(props: PageProps<Extract<KcContext,
</div>
</div>
)}
<div className={getClassName("kcFormGroupClass")} style={{ "marginBottom": 30 }}>


<div style={{
marginLeft: "1.5em",
marginRight: "1.5em"
}}
>
<div
dangerouslySetInnerHTML={{__html: kcContext.properties.REGISTRATION_TERMS_MESSAGE || ''}}
>
</div>
<div>
<label><input
type="checkbox"
id="terms"
name="terms"
onChange={(e) => {
setDidAgree(e.target.checked);
}}
/> I agree</label>

</div>

</div>


<div className={getClassName("kcFormGroupClass")} style={{ marginBottom: 30 }}>
<AcceptanceOfTerms
termsMessage={kcContext.properties.REGISTRATION_TERMS_MESSAGE || ''}
onAgreeChange={setDidAgree}
/>

<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
<input
Expand All @@ -120,4 +95,4 @@ export default function RegisterUserProfile(props: PageProps<Extract<KcContext,
</form>
</Template>
);
}
}

0 comments on commit c10dde4

Please sign in to comment.