diff --git a/package.json b/package.json index 7960676..8a24f90 100755 --- a/package.json +++ b/package.json @@ -13,6 +13,12 @@ "keycloak": "yarn build && keycloakify", "download-builtin-keycloak-theme": "download-builtin-keycloak-theme 15.0.2" }, + "keycloakify": { + "extraPages": [ + "my-extra-page-1.ftl", + "my-extra-page-2.ftl" + ] + }, "author": "u/garronej", "license": "MIT", "keywords": [], @@ -20,7 +26,8 @@ "@emotion/react": "^11.9.0", "keycloakify": "^6.0.0", "react": "18.1.0", - "react-dom": "18.1.0" + "react-dom": "18.1.0", + "evt": "^2.4.1" }, "devDependencies": { "@types/node": "^15.3.1", diff --git a/src/KcApp/KcApp.tsx b/src/KcApp/KcApp.tsx index ca05e14..1f5ea8e 100644 --- a/src/KcApp/KcApp.tsx +++ b/src/KcApp/KcApp.tsx @@ -1,70 +1,41 @@ -import "./KcApp.css"; +import { lazy, Suspense } from "react"; import type { KcContext } from "./kcContext"; -import KcAppBase, { defaultKcProps, useDownloadTerms, useI18n } from "keycloakify"; -import tos_en_url from "./tos_en.md"; -import tos_fr_url from "./tos_fr.md"; +import KcAppBase, { defaultKcProps } from "keycloakify"; +import { useI18n } from "./i18n"; + +const Terms = lazy(() => import("./Terms")); export type Props = { kcContext: KcContext; }; -export default function KcApp(props: Props) { - const { kcContext } = props; +export default function KcApp({ kcContext }: Props) { + const i18n = useI18n({ kcContext }); - useDownloadTerms({ - kcContext, - "downloadTermMarkdown": async ({ currentLanguageTag }) => { - const markdownString = await fetch( - (() => { - switch (currentLanguageTag) { - case "fr": - return tos_fr_url; - default: - return tos_en_url; - } - })(), - ).then(response => response.text()); - - return markdownString; - }, - }); - - const i18n = useI18n({ - kcContext, - // NOTE: Here you can override the default i18n messages - // or define new ones that, for example, you would have - // defined in the Keycloak admin UI for UserProfile - // https://user-images.githubusercontent.com/6702424/182050652-522b6fe6-8ee5-49df-aca3-dba2d33f24a5.png - "extraMessages": { - "en": { - "foo": "foo in English", - // Here we overwrite the default english value for the message "doForgotPassword" - // that is "Forgot Password?" see: https://github.com/InseeFrLab/keycloakify/blob/f0ae5ea908e0aa42391af323b6d5e2fd371af851/src/lib/i18n/generated_messages/18.0.1/login/en.ts#L17 - "doForgotPassword": "I forgot my password" - }, - "fr": { - /* spell-checker: disable */ - "foo": "foo en Francais", - "doForgotPassword": "J'ai oublié mon mot de passe" - /* spell-checker: enable */ - }, - }, - }); - - //NOTE: Locale not yet downloaded + //NOTE: Locales not yet downloaded if (i18n === null) { return null; } + const props = { + i18n, + ...defaultKcProps, + // NOTE: The classes are defined in ./KcApp.css + "kcHeaderWrapperClass": "my-color my-font", + }; + return ( - + + {(() => { + switch (kcContext.pageId) { + case "register.ftl": return ; + case "terms.ftl": return ; + case "my-extra-page-1.ftl": return ; + case "my-extra-page-2.ftl": return ; + default: return ; + } + })()} + ); + } diff --git a/src/KcApp/Terms.tsx b/src/KcApp/Terms.tsx new file mode 100644 index 0000000..c3364df --- /dev/null +++ b/src/KcApp/Terms.tsx @@ -0,0 +1,96 @@ +import { memo } from "react"; +import Template from "keycloakify/lib/components/Template"; +import type { KcProps } from "keycloakify"; +import { useDownloadTerms } from "keycloakify"; +import type { KcContext } from "./kcContext"; +import type { I18n } from "./i18n"; +import { evtTermMarkdown } from "keycloakify/lib/components/Terms"; +import { useRerenderOnStateChange } from "evt/hooks"; +import tos_en_url from "./tos_en.md"; +import tos_fr_url from "./tos_fr.md"; +import { useCssAndCx } from "keycloakify/lib/tools/useCssAndCx"; + +/** + * NOTE: Yo do not need to do all this to put your own Terms and conditions + * this is if you want component level customization. + * If the default works for you you can just use the useDownloadTerms hook + * in the KcApp.tsx + * Example: https://github.com/garronej/keycloakify-starter/blob/a20c21b2aae7c6dc6dbea294f3d321955ddf9355/src/KcApp/KcApp.tsx#L14-L30 + */ + +type KcContext_Terms = Extract; + +const Terms = memo( + ({ + kcContext, + i18n, + ...props + }: { kcContext: KcContext_Terms; i18n: I18n } & KcProps) => { + const { url } = kcContext; + + useDownloadTerms({ + kcContext, + "downloadTermMarkdown": async ({ currentLanguageTag }) => { + + const markdownString = await fetch((() => { + switch (currentLanguageTag) { + case "fr": return tos_fr_url; + default: return tos_en_url; + } + })()).then(response => response.text()); + + return markdownString; + }, + }); + + useRerenderOnStateChange(evtTermMarkdown); + + const { cx } = useCssAndCx(); + + if (evtTermMarkdown.state === undefined) { + return null; + } + + const { msg, msgStr } = i18n; + + return ( +