From 6d1cbdc4630a242a80955a9d82aae474def7267b Mon Sep 17 00:00:00 2001 From: garronej Date: Tue, 6 Sep 2022 19:12:59 +0200 Subject: [PATCH 01/77] Bump version --- .github/workflows/ci.yaml | 2 -- README.md | 6 ++++-- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4d84f3b5..ce3b4939 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,11 +3,9 @@ on: push: branches: - main - - v6 pull_request: branches: - main - - v6 jobs: diff --git a/README.md b/README.md index aabb1362..bd3111b3 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

- 🔏 Create Keycloak themes using React 🔏 + 🔏 Create Keycloak themes using React 🔏

@@ -36,6 +36,8 @@

+> 🗣 V6 have been released 🎉 (It features major improvements)[#600]. Checkout [the migration guide](https://docs.keycloakify.dev/v5-to-v6). + # Changelog highlights ## 6.0.0 @@ -45,7 +47,7 @@ - Real i18n API. - Actual documentation for build options. -Checkout the migration guide. +Checkout [the migration guide](https://docs.keycloakify.dev/v5-to-v6) ## 5.8.0 diff --git a/package.json b/package.json index eaeb88d1..8deef68e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "keycloakify", - "version": "6.0.0-beta.14", + "version": "6.0.0", "description": "Keycloak theme generator for Reacts app", "repository": { "type": "git", From b4a22fc9dd063bf48549189145aa6d7f2257c998 Mon Sep 17 00:00:00 2001 From: garronej Date: Tue, 6 Sep 2022 19:13:46 +0200 Subject: [PATCH 02/77] Fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bd3111b3..787450d5 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@

-> 🗣 V6 have been released 🎉 (It features major improvements)[#600]. Checkout [the migration guide](https://docs.keycloakify.dev/v5-to-v6). +> 🗣 V6 have been released 🎉 [It features major improvements](/#600). Checkout [the migration guide](https://docs.keycloakify.dev/v5-to-v6). # Changelog highlights From c059eff17013679b8c439ee6c2ca9910f26bd41e Mon Sep 17 00:00:00 2001 From: garronej Date: Tue, 6 Sep 2022 19:14:39 +0200 Subject: [PATCH 03/77] Update README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 787450d5..0037c5f0 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,9 @@

-> 🗣 V6 have been released 🎉 [It features major improvements](/#600). Checkout [the migration guide](https://docs.keycloakify.dev/v5-to-v6). +> 🗣 V6 have been released 🎉 +> [It features major improvements](/#600). +> Checkout [the migration guide](https://docs.keycloakify.dev/v5-to-v6). # Changelog highlights From 33a264b3d04c7c946d1011beacf5dfc7aa7119c2 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Wed, 7 Sep 2022 00:32:38 +0200 Subject: [PATCH 04/77] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0037c5f0..b46df429 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@

> 🗣 V6 have been released 🎉 -> [It features major improvements](/#600). +> [It features major improvements](https://github.com/InseeFrLab/keycloakify#600). > Checkout [the migration guide](https://docs.keycloakify.dev/v5-to-v6). # Changelog highlights From 875322669cd50328c34cc6b0c167eb5b916eded1 Mon Sep 17 00:00:00 2001 From: garronej Date: Wed, 7 Sep 2022 11:25:46 +0200 Subject: [PATCH 05/77] Rename isAppAndKeycloakServerSharingSameDomain to areAppAndKeycloakServerSharingSameDomain #145 --- src/bin/keycloakify/BuildOptions.ts | 16 ++++++++-------- src/bin/keycloakify/generateFtl/generateFtl.ts | 6 +++--- .../generateKeycloakThemeResources.ts | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/bin/keycloakify/BuildOptions.ts b/src/bin/keycloakify/BuildOptions.ts index 45fabb76..92f7c13c 100644 --- a/src/bin/keycloakify/BuildOptions.ts +++ b/src/bin/keycloakify/BuildOptions.ts @@ -11,7 +11,7 @@ type ParsedPackageJson = { keycloakify?: { extraPages?: string[]; extraThemeProperties?: string[]; - isAppAndKeycloakServerSharingSameDomain?: boolean; + areAppAndKeycloakServerSharingSameDomain?: boolean; }; }; @@ -23,7 +23,7 @@ const zParsedPackageJson = z.object({ .object({ "extraPages": z.array(z.string()).optional(), "extraThemeProperties": z.array(z.string()).optional(), - "isAppAndKeycloakServerSharingSameDomain": z.boolean().optional() + "areAppAndKeycloakServerSharingSameDomain": z.boolean().optional() }) .optional() }); @@ -56,11 +56,11 @@ export namespace BuildOptions { }; export type SameDomain = CommonExternalAssets & { - isAppAndKeycloakServerSharingSameDomain: true; + areAppAndKeycloakServerSharingSameDomain: true; }; export type DifferentDomains = CommonExternalAssets & { - isAppAndKeycloakServerSharingSameDomain: false; + areAppAndKeycloakServerSharingSameDomain: false; urlOrigin: string; urlPathname: string | undefined; }; @@ -140,10 +140,10 @@ export function readBuildOptions(params: { "isStandalone": false }); - if (parsedPackageJson.keycloakify?.isAppAndKeycloakServerSharingSameDomain) { + if (parsedPackageJson.keycloakify?.areAppAndKeycloakServerSharingSameDomain) { return id({ ...commonExternalAssets, - "isAppAndKeycloakServerSharingSameDomain": true + "areAppAndKeycloakServerSharingSameDomain": true }); } else { assert( @@ -155,14 +155,14 @@ export function readBuildOptions(params: { "public/CNAME file.", "Alternatively, if your app and the Keycloak server are on the same domain, ", "eg https://example.com is your app and https://example.com/auth is the keycloak", - 'admin UI, you can set "keycloakify": { "isAppAndKeycloakServerSharingSameDomain": true }', + 'admin UI, you can set "keycloakify": { "areAppAndKeycloakServerSharingSameDomain": true }', "in your package.json" ].join(" ") ); return id({ ...commonExternalAssets, - "isAppAndKeycloakServerSharingSameDomain": false, + "areAppAndKeycloakServerSharingSameDomain": false, "urlOrigin": url.origin, "urlPathname": url.pathname }); diff --git a/src/bin/keycloakify/generateFtl/generateFtl.ts b/src/bin/keycloakify/generateFtl/generateFtl.ts index f57f4990..1209cfd6 100644 --- a/src/bin/keycloakify/generateFtl/generateFtl.ts +++ b/src/bin/keycloakify/generateFtl/generateFtl.ts @@ -46,11 +46,11 @@ export namespace BuildOptionsLike { }; export type SameDomain = CommonExternalAssets & { - isAppAndKeycloakServerSharingSameDomain: true; + areAppAndKeycloakServerSharingSameDomain: true; }; export type DifferentDomains = CommonExternalAssets & { - isAppAndKeycloakServerSharingSameDomain: false; + areAppAndKeycloakServerSharingSameDomain: false; urlOrigin: string; urlPathname: string | undefined; }; @@ -76,7 +76,7 @@ export function generateFtlFilesCodeFactory(params: { const $ = cheerio.load(indexHtmlCode); fix_imports_statements: { - if (!buildOptions.isStandalone && buildOptions.isAppAndKeycloakServerSharingSameDomain) { + if (!buildOptions.isStandalone && buildOptions.areAppAndKeycloakServerSharingSameDomain) { break fix_imports_statements; } diff --git a/src/bin/keycloakify/generateKeycloakThemeResources.ts b/src/bin/keycloakify/generateKeycloakThemeResources.ts index 85374cfd..c149957b 100644 --- a/src/bin/keycloakify/generateKeycloakThemeResources.ts +++ b/src/bin/keycloakify/generateKeycloakThemeResources.ts @@ -34,11 +34,11 @@ export namespace BuildOptionsLike { }; export type SameDomain = CommonExternalAssets & { - isAppAndKeycloakServerSharingSameDomain: true; + areAppAndKeycloakServerSharingSameDomain: true; }; export type DifferentDomains = CommonExternalAssets & { - isAppAndKeycloakServerSharingSameDomain: false; + areAppAndKeycloakServerSharingSameDomain: false; urlOrigin: string; urlPathname: string | undefined; }; @@ -97,7 +97,7 @@ export function generateKeycloakThemeResources(params: { } if (/\.js?$/i.test(filePath)) { - if (!buildOptions.isStandalone && buildOptions.isAppAndKeycloakServerSharingSameDomain) { + if (!buildOptions.isStandalone && buildOptions.areAppAndKeycloakServerSharingSameDomain) { return undefined; } From 987f3d758625714186532f7ebd7e40c6f8a78b63 Mon Sep 17 00:00:00 2001 From: garronej Date: Wed, 7 Sep 2022 11:26:10 +0200 Subject: [PATCH 06/77] Bump version (changelog ignore) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8deef68e..161102bf 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "keycloakify", - "version": "6.0.0", + "version": "6.0.1", "description": "Keycloak theme generator for Reacts app", "repository": { "type": "git", From a13f710325ae105c09df43e380847774d766782f Mon Sep 17 00:00:00 2001 From: garronej Date: Wed, 7 Sep 2022 11:50:24 +0200 Subject: [PATCH 07/77] Important fix for --external-assets --- .../replacers/replaceImportsFromStaticInJsCode.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bin/keycloakify/replacers/replaceImportsFromStaticInJsCode.ts b/src/bin/keycloakify/replacers/replaceImportsFromStaticInJsCode.ts index d6c0c25b..ac0ffceb 100644 --- a/src/bin/keycloakify/replacers/replaceImportsFromStaticInJsCode.ts +++ b/src/bin/keycloakify/replacers/replaceImportsFromStaticInJsCode.ts @@ -57,7 +57,7 @@ export function replaceImportsFromStaticInJsCode(params: { jsCode: string; build : ` var p= ""; Object.defineProperty(${n}, "p", { - get: function() { return "${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}" : p; }, + get: function() { return "${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}/" : p; }, set: function (value){ p = value;} }); ` @@ -73,13 +73,13 @@ export function replaceImportsFromStaticInJsCode(params: { jsCode: string; build .replace(/([a-zA-Z]+\.[a-zA-Z]+)\+"static\//g, (...[, group]) => buildOptions.isStandalone ? `window.${ftlValuesGlobalName}.url.resourcesPath + "/build/static/` - : `("${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}" : ${group}) + "static/` + : `("${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}/" : ${group}) + "static/` ) //TODO: Write a test case for this .replace(/".chunk.css",([a-zA-Z])+=([a-zA-Z]+\.[a-zA-Z]+)\+([a-zA-Z]+),/, (...[, group1, group2, group3]) => buildOptions.isStandalone ? `".chunk.css",${group1} = window.${ftlValuesGlobalName}.url.resourcesPath + "/build/" + ${group3},` - : `".chunk.css",${group1} = ("${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}" : ${group2}) + ${group3},` + : `".chunk.css",${group1} = ("${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}/" : ${group2}) + ${group3},` ); return { fixedJsCode }; From 9262d21829dc1c88bccd8d3f42ff77baab81a87e Mon Sep 17 00:00:00 2001 From: garronej Date: Wed, 7 Sep 2022 11:50:41 +0200 Subject: [PATCH 08/77] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 161102bf..7ed32c3c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "keycloakify", - "version": "6.0.1", + "version": "6.0.2", "description": "Keycloak theme generator for Reacts app", "repository": { "type": "git", From ee407c32ada300f067f54d81c8f03fe7eb0d80ce Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Wed, 7 Sep 2022 11:53:18 +0200 Subject: [PATCH 09/77] Create FUNDING.yaml --- .github/FUNDING.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/FUNDING.yaml diff --git a/.github/FUNDING.yaml b/.github/FUNDING.yaml new file mode 100644 index 00000000..e4fc35a1 --- /dev/null +++ b/.github/FUNDING.yaml @@ -0,0 +1,5 @@ +# These are supported funding model platforms + +github: [garronej] +open_collective: keycloakify +custom: ['https://www.ringerhq.com/experts/garronej'] From c0a0eb02fbaaf8a662a2d474c2dd6c51487fa932 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Wed, 7 Sep 2022 11:59:42 +0200 Subject: [PATCH 10/77] Remove Open collectivity --- .github/FUNDING.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/FUNDING.yaml b/.github/FUNDING.yaml index e4fc35a1..daf83ff5 100644 --- a/.github/FUNDING.yaml +++ b/.github/FUNDING.yaml @@ -1,5 +1,4 @@ # These are supported funding model platforms github: [garronej] -open_collective: keycloakify custom: ['https://www.ringerhq.com/experts/garronej'] From 0c315385ddc38fd29d4814a95f469928085ad438 Mon Sep 17 00:00:00 2001 From: garronej Date: Wed, 7 Sep 2022 12:00:23 +0200 Subject: [PATCH 11/77] Update fix tests --- src/test/bin/replaceImportFromStatic.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/bin/replaceImportFromStatic.ts b/src/test/bin/replaceImportFromStatic.ts index 610d3809..2a498cad 100644 --- a/src/test/bin/replaceImportFromStatic.ts +++ b/src/test/bin/replaceImportFromStatic.ts @@ -103,13 +103,13 @@ import { assetIsSameCode } from "../tools/assertIsSameCode"; const fixedJsCodeExpected = ` function f() { - return ("kcContext" in window ? "https://demo-app.keycloakify.dev" : a.p) + "static/js/" + ({}[e] || e) + "." + { + return ("kcContext" in window ? "https://demo-app.keycloakify.dev/" : a.p) + "static/js/" + ({}[e] || e) + "." + { 3: "0664cdc0" }[e] + ".chunk.js" } function sameAsF() { - return ("kcContext" in window ? "https://demo-app.keycloakify.dev" : a.p) + "static/js/" + ({}[e] || e) + "." + { + return ("kcContext" in window ? "https://demo-app.keycloakify.dev/" : a.p) + "static/js/" + ({}[e] || e) + "." + { 3: "0664cdc0" }[e] + ".chunk.js" } @@ -119,7 +119,7 @@ import { assetIsSameCode } from "../tools/assertIsSameCode"; if( pd === undefined || pd.configurable ){ var p= ""; Object.defineProperty(__webpack_require__, "p", { - get: function() { return "kcContext" in window ? "https://demo-app.keycloakify.dev" : p; }, + get: function() { return "kcContext" in window ? "https://demo-app.keycloakify.dev/" : p; }, set: function (value){ p = value; } }); } @@ -137,7 +137,7 @@ import { assetIsSameCode } from "../tools/assertIsSameCode"; if( pd === undefined || pd.configurable ){ var p= ""; Object.defineProperty(t, "p", { - get: function() { return "kcContext" in window ? "https://demo-app.keycloakify.dev" : p; }, + get: function() { return "kcContext" in window ? "https://demo-app.keycloakify.dev/" : p; }, set: function (value){ p = value; } }); } From a0be35db8b35fe8482a2fa637dc31482f736d196 Mon Sep 17 00:00:00 2001 From: garronej Date: Wed, 7 Sep 2022 13:39:54 +0200 Subject: [PATCH 12/77] Fix compat with StrictMode react 18 --- src/lib/i18n/index.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/lib/i18n/index.tsx b/src/lib/i18n/index.tsx index 5e63620e..289ce92c 100644 --- a/src/lib/i18n/index.tsx +++ b/src/lib/i18n/index.tsx @@ -83,8 +83,6 @@ export function __unsafe_useI18n(params: return; } - let isMounted = true; - refHasStartedFetching.current = true; (async () => { @@ -144,10 +142,6 @@ export function __unsafe_useI18n(params: })() ]).then(modules => modules.map(module => module.default)); - if (!isMounted) { - return; - } - setI18n({ ...createI18nTranslationFunctions({ "fallbackMessages": { @@ -180,10 +174,6 @@ export function __unsafe_useI18n(params: ) }); })(); - - return () => { - isMounted = false; - }; }, []); return i18n ?? null; From da4146eb59d7dc2074bdf0899f3336fa229288d3 Mon Sep 17 00:00:00 2001 From: garronej Date: Wed, 7 Sep 2022 13:40:18 +0200 Subject: [PATCH 13/77] Bump version (changelog ignore) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7ed32c3c..175ea53a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "keycloakify", - "version": "6.0.2", + "version": "6.0.3", "description": "Keycloak theme generator for Reacts app", "repository": { "type": "git", From 80d4a808d390e40b2ba7a234620216ba1b1bf1c8 Mon Sep 17 00:00:00 2001 From: garronej Date: Wed, 7 Sep 2022 13:45:34 +0200 Subject: [PATCH 14/77] Update readme --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b46df429..38eb42c8 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,14 @@
Home - Documentation -

+

+

---- Project starter / Demo setup ----

+

+ CSS Level customization + - + Component Level customization +

+

----

From 11b2342da0dfe03bddffef5d62e7f90109753170 Mon Sep 17 00:00:00 2001 From: German Ivanov Date: Thu, 8 Sep 2022 12:06:26 +0300 Subject: [PATCH 15/77] feat: add silent flag --- package.json | 2 ++ src/bin/create-keycloak-email-directory.ts | 11 +++++--- src/bin/download-builtin-keycloak-theme.ts | 16 +++++++---- src/bin/generate-i18n-messages.ts | 12 ++++++--- src/bin/keycloakify/BuildOptions.ts | 7 +++-- .../generateKeycloakThemeResources.ts | 8 ++++-- src/bin/keycloakify/keycloakify.ts | 11 +++++--- src/bin/tools/cliOptions.ts | 15 +++++++++++ src/bin/tools/downloadAndUnzip.ts | 10 +++++-- src/bin/tools/logger.ts | 27 +++++++++++++++++++ yarn.lock | 10 +++++++ 11 files changed, 109 insertions(+), 20 deletions(-) create mode 100644 src/bin/tools/cliOptions.ts create mode 100644 src/bin/tools/logger.ts diff --git a/package.json b/package.json index 175ea53a..2ccc6101 100755 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "devDependencies": { "@emotion/react": "^11.4.1", "@types/memoizee": "^0.4.7", + "@types/minimist": "^1.2.2", "@types/node": "^17.0.25", "@types/react": "18.0.9", "copyfiles": "^2.4.1", @@ -78,6 +79,7 @@ "evt": "^2.4.0", "memoizee": "^0.4.15", "minimal-polyfills": "^2.2.2", + "minimist": "^1.2.6", "path-browserify": "^1.0.1", "powerhooks": "^0.20.15", "react-markdown": "^5.0.3", diff --git a/src/bin/create-keycloak-email-directory.ts b/src/bin/create-keycloak-email-directory.ts index 9d72d0bb..1a3dc77d 100644 --- a/src/bin/create-keycloak-email-directory.ts +++ b/src/bin/create-keycloak-email-directory.ts @@ -6,11 +6,15 @@ import { join as pathJoin, basename as pathBasename } from "path"; import { transformCodebase } from "./tools/transformCodebase"; import { promptKeycloakVersion } from "./promptKeycloakVersion"; import * as fs from "fs"; +import { getCliOptions } from "./tools/cliOptions"; +import { getLogger } from "./tools/logger"; if (require.main === module) { (async () => { + const { isSilent } = getCliOptions(process.argv.slice(2)); + const logger = getLogger({ isSilent }); if (fs.existsSync(keycloakThemeEmailDirPath)) { - console.log(`There is already a ./${pathBasename(keycloakThemeEmailDirPath)} directory in your project. Aborting.`); + logger.warn(`There is already a ./${pathBasename(keycloakThemeEmailDirPath)} directory in your project. Aborting.`); process.exit(-1); } @@ -21,7 +25,8 @@ if (require.main === module) { downloadBuiltinKeycloakTheme({ keycloakVersion, - "destDirPath": builtinKeycloakThemeTmpDirPath + "destDirPath": builtinKeycloakThemeTmpDirPath, + "isSilent": isSilent }); transformCodebase({ @@ -29,7 +34,7 @@ if (require.main === module) { "destDirPath": keycloakThemeEmailDirPath }); - console.log(`./${pathBasename(keycloakThemeEmailDirPath)} ready to be customized`); + logger.log(`./${pathBasename(keycloakThemeEmailDirPath)} ready to be customized`); fs.rmSync(builtinKeycloakThemeTmpDirPath, { "recursive": true, "force": true }); })(); diff --git a/src/bin/download-builtin-keycloak-theme.ts b/src/bin/download-builtin-keycloak-theme.ts index 3aa7ede9..12bef872 100644 --- a/src/bin/download-builtin-keycloak-theme.ts +++ b/src/bin/download-builtin-keycloak-theme.ts @@ -4,31 +4,37 @@ import { keycloakThemeBuildingDirPath } from "./keycloakify"; import { join as pathJoin } from "path"; import { downloadAndUnzip } from "./tools/downloadAndUnzip"; import { promptKeycloakVersion } from "./promptKeycloakVersion"; +import { getCliOptions } from "./tools/cliOptions"; +import { getLogger } from "./tools/logger"; -export function downloadBuiltinKeycloakTheme(params: { keycloakVersion: string; destDirPath: string }) { - const { keycloakVersion, destDirPath } = params; +export function downloadBuiltinKeycloakTheme(params: { keycloakVersion: string; destDirPath: string; isSilent: boolean }) { + const { keycloakVersion, destDirPath, isSilent } = params; for (const ext of ["", "-community"]) { downloadAndUnzip({ "destDirPath": destDirPath, "url": `https://github.com/keycloak/keycloak/archive/refs/tags/${keycloakVersion}.zip`, "pathOfDirToExtractInArchive": `keycloak-${keycloakVersion}/themes/src/main/resources${ext}/theme`, - "cacheDirPath": pathJoin(keycloakThemeBuildingDirPath, ".cache") + "cacheDirPath": pathJoin(keycloakThemeBuildingDirPath, ".cache"), + "isSilent": isSilent }); } } if (require.main === module) { (async () => { + const { isSilent } = getCliOptions(process.argv.slice(2)); + const logger = getLogger({ isSilent }); const { keycloakVersion } = await promptKeycloakVersion(); const destDirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme"); - console.log(`Downloading builtins theme of Keycloak ${keycloakVersion} here ${destDirPath}`); + logger.log(`Downloading builtins theme of Keycloak ${keycloakVersion} here ${destDirPath}`); downloadBuiltinKeycloakTheme({ keycloakVersion, - destDirPath + destDirPath, + isSilent }); })(); } diff --git a/src/bin/generate-i18n-messages.ts b/src/bin/generate-i18n-messages.ts index 431efe7d..2de2bf1d 100644 --- a/src/bin/generate-i18n-messages.ts +++ b/src/bin/generate-i18n-messages.ts @@ -5,6 +5,8 @@ import { crawl } from "./tools/crawl"; import { downloadBuiltinKeycloakTheme } from "./download-builtin-keycloak-theme"; import { getProjectRoot } from "./tools/getProjectRoot"; import { rm_rf, rm_r } from "./tools/rm"; +import { getCliOptions } from "./tools/cliOptions"; +import { getLogger } from "./tools/logger"; //NOTE: To run without argument when we want to generate src/i18n/generated_kcMessages files, // update the version array for generating for newer version. @@ -12,8 +14,11 @@ import { rm_rf, rm_r } from "./tools/rm"; //@ts-ignore const propertiesParser = require("properties-parser"); +const { isSilent } = getCliOptions(process.argv.slice(2)); +const logger = getLogger({ isSilent }); + for (const keycloakVersion of ["11.0.3", "15.0.2", "18.0.1"]) { - console.log({ keycloakVersion }); + logger.log(JSON.stringify({ keycloakVersion })); const tmpDirPath = pathJoin(getProjectRoot(), "tmp_xImOef9dOd44"); @@ -21,7 +26,8 @@ for (const keycloakVersion of ["11.0.3", "15.0.2", "18.0.1"]) { downloadBuiltinKeycloakTheme({ keycloakVersion, - "destDirPath": tmpDirPath + "destDirPath": tmpDirPath, + "isSilent": isSilent }); type Dictionary = { [idiomId: string]: string }; @@ -75,7 +81,7 @@ for (const keycloakVersion of ["11.0.3", "15.0.2", "18.0.1"]) { ) ); - console.log(`${filePath} wrote`); + logger.log(`${filePath} wrote`); }); }); } diff --git a/src/bin/keycloakify/BuildOptions.ts b/src/bin/keycloakify/BuildOptions.ts index 92f7c13c..c6565e62 100644 --- a/src/bin/keycloakify/BuildOptions.ts +++ b/src/bin/keycloakify/BuildOptions.ts @@ -35,6 +35,7 @@ export type BuildOptions = BuildOptions.Standalone | BuildOptions.ExternalAssets export namespace BuildOptions { export type Common = { + isSilent: boolean; version: string; themeName: string; extraPages?: string[]; @@ -71,8 +72,9 @@ export function readBuildOptions(params: { packageJson: string; CNAME: string | undefined; isExternalAssetsCliParamProvided: boolean; + isSilent: boolean; }): BuildOptions { - const { packageJson, CNAME, isExternalAssetsCliParamProvided } = params; + const { packageJson, CNAME, isExternalAssetsCliParamProvided, isSilent } = params; const parsedPackageJson = zParsedPackageJson.parse(JSON.parse(packageJson)); @@ -130,7 +132,8 @@ export function readBuildOptions(params: { })(), "version": version, extraPages, - extraThemeProperties + extraThemeProperties, + isSilent }; })(); diff --git a/src/bin/keycloakify/generateKeycloakThemeResources.ts b/src/bin/keycloakify/generateKeycloakThemeResources.ts index c149957b..2f645fc2 100644 --- a/src/bin/keycloakify/generateKeycloakThemeResources.ts +++ b/src/bin/keycloakify/generateKeycloakThemeResources.ts @@ -11,6 +11,7 @@ import { isInside } from "../tools/isInside"; import type { BuildOptions } from "./BuildOptions"; import { assert } from "tsafe/assert"; import { Reflect } from "tsafe/Reflect"; +import { getLogger } from "../tools/logger"; export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets; @@ -19,6 +20,7 @@ export namespace BuildOptionsLike { themeName: string; extraPages?: string[]; extraThemeProperties?: string[]; + isSilent: boolean; }; export type Standalone = Common & { @@ -60,6 +62,7 @@ export function generateKeycloakThemeResources(params: { }): { doBundlesEmailTemplate: boolean } { const { reactAppBuildDirPath, keycloakThemeBuildingDirPath, keycloakThemeEmailDirPath, keycloakVersion, buildOptions } = params; + const logger = getLogger({ isSilent: buildOptions.isSilent }); const themeDirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", buildOptions.themeName, "login"); let allCssGlobalsToDefine: Record = {}; @@ -117,7 +120,7 @@ export function generateKeycloakThemeResources(params: { email: { if (!fs.existsSync(keycloakThemeEmailDirPath)) { - console.log( + logger.log( [ `Not bundling email template because ${pathBasename(keycloakThemeEmailDirPath)} does not exist`, `To start customizing the email template, run: 👉 npx create-keycloak-email-directory 👈` @@ -154,7 +157,8 @@ export function generateKeycloakThemeResources(params: { downloadBuiltinKeycloakTheme({ keycloakVersion, - "destDirPath": tmpDirPath + "destDirPath": tmpDirPath, + isSilent: buildOptions.isSilent }); const themeResourcesDirPath = pathJoin(themeDirPath, "resources"); diff --git a/src/bin/keycloakify/keycloakify.ts b/src/bin/keycloakify/keycloakify.ts index d30f3f2e..729461ae 100644 --- a/src/bin/keycloakify/keycloakify.ts +++ b/src/bin/keycloakify/keycloakify.ts @@ -5,6 +5,8 @@ import * as child_process from "child_process"; import { generateStartKeycloakTestingContainer } from "./generateStartKeycloakTestingContainer"; import * as fs from "fs"; import { readBuildOptions } from "./BuildOptions"; +import { getLogger } from "../tools/logger"; +import { getCliOptions } from "../tools/cliOptions"; const reactProjectDirPath = process.cwd(); @@ -12,7 +14,9 @@ export const keycloakThemeBuildingDirPath = pathJoin(reactProjectDirPath, "build export const keycloakThemeEmailDirPath = pathJoin(keycloakThemeBuildingDirPath, "..", "keycloak_email"); export function main() { - console.log("🔏 Building the keycloak theme...⌚"); + const { isSilent, hasExternalAssets } = getCliOptions(process.argv.slice(2)); + const logger = getLogger({ isSilent }); + logger.log("🔏 Building the keycloak theme...⌚"); const buildOptions = readBuildOptions({ "packageJson": fs.readFileSync(pathJoin(reactProjectDirPath, "package.json")).toString("utf8"), @@ -25,7 +29,8 @@ export function main() { return fs.readFileSync(cnameFilePath).toString("utf8"); })(), - "isExternalAssetsCliParamProvided": process.argv[2]?.toLowerCase() === "--external-assets" + "isExternalAssetsCliParamProvided": hasExternalAssets, + "isSilent": isSilent }); const { doBundlesEmailTemplate } = generateKeycloakThemeResources({ @@ -59,7 +64,7 @@ export function main() { buildOptions }); - console.log( + logger.log( [ "", `✅ Your keycloak theme has been generated and bundled into ./${pathRelative(reactProjectDirPath, jarFilePath)} 🚀`, diff --git a/src/bin/tools/cliOptions.ts b/src/bin/tools/cliOptions.ts new file mode 100644 index 00000000..9a1b39c6 --- /dev/null +++ b/src/bin/tools/cliOptions.ts @@ -0,0 +1,15 @@ +import parseArgv from "minimist"; + +export type CliOptions = { + isSilent: boolean; + hasExternalAssets: boolean; +}; + +export const getCliOptions = (processArgv: string[]): CliOptions => { + const argv = parseArgv(processArgv); + + return { + isSilent: typeof argv["silent"] === "boolean" ? argv["silent"] : false, + hasExternalAssets: argv["external-assets"] !== undefined + }; +}; diff --git a/src/bin/tools/downloadAndUnzip.ts b/src/bin/tools/downloadAndUnzip.ts index 1522e327..a84cadfb 100644 --- a/src/bin/tools/downloadAndUnzip.ts +++ b/src/bin/tools/downloadAndUnzip.ts @@ -6,7 +6,13 @@ import { rm, rm_rf } from "./rm"; import * as crypto from "crypto"; /** assert url ends with .zip */ -export function downloadAndUnzip(params: { url: string; destDirPath: string; pathOfDirToExtractInArchive?: string; cacheDirPath: string }) { +export function downloadAndUnzip(params: { + isSilent: boolean; + url: string; + destDirPath: string; + pathOfDirToExtractInArchive?: string; + cacheDirPath: string; +}) { const { url, destDirPath, pathOfDirToExtractInArchive, cacheDirPath } = params; const extractDirPath = pathJoin( @@ -54,7 +60,7 @@ export function downloadAndUnzip(params: { url: string; destDirPath: string; pat const zipFileBasename = pathBasename(url); - execSync(`curl -L ${url} -o ${zipFileBasename}`, { "cwd": extractDirPath }); + execSync(`curl -L ${url} -o ${zipFileBasename} ${params.isSilent ? "-s" : ""}`, { "cwd": extractDirPath }); execSync(`unzip -o ${zipFileBasename}${pathOfDirToExtractInArchive === undefined ? "" : ` "${pathOfDirToExtractInArchive}/**/*"`}`, { "cwd": extractDirPath diff --git a/src/bin/tools/logger.ts b/src/bin/tools/logger.ts new file mode 100644 index 00000000..638d93d5 --- /dev/null +++ b/src/bin/tools/logger.ts @@ -0,0 +1,27 @@ +type LoggerOpts = { + force?: boolean; +}; + +type Logger = { + log: (message: string, opts?: LoggerOpts) => void; + warn: (message: string) => void; + error: (message: string) => void; +}; + +export const getLogger = ({ isSilent }: { isSilent?: boolean } = {}): Logger => { + return { + log: (message, { force } = {}) => { + if (isSilent && !force) { + return; + } + + console.log(message); + }, + warn: message => { + console.warn(message); + }, + error: message => { + console.error(message); + } + }; +}; diff --git a/yarn.lock b/yarn.lock index bba0ebc0..0f6e47dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -265,6 +265,11 @@ resolved "https://registry.yarnpkg.com/@types/memoizee/-/memoizee-0.4.8.tgz#04adc0c266a0f5d72db0556fdda2ba17dad9b519" integrity sha512-qDpXKGgwKywnQt/64fH1O0LiPA++QGIYeykEUiZ51HymKVRLnUSGcRuF60IfpPeeXiuRwiR/W4y7S5VzbrgLCA== +"@types/minimist@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" + integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== + "@types/node@^17.0.25": version "17.0.45" resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" @@ -1188,6 +1193,11 @@ minimatch@^3.0.3, minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" +minimist@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" From 1a3e4c68bb242234ca3a5da4d85f544f5b948505 Mon Sep 17 00:00:00 2001 From: German Ivanov Date: Thu, 8 Sep 2022 15:43:03 +0300 Subject: [PATCH 16/77] test: update tests to include silent flag --- src/test/bin/generateKeycloakThemeResources.ts | 3 ++- src/test/bin/setupSampleReactProject.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/bin/generateKeycloakThemeResources.ts b/src/test/bin/generateKeycloakThemeResources.ts index 16ef1a04..d9ac2991 100644 --- a/src/test/bin/generateKeycloakThemeResources.ts +++ b/src/test/bin/generateKeycloakThemeResources.ts @@ -14,6 +14,7 @@ generateKeycloakThemeResources({ "extraPages": ["my-custom-page.ftl"], "extraThemeProperties": ["env=test"], "isStandalone": true, - "urlPathname": "/keycloakify-demo-app/" + "urlPathname": "/keycloakify-demo-app/", + "isSilent": false } }); diff --git a/src/test/bin/setupSampleReactProject.ts b/src/test/bin/setupSampleReactProject.ts index 63231841..9c325c1d 100644 --- a/src/test/bin/setupSampleReactProject.ts +++ b/src/test/bin/setupSampleReactProject.ts @@ -8,6 +8,7 @@ export function setupSampleReactProject() { downloadAndUnzip({ "url": "https://github.com/InseeFrLab/keycloakify/releases/download/v0.0.1/sample_build_dir_and_package_json.zip", "destDirPath": sampleReactProjectDirPath, - "cacheDirPath": pathJoin(sampleReactProjectDirPath, "build_keycloak", ".cache") + "cacheDirPath": pathJoin(sampleReactProjectDirPath, "build_keycloak", ".cache"), + "isSilent": false }); } From fb3b0e2c290f67818e26ddd0b944a1d7af3f54fa Mon Sep 17 00:00:00 2001 From: German Ivanov Date: Thu, 8 Sep 2022 15:46:27 +0300 Subject: [PATCH 17/77] fix: make sure external assets flag is a boolean --- src/bin/tools/cliOptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/tools/cliOptions.ts b/src/bin/tools/cliOptions.ts index 9a1b39c6..97f7c609 100644 --- a/src/bin/tools/cliOptions.ts +++ b/src/bin/tools/cliOptions.ts @@ -10,6 +10,6 @@ export const getCliOptions = (processArgv: string[]): CliOptions => { return { isSilent: typeof argv["silent"] === "boolean" ? argv["silent"] : false, - hasExternalAssets: argv["external-assets"] !== undefined + hasExternalAssets: typeof argv["external-assets"] === "boolean" ? argv["external-assets"] : false }; }; From a2dc51d811e1b51e58c6644a6f620ccb88589a0d Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Thu, 8 Sep 2022 15:13:09 +0200 Subject: [PATCH 18/77] Update src/bin/create-keycloak-email-directory.ts --- src/bin/create-keycloak-email-directory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/create-keycloak-email-directory.ts b/src/bin/create-keycloak-email-directory.ts index 1a3dc77d..dfe70ae5 100644 --- a/src/bin/create-keycloak-email-directory.ts +++ b/src/bin/create-keycloak-email-directory.ts @@ -26,7 +26,7 @@ if (require.main === module) { downloadBuiltinKeycloakTheme({ keycloakVersion, "destDirPath": builtinKeycloakThemeTmpDirPath, - "isSilent": isSilent + isSilent }); transformCodebase({ From 84908e2ec0b0945a8ea48e26b07199035fbda3b2 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Thu, 8 Sep 2022 15:13:15 +0200 Subject: [PATCH 19/77] Update src/bin/generate-i18n-messages.ts --- src/bin/generate-i18n-messages.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/generate-i18n-messages.ts b/src/bin/generate-i18n-messages.ts index 2de2bf1d..d380624e 100644 --- a/src/bin/generate-i18n-messages.ts +++ b/src/bin/generate-i18n-messages.ts @@ -27,7 +27,7 @@ for (const keycloakVersion of ["11.0.3", "15.0.2", "18.0.1"]) { downloadBuiltinKeycloakTheme({ keycloakVersion, "destDirPath": tmpDirPath, - "isSilent": isSilent + isSilent }); type Dictionary = { [idiomId: string]: string }; From 36e32d6ddc3e6f316ee72a3b08b262a0637c854f Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Thu, 8 Sep 2022 15:13:21 +0200 Subject: [PATCH 20/77] Update src/bin/download-builtin-keycloak-theme.ts --- src/bin/download-builtin-keycloak-theme.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/download-builtin-keycloak-theme.ts b/src/bin/download-builtin-keycloak-theme.ts index 12bef872..e98eaddc 100644 --- a/src/bin/download-builtin-keycloak-theme.ts +++ b/src/bin/download-builtin-keycloak-theme.ts @@ -16,7 +16,7 @@ export function downloadBuiltinKeycloakTheme(params: { keycloakVersion: string; "url": `https://github.com/keycloak/keycloak/archive/refs/tags/${keycloakVersion}.zip`, "pathOfDirToExtractInArchive": `keycloak-${keycloakVersion}/themes/src/main/resources${ext}/theme`, "cacheDirPath": pathJoin(keycloakThemeBuildingDirPath, ".cache"), - "isSilent": isSilent + isSilent }); } } From a24945bc1bc7779c55b1856d78b7f82114e5c38d Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Thu, 8 Sep 2022 15:18:21 +0200 Subject: [PATCH 21/77] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ccc6101..8c6ded81 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "keycloakify", - "version": "6.0.3", + "version": "6.1.0", "description": "Keycloak theme generator for Reacts app", "repository": { "type": "git", From d8b00da3a1649de5ac2e03158a61109d34a5de2f Mon Sep 17 00:00:00 2001 From: garronej Date: Thu, 8 Sep 2022 15:27:41 +0200 Subject: [PATCH 22/77] Update tss-react --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8c6ded81..3c470944 100755 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "react-markdown": "^5.0.3", "scripting-tools": "^0.19.13", "tsafe": "^1.0.1", - "tss-react": "^4.1.1", + "tss-react": "^4.1.3", "zod": "^3.17.10" } } diff --git a/yarn.lock b/yarn.lock index 0f6e47dc..0a3e56b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1743,10 +1743,10 @@ tslib@^2.1.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== -tss-react@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/tss-react/-/tss-react-4.1.1.tgz#207220417e4b2f8eb26d8280ab9cdeb385063069" - integrity sha512-K1U2s/GGw+XycUjJGztJsLUhwm8KJWz5afL5WZU3SwMeQsA+gbETM6bSxVk2/DXBdw9uYLL9jkSYPAXh0tfYBw== +tss-react@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/tss-react/-/tss-react-4.1.3.tgz#170a2edd85e32ba3b752416eeb45438c35e90243" + integrity sha512-Ul99aVoVngHY2nwFC87jZlGP+K3LfG9ZRakimOzRwgJz77f/zXWuY2FVzwaSc+OW804twNaxZZRtLlpagex8sg== dependencies: "@emotion/cache" "*" "@emotion/serialize" "*" From 415988379146db82224d72e08987dabbe3f96aed Mon Sep 17 00:00:00 2001 From: garronej Date: Fri, 9 Sep 2022 02:07:29 +0200 Subject: [PATCH 23/77] Feature update-user-profile.ftl #164 --- .../keycloakify/generateFtl/generateFtl.ts | 3 +- src/lib/components/KcApp.tsx | 3 + src/lib/components/RegisterUserProfile.tsx | 167 +------------- src/lib/components/UpdateUserProfile.tsx | 77 +++++++ .../components/shared/UserProfileCommons.tsx | 172 +++++++++++++++ src/lib/getKcContext/KcContextBase.ts | 12 +- .../kcContextMocks/kcContextMocks.ts | 203 +++++++++--------- src/lib/useFormValidationSlice.tsx | 2 +- 8 files changed, 381 insertions(+), 258 deletions(-) create mode 100644 src/lib/components/UpdateUserProfile.tsx create mode 100644 src/lib/components/shared/UserProfileCommons.tsx diff --git a/src/bin/keycloakify/generateFtl/generateFtl.ts b/src/bin/keycloakify/generateFtl/generateFtl.ts index 1209cfd6..adc337d2 100644 --- a/src/bin/keycloakify/generateFtl/generateFtl.ts +++ b/src/bin/keycloakify/generateFtl/generateFtl.ts @@ -27,7 +27,8 @@ export const pageIds = [ "login-idp-link-email.ftl", "login-page-expired.ftl", "login-config-totp.ftl", - "logout-confirm.ftl" + "logout-confirm.ftl", + "update-user-profile.ftl" ] as const; export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets; diff --git a/src/lib/components/KcApp.tsx b/src/lib/components/KcApp.tsx index 0cee851d..5470e9b3 100644 --- a/src/lib/components/KcApp.tsx +++ b/src/lib/components/KcApp.tsx @@ -20,6 +20,7 @@ const LoginPageExpired = lazy(() => import("./LoginPageExpired")); const LoginIdpLinkEmail = lazy(() => import("./LoginIdpLinkEmail")); const LoginConfigTotp = lazy(() => import("./LoginConfigTotp")); const LogoutConfirm = lazy(() => import("./LogoutConfirm")); +const UpdateUserProfile = lazy(() => import("./UpdateUserProfile")); const KcApp = memo(({ kcContext, i18n: userProvidedI18n, ...kcProps }: { kcContext: KcContextBase; i18n?: I18n } & KcProps) => { const i18n = (function useClosure() { @@ -74,6 +75,8 @@ const KcApp = memo(({ kcContext, i18n: userProvidedI18n, ...kcProps }: { kcConte return ; case "logout-confirm.ftl": return ; + case "update-user-profile.ftl": + return ; } })()} diff --git a/src/lib/components/RegisterUserProfile.tsx b/src/lib/components/RegisterUserProfile.tsx index e11f85bb..e0cb2ae1 100644 --- a/src/lib/components/RegisterUserProfile.tsx +++ b/src/lib/components/RegisterUserProfile.tsx @@ -1,12 +1,10 @@ -import React, { useMemo, memo, useEffect, useState, Fragment } from "react"; +import React, { useMemo, memo, useState } from "react"; import Template from "./Template"; import type { KcProps } from "./KcProps"; -import type { KcContextBase, Attribute } from "../getKcContext/KcContextBase"; +import type { KcContextBase } from "../getKcContext/KcContextBase"; import { useCssAndCx } from "../tools/useCssAndCx"; -import type { ReactComponent } from "../tools/ReactComponent"; -import { useCallbackFactory } from "powerhooks/useCallbackFactory"; -import { useFormValidationSlice } from "../useFormValidationSlice"; import type { I18n } from "../i18n"; +import { UserProfileFormFields } from "./shared/UserProfileCommons"; const RegisterUserProfile = memo(({ kcContext, i18n, ...props_ }: { kcContext: KcContextBase.RegisterUserProfile; i18n: I18n } & KcProps) => { const { url, messagesPerField, recaptchaRequired, recaptchaSiteKey } = kcContext; @@ -34,7 +32,13 @@ const RegisterUserProfile = memo(({ kcContext, i18n, ...props_ }: { kcContext: K headerNode={msg("registerTitle")} formNode={
- + {recaptchaRequired && (
@@ -66,155 +70,4 @@ const RegisterUserProfile = memo(({ kcContext, i18n, ...props_ }: { kcContext: K ); }); -type UserProfileFormFieldsProps = { kcContext: KcContextBase.RegisterUserProfile; i18n: I18n } & KcProps & - Partial>> & { - onIsFormSubmittableValueChange: (isFormSubmittable: boolean) => void; - }; - -const UserProfileFormFields = memo(({ kcContext, onIsFormSubmittableValueChange, i18n, ...props }: UserProfileFormFieldsProps) => { - const { cx, css } = useCssAndCx(); - - const { advancedMsg } = i18n; - - const { - formValidationState: { fieldStateByAttributeName, isFormSubmittable }, - formValidationReducer, - attributesWithPassword - } = useFormValidationSlice({ - kcContext, - i18n - }); - - useEffect(() => { - onIsFormSubmittableValueChange(isFormSubmittable); - }, [isFormSubmittable]); - - const onChangeFactory = useCallbackFactory( - ( - [name]: [string], - [ - { - target: { value } - } - ]: [React.ChangeEvent] - ) => - formValidationReducer({ - "action": "update value", - name, - "newValue": value - }) - ); - - const onBlurFactory = useCallbackFactory(([name]: [string]) => - formValidationReducer({ - "action": "focus lost", - name - }) - ); - - let currentGroup = ""; - - return ( - <> - {attributesWithPassword.map((attribute, i) => { - const { group = "", groupDisplayHeader = "", groupDisplayDescription = "" } = attribute; - - const { value, displayableErrors } = fieldStateByAttributeName[attribute.name]; - - const formGroupClassName = cx(props.kcFormGroupClass, displayableErrors.length !== 0 && props.kcFormGroupErrorClass); - - return ( - - {group !== currentGroup && (currentGroup = group) !== "" && ( -
-
- -
- {groupDisplayDescription !== "" && ( -
- -
- )} -
- )} -
-
- - {attribute.required && <>*} -
-
- {(() => { - const { options } = attribute.validators; - - if (options !== undefined) { - return ( - - ); - } - - return ( - { - switch (attribute.name) { - case "password-confirm": - case "password": - return "password"; - default: - return "text"; - } - })()} - id={attribute.name} - name={attribute.name} - value={value} - onChange={onChangeFactory(attribute.name)} - className={cx(props.kcInputClass)} - aria-invalid={displayableErrors.length !== 0} - disabled={attribute.readOnly} - autoComplete={attribute.autocomplete} - onBlur={onBlurFactory(attribute.name)} - /> - ); - })()} - {displayableErrors.length !== 0 && ( - span": { "display": "block" } - }) - )} - aria-live="polite" - > - {displayableErrors.map(({ errorMessage }) => errorMessage)} - - )} -
-
-
- ); - })} - - ); -}); - export default RegisterUserProfile; diff --git a/src/lib/components/UpdateUserProfile.tsx b/src/lib/components/UpdateUserProfile.tsx new file mode 100644 index 00000000..bf8876f0 --- /dev/null +++ b/src/lib/components/UpdateUserProfile.tsx @@ -0,0 +1,77 @@ +import React, { useState, memo } from "react"; +import Template from "./Template"; +import type { KcProps } from "./KcProps"; +import type { KcContextBase } from "../getKcContext/KcContextBase"; +import { useCssAndCx } from "../tools/useCssAndCx"; +import type { I18n } from "../i18n"; +import { UserProfileFormFields } from "./shared/UserProfileCommons"; + +const LoginUpdateProfile = memo(({ kcContext, i18n, ...props }: { kcContext: KcContextBase.UpdateUserProfile; i18n: I18n } & KcProps) => { + const { cx } = useCssAndCx(); + + const { msg, msgStr } = i18n; + + const { url, isAppInitiatedAction } = kcContext; + + const [isFomSubmittable, setIsFomSubmittable] = useState(false); + + return ( +