Implement LoginVerifyEmail
This commit is contained in:
parent
438ca4595f
commit
adc6d69201
@ -9,7 +9,7 @@ import fs from "fs";
|
|||||||
import { join as pathJoin } from "path";
|
import { join as pathJoin } from "path";
|
||||||
import { objectKeys } from "evt/tools/typeSafety/objectKeys";
|
import { objectKeys } from "evt/tools/typeSafety/objectKeys";
|
||||||
|
|
||||||
export const pageIds= [ "login.ftl", "register.ftl", "info.ftl", "error.ftl", "login-reset-password.ftl"] as const;
|
export const pageIds = ["login.ftl", "register.ftl", "info.ftl", "error.ftl", "login-reset-password.ftl", "login-verify-email.ftl"] as const;
|
||||||
|
|
||||||
export type PageId = typeof pageIds[number];
|
export type PageId = typeof pageIds[number];
|
||||||
|
|
||||||
@ -19,8 +19,14 @@ function loadAdjacentFile(fileBasename: string){
|
|||||||
};
|
};
|
||||||
|
|
||||||
function loadFtlFile(ftlFileBasename: PageId | "template.ftl") {
|
function loadFtlFile(ftlFileBasename: PageId | "template.ftl") {
|
||||||
|
try {
|
||||||
|
|
||||||
return loadAdjacentFile(ftlFileBasename)
|
return loadAdjacentFile(ftlFileBasename)
|
||||||
.match(/^<script>const _=((?:.|\n)+)<\/script>[\n]?$/)![1];
|
.match(/^<script>const _=((?:.|\n)+)<\/script>[\n]?$/)![1];
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
return "{}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateFtlFilesCodeFactory(
|
export function generateFtlFilesCodeFactory(
|
||||||
|
@ -4,11 +4,11 @@ import { Template } from "./Template";
|
|||||||
import type { KcProps } from "./KcProps";
|
import type { KcProps } from "./KcProps";
|
||||||
import { assert } from "../tools/assert";
|
import { assert } from "../tools/assert";
|
||||||
import { kcContext } from "../kcContext";
|
import { kcContext } from "../kcContext";
|
||||||
import { useKcTranslation } from "../i18n/useKcTranslation";
|
import { useKcMessage } from "../i18n/useKcMessage";
|
||||||
|
|
||||||
export const Error = memo((props: KcProps) => {
|
export const Error = memo((props: KcProps) => {
|
||||||
|
|
||||||
const { t } = useKcTranslation();
|
const { msg } = useKcMessage();
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
kcContext !== undefined &&
|
kcContext !== undefined &&
|
||||||
@ -22,7 +22,7 @@ export const Error = memo((props: KcProps) => {
|
|||||||
<Template
|
<Template
|
||||||
{...props}
|
{...props}
|
||||||
displayMessage={false}
|
displayMessage={false}
|
||||||
headerNode={t("errorTitle")}
|
headerNode={msg("errorTitle")}
|
||||||
formNode={
|
formNode={
|
||||||
<div id="kc-error-message">
|
<div id="kc-error-message">
|
||||||
<p className="instruction">{message.summary}</p>
|
<p className="instruction">{message.summary}</p>
|
||||||
@ -30,7 +30,7 @@ export const Error = memo((props: KcProps) => {
|
|||||||
client !== undefined && client.baseUrl !== undefined &&
|
client !== undefined && client.baseUrl !== undefined &&
|
||||||
<p>
|
<p>
|
||||||
<a id="backToApplication" href={client.baseUrl}>
|
<a id="backToApplication" href={client.baseUrl}>
|
||||||
{t("backToApplication")}
|
{msg("backToApplication")}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,11 @@ import { Template } from "./Template";
|
|||||||
import type { KcProps } from "./KcProps";
|
import type { KcProps } from "./KcProps";
|
||||||
import { assert } from "../tools/assert";
|
import { assert } from "../tools/assert";
|
||||||
import { kcContext } from "../kcContext";
|
import { kcContext } from "../kcContext";
|
||||||
import { useKcTranslation } from "../i18n/useKcTranslation";
|
import { useKcMessage } from "../i18n/useKcMessage";
|
||||||
|
|
||||||
export const Info = memo((props: KcProps) => {
|
export const Info = memo((props: KcProps) => {
|
||||||
|
|
||||||
const { t } = useKcTranslation();
|
const { msg } = useKcMessage();
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
kcContext !== undefined &&
|
kcContext !== undefined &&
|
||||||
@ -45,7 +45,7 @@ export const Info = memo((props: KcProps) => {
|
|||||||
<b>
|
<b>
|
||||||
{
|
{
|
||||||
requiredActions
|
requiredActions
|
||||||
.map(requiredAction => t(`requiredAction.${requiredAction}` as const))
|
.map(requiredAction => msg(`requiredAction.${requiredAction}` as const))
|
||||||
.join(",")
|
.join(",")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,13 +57,13 @@ export const Info = memo((props: KcProps) => {
|
|||||||
{
|
{
|
||||||
!skipLink &&
|
!skipLink &&
|
||||||
pageRedirectUri !== undefined ?
|
pageRedirectUri !== undefined ?
|
||||||
<p><a href="${pageRedirectUri}">${(t("backToApplication"))}</a></p>
|
<p><a href="${pageRedirectUri}">${(msg("backToApplication"))}</a></p>
|
||||||
:
|
:
|
||||||
actionUri !== undefined ?
|
actionUri !== undefined ?
|
||||||
<p><a href="${actionUri}">${t("proceedWithAction")}</a></p>
|
<p><a href="${actionUri}">${msg("proceedWithAction")}</a></p>
|
||||||
:
|
:
|
||||||
client.baseUrl !== undefined &&
|
client.baseUrl !== undefined &&
|
||||||
<p><a href="${client.baseUrl}">${t("backToApplication")}</a></p>
|
<p><a href="${client.baseUrl}">${msg("backToApplication")}</a></p>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import { Register } from "./Register";
|
|||||||
import { Info } from "./Info";
|
import { Info } from "./Info";
|
||||||
import { Error } from "./Error";
|
import { Error } from "./Error";
|
||||||
import { LoginResetPassword } from "./LoginResetPassword";
|
import { LoginResetPassword } from "./LoginResetPassword";
|
||||||
|
import { LoginVerifyEmail } from "./LoginVerifyEmail";
|
||||||
|
|
||||||
export const KcApp = memo((props: KcProps) => {
|
export const KcApp = memo((props: KcProps) => {
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ export const KcApp = memo((props: KcProps) => {
|
|||||||
case "info.ftl": return <Info {...props} />;
|
case "info.ftl": return <Info {...props} />;
|
||||||
case "error.ftl": return <Error {...props} />;
|
case "error.ftl": return <Error {...props} />;
|
||||||
case "login-reset-password.ftl": return <LoginResetPassword {...props} />;
|
case "login-reset-password.ftl": return <LoginResetPassword {...props} />;
|
||||||
|
case "login-verify-email.ftl": return <LoginVerifyEmail {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
@ -4,13 +4,13 @@ import { Template } from "./Template";
|
|||||||
import type { KcProps } from "./KcProps";
|
import type { KcProps } from "./KcProps";
|
||||||
import { assert } from "../tools/assert";
|
import { assert } from "../tools/assert";
|
||||||
import { kcContext } from "../kcContext";
|
import { kcContext } from "../kcContext";
|
||||||
import { useKcTranslation } from "../i18n/useKcTranslation";
|
import { useKcMessage } from "../i18n/useKcMessage";
|
||||||
import { cx } from "tss-react";
|
import { cx } from "tss-react";
|
||||||
import { useConstCallback } from "powerhooks";
|
import { useConstCallback } from "powerhooks";
|
||||||
|
|
||||||
export const Login = memo((props: KcProps) => {
|
export const Login = memo((props: KcProps) => {
|
||||||
|
|
||||||
const { t, tStr } = useKcTranslation();
|
const { msg, msgStr } = useKcMessage();
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
kcContext !== undefined &&
|
kcContext !== undefined &&
|
||||||
@ -34,7 +34,7 @@ export const Login = memo((props: KcProps) => {
|
|||||||
{...props}
|
{...props}
|
||||||
displayInfo={social.displayInfo}
|
displayInfo={social.displayInfo}
|
||||||
displayWide={realm.password && social.providers !== undefined}
|
displayWide={realm.password && social.providers !== undefined}
|
||||||
headerNode={t("doLogIn")}
|
headerNode={msg("doLogIn")}
|
||||||
formNode={
|
formNode={
|
||||||
<div
|
<div
|
||||||
id="kc-form"
|
id="kc-form"
|
||||||
@ -52,12 +52,12 @@ export const Login = memo((props: KcProps) => {
|
|||||||
<label htmlFor="username" className={cx(props.kcLabelClass)}>
|
<label htmlFor="username" className={cx(props.kcLabelClass)}>
|
||||||
{
|
{
|
||||||
!realm.loginWithEmailAllowed ?
|
!realm.loginWithEmailAllowed ?
|
||||||
t("username")
|
msg("username")
|
||||||
:
|
:
|
||||||
(
|
(
|
||||||
!realm.registrationEmailAsUsername ?
|
!realm.registrationEmailAsUsername ?
|
||||||
t("usernameOrEmail") :
|
msg("usernameOrEmail") :
|
||||||
t("email")
|
msg("email")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</label>
|
</label>
|
||||||
@ -73,7 +73,7 @@ export const Login = memo((props: KcProps) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className={cx(props.kcFormGroupClass)}>
|
<div className={cx(props.kcFormGroupClass)}>
|
||||||
<label htmlFor="password" className={cx(props.kcLabelClass)}>
|
<label htmlFor="password" className={cx(props.kcLabelClass)}>
|
||||||
{t("password")}
|
{msg("password")}
|
||||||
</label>
|
</label>
|
||||||
<input tabIndex={2} id="password" className={cx(props.kcInputClass)} name="password" type="password" autoComplete="off" />
|
<input tabIndex={2} id="password" className={cx(props.kcInputClass)} name="password" type="password" autoComplete="off" />
|
||||||
</div>
|
</div>
|
||||||
@ -87,7 +87,7 @@ export const Login = memo((props: KcProps) => {
|
|||||||
<div className="checkbox">
|
<div className="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input tabIndex={3} id="rememberMe" name="rememberMe" type="checkbox" {...(login.rememberMe ? { "checked": true } : {})} />
|
<input tabIndex={3} id="rememberMe" name="rememberMe" type="checkbox" {...(login.rememberMe ? { "checked": true } : {})} />
|
||||||
{t("rememberMe")}
|
{msg("rememberMe")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ export const Login = memo((props: KcProps) => {
|
|||||||
{
|
{
|
||||||
realm.resetPasswordAllowed &&
|
realm.resetPasswordAllowed &&
|
||||||
<span>
|
<span>
|
||||||
<a tabIndex={5} href={url.loginResetCredentialsUrl}>{t("doForgotPassword")}</a>
|
<a tabIndex={5} href={url.loginResetCredentialsUrl}>{msg("doForgotPassword")}</a>
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -112,7 +112,7 @@ export const Login = memo((props: KcProps) => {
|
|||||||
<input
|
<input
|
||||||
tabIndex={4}
|
tabIndex={4}
|
||||||
className={cx(props.kcButtonClass, props.kcButtonPrimaryClass, props.kcButtonBlockClass, props.kcButtonLargeClass)} name="login" id="kc-login" type="submit"
|
className={cx(props.kcButtonClass, props.kcButtonPrimaryClass, props.kcButtonBlockClass, props.kcButtonLargeClass)} name="login" id="kc-login" type="submit"
|
||||||
value={tStr("doLogIn")}
|
value={msgStr("doLogIn")}
|
||||||
disabled={isLoginButtonDisabled}
|
disabled={isLoginButtonDisabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -138,7 +138,7 @@ export const Login = memo((props: KcProps) => {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
displayInfoNode={
|
infoNode={
|
||||||
(
|
(
|
||||||
realm.password &&
|
realm.password &&
|
||||||
realm.registrationAllowed &&
|
realm.registrationAllowed &&
|
||||||
@ -146,9 +146,9 @@ export const Login = memo((props: KcProps) => {
|
|||||||
) &&
|
) &&
|
||||||
<div id="kc-registration">
|
<div id="kc-registration">
|
||||||
<span>
|
<span>
|
||||||
{t("noAccount")}
|
{msg("noAccount")}
|
||||||
<a tabIndex={6} href={url.registrationUrl}>
|
<a tabIndex={6} href={url.registrationUrl}>
|
||||||
{t("doRegister")}
|
{msg("doRegister")}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,12 +4,12 @@ import { Template } from "./Template";
|
|||||||
import type { KcProps } from "./KcProps";
|
import type { KcProps } from "./KcProps";
|
||||||
import { assert } from "../tools/assert";
|
import { assert } from "../tools/assert";
|
||||||
import { kcContext } from "../kcContext";
|
import { kcContext } from "../kcContext";
|
||||||
import { useKcTranslation } from "../i18n/useKcTranslation";
|
import { useKcMessage } from "../i18n/useKcMessage";
|
||||||
import { cx } from "tss-react";
|
import { cx } from "tss-react";
|
||||||
|
|
||||||
export const LoginResetPassword = memo((props: KcProps) => {
|
export const LoginResetPassword = memo((props: KcProps) => {
|
||||||
|
|
||||||
const { t, tStr } = useKcTranslation();
|
const { msg, msgStr } = useKcMessage();
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
kcContext !== undefined &&
|
kcContext !== undefined &&
|
||||||
@ -26,7 +26,7 @@ export const LoginResetPassword = memo((props: KcProps) => {
|
|||||||
<Template
|
<Template
|
||||||
{...props}
|
{...props}
|
||||||
displayMessage={false}
|
displayMessage={false}
|
||||||
headerNode={t("emailForgotTitle")}
|
headerNode={msg("emailForgotTitle")}
|
||||||
formNode={
|
formNode={
|
||||||
<form id="kc-reset-password-form" className={cx(props.kcFormClass)} action={url.loginAction} method="post">
|
<form id="kc-reset-password-form" className={cx(props.kcFormClass)} action={url.loginAction} method="post">
|
||||||
<div className={cx(props.kcFormGroupClass)}>
|
<div className={cx(props.kcFormGroupClass)}>
|
||||||
@ -34,11 +34,11 @@ export const LoginResetPassword = memo((props: KcProps) => {
|
|||||||
<label htmlFor="username" className={cx(props.kcLabelClass)}>
|
<label htmlFor="username" className={cx(props.kcLabelClass)}>
|
||||||
{
|
{
|
||||||
!realm.loginWithEmailAllowed ?
|
!realm.loginWithEmailAllowed ?
|
||||||
t("username")
|
msg("username")
|
||||||
:
|
:
|
||||||
!realm.registrationEmailAsUsername ?
|
!realm.registrationEmailAsUsername ?
|
||||||
t("usernameOrEmail") :
|
msg("usernameOrEmail") :
|
||||||
t("email")
|
msg("email")
|
||||||
}
|
}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@ -60,7 +60,7 @@ export const LoginResetPassword = memo((props: KcProps) => {
|
|||||||
<div id="kc-form-options" className={cx(props.kcFormOptionsClass)}>
|
<div id="kc-form-options" className={cx(props.kcFormOptionsClass)}>
|
||||||
<div className={cx(props.kcFormOptionsWrapperClass)}>
|
<div className={cx(props.kcFormOptionsWrapperClass)}>
|
||||||
<span>
|
<span>
|
||||||
<a href={url.loginUrl}>{t("backToLogin")}</a>
|
<a href={url.loginUrl}>{msg("backToLogin")}</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -72,13 +72,13 @@ export const LoginResetPassword = memo((props: KcProps) => {
|
|||||||
props.kcButtonBlockClass, props.kcButtonLargeClass
|
props.kcButtonBlockClass, props.kcButtonLargeClass
|
||||||
)}
|
)}
|
||||||
type="submit"
|
type="submit"
|
||||||
defaultValue={tStr("doSubmit")}
|
defaultValue={msgStr("doSubmit")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
}
|
}
|
||||||
infoNode={t("emailInstruction")}
|
infoNode={msg("emailInstruction")}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
44
src/lib/components/LoginVerifyEmail.tsx
Normal file
44
src/lib/components/LoginVerifyEmail.tsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
import { memo } from "react";
|
||||||
|
import { Template } from "./Template";
|
||||||
|
import type { KcProps } from "./KcProps";
|
||||||
|
import { assert } from "../tools/assert";
|
||||||
|
import { kcContext } from "../kcContext";
|
||||||
|
import { useKcMessage } from "../i18n/useKcMessage";
|
||||||
|
|
||||||
|
export const LoginVerifyEmail = memo((props: KcProps) => {
|
||||||
|
|
||||||
|
const { msg } = useKcMessage();
|
||||||
|
|
||||||
|
assert(
|
||||||
|
kcContext !== undefined &&
|
||||||
|
kcContext.pageId === "login-verify-email.ftl"
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
url
|
||||||
|
} = kcContext;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Template
|
||||||
|
{...props}
|
||||||
|
displayMessage={false}
|
||||||
|
headerNode={msg("emailVerifyTitle")}
|
||||||
|
formNode={
|
||||||
|
<>
|
||||||
|
<p className="instruction">
|
||||||
|
{msg("emailVerifyInstruction1")}
|
||||||
|
</p>
|
||||||
|
<p className="instruction">
|
||||||
|
{msg("emailVerifyInstruction2")}
|
||||||
|
<a href={url.loginAction}>{msg("doClickHere")}</a>
|
||||||
|
{msg("emailVerifyInstruction3")}
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -3,12 +3,12 @@ import { Template } from "./Template";
|
|||||||
import type { KcProps } from "./KcProps";
|
import type { KcProps } from "./KcProps";
|
||||||
import { assert } from "../tools/assert";
|
import { assert } from "../tools/assert";
|
||||||
import { kcContext } from "../kcContext";
|
import { kcContext } from "../kcContext";
|
||||||
import { useKcTranslation } from "../i18n/useKcTranslation";
|
import { useKcMessage } from "../i18n/useKcMessage";
|
||||||
import { cx } from "tss-react";
|
import { cx } from "tss-react";
|
||||||
|
|
||||||
export const Register = memo((props: KcProps) => {
|
export const Register = memo((props: KcProps) => {
|
||||||
|
|
||||||
const { t, tStr } = useKcTranslation();
|
const { msg, msgStr } = useKcMessage();
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
kcContext !== undefined &&
|
kcContext !== undefined &&
|
||||||
@ -28,13 +28,13 @@ export const Register = memo((props: KcProps) => {
|
|||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...props}
|
{...props}
|
||||||
headerNode={t("registerTitle")}
|
headerNode={msg("registerTitle")}
|
||||||
formNode={
|
formNode={
|
||||||
<form id="kc-register-form" className={cx(props.kcFormClass)} action={url.registrationAction} method="post">
|
<form id="kc-register-form" className={cx(props.kcFormClass)} action={url.registrationAction} method="post">
|
||||||
|
|
||||||
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists('firstName', props.kcFormGroupErrorClass))}>
|
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists('firstName', props.kcFormGroupErrorClass))}>
|
||||||
<div className={cx(props.kcLabelWrapperClass)}>
|
<div className={cx(props.kcLabelWrapperClass)}>
|
||||||
<label htmlFor="firstName" className={cx(props.kcLabelClass)}>{t("firstName")}</label>
|
<label htmlFor="firstName" className={cx(props.kcLabelClass)}>{msg("firstName")}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={cx(props.kcInputWrapperClass)}>
|
<div className={cx(props.kcInputWrapperClass)}>
|
||||||
<input type="text" id="firstName" className={cx(props.kcInputClass)} name="firstName"
|
<input type="text" id="firstName" className={cx(props.kcInputClass)} name="firstName"
|
||||||
@ -45,7 +45,7 @@ export const Register = memo((props: KcProps) => {
|
|||||||
|
|
||||||
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists("lastName", props.kcFormGroupErrorClass))}>
|
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists("lastName", props.kcFormGroupErrorClass))}>
|
||||||
<div className={cx(props.kcLabelWrapperClass)}>
|
<div className={cx(props.kcLabelWrapperClass)}>
|
||||||
<label htmlFor="lastName" className={cx(props.kcLabelClass)}>{t("lastName")}</label>
|
<label htmlFor="lastName" className={cx(props.kcLabelClass)}>{msg("lastName")}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={cx(props.kcInputWrapperClass)}>
|
<div className={cx(props.kcInputWrapperClass)}>
|
||||||
<input type="text" id="lastName" className={cx(props.kcInputClass)} name="lastName"
|
<input type="text" id="lastName" className={cx(props.kcInputClass)} name="lastName"
|
||||||
@ -56,7 +56,7 @@ export const Register = memo((props: KcProps) => {
|
|||||||
|
|
||||||
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists('email', props.kcFormGroupErrorClass))}>
|
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists('email', props.kcFormGroupErrorClass))}>
|
||||||
<div className={cx(props.kcLabelWrapperClass)}>
|
<div className={cx(props.kcLabelWrapperClass)}>
|
||||||
<label htmlFor="email" className={cx(props.kcLabelClass)}>{t("email")}</label>
|
<label htmlFor="email" className={cx(props.kcLabelClass)}>{msg("email")}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={cx(props.kcInputWrapperClass)}>
|
<div className={cx(props.kcInputWrapperClass)}>
|
||||||
<input type="text" id="email" className={cx(props.kcInputClass)} name="email"
|
<input type="text" id="email" className={cx(props.kcInputClass)} name="email"
|
||||||
@ -69,7 +69,7 @@ export const Register = memo((props: KcProps) => {
|
|||||||
|
|
||||||
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists('username', props.kcFormGroupErrorClass))}>
|
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists('username', props.kcFormGroupErrorClass))}>
|
||||||
<div className={cx(props.kcLabelWrapperClass)}>
|
<div className={cx(props.kcLabelWrapperClass)}>
|
||||||
<label htmlFor="username" className={cx(props.kcLabelClass)}>{t("username")}</label>
|
<label htmlFor="username" className={cx(props.kcLabelClass)}>{msg("username")}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={cx(props.kcInputWrapperClass)}>
|
<div className={cx(props.kcInputWrapperClass)}>
|
||||||
<input type="text" id="username" className={cx(props.kcInputClass)} name="username"
|
<input type="text" id="username" className={cx(props.kcInputClass)} name="username"
|
||||||
@ -84,7 +84,7 @@ export const Register = memo((props: KcProps) => {
|
|||||||
|
|
||||||
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists("password", props.kcFormGroupErrorClass))}>
|
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists("password", props.kcFormGroupErrorClass))}>
|
||||||
<div className={cx(props.kcLabelWrapperClass)}>
|
<div className={cx(props.kcLabelWrapperClass)}>
|
||||||
<label htmlFor="password" className={cx(props.kcLabelClass)}>{t("password")}</label>
|
<label htmlFor="password" className={cx(props.kcLabelClass)}>{msg("password")}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={cx(props.kcInputWrapperClass)}>
|
<div className={cx(props.kcInputWrapperClass)}>
|
||||||
<input type="password" id="password" className={cx(props.kcInputClass)} name="password" autoComplete="new-password" />
|
<input type="password" id="password" className={cx(props.kcInputClass)} name="password" autoComplete="new-password" />
|
||||||
@ -93,7 +93,7 @@ export const Register = memo((props: KcProps) => {
|
|||||||
|
|
||||||
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists("password-confirm", props.kcFormGroupErrorClass))}>
|
<div className={cx(props.kcFormGroupClass, messagesPerField.printIfExists("password-confirm", props.kcFormGroupErrorClass))}>
|
||||||
<div className={cx(props.kcLabelWrapperClass)}>
|
<div className={cx(props.kcLabelWrapperClass)}>
|
||||||
<label htmlFor="password-confirm" className={cx(props.kcLabelClass)}>{t("passwordConfirm")}</label>
|
<label htmlFor="password-confirm" className={cx(props.kcLabelClass)}>{msg("passwordConfirm")}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={cx(props.kcInputWrapperClass)}>
|
<div className={cx(props.kcInputWrapperClass)}>
|
||||||
<input type="password" id="password-confirm" className={cx(props.kcInputClass)} name="password-confirm" />
|
<input type="password" id="password-confirm" className={cx(props.kcInputClass)} name="password-confirm" />
|
||||||
@ -113,13 +113,13 @@ export const Register = memo((props: KcProps) => {
|
|||||||
<div className={cx(props.kcFormGroupClass)}>
|
<div className={cx(props.kcFormGroupClass)}>
|
||||||
<div id="kc-form-options" className={cx(props.kcFormOptionsClass)}>
|
<div id="kc-form-options" className={cx(props.kcFormOptionsClass)}>
|
||||||
<div className={cx(props.kcFormOptionsWrapperClass)}>
|
<div className={cx(props.kcFormOptionsWrapperClass)}>
|
||||||
<span><a href={url.loginUrl}>{t("backToLogin")}</a></span>
|
<span><a href={url.loginUrl}>{msg("backToLogin")}</a></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="kc-form-buttons" className={cx(props.kcFormButtonsClass)}>
|
<div id="kc-form-buttons" className={cx(props.kcFormButtonsClass)}>
|
||||||
<input className={cx(props.kcButtonClass, props.kcButtonPrimaryClass, props.kcButtonBlockClass, props.kcButtonLargeClass)} type="submit"
|
<input className={cx(props.kcButtonClass, props.kcButtonPrimaryClass, props.kcButtonBlockClass, props.kcButtonLargeClass)} type="submit"
|
||||||
defaultValue={tStr("doRegister")} />
|
defaultValue={msgStr("doRegister")} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form >
|
</form >
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
import { useReducer, useEffect, memo } from "react";
|
import { useReducer, useEffect, memo } from "react";
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import { useKcTranslation } from "../i18n/useKcTranslation";
|
import { useKcMessage } from "../i18n/useKcMessage";
|
||||||
import { useKcLanguageTag } from "../i18n/useKcLanguageTag";
|
import { useKcLanguageTag } from "../i18n/useKcLanguageTag";
|
||||||
import { kcContext } from "../kcContext";
|
import { kcContext } from "../kcContext";
|
||||||
import { assert } from "../tools/assert";
|
import { assert } from "../tools/assert";
|
||||||
@ -44,7 +44,7 @@ export const Template = memo((props: TemplateProps) => {
|
|||||||
|
|
||||||
useEffect(() => { console.log("Rendering this page with react using keycloakify") }, []);
|
useEffect(() => { console.log("Rendering this page with react using keycloakify") }, []);
|
||||||
|
|
||||||
const { t } = useKcTranslation();
|
const { msg } = useKcMessage();
|
||||||
|
|
||||||
const { kcLanguageTag, setKcLanguageTag } = useKcLanguageTag();
|
const { kcLanguageTag, setKcLanguageTag } = useKcLanguageTag();
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ export const Template = memo((props: TemplateProps) => {
|
|||||||
|
|
||||||
<div id="kc-header" className={cx(props.kcHeaderClass)}>
|
<div id="kc-header" className={cx(props.kcHeaderClass)}>
|
||||||
<div id="kc-header-wrapper" className={cx(props.kcHeaderWrapperClass)}>
|
<div id="kc-header-wrapper" className={cx(props.kcHeaderWrapperClass)}>
|
||||||
{t("loginTitleHtml", realm.displayNameHtml)}
|
{msg("loginTitleHtml", realm.displayNameHtml)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ export const Template = memo((props: TemplateProps) => {
|
|||||||
<div className={cx(props.kcLabelWrapperClass, "subtitle")}>
|
<div className={cx(props.kcLabelWrapperClass, "subtitle")}>
|
||||||
<span className="subtitle">
|
<span className="subtitle">
|
||||||
<span className="required">*</span>
|
<span className="required">*</span>
|
||||||
{t("requiredFields")}
|
{msg("requiredFields")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-10">
|
<div className="col-md-10">
|
||||||
@ -201,7 +201,7 @@ export const Template = memo((props: TemplateProps) => {
|
|||||||
displayRequiredFields ? (
|
displayRequiredFields ? (
|
||||||
<div className={cx(props.kcContentWrapperClass)}>
|
<div className={cx(props.kcContentWrapperClass)}>
|
||||||
<div className={cx(props.kcLabelWrapperClass, "subtitle")}>
|
<div className={cx(props.kcLabelWrapperClass, "subtitle")}>
|
||||||
<span className="subtitle"><span className="required">*</span> {t("requiredFields")}</span>
|
<span className="subtitle"><span className="required">*</span> {msg("requiredFields")}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-10">
|
<div className="col-md-10">
|
||||||
{showUsernameNode}
|
{showUsernameNode}
|
||||||
@ -211,7 +211,7 @@ export const Template = memo((props: TemplateProps) => {
|
|||||||
<a id="reset-login" href={url.loginRestartFlowUrl}>
|
<a id="reset-login" href={url.loginRestartFlowUrl}>
|
||||||
<div className="kc-login-tooltip">
|
<div className="kc-login-tooltip">
|
||||||
<i className={cx(props.kcResetFlowIcon)}></i>
|
<i className={cx(props.kcResetFlowIcon)}></i>
|
||||||
<span className="kc-tooltip-text">{t("restartLoginTooltip")}</span>
|
<span className="kc-tooltip-text">{msg("restartLoginTooltip")}</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -227,7 +227,7 @@ export const Template = memo((props: TemplateProps) => {
|
|||||||
<a id="reset-login" href={url.loginRestartFlowUrl}>
|
<a id="reset-login" href={url.loginRestartFlowUrl}>
|
||||||
<div className="kc-login-tooltip">
|
<div className="kc-login-tooltip">
|
||||||
<i className={cx(props.kcResetFlowIcon)}></i>
|
<i className={cx(props.kcResetFlowIcon)}></i>
|
||||||
<span className="kc-tooltip-text">{t("restartLoginTooltip")}</span>
|
<span className="kc-tooltip-text">{msg("restartLoginTooltip")}</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -269,7 +269,7 @@ export const Template = memo((props: TemplateProps) => {
|
|||||||
<div className={cx(displayWide && [props.kcFormSocialAccountContentClass, props.kcFormSocialAccountClass])} >
|
<div className={cx(displayWide && [props.kcFormSocialAccountContentClass, props.kcFormSocialAccountClass])} >
|
||||||
<div className={cx(props.kcFormGroupClass)}>
|
<div className={cx(props.kcFormGroupClass)}>
|
||||||
<input type="hidden" name="tryAnotherWay" value="on" />
|
<input type="hidden" name="tryAnotherWay" value="on" />
|
||||||
<a href="#" id="try-another-way" onClick={onTryAnotherWayClick}>{t("doTryAnotherWay")}</a>
|
<a href="#" id="try-another-way" onClick={onTryAnotherWayClick}>{msg("doTryAnotherWay")}</a>
|
||||||
</div>
|
</div>
|
||||||
</div >
|
</div >
|
||||||
</form>
|
</form>
|
||||||
|
@ -7,11 +7,11 @@ import { id } from "evt/tools/typeSafety/id";
|
|||||||
|
|
||||||
export type MessageKey = keyof typeof messages["en"];
|
export type MessageKey = keyof typeof messages["en"];
|
||||||
|
|
||||||
export function useKcTranslation() {
|
export function useKcMessage() {
|
||||||
|
|
||||||
const { kcLanguageTag } = useKcLanguageTag();
|
const { kcLanguageTag } = useKcLanguageTag();
|
||||||
|
|
||||||
const tStr = useConstCallback(
|
const msgStr = useConstCallback(
|
||||||
(key: MessageKey, ...args: (string | undefined)[]): string => {
|
(key: MessageKey, ...args: (string | undefined)[]): string => {
|
||||||
|
|
||||||
let str: string = messages[kcLanguageTag as any as "en"][key] ?? messages["en"][key];
|
let str: string = messages[kcLanguageTag as any as "en"][key] ?? messages["en"][key];
|
||||||
@ -31,13 +31,13 @@ export function useKcTranslation() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const t = useConstCallback(
|
const msg = useConstCallback(
|
||||||
id<(...args: Parameters<typeof tStr>) => ReactNode>(
|
id<(...args: Parameters<typeof msgStr>) => ReactNode>(
|
||||||
(key, ...args) =>
|
(key, ...args) =>
|
||||||
<span className={key} dangerouslySetInnerHTML={{ "__html": tStr(key, ...args) }} />
|
<span className={key} dangerouslySetInnerHTML={{ "__html": msgStr(key, ...args) }} />
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return { t, tStr };
|
return { msg, msgStr };
|
||||||
|
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ export * from "./kcContext";
|
|||||||
|
|
||||||
export * from "./i18n/KcLanguageTag";
|
export * from "./i18n/KcLanguageTag";
|
||||||
export * from "./i18n/useKcLanguageTag";
|
export * from "./i18n/useKcLanguageTag";
|
||||||
export * from "./i18n/useKcTranslation";
|
export * from "./i18n/useKcMessage";
|
||||||
|
|
||||||
export * from "./components/KcProps";
|
export * from "./components/KcProps";
|
||||||
export * from "./components/Login";
|
export * from "./components/Login";
|
||||||
@ -10,5 +10,7 @@ export * from "./components/Template";
|
|||||||
export * from "./components/KcApp";
|
export * from "./components/KcApp";
|
||||||
export * from "./components/Info";
|
export * from "./components/Info";
|
||||||
export * from "./components/Error";
|
export * from "./components/Error";
|
||||||
|
export * from "./components/LoginResetPassword";
|
||||||
|
export * from "./components/LoginVerifyEmail";
|
||||||
|
|
||||||
export * from "./tools/assert";
|
export * from "./tools/assert";
|
@ -4,13 +4,15 @@ import type { PageId } from "../bin/build-keycloak-theme/generateFtl";
|
|||||||
import { id } from "evt/tools/typeSafety/id";
|
import { id } from "evt/tools/typeSafety/id";
|
||||||
import type { KcLanguageTag } from "./i18n/KcLanguageTag";
|
import type { KcLanguageTag } from "./i18n/KcLanguageTag";
|
||||||
import { doExtends } from "evt/tools/typeSafety/doExtends";
|
import { doExtends } from "evt/tools/typeSafety/doExtends";
|
||||||
import type { MessageKey } from "./i18n/useKcTranslation";
|
import type { MessageKey } from "./i18n/useKcMessage";
|
||||||
import type { LanguageLabel } from "./i18n/KcLanguageTag";
|
import type { LanguageLabel } from "./i18n/KcLanguageTag";
|
||||||
|
|
||||||
type ExtractAfterStartingWith<Prefix extends string, StrEnum> =
|
type ExtractAfterStartingWith<Prefix extends string, StrEnum> =
|
||||||
StrEnum extends `${Prefix}${infer U}` ? U : never;
|
StrEnum extends `${Prefix}${infer U}` ? U : never;
|
||||||
|
|
||||||
export type KcContext = KcContext.Login | KcContext.Register | KcContext.Info | KcContext.Error | KcContext.LoginResetPassword;
|
export type KcContext =
|
||||||
|
KcContext.Login | KcContext.Register | KcContext.Info |
|
||||||
|
KcContext.Error | KcContext.LoginResetPassword | KcContext.LoginVerifyEmail;
|
||||||
export declare namespace KcContext {
|
export declare namespace KcContext {
|
||||||
|
|
||||||
export type Template = {
|
export type Template = {
|
||||||
@ -145,6 +147,10 @@ export declare namespace KcContext {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type LoginVerifyEmail = Template & {
|
||||||
|
pageId: "login-verify-email.ftl";
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
doExtends<KcContext["pageId"], PageId>();
|
doExtends<KcContext["pageId"], PageId>();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user