From 4ca2bc59b663134f8b6ff732e1003edf9fccc090 Mon Sep 17 00:00:00 2001 From: garronej Date: Mon, 11 Oct 2021 03:25:02 +0200 Subject: [PATCH] Support register-user-profile.ftl --- .../generateFtl/common.ftl | 140 +++++------ .../generateFtl/generateFtl.ts | 11 +- src/lib/components/KcApp.tsx | 2 + src/lib/components/KcProps.ts | 6 + src/lib/components/RegisterUserProfile.tsx | 226 ++++++++++++++++++ src/lib/getKcContext/KcContextBase.ts | 73 +++--- src/lib/i18n/useKcMessage.tsx | 10 +- src/lib/tools/ReactComponent.ts | 6 + 8 files changed, 346 insertions(+), 128 deletions(-) create mode 100644 src/lib/components/RegisterUserProfile.tsx create mode 100644 src/lib/tools/ReactComponent.ts diff --git a/src/bin/build-keycloak-theme/generateFtl/common.ftl b/src/bin/build-keycloak-theme/generateFtl/common.ftl index eb6dfad1..3482119e 100644 --- a/src/bin/build-keycloak-theme/generateFtl/common.ftl +++ b/src/bin/build-keycloak-theme/generateFtl/common.ftl @@ -134,97 +134,67 @@ obj, { "messagesPerField": { - "printIfExists": function (key, x) { - switch(key){ - case "userLabel": return (function (){ + + <#assign fieldNames = ["global", "userLabel", "username", "email", "firstName", "lastName", "password", "password-confirm"]> + + <#attempt> + <#list profile.attributes as attribute> + <#assign fieldNames += [attribute.name]> + + <#recover> + + + "printIfExists": function (fieldName, x) { + <#list fieldNames as fieldName> + if(fieldName === "${fieldName}" ){ <#attempt> - return "${messagesPerField.printIfExists('userLabel','1')}" ? x : undefined; + return "${messagesPerField.printIfExists(fieldName,'1')}" ? x : undefined; <#recover> - })(); - case "username": return (function (){ - <#attempt> - return "${messagesPerField.printIfExists('username','1')}" ? x : undefined; - <#recover> - - })(); - case "email": return (function (){ - <#attempt> - return "${messagesPerField.printIfExists('email','1')}" ? x : undefined; - <#recover> - - })(); - case "firstName": return (function (){ - <#attempt> - return "${messagesPerField.printIfExists('firstName','1')}" ? x : undefined; - <#recover> - - })(); - case "lastName": return (function (){ - <#attempt> - return "${messagesPerField.printIfExists('lastName','1')}" ? x : undefined; - <#recover> - - })(); - case "password": return (function (){ - <#attempt> - return "${messagesPerField.printIfExists('password','1')}" ? x : undefined; - <#recover> - - })(); - case "password-confirm": return (function (){ - <#attempt> - return "${messagesPerField.printIfExists('password-confirm','1')}" ? x : undefined; - <#recover> - - })(); - } + } + + throw new Error("There is no " + fieldName " field"); }, - "existsError": function (key) { - - <#attempt> - - <#list profile.attributes as attribute> - - if(key === "${attribute.name}" ){ - - return <#if messagesPerField.existsError('${attribute.name}')>true<#else>false; - - } - - - - <#recover> - - - throw new Error(key + " is not an exsisting profile attribute name"); - - }, - "get": function (key) { - - <#attempt> - - <#list profile.attributes as attribute> - - <#if messagesPerField.existsError('${attribute.name}')> - - if(key === "${attribute.name}" ){ - return "${messagesPerField.get('${attribute.name}')?no_esc}" - } - - - - - - <#recover> - - - throw new Error(" there is no message for " + key); - - } + "existsError": function (fieldName) { + <#list fieldNames as fieldName> + if(fieldName === "${fieldName}" ){ + <#attempt> + return <#if messagesPerField.existsError('${fieldName}')>true<#else>false; + <#recover> + + } + + throw new Error("There is no " + fieldName " field"); + }, + "get": function (fieldName) { + <#list fieldNames as fieldName> + if(fieldName === "${fieldName}" ){ + <#attempt> + <#if messagesPerField.existsError('${fieldName}')> + if(fieldName === "${fieldName}" ){ + return "${messagesPerField.get('${fieldName}')?no_esc}"; + } + + <#recover> + + } + + throw new Error("There is no " + fieldName " field"); + }, + "exists": function (fieldName) { + <#list fieldNames as fieldName> + if(fieldName === "${fieldName}" ){ + <#attempt> + return <#if messagesPerField.exists('${fieldName}')>true<#else>false; + <#recover> + + } + + throw new Error("There is no " + fieldName " field"); + } }, "msg": function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); }, - "advancedMsg": function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); }, + "advancedMsg": function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); } } ); diff --git a/src/bin/build-keycloak-theme/generateFtl/generateFtl.ts b/src/bin/build-keycloak-theme/generateFtl/generateFtl.ts index 4fa144ca..f6cbd866 100644 --- a/src/bin/build-keycloak-theme/generateFtl/generateFtl.ts +++ b/src/bin/build-keycloak-theme/generateFtl/generateFtl.ts @@ -1,5 +1,3 @@ - - import cheerio from "cheerio"; import { replaceImportsFromStaticInJsCode, @@ -12,11 +10,10 @@ import { objectKeys } from "tsafe/objectKeys"; import { ftlValuesGlobalName } from "../ftlValuesGlobalName"; export const pageIds = [ - "login.ftl", "register.ftl", "info.ftl", - "error.ftl", "login-reset-password.ftl", - "login-verify-email.ftl", "terms.ftl", - "login-otp.ftl", "login-update-profile.ftl", - "login-idp-link-confirm.ftl" + "login.ftl", "register.ftl", "register-user-profile.ftl", + "info.ftl", "error.ftl", "login-reset-password.ftl", + "login-verify-email.ftl", "terms.ftl", "login-otp.ftl", + "login-update-profile.ftl", "login-idp-link-confirm.ftl" ] as const; export type PageId = typeof pageIds[number]; diff --git a/src/lib/components/KcApp.tsx b/src/lib/components/KcApp.tsx index 81b0e0ba..5b6b8c17 100644 --- a/src/lib/components/KcApp.tsx +++ b/src/lib/components/KcApp.tsx @@ -4,6 +4,7 @@ import type { KcContextBase } from "../getKcContext/KcContextBase"; import type { KcProps } from "./KcProps"; import { Login } from "./Login"; import { Register } from "./Register"; +import { RegisterUserProfile } from "./RegisterUserProfile"; import { Info } from "./Info"; import { Error } from "./Error"; import { LoginResetPassword } from "./LoginResetPassword"; @@ -17,6 +18,7 @@ export const KcApp = memo(({ kcContext, ...props }: { kcContext: KcContextBase; switch (kcContext.pageId) { case "login.ftl": return ; case "register.ftl": return ; + case "register-user-profile.ftl": return ; case "info.ftl": return ; case "error.ftl": return ; case "login-reset-password.ftl": return ; diff --git a/src/lib/components/KcProps.ts b/src/lib/components/KcProps.ts index e72df457..0112dd16 100644 --- a/src/lib/components/KcProps.ts +++ b/src/lib/components/KcProps.ts @@ -94,12 +94,14 @@ export type KcProps = KcPropsGeneric< "kcFormGroupErrorClass" | "kcLabelClass" | "kcInputClass" | + "kcInputErrorMessageClass" | "kcInputWrapperClass" | "kcFormOptionsClass" | "kcFormButtonsClass" | "kcFormSettingClass" | "kcTextareaClass" | "kcInfoAreaClass" | + "kcFormGroupHeader" | "kcButtonClass" | "kcButtonPrimaryClass" | "kcButtonDefaultClass" | @@ -147,6 +149,7 @@ export const defaultKcProps = { "kcFormGroupErrorClass": ["has-error"], "kcLabelClass": ["control-label"], "kcInputClass": ["form-control"], + "kcInputErrorMessageClass": ["pf-c-form__helper-text", "pf-m-error", "required", "kc-feedback-text"], "kcInputWrapperClass": ["col-xs-12", "col-sm-12", "col-md-12", "col-lg-12"], "kcFormOptionsClass": ["col-xs-12", "col-sm-12", "col-md-12", "col-lg-12"], "kcFormButtonsClass": ["col-xs-12", "col-sm-12", "col-md-12", "col-lg-12"], @@ -155,6 +158,9 @@ export const defaultKcProps = { "kcInfoAreaClass": ["col-xs-12", "col-sm-4", "col-md-4", "col-lg-5", "details"], + // user-profile grouping + "kcFormGroupHeader": ["pf-c-form__group"], + // css classes for form buttons main class used for all buttons "kcButtonClass": ["btn"], // classes defining priority of the button - primary or default (there is typically only one priority button for the form) diff --git a/src/lib/components/RegisterUserProfile.tsx b/src/lib/components/RegisterUserProfile.tsx new file mode 100644 index 00000000..b2e26042 --- /dev/null +++ b/src/lib/components/RegisterUserProfile.tsx @@ -0,0 +1,226 @@ + +import { memo, Fragment } from "react"; +import { Template } from "./Template"; +import type { KcProps } from "./KcProps"; +import type { KcContextBase } from "../getKcContext/KcContextBase"; +import { useKcMessage } from "../i18n/useKcMessage"; +import { useCssAndCx } from "tss-react"; +import type { ReactComponent } from "../tools/ReactComponent"; + +export const RegisterUserProfile = memo(({ kcContext, ...props }: { kcContext: KcContextBase.RegisterUserProfile; } & KcProps) => { + + const { + url, + messagesPerField, + realm, + passwordRequired, + recaptchaRequired, + recaptchaSiteKey + } = kcContext; + + const { msg, msgStr } = useKcMessage(); + + const { cx } = useCssAndCx(); + + return ( +