From 9936008ffbe07fe9533e8d5946b06e0c952e7bfe Mon Sep 17 00:00:00 2001 From: Lina Date: Tue, 15 Jul 2025 14:59:19 +0200 Subject: [PATCH 01/17] Translated version of the project settings page --- i18n/i18n.ts | 22 +++++++++++++++ i18n/locales/de/settings.json | 19 +++++++++++++ i18n/locales/en/settings.json | 19 +++++++++++++ package.json | 3 +- pages/_app.tsx | 6 ++-- pages/settings.tsx | 39 ++++++++++++++++--------- pkg/ui/NodeInputDefault.tsx | 50 +++++++++++++++++++++++++++++++-- pkg/ui/NodeInputSubmit.tsx | 18 +++++++++++- submodules/javascript-functions | 2 +- submodules/react-components | 2 +- 10 files changed, 159 insertions(+), 21 deletions(-) create mode 100644 i18n/i18n.ts create mode 100644 i18n/locales/de/settings.json create mode 100644 i18n/locales/en/settings.json diff --git a/i18n/i18n.ts b/i18n/i18n.ts new file mode 100644 index 0000000..263a1de --- /dev/null +++ b/i18n/i18n.ts @@ -0,0 +1,22 @@ +import i18n from 'i18next' +import settingsEN from './locales/en/settings.json' + +import settingsDE from './locales/de/settings.json' + +i18n.init({ + resources: { + en: { + settings: settingsEN + }, + de: { + settings: settingsDE, + }, + }, + ns: ["settings"], + fallbackLng: 'en', + interpolation: { + escapeValue: false // not needed for react as it escapes by default + }, +}); + +export default i18n \ No newline at end of file diff --git a/i18n/locales/de/settings.json b/i18n/locales/de/settings.json new file mode 100644 index 0000000..b22a8ab --- /dev/null +++ b/i18n/locales/de/settings.json @@ -0,0 +1,19 @@ +{ + "title": "Kontoeinstellungen", + "heading": "Profilverwaltung und Sicherheitseinstellungen", + "subtitle": "Profileinstellungen", + "changePassword": "Passwort ändern", + "setPassword": "Passwort festlegen", + "backUpCodes": "Verwalten von 2FA-Backup-Wiederherstellungscodes", + "backUpCodesDescription": "Wiederherstellungscodes können in Paniksituationen verwendet werden, wenn Sie den Zugriff auf Ihr 2FA-Gerät verloren haben.", + "totpAuthenticator": "2FA TOTP Authenticator App verwalten", + "addTotpAuthenticator": "Fügen Sie Ihrem Konto eine TOTP-Authentifikator-App hinzu, um die Sicherheit Ihres Kontos zu verbessern.", + "popularAuthenticatorApps": "Beliebte Authenticator-Apps sind", + "and": "und", + "back": "Zurück", + "email": "E-Mail", + "firstName": "Vorname", + "lastName": "Nachname", + "password": "Passwort", + "save": "Speichern" +} \ No newline at end of file diff --git a/i18n/locales/en/settings.json b/i18n/locales/en/settings.json new file mode 100644 index 0000000..95b2368 --- /dev/null +++ b/i18n/locales/en/settings.json @@ -0,0 +1,19 @@ +{ + "title": "Account settings", + "heading": "Profile management and security settings", + "subtitle": "Profile Settings", + "changePassword": "Change Password", + "setPassword": "Set Password", + "backUpCodes": "Manage 2FA backup recovery codes", + "backUpCodesDescription": "Recovery codes can be used in panic situations where you have lost access to your 2FA device.", + "totpAuthenticator": "Manage 2FA TOTP Authenticator App", + "addTotpAuthenticator": "Add a TOTP Authenticator App to your account to improve your account security.", + "popularAuthenticatorApps": "Popular Authenticator Apps are", + "and": "and", + "back": "Back", + "email": "E-Mail", + "firstName": "First Name", + "lastName": "Last Name", + "password": "Password", + "save": "Save" +} \ No newline at end of file diff --git a/package.json b/package.json index 9489b07..457ecaf 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "eslint": "8.38.0", "eslint-config-next": "13.3.0", "express": "^4.18.2", + "i18next": "^25.3.2", "next": "^12.2.0", "react": "^17.0.2", "react-dom": "^17.0.2", @@ -42,4 +43,4 @@ "postcss": "^8.4.23", "tailwindcss": "^3.4.4" } -} \ No newline at end of file +} diff --git a/pages/_app.tsx b/pages/_app.tsx index 96e8c82..16dfdb6 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,8 +1,10 @@ +import i18n from "@/i18n/i18n"; import "../styles/tailwind.css" import '@/submodules/tailwind-config/global.css'; import { theme, globalStyles, ThemeProps } from "@ory/themes" import type { AppProps } from "next/app" import Head from "next/head" +import { I18nextProvider } from "react-i18next"; import { ToastContainer } from "react-toastify" import "react-toastify/dist/ReactToastify.css" import { ThemeProvider } from "styled-components" @@ -14,7 +16,7 @@ const GlobalStyle = createGlobalStyle((props: ThemeProps) => function MyApp({ Component, pageProps }: AppProps) { return ( - <> + kern - + ) } diff --git a/pages/settings.tsx b/pages/settings.tsx index 9bffed2..85efa08 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -3,7 +3,7 @@ import { AxiosError } from "axios" import type { NextPage } from "next" import Head from "next/head" import { useRouter } from "next/router" -import { useCallback, useEffect, useState } from "react" +import { useCallback, useEffect, useMemo, useState } from "react" import { Flow, Messages } from "../pkg" import { handleFlowError } from "../pkg/errors" @@ -17,6 +17,8 @@ import { Application, CurrentPage } from "@/submodules/react-components/hooks/we import { AdminMessage } from "@/submodules/react-components/types/admin-messages" import { postProcessAdminMessages } from "@/submodules/react-components/helpers/admin-messages-helper" import AdminMessages from "@/submodules/react-components/components/AdminMessages" +import { useTranslation } from "react-i18next" +import { useConsoleLog } from "@/submodules/react-components/hooks/useConsoleLog" const Settings: NextPage = () => { const [initialFlow, setInitialFlow]: any = useState() @@ -32,6 +34,8 @@ const Settings: NextPage = () => { // Get ?flow=... from the URL const router = useRouter() const { flow: flowId, return_to: returnTo } = router.query + const { t, i18n } = useTranslation('settings'); + const [language, setLanguage] = useState(undefined); useEffect(() => { getUserInfoExtended((res) => { @@ -42,6 +46,7 @@ const Settings: NextPage = () => { WebSocketsService.setConnectionOpened(true); WebSocketsService.initWsNotifications(); } + setLanguage(res?.languageDisplay); } }); }, []); @@ -62,6 +67,11 @@ const Settings: NextPage = () => { useWebsocket(user?.organizationId, Application.ENTRY, CurrentPage.ENTRY_LAYOUT, handleWebsocketNotification) + useEffect(() => { + if (!language) return; + i18n.changeLanguage(language); + }, [language, i18n]); + useEffect(() => { // If the router is not ready yet, or we already have a flow, do nothing. if (!router.isReady || initialFlow) { @@ -170,21 +180,24 @@ const Settings: NextPage = () => { return Promise.reject(err) }) + + useConsoleLog(changedFlow) + return ( <> - Account settings + {t('title')}
-
-

Profile management and security settings

+ {language &&
+

{t('heading')}

-

Profile Settings

+

{t('subtitle')}

{
{!isOidc ?
-

{flowId ? 'Set' : 'Change'} password

+

{flowId ? t('changePassword') : t('setPassword')}

{
: null} {containsBackupCodes ? (
-

Manage 2FA backup recovery codes

-

Recovery codes can be used in panic situations where you have lost access to your 2FA device.

+

{t('backUpCodes')}

+

{t('backUpCodesDescription')}

{
) : (<> )} {containsTotp ? (
-

Manage 2FA TOTP Authenticator App

-

Add a TOTP Authenticator App to your account to improve your account security. - Popular Authenticator Apps are LastPass and Google +

{t('totpAuthenticator')}

+

{t('addTotpAuthenticator')} + {t('popularAuthenticatorApps')} LastPass{t('and')} Google Authenticator (iOS, {

-
+
}
diff --git a/pkg/ui/NodeInputDefault.tsx b/pkg/ui/NodeInputDefault.tsx index 0619fce..710d9ce 100644 --- a/pkg/ui/NodeInputDefault.tsx +++ b/pkg/ui/NodeInputDefault.tsx @@ -3,9 +3,15 @@ import { TextInput } from "@ory/themes" import { NodeInputProps } from "./helpers" import { getNodeLabel } from "@ory/integrations/ui" import { Message } from "./Messages" +import { useEffect, useState } from "react" +import { useTranslation } from "react-i18next" export function NodeInputDefault(props: NodeInputProps) { const { node, attributes, value = "", setValue, disabled } = props + const { t } = useTranslation('settings'); + const [labelName, setLabelName] = useState(""); + const [placeholderName, setPlaceholderName] = useState(""); + // Some attributes have dynamic JavaScript - this is for example required for WebAuthn. const onClick = () => { @@ -18,10 +24,50 @@ export function NodeInputDefault(props: NodeInputProps) { } } + useEffect(() => { + // The settings page needs translated placeholders. + switch (getNodeLabel(node)) { + case "E-Mail": + setPlaceholderName(t('email')); + break; + case "First Name": + setPlaceholderName(t('firstName')); + break; + case "Last Name": + setPlaceholderName(t('lastName')); + break; + case "Password": + setPlaceholderName(t('password')); + break; + default: + setPlaceholderName(getNodeLabel(node)); + } + }, [node, t]); + + useEffect(() => { + // The settings page needs translated labels. + switch (getNodeLabel(node)) { + case "E-Mail": + setLabelName(t('email')); + break; + case "First Name": + setLabelName(t('firstName')); + break; + case "Last Name": + setLabelName(t('lastName')); + break; + case "Password": + setLabelName(t('password')); + break; + default: + setLabelName(getNodeLabel(node)); + } + }, [node, t]); + // Render a generic text input field. return ( { setValue(e.target.value) @@ -29,7 +75,7 @@ export function NodeInputDefault(props: NodeInputProps) { className={"text-input" + (props.visible ? "" : " hidden")} type={attributes.type} name={attributes.name} - placeholder={getNodeLabel(node)} + placeholder={placeholderName} value={value} disabled={attributes.disabled || disabled} help={node.messages.length > 0} diff --git a/pkg/ui/NodeInputSubmit.tsx b/pkg/ui/NodeInputSubmit.tsx index 331c7b3..1c79504 100644 --- a/pkg/ui/NodeInputSubmit.tsx +++ b/pkg/ui/NodeInputSubmit.tsx @@ -2,6 +2,8 @@ import { getNodeLabel } from "@ory/integrations/ui" import { Button } from "@ory/themes" import { NodeInputProps } from "./helpers" +import { useEffect, useState } from "react" +import { useTranslation } from "react-i18next" export function NodeInputSubmit({ @@ -9,6 +11,20 @@ export function NodeInputSubmit({ attributes, disabled, }: NodeInputProps) { + const { t } = useTranslation('settings'); + const [buttonName, setButtonName] = useState(""); + + useEffect(() => { + // The settings page needs translated labels. + switch (getNodeLabel(node)) { + case "Save": + setButtonName(t('save')); + break; + default: + setButtonName(getNodeLabel(node)); + } + }, [node, t]); + return ( <> {node.meta.label?.text == "Sign up" ? @@ -22,7 +38,7 @@ export function NodeInputSubmit({ value={attributes.value || ""} disabled={attributes.disabled || disabled} > - {getNodeLabel(node)} + {buttonName} ) diff --git a/submodules/javascript-functions b/submodules/javascript-functions index 5a07039..dcbd2e8 160000 --- a/submodules/javascript-functions +++ b/submodules/javascript-functions @@ -1 +1 @@ -Subproject commit 5a070394a45b5ed5a86efd0fc42370331e0ab101 +Subproject commit dcbd2e811fdf0f3f950ec0a612371fd38f6152b7 diff --git a/submodules/react-components b/submodules/react-components index 66af8ce..1f1dc08 160000 --- a/submodules/react-components +++ b/submodules/react-components @@ -1 +1 @@ -Subproject commit 66af8ce324318e31af8d6e2d812396d32dad57ef +Subproject commit 1f1dc08839bbf7e02e1ddafa774af43fdbb7197a From 8dcc9c19acc83ecb6d0304265765eb631c7ea154 Mon Sep 17 00:00:00 2001 From: Lina Date: Tue, 15 Jul 2025 16:54:21 +0200 Subject: [PATCH 02/17] Added messages in different languages --- pages/settings.tsx | 86 ++++++++++++++++++++++++---------------- pkg/ui/Messages.tsx | 6 ++- util/helper-functions.ts | 17 ++++++-- 3 files changed, 69 insertions(+), 40 deletions(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index 85efa08..e40d446 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -18,7 +18,6 @@ import { AdminMessage } from "@/submodules/react-components/types/admin-messages import { postProcessAdminMessages } from "@/submodules/react-components/helpers/admin-messages-helper" import AdminMessages from "@/submodules/react-components/components/AdminMessages" import { useTranslation } from "react-i18next" -import { useConsoleLog } from "@/submodules/react-components/hooks/useConsoleLog" const Settings: NextPage = () => { const [initialFlow, setInitialFlow]: any = useState() @@ -36,6 +35,8 @@ const Settings: NextPage = () => { const { flow: flowId, return_to: returnTo } = router.query const { t, i18n } = useTranslation('settings'); const [language, setLanguage] = useState(undefined); + const [showPassword, setShowPassword] = useState(false); + const [showAuthenticator, setShowAuthenticator] = useState(false); useEffect(() => { getUserInfoExtended((res) => { @@ -114,7 +115,7 @@ const Settings: NextPage = () => { setChangedFlow(initialFlow) //prevent password change option display if sso - requestAnimationFrame(() => { + setTimeout(() => { if (["microsoft", "google"].includes(initialFlow.identity.metadata_public?.registration_scope?.provider_id)) { initialFlow.ui.nodes = initialFlow.ui.nodes.filter((node: UiNode) => node.group !== "password"); setIsOidc(true); @@ -128,7 +129,7 @@ const Settings: NextPage = () => { document.querySelector('button[value="Google"]')?.setAttribute("class", "hidden"); } } - }); + }, 100); }, [initialFlow]) useEffect(() => { @@ -136,7 +137,7 @@ const Settings: NextPage = () => { const firstNameButtonVal = (document.querySelector('input[name="traits.name.first"]') as HTMLInputElement)?.value; const lastNameButtonVal = (document.querySelector('input[name="traits.name.last"]') as HTMLInputElement)?.value; if (isOidc && isOidcInvitation) { - if (firstNameButtonVal === "" || lastNameButtonVal === "") { + if ((firstNameButtonVal === "" || lastNameButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined) && flowId) { setBackButtonDisabled(true); } else { setBackButtonDisabled(false); @@ -144,7 +145,14 @@ const Settings: NextPage = () => { } else { const emailButtonVal = (document.querySelector('input[name="traits.email"]') as HTMLInputElement)?.value; const passwordButtonVal = (document.querySelector('input[name="password"]') as HTMLInputElement)?.value; - if (firstNameButtonVal === "" || lastNameButtonVal === "" || emailButtonVal === "" || passwordButtonVal === "") { + if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && firstNameButtonVal !== undefined && lastNameButtonVal !== undefined) { + setShowPassword(true); + } + if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && passwordButtonVal !== "" && passwordButtonVal !== undefined) { + setShowAuthenticator(true); + } + + if ((firstNameButtonVal === "" || lastNameButtonVal === "" || emailButtonVal === "" || passwordButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined || emailButtonVal === undefined || passwordButtonVal === undefined) && flowId) { setBackButtonDisabled(true); } else { setBackButtonDisabled(false); @@ -155,6 +163,12 @@ const Settings: NextPage = () => { useEffect(() => { if (!changedFlow) return; if (changedFlow.ui.messages) { + initialFlow.ui.messages = initialFlow.ui.messages.map((message: any) => { + if (message.id === 1060001) { + return { ...message, id: 1060001 + 'a' }; + } + return message; + }); setMessages(changedFlow.ui.messages); } }, [changedFlow]) @@ -181,8 +195,6 @@ const Settings: NextPage = () => { return Promise.reject(err) }) - useConsoleLog(changedFlow) - return ( <> @@ -205,7 +217,8 @@ const Settings: NextPage = () => { flow={changedFlow} />
- {!isOidc ? + + {((flowId && !isOidc && showPassword) || !flowId) && (

{flowId ? t('changePassword') : t('setPassword')}

{ only="password" flow={changedFlow} /> -
: null} + + )} - {containsBackupCodes ? (
-

{t('backUpCodes')}

-

{t('backUpCodesDescription')}

- -
) : (<> )} + {showAuthenticator && <> + {containsBackupCodes ? (
+

{t('backUpCodes')}

+

{t('backUpCodesDescription')}

+ +
) : (<> )} - {containsTotp ? (
-

{t('totpAuthenticator')}

-

{t('addTotpAuthenticator')} - {t('popularAuthenticatorApps')} LastPass{t('and')} Google - Authenticator (iOS, Android). -

- -
) : (<> )} + {containsTotp ? (
+

{t('totpAuthenticator')}

+

{t('addTotpAuthenticator')} + {t('popularAuthenticatorApps')} LastPass{t('and')} Google + Authenticator (iOS, Android). +

+ +
) : (<> )} + } {isOidc && isOidcInvitation ? (
{ + const { i18n } = useTranslation(); + const language = i18n.language; + return ( - {displayMessage(message)} + {displayMessage(message, language)} ) diff --git a/util/helper-functions.ts b/util/helper-functions.ts index 466d040..5d0e54a 100644 --- a/util/helper-functions.ts +++ b/util/helper-functions.ts @@ -1,7 +1,15 @@ -const customMessageOverrides = { - 1060001: "Welcome to the app! You have successfully registered. Set your first, last name and password to continue.", +const customMessageOverridesEnglish = { + 1060001: "Welcome to the app! You have successfully registered. Set your first and last name to continue.", + '1060001a': "Welcome to the app! You have successfully registered. Set your first, last name and link your account to continue.", + 1050001: "Your changes are saved!", }; +const customMessageOverridesGerman = { + 1060001: "Willkommen in der App! Sie haben sich erfolgreich registriert. Bitte geben Sie Ihren Vor- und Nachnamen ein, um fortzufahren.", + '1060001a': "Willkommen in der App! Sie haben sich erfolgreich registriert. Bitte geben Sie Ihren Vor- und Nachnamen ein und verknüpfen Sie Ihr Konto, um fortzufahren.", + 1050001: "Ihre Änderungen wurden gespeichert!", +} + export function getValueIdentifier(selectedRole: any) { let value = ''; if (selectedRole === 'engineer') { @@ -64,6 +72,7 @@ export function prepareNodes(flow: any) { return filteredNodes; } -export function displayMessage(msg: any): string { - return customMessageOverrides[msg.id] || msg.text; +export function displayMessage(msg: any, language: string): string { + const selectDictMessages = language === "de" ? customMessageOverridesGerman : customMessageOverridesEnglish; + return selectDictMessages[msg.id] || msg.text; } \ No newline at end of file From 0c82a2f03daaf0a367a508cbd2da9346617db0ae Mon Sep 17 00:00:00 2001 From: Lina Date: Tue, 15 Jul 2025 17:28:45 +0200 Subject: [PATCH 03/17] Added dutch support to the app --- i18n/i18n.ts | 5 +++++ i18n/locales/nl/settings.json | 19 +++++++++++++++++++ util/helper-functions.ts | 8 +++++++- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 i18n/locales/nl/settings.json diff --git a/i18n/i18n.ts b/i18n/i18n.ts index 263a1de..59cb72c 100644 --- a/i18n/i18n.ts +++ b/i18n/i18n.ts @@ -3,6 +3,8 @@ import settingsEN from './locales/en/settings.json' import settingsDE from './locales/de/settings.json' +import settingsNL from './locales/nl/settings.json' + i18n.init({ resources: { en: { @@ -11,6 +13,9 @@ i18n.init({ de: { settings: settingsDE, }, + nl: { + settings: settingsNL, + }, }, ns: ["settings"], fallbackLng: 'en', diff --git a/i18n/locales/nl/settings.json b/i18n/locales/nl/settings.json new file mode 100644 index 0000000..f19471b --- /dev/null +++ b/i18n/locales/nl/settings.json @@ -0,0 +1,19 @@ +{ + "title": "Accountinstellingen", + "heading": "Profielbeheer en beveiligingsinstellingen", + "subtitle": "Profielinstellingen", + "changePassword": "Wachtwoord wijzigen", + "setPassword": "Wachtwoord instellen", + "backUpCodes": "Beheer 2FA-back-upherstelcodes", + "backUpCodesDescription": "Herstelcodes kunnen worden gebruikt in panieksituaties waarin u geen toegang meer hebt tot uw 2FA-apparaat.", + "totpAuthenticator": "Beheer 2FA TOTP Authenticator-app", + "addTotpAuthenticator": "Voeg een TOTP Authenticator-app toe aan uw account om de beveiliging ervan te verbeteren.", + "popularAuthenticatorApps": "Populaire authenticatie-apps zijn", + "and": "En", + "back": "Rug", + "email": "E-mail", + "firstName": "Voornaam", + "lastName": "Achternaam", + "password": "Wachtwoord", + "save": "Redden" +} \ No newline at end of file diff --git a/util/helper-functions.ts b/util/helper-functions.ts index 5d0e54a..5bfb3ad 100644 --- a/util/helper-functions.ts +++ b/util/helper-functions.ts @@ -10,6 +10,12 @@ const customMessageOverridesGerman = { 1050001: "Ihre Änderungen wurden gespeichert!", } +const customMessageOverridesDutch = { + 1060001: "Welkom bij de app! Je bent succesvol geregistreerd. Vul je voor- en achternaam in om verder te gaan.", + '1060001a': "Welkom bij de app! Je bent succesvol geregistreerd. Vul je voor- en achternaam in en koppel je account om verder te gaan.", + 1050001: "Uw wijzigingen zijn opgeslagen!", +} + export function getValueIdentifier(selectedRole: any) { let value = ''; if (selectedRole === 'engineer') { @@ -73,6 +79,6 @@ export function prepareNodes(flow: any) { } export function displayMessage(msg: any, language: string): string { - const selectDictMessages = language === "de" ? customMessageOverridesGerman : customMessageOverridesEnglish; + const selectDictMessages = language === "de" ? customMessageOverridesGerman : language === "nl" ? customMessageOverridesDutch : customMessageOverridesEnglish; return selectDictMessages[msg.id] || msg.text; } \ No newline at end of file From f373fddd6754df861328f77642f6c2bcbb828634 Mon Sep 17 00:00:00 2001 From: Lina Date: Wed, 16 Jul 2025 09:44:19 +0200 Subject: [PATCH 04/17] Smaller condition fix --- pages/settings.tsx | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index e40d446..1c4a084 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -18,6 +18,7 @@ import { AdminMessage } from "@/submodules/react-components/types/admin-messages import { postProcessAdminMessages } from "@/submodules/react-components/helpers/admin-messages-helper" import AdminMessages from "@/submodules/react-components/components/AdminMessages" import { useTranslation } from "react-i18next" +import { useConsoleLog } from "@/submodules/react-components/hooks/useConsoleLog" const Settings: NextPage = () => { const [initialFlow, setInitialFlow]: any = useState() @@ -37,6 +38,14 @@ const Settings: NextPage = () => { const [language, setLanguage] = useState(undefined); const [showPassword, setShowPassword] = useState(false); const [showAuthenticator, setShowAuthenticator] = useState(false); + const [loadPage, setLoadPage] = useState(false); + + useEffect(() => { + if (loadPage) return; + setTimeout(() => { + setLoadPage(true); + }, 1000); + }, [loadPage]); useEffect(() => { getUserInfoExtended((res) => { @@ -164,14 +173,14 @@ const Settings: NextPage = () => { if (!changedFlow) return; if (changedFlow.ui.messages) { initialFlow.ui.messages = initialFlow.ui.messages.map((message: any) => { - if (message.id === 1060001) { + if (message.id === 1060001 && isOidc && isOidcInvitation) { return { ...message, id: 1060001 + 'a' }; } return message; }); setMessages(changedFlow.ui.messages); } - }, [changedFlow]) + }, [changedFlow, isOidc, isOidcInvitation]) const onSubmit = (values: UpdateSettingsFlowBody) => ory @@ -218,17 +227,21 @@ const Settings: NextPage = () => { />
- {((flowId && !isOidc && showPassword) || !flowId) && ( -
-

{flowId ? t('changePassword') : t('setPassword')}

- -
- )} + {loadPage && <> + {!(isOidc && isOidcInvitation) && <> + {((flowId && showPassword) || !flowId) && ( +
+

{!flowId ? t('changePassword') : t('setPassword')}

+ +
+ )} + } + } {showAuthenticator && <> {containsBackupCodes ? (
From f48591e6e8e894a3851d4a87a41ce0819c284aad Mon Sep 17 00:00:00 2001 From: Lina Date: Thu, 17 Jul 2025 08:59:12 +0200 Subject: [PATCH 05/17] PR comments --- pages/settings.tsx | 22 +++++++++++++++++++--- util/helper-functions.ts | 10 ++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index 1c4a084..e5bf492 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -173,14 +173,19 @@ const Settings: NextPage = () => { if (!changedFlow) return; if (changedFlow.ui.messages) { initialFlow.ui.messages = initialFlow.ui.messages.map((message: any) => { - if (message.id === 1060001 && isOidc && isOidcInvitation) { - return { ...message, id: 1060001 + 'a' }; + if (flowId && !isOidc) { + if (message.id === 1060001 && isOidc && isOidcInvitation) { + return { ...message, id: 1060001 + 'a' }; + } + if (message.id === 1050001 && showPassword) { + return { ...message, id: 1050001 + 'a' }; + } } return message; }); setMessages(changedFlow.ui.messages); } - }, [changedFlow, isOidc, isOidcInvitation]) + }, [changedFlow, isOidc, isOidcInvitation, showPassword, flowId, isOidc]) const onSubmit = (values: UpdateSettingsFlowBody) => ory @@ -204,6 +209,17 @@ const Settings: NextPage = () => { return Promise.reject(err) }) + useEffect(() => { + if (backButtonDisabled || !changedFlow || !changedFlow.ui.messages || !flowId) return; + changedFlow.ui.messages = changedFlow.ui.messages.map((message: any) => { + if (message.id === '1050001a' && !isOidc) { + return { ...message, id: "1050001ab" }; + } + return message; + }); + setMessages(changedFlow.ui.messages); + }, [backButtonDisabled, changedFlow, flowId, isOidc]); + return ( <> diff --git a/util/helper-functions.ts b/util/helper-functions.ts index 5bfb3ad..6b751f0 100644 --- a/util/helper-functions.ts +++ b/util/helper-functions.ts @@ -2,18 +2,28 @@ const customMessageOverridesEnglish = { 1060001: "Welcome to the app! You have successfully registered. Set your first and last name to continue.", '1060001a': "Welcome to the app! You have successfully registered. Set your first, last name and link your account to continue.", 1050001: "Your changes are saved!", + '1050001a': "Your changes are saved! Please set your password to continue.", + '1050001ab': "Your password has been set successfully! ", + 4000032: "The password must be at least 8 characters long, but got less.", + 4000034: "The password has been found in data breaches and must no longer be used." }; const customMessageOverridesGerman = { 1060001: "Willkommen in der App! Sie haben sich erfolgreich registriert. Bitte geben Sie Ihren Vor- und Nachnamen ein, um fortzufahren.", '1060001a': "Willkommen in der App! Sie haben sich erfolgreich registriert. Bitte geben Sie Ihren Vor- und Nachnamen ein und verknüpfen Sie Ihr Konto, um fortzufahren.", 1050001: "Ihre Änderungen wurden gespeichert!", + '1050001a': "Ihre Änderungen wurden gespeichert! Bitte setzen Sie Ihr Passwort, um fortzufahren.", + 4000032: "Das Passwort muss mindestens 8 Zeichen lang sein, aber es wurden weniger als 8 Zeichen eingegeben.", + 4000034: "Das Passwort wurde in Datenpannen gefunden und darf nicht mehr verwendet werden." } const customMessageOverridesDutch = { 1060001: "Welkom bij de app! Je bent succesvol geregistreerd. Vul je voor- en achternaam in om verder te gaan.", '1060001a': "Welkom bij de app! Je bent succesvol geregistreerd. Vul je voor- en achternaam in en koppel je account om verder te gaan.", 1050001: "Uw wijzigingen zijn opgeslagen!", + '1050001a': "Uw wijzigingen zijn opgeslagen! Stel uw wachtwoord in om verder te gaan.", + 4000032: "Het wachtwoord moet minimaal 8 tekens lang zijn, maar er zijn minder dan 8 tekens ingevoerd.", + 4000034: "Het wachtwoord is gevonden in datalekken en mag niet meer worden gebruikt." } export function getValueIdentifier(selectedRole: any) { From 4bc2fd1b641250ee8c2eefe54fa561646f3dc7ed Mon Sep 17 00:00:00 2001 From: Lina Date: Thu, 17 Jul 2025 09:20:01 +0200 Subject: [PATCH 06/17] Translations added --- util/helper-functions.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/util/helper-functions.ts b/util/helper-functions.ts index 6b751f0..7c5d250 100644 --- a/util/helper-functions.ts +++ b/util/helper-functions.ts @@ -13,6 +13,7 @@ const customMessageOverridesGerman = { '1060001a': "Willkommen in der App! Sie haben sich erfolgreich registriert. Bitte geben Sie Ihren Vor- und Nachnamen ein und verknüpfen Sie Ihr Konto, um fortzufahren.", 1050001: "Ihre Änderungen wurden gespeichert!", '1050001a': "Ihre Änderungen wurden gespeichert! Bitte setzen Sie Ihr Passwort, um fortzufahren.", + '1050001ab': "Ihr Passwort wurde erfolgreich gesetzt! ", 4000032: "Das Passwort muss mindestens 8 Zeichen lang sein, aber es wurden weniger als 8 Zeichen eingegeben.", 4000034: "Das Passwort wurde in Datenpannen gefunden und darf nicht mehr verwendet werden." } @@ -22,6 +23,7 @@ const customMessageOverridesDutch = { '1060001a': "Welkom bij de app! Je bent succesvol geregistreerd. Vul je voor- en achternaam in en koppel je account om verder te gaan.", 1050001: "Uw wijzigingen zijn opgeslagen!", '1050001a': "Uw wijzigingen zijn opgeslagen! Stel uw wachtwoord in om verder te gaan.", + '1050001ab': "Uw wachtwoord is succesvol ingesteld! ", 4000032: "Het wachtwoord moet minimaal 8 tekens lang zijn, maar er zijn minder dan 8 tekens ingevoerd.", 4000034: "Het wachtwoord is gevonden in datalekken en mag niet meer worden gebruikt." } From 2eac6f3610b17ebc4a6f133480bde4e4940af5ab Mon Sep 17 00:00:00 2001 From: Lina Date: Thu, 17 Jul 2025 15:26:46 +0200 Subject: [PATCH 07/17] PR comments --- pages/settings.tsx | 19 ++++++++++--------- pkg/ui/NodeInputDefault.tsx | 25 ++----------------------- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index e5bf492..604b4f8 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -3,7 +3,7 @@ import { AxiosError } from "axios" import type { NextPage } from "next" import Head from "next/head" import { useRouter } from "next/router" -import { useCallback, useEffect, useMemo, useState } from "react" +import { useCallback, useEffect, useState } from "react" import { Flow, Messages } from "../pkg" import { handleFlowError } from "../pkg/errors" @@ -18,7 +18,6 @@ import { AdminMessage } from "@/submodules/react-components/types/admin-messages import { postProcessAdminMessages } from "@/submodules/react-components/helpers/admin-messages-helper" import AdminMessages from "@/submodules/react-components/components/AdminMessages" import { useTranslation } from "react-i18next" -import { useConsoleLog } from "@/submodules/react-components/hooks/useConsoleLog" const Settings: NextPage = () => { const [initialFlow, setInitialFlow]: any = useState() @@ -172,8 +171,9 @@ const Settings: NextPage = () => { useEffect(() => { if (!changedFlow) return; if (changedFlow.ui.messages) { - initialFlow.ui.messages = initialFlow.ui.messages.map((message: any) => { - if (flowId && !isOidc) { + const messagesCopy = [...initialFlow.ui.messages]; + const messagesMapped = messagesCopy.map((message: any) => { + if (flowId) { if (message.id === 1060001 && isOidc && isOidcInvitation) { return { ...message, id: 1060001 + 'a' }; } @@ -183,7 +183,7 @@ const Settings: NextPage = () => { } return message; }); - setMessages(changedFlow.ui.messages); + setMessages(messagesMapped); } }, [changedFlow, isOidc, isOidcInvitation, showPassword, flowId, isOidc]) @@ -211,13 +211,14 @@ const Settings: NextPage = () => { useEffect(() => { if (backButtonDisabled || !changedFlow || !changedFlow.ui.messages || !flowId) return; - changedFlow.ui.messages = changedFlow.ui.messages.map((message: any) => { - if (message.id === '1050001a' && !isOidc) { - return { ...message, id: "1050001ab" }; + const messagesCopy = [...changedFlow.ui.messages]; + const messagesMapped = messagesCopy.map((message: any) => { + if (message.id === 1050001 && !isOidc) { + return { ...message, id: 1050001 + 'ab' }; } return message; }); - setMessages(changedFlow.ui.messages); + setMessages(messagesMapped); }, [backButtonDisabled, changedFlow, flowId, isOidc]); return ( diff --git a/pkg/ui/NodeInputDefault.tsx b/pkg/ui/NodeInputDefault.tsx index 710d9ce..0e5e64b 100644 --- a/pkg/ui/NodeInputDefault.tsx +++ b/pkg/ui/NodeInputDefault.tsx @@ -10,7 +10,6 @@ export function NodeInputDefault(props: NodeInputProps) { const { node, attributes, value = "", setValue, disabled } = props const { t } = useTranslation('settings'); const [labelName, setLabelName] = useState(""); - const [placeholderName, setPlaceholderName] = useState(""); // Some attributes have dynamic JavaScript - this is for example required for WebAuthn. @@ -25,27 +24,7 @@ export function NodeInputDefault(props: NodeInputProps) { } useEffect(() => { - // The settings page needs translated placeholders. - switch (getNodeLabel(node)) { - case "E-Mail": - setPlaceholderName(t('email')); - break; - case "First Name": - setPlaceholderName(t('firstName')); - break; - case "Last Name": - setPlaceholderName(t('lastName')); - break; - case "Password": - setPlaceholderName(t('password')); - break; - default: - setPlaceholderName(getNodeLabel(node)); - } - }, [node, t]); - - useEffect(() => { - // The settings page needs translated labels. + // The settings page needs translated labels & placeholder. switch (getNodeLabel(node)) { case "E-Mail": setLabelName(t('email')); @@ -75,7 +54,7 @@ export function NodeInputDefault(props: NodeInputProps) { className={"text-input" + (props.visible ? "" : " hidden")} type={attributes.type} name={attributes.name} - placeholder={placeholderName} + placeholder={labelName} value={value} disabled={attributes.disabled || disabled} help={node.messages.length > 0} From 167ec2ab8f0852dd347f584afa12172aba61540c Mon Sep 17 00:00:00 2001 From: Lina Date: Thu, 17 Jul 2025 15:57:57 +0200 Subject: [PATCH 08/17] PR comments --- pages/settings.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index 604b4f8..e90180a 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -221,6 +221,8 @@ const Settings: NextPage = () => { setMessages(messagesMapped); }, [backButtonDisabled, changedFlow, flowId, isOidc]); + + return ( <> @@ -245,7 +247,7 @@ const Settings: NextPage = () => {
{loadPage && <> - {!(isOidc && isOidcInvitation) && <> + {!isOidc && <> {((flowId && showPassword) || !flowId) && (

{!flowId ? t('changePassword') : t('setPassword')}

@@ -290,7 +292,7 @@ const Settings: NextPage = () => {
) : (<> )} } - {isOidc && isOidcInvitation ? (
+ {(isOidc && isOidcInvitation) ? (
Date: Thu, 17 Jul 2025 17:12:06 +0200 Subject: [PATCH 09/17] PR comments --- pages/settings.tsx | 1 + styles/tailwind.css | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index e90180a..93e4475 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -155,6 +155,7 @@ const Settings: NextPage = () => { const passwordButtonVal = (document.querySelector('input[name="password"]') as HTMLInputElement)?.value; if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && firstNameButtonVal !== undefined && lastNameButtonVal !== undefined) { setShowPassword(true); + document.querySelector('button[value="profile"]')?.setAttribute("class", "hidden"); } if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && passwordButtonVal !== "" && passwordButtonVal !== undefined) { setShowAuthenticator(true); diff --git a/styles/tailwind.css b/styles/tailwind.css index a182057..e01732f 100644 --- a/styles/tailwind.css +++ b/styles/tailwind.css @@ -257,5 +257,5 @@ button.button-sign-in:focus { } .hidden { - display: none; + display: none !important; } \ No newline at end of file From 8ce81b12be0b28706cc1881af6fd80e28c02514c Mon Sep 17 00:00:00 2001 From: Lina Date: Thu, 17 Jul 2025 17:23:10 +0200 Subject: [PATCH 10/17] PR comments --- util/helper-functions.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/util/helper-functions.ts b/util/helper-functions.ts index 7c5d250..f63121c 100644 --- a/util/helper-functions.ts +++ b/util/helper-functions.ts @@ -5,7 +5,8 @@ const customMessageOverridesEnglish = { '1050001a': "Your changes are saved! Please set your password to continue.", '1050001ab': "Your password has been set successfully! ", 4000032: "The password must be at least 8 characters long, but got less.", - 4000034: "The password has been found in data breaches and must no longer be used." + 4000034: "The password has been found in data breaches and must no longer be used.", + 4060004: "This link is invalid, add your email below to receive a new one" }; const customMessageOverridesGerman = { @@ -15,7 +16,8 @@ const customMessageOverridesGerman = { '1050001a': "Ihre Änderungen wurden gespeichert! Bitte setzen Sie Ihr Passwort, um fortzufahren.", '1050001ab': "Ihr Passwort wurde erfolgreich gesetzt! ", 4000032: "Das Passwort muss mindestens 8 Zeichen lang sein, aber es wurden weniger als 8 Zeichen eingegeben.", - 4000034: "Das Passwort wurde in Datenpannen gefunden und darf nicht mehr verwendet werden." + 4000034: "Das Passwort wurde in Datenpannen gefunden und darf nicht mehr verwendet werden.", + 4060004: "Dieser Link ist ungültig, geben Sie Ihre E-Mail unten ein, um einen neuen zu erhalten" } const customMessageOverridesDutch = { @@ -25,7 +27,8 @@ const customMessageOverridesDutch = { '1050001a': "Uw wijzigingen zijn opgeslagen! Stel uw wachtwoord in om verder te gaan.", '1050001ab': "Uw wachtwoord is succesvol ingesteld! ", 4000032: "Het wachtwoord moet minimaal 8 tekens lang zijn, maar er zijn minder dan 8 tekens ingevoerd.", - 4000034: "Het wachtwoord is gevonden in datalekken en mag niet meer worden gebruikt." + 4000034: "Het wachtwoord is gevonden in datalekken en mag niet meer worden gebruikt.", + 4060004: "Deze link is ongeldig, voeg uw e-mailadres hieronder toe om een nieuwe te ontvangen." } export function getValueIdentifier(selectedRole: any) { From 96cb4af9987402640f54820c3b5b954d1bc43e92 Mon Sep 17 00:00:00 2001 From: Lina Date: Thu, 17 Jul 2025 17:36:49 +0200 Subject: [PATCH 11/17] PR comments --- pages/settings.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index 93e4475..ab67c18 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -219,11 +219,15 @@ const Settings: NextPage = () => { } return message; }); + messagesCopy.forEach((message: any) => { + if (message.id === '1050001ab') { + router.push('/cognition'); + } + }) setMessages(messagesMapped); }, [backButtonDisabled, changedFlow, flowId, isOidc]); - return ( <> From 01be65b9ce848127dda5006ebd1b91226232a2e2 Mon Sep 17 00:00:00 2001 From: Lina Date: Fri, 18 Jul 2025 11:08:32 +0200 Subject: [PATCH 12/17] Test --- pages/settings.tsx | 111 ++++++++++++++++++++++----------------- util/helper-functions.ts | 3 ++ 2 files changed, 65 insertions(+), 49 deletions(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index ab67c18..5d706f1 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -40,11 +40,24 @@ const Settings: NextPage = () => { const [loadPage, setLoadPage] = useState(false); useEffect(() => { - if (loadPage) return; - setTimeout(() => { - setLoadPage(true); - }, 1000); - }, [loadPage]); + const onLoad = () => { + console.log('All elements including images and external resources are fully loaded.'); + setTimeout(() => { setLoadPage(true); }, 1000); + }; + + if (document.readyState === 'complete') { + onLoad(); + } else { + window.addEventListener('load', onLoad); + return () => window.removeEventListener('load', onLoad); + } + }, []); + // useEffect(() => { + // if (loadPage) return; + // setTimeout(() => { + // setLoadPage(true); + // }, 1000); + // }, [loadPage]); useEffect(() => { getUserInfoExtended((res) => { @@ -141,33 +154,35 @@ const Settings: NextPage = () => { }, [initialFlow]) useEffect(() => { - if (!changedFlow || !initialFlow) return; - const firstNameButtonVal = (document.querySelector('input[name="traits.name.first"]') as HTMLInputElement)?.value; - const lastNameButtonVal = (document.querySelector('input[name="traits.name.last"]') as HTMLInputElement)?.value; - if (isOidc && isOidcInvitation) { - if ((firstNameButtonVal === "" || lastNameButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined) && flowId) { - setBackButtonDisabled(true); + if (!changedFlow || !initialFlow || !loadPage) return; + setTimeout(() => { + const firstNameButtonVal = (document.querySelector('input[name="traits.name.first"]') as HTMLInputElement)?.value; + const lastNameButtonVal = (document.querySelector('input[name="traits.name.last"]') as HTMLInputElement)?.value; + if (isOidc && isOidcInvitation) { + if ((firstNameButtonVal === "" || lastNameButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined) && flowId) { + setBackButtonDisabled(true); + } else { + setBackButtonDisabled(false); + } } else { - setBackButtonDisabled(false); - } - } else { - const emailButtonVal = (document.querySelector('input[name="traits.email"]') as HTMLInputElement)?.value; - const passwordButtonVal = (document.querySelector('input[name="password"]') as HTMLInputElement)?.value; - if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && firstNameButtonVal !== undefined && lastNameButtonVal !== undefined) { - setShowPassword(true); - document.querySelector('button[value="profile"]')?.setAttribute("class", "hidden"); - } - if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && passwordButtonVal !== "" && passwordButtonVal !== undefined) { - setShowAuthenticator(true); - } + const emailButtonVal = (document.querySelector('input[name="traits.email"]') as HTMLInputElement)?.value; + const passwordButtonVal = (document.querySelector('input[name="password"]') as HTMLInputElement)?.value; + if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && firstNameButtonVal !== undefined && lastNameButtonVal !== undefined) { + setShowPassword(true); + document.querySelector('button[value="profile"]')?.setAttribute("class", "hidden"); + } + if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && passwordButtonVal !== "" && passwordButtonVal !== undefined) { + setShowAuthenticator(true); + } - if ((firstNameButtonVal === "" || lastNameButtonVal === "" || emailButtonVal === "" || passwordButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined || emailButtonVal === undefined || passwordButtonVal === undefined) && flowId) { - setBackButtonDisabled(true); - } else { - setBackButtonDisabled(false); + if ((firstNameButtonVal === "" || lastNameButtonVal === "" || emailButtonVal === "" || passwordButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined || emailButtonVal === undefined || passwordButtonVal === undefined) && flowId) { + setBackButtonDisabled(true); + } else { + setBackButtonDisabled(false); + } } - } - }, [isOidc, isOidcInvitation, initialFlow, changedFlow]); + }, 0); // Wait for the page to load + }, [isOidc, isOidcInvitation, initialFlow, changedFlow, loadPage]); useEffect(() => { if (!changedFlow) return; @@ -181,6 +196,10 @@ const Settings: NextPage = () => { if (message.id === 1050001 && showPassword) { return { ...message, id: 1050001 + 'a' }; } + if (message.id === 1060001 && !isOidc && !isOidcInvitation) { + return { ...message, id: 1060001 + 'b' }; + + } } return message; }); @@ -219,11 +238,7 @@ const Settings: NextPage = () => { } return message; }); - messagesCopy.forEach((message: any) => { - if (message.id === '1050001ab') { - router.push('/cognition'); - } - }) + console.log(messagesMapped); setMessages(messagesMapped); }, [backButtonDisabled, changedFlow, flowId, isOidc]); @@ -238,7 +253,7 @@ const Settings: NextPage = () => {
- {language &&
+ {(language && loadPage) &&

{t('heading')}

@@ -251,20 +266,18 @@ const Settings: NextPage = () => { />
- {loadPage && <> - {!isOidc && <> - {((flowId && showPassword) || !flowId) && ( -
-

{!flowId ? t('changePassword') : t('setPassword')}

- -
- )} - } + {!isOidc && <> + {((flowId && showPassword) || !flowId) && ( +
+

{!flowId ? t('changePassword') : t('setPassword')}

+ +
+ )} } {showAuthenticator && <> diff --git a/util/helper-functions.ts b/util/helper-functions.ts index f63121c..d9c6221 100644 --- a/util/helper-functions.ts +++ b/util/helper-functions.ts @@ -1,6 +1,7 @@ const customMessageOverridesEnglish = { 1060001: "Welcome to the app! You have successfully registered. Set your first and last name to continue.", '1060001a': "Welcome to the app! You have successfully registered. Set your first, last name and link your account to continue.", + '1060001b': "Welcome to the app! You have successfully recovered your account.", 1050001: "Your changes are saved!", '1050001a': "Your changes are saved! Please set your password to continue.", '1050001ab': "Your password has been set successfully! ", @@ -12,6 +13,7 @@ const customMessageOverridesEnglish = { const customMessageOverridesGerman = { 1060001: "Willkommen in der App! Sie haben sich erfolgreich registriert. Bitte geben Sie Ihren Vor- und Nachnamen ein, um fortzufahren.", '1060001a': "Willkommen in der App! Sie haben sich erfolgreich registriert. Bitte geben Sie Ihren Vor- und Nachnamen ein und verknüpfen Sie Ihr Konto, um fortzufahren.", + '1060001b': "Willkommen in der App! Sie haben Ihr Konto erfolgreich wiederhergestellt.", 1050001: "Ihre Änderungen wurden gespeichert!", '1050001a': "Ihre Änderungen wurden gespeichert! Bitte setzen Sie Ihr Passwort, um fortzufahren.", '1050001ab': "Ihr Passwort wurde erfolgreich gesetzt! ", @@ -23,6 +25,7 @@ const customMessageOverridesGerman = { const customMessageOverridesDutch = { 1060001: "Welkom bij de app! Je bent succesvol geregistreerd. Vul je voor- en achternaam in om verder te gaan.", '1060001a': "Welkom bij de app! Je bent succesvol geregistreerd. Vul je voor- en achternaam in en koppel je account om verder te gaan.", + '1060001b': "Welkom bij de app! Je hebt je account succesvol hersteld.", 1050001: "Uw wijzigingen zijn opgeslagen!", '1050001a': "Uw wijzigingen zijn opgeslagen! Stel uw wachtwoord in om verder te gaan.", '1050001ab': "Uw wachtwoord is succesvol ingesteld! ", From 1f877401d93c5ff74d6f712e91d8ba042e7e1288 Mon Sep 17 00:00:00 2001 From: Lina Date: Fri, 18 Jul 2025 11:27:42 +0200 Subject: [PATCH 13/17] Test --- pages/settings.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index 5d706f1..7dadbee 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -233,12 +233,12 @@ const Settings: NextPage = () => { if (backButtonDisabled || !changedFlow || !changedFlow.ui.messages || !flowId) return; const messagesCopy = [...changedFlow.ui.messages]; const messagesMapped = messagesCopy.map((message: any) => { - if (message.id === 1050001 && !isOidc) { - return { ...message, id: 1050001 + 'ab' }; + if (message.id === 1060001 && !isOidc) { + router.push('/cognition'); + return { ...message, id: '1050001ab' }; } return message; }); - console.log(messagesMapped); setMessages(messagesMapped); }, [backButtonDisabled, changedFlow, flowId, isOidc]); From 4cceff34006cf0d376ffce26ddc9754264d9a710 Mon Sep 17 00:00:00 2001 From: Lina Date: Fri, 18 Jul 2025 12:24:55 +0200 Subject: [PATCH 14/17] Test --- pages/settings.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index 7dadbee..70cfce7 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -18,6 +18,7 @@ import { AdminMessage } from "@/submodules/react-components/types/admin-messages import { postProcessAdminMessages } from "@/submodules/react-components/helpers/admin-messages-helper" import AdminMessages from "@/submodules/react-components/components/AdminMessages" import { useTranslation } from "react-i18next" +import { useConsoleLog } from "@/submodules/react-components/hooks/useConsoleLog" const Settings: NextPage = () => { const [initialFlow, setInitialFlow]: any = useState() @@ -154,6 +155,7 @@ const Settings: NextPage = () => { }, [initialFlow]) useEffect(() => { + console.log(loadPage); if (!changedFlow || !initialFlow || !loadPage) return; setTimeout(() => { const firstNameButtonVal = (document.querySelector('input[name="traits.name.first"]') as HTMLInputElement)?.value; @@ -175,6 +177,7 @@ const Settings: NextPage = () => { setShowAuthenticator(true); } + console.log(firstNameButtonVal, lastNameButtonVal, emailButtonVal, passwordButtonVal, flowId); if ((firstNameButtonVal === "" || lastNameButtonVal === "" || emailButtonVal === "" || passwordButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined || emailButtonVal === undefined || passwordButtonVal === undefined) && flowId) { setBackButtonDisabled(true); } else { @@ -182,7 +185,7 @@ const Settings: NextPage = () => { } } }, 0); // Wait for the page to load - }, [isOidc, isOidcInvitation, initialFlow, changedFlow, loadPage]); + }, [isOidc, isOidcInvitation, initialFlow, changedFlow, loadPage, flowId]); useEffect(() => { if (!changedFlow) return; @@ -229,18 +232,24 @@ const Settings: NextPage = () => { return Promise.reject(err) }) + useConsoleLog(showPassword, 'showPassword'); + useConsoleLog(backButtonDisabled, 'backButtonDisabled'); + + useEffect(() => { + console.log('useEffect triggered for messages update', backButtonDisabled, changedFlow, flowId, isOidc, showPassword); if (backButtonDisabled || !changedFlow || !changedFlow.ui.messages || !flowId) return; const messagesCopy = [...changedFlow.ui.messages]; const messagesMapped = messagesCopy.map((message: any) => { - if (message.id === 1060001 && !isOidc) { + console.log(message.id, isOidc, showPassword, backButtonDisabled, message.id === 1060001 && !isOidc && showPassword && backButtonDisabled); + if (message.id === 1060001 && !isOidc && showPassword && !backButtonDisabled) { router.push('/cognition'); return { ...message, id: '1050001ab' }; } return message; }); setMessages(messagesMapped); - }, [backButtonDisabled, changedFlow, flowId, isOidc]); + }, [backButtonDisabled, changedFlow, flowId, isOidc, showPassword]); return ( From 743378e657d79a651edbfd9e31bfbd78b7050421 Mon Sep 17 00:00:00 2001 From: Lina Date: Fri, 18 Jul 2025 13:33:30 +0200 Subject: [PATCH 15/17] Test --- pages/settings.tsx | 50 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index 70cfce7..ef89f27 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -157,34 +157,34 @@ const Settings: NextPage = () => { useEffect(() => { console.log(loadPage); if (!changedFlow || !initialFlow || !loadPage) return; - setTimeout(() => { - const firstNameButtonVal = (document.querySelector('input[name="traits.name.first"]') as HTMLInputElement)?.value; - const lastNameButtonVal = (document.querySelector('input[name="traits.name.last"]') as HTMLInputElement)?.value; - if (isOidc && isOidcInvitation) { - if ((firstNameButtonVal === "" || lastNameButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined) && flowId) { - setBackButtonDisabled(true); - } else { - setBackButtonDisabled(false); - } + // setTimeout(() => { + const firstNameButtonVal = (document.querySelector('input[name="traits.name.first"]') as HTMLInputElement)?.value; + const lastNameButtonVal = (document.querySelector('input[name="traits.name.last"]') as HTMLInputElement)?.value; + if (isOidc && isOidcInvitation) { + if ((firstNameButtonVal === "" || lastNameButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined) && flowId) { + setBackButtonDisabled(true); } else { - const emailButtonVal = (document.querySelector('input[name="traits.email"]') as HTMLInputElement)?.value; - const passwordButtonVal = (document.querySelector('input[name="password"]') as HTMLInputElement)?.value; - if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && firstNameButtonVal !== undefined && lastNameButtonVal !== undefined) { - setShowPassword(true); - document.querySelector('button[value="profile"]')?.setAttribute("class", "hidden"); - } - if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && passwordButtonVal !== "" && passwordButtonVal !== undefined) { - setShowAuthenticator(true); - } + setBackButtonDisabled(false); + } + } else { + const emailButtonVal = (document.querySelector('input[name="traits.email"]') as HTMLInputElement)?.value; + const passwordButtonVal = (document.querySelector('input[name="password"]') as HTMLInputElement)?.value; + if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && firstNameButtonVal !== undefined && lastNameButtonVal !== undefined) { + setShowPassword(true); + document.querySelector('button[value="profile"]')?.setAttribute("class", "hidden"); + } + if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && passwordButtonVal !== "" && passwordButtonVal !== undefined) { + setShowAuthenticator(true); + } - console.log(firstNameButtonVal, lastNameButtonVal, emailButtonVal, passwordButtonVal, flowId); - if ((firstNameButtonVal === "" || lastNameButtonVal === "" || emailButtonVal === "" || passwordButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined || emailButtonVal === undefined || passwordButtonVal === undefined) && flowId) { - setBackButtonDisabled(true); - } else { - setBackButtonDisabled(false); - } + console.log(firstNameButtonVal, lastNameButtonVal, emailButtonVal, passwordButtonVal, flowId); + if ((firstNameButtonVal === "" || lastNameButtonVal === "" || emailButtonVal === "" || passwordButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined || emailButtonVal === undefined || passwordButtonVal === undefined) && flowId) { + setBackButtonDisabled(true); + } else { + setBackButtonDisabled(false); } - }, 0); // Wait for the page to load + } + // }, 0); // Wait for the page to load }, [isOidc, isOidcInvitation, initialFlow, changedFlow, loadPage, flowId]); useEffect(() => { From 59c6eefcf914c4feaad8213a15b1da982f552730 Mon Sep 17 00:00:00 2001 From: Lina Date: Fri, 18 Jul 2025 13:43:25 +0200 Subject: [PATCH 16/17] Test --- pages/settings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index ef89f27..0caed1a 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -242,7 +242,7 @@ const Settings: NextPage = () => { const messagesCopy = [...changedFlow.ui.messages]; const messagesMapped = messagesCopy.map((message: any) => { console.log(message.id, isOidc, showPassword, backButtonDisabled, message.id === 1060001 && !isOidc && showPassword && backButtonDisabled); - if (message.id === 1060001 && !isOidc && showPassword && !backButtonDisabled) { + if (message.id === 1050001 && !isOidc && showPassword && !backButtonDisabled) { router.push('/cognition'); return { ...message, id: '1050001ab' }; } From 1af76747724329a7d6022f8b5b9e1b2bec908eb5 Mon Sep 17 00:00:00 2001 From: Lina Date: Mon, 21 Jul 2025 14:41:19 +0200 Subject: [PATCH 17/17] PR comments --- pages/settings.tsx | 66 ++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/pages/settings.tsx b/pages/settings.tsx index 0caed1a..f47ed52 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -18,7 +18,6 @@ import { AdminMessage } from "@/submodules/react-components/types/admin-messages import { postProcessAdminMessages } from "@/submodules/react-components/helpers/admin-messages-helper" import AdminMessages from "@/submodules/react-components/components/AdminMessages" import { useTranslation } from "react-i18next" -import { useConsoleLog } from "@/submodules/react-components/hooks/useConsoleLog" const Settings: NextPage = () => { const [initialFlow, setInitialFlow]: any = useState() @@ -39,26 +38,27 @@ const Settings: NextPage = () => { const [showPassword, setShowPassword] = useState(false); const [showAuthenticator, setShowAuthenticator] = useState(false); const [loadPage, setLoadPage] = useState(false); + const [canShow, setCanShow] = useState(false); useEffect(() => { - const onLoad = () => { - console.log('All elements including images and external resources are fully loaded.'); - setTimeout(() => { setLoadPage(true); }, 1000); - }; - - if (document.readyState === 'complete') { - onLoad(); - } else { - window.addEventListener('load', onLoad); - return () => window.removeEventListener('load', onLoad); - } - }, []); - // useEffect(() => { - // if (loadPage) return; - // setTimeout(() => { - // setLoadPage(true); - // }, 1000); - // }, [loadPage]); + if (loadPage) return; + setTimeout(() => { + setLoadPage(true); + const emailButtonVal = (document.querySelector('input[name="traits.email"]') as HTMLInputElement)?.value; + const firstNameButtonVal = (document.querySelector('input[name="traits.name.first"]') as HTMLInputElement)?.value; + const lastNameButtonVal = (document.querySelector('input[name="traits.name.last"]') as HTMLInputElement)?.value; + if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && firstNameButtonVal !== undefined && lastNameButtonVal !== undefined && emailButtonVal !== "" && emailButtonVal !== undefined && flowId) { + setShowPassword(true); + document.querySelector('button[value="profile"]')?.setAttribute("class", "hidden"); + setTimeout(() => { + const existsPassword = document.querySelector('input[name="password"]') !== null; + if (!existsPassword) { + document.querySelector('button[value="profile"]')?.setAttribute("class", "block"); + } + }, 100); + } + }, 1000); + }, [loadPage, flowId]); useEffect(() => { getUserInfoExtended((res) => { @@ -124,7 +124,7 @@ const Settings: NextPage = () => { }, [flowId, router, router.isReady, returnTo, initialFlow]) useEffect(() => { - if (!initialFlow) return; + if (!initialFlow || !loadPage) return; initialFlow.ui.nodes = prepareNodes(initialFlow); const checkIfTotp = initialFlow.ui.nodes.find((node: UiNode) => node.group === "totp"); const checkIfBackupCodes = initialFlow.ui.nodes.find((node: UiNode) => node.group === "lookup_secret"); @@ -141,6 +141,7 @@ const Settings: NextPage = () => { if (["microsoft", "google"].includes(initialFlow.identity.metadata_public?.registration_scope?.provider_id)) { initialFlow.ui.nodes = initialFlow.ui.nodes.filter((node: UiNode) => node.group !== "password"); setIsOidc(true); + setCanShow(true); if (initialFlow.identity.metadata_public?.registration_scope?.invitation_sso) { setIsOidcInvitation(true); } @@ -151,13 +152,15 @@ const Settings: NextPage = () => { document.querySelector('button[value="Google"]')?.setAttribute("class", "hidden"); } } + else { + setIsOidc(false); + setCanShow(true); + } }, 100); - }, [initialFlow]) + }, [initialFlow, loadPage]) useEffect(() => { - console.log(loadPage); if (!changedFlow || !initialFlow || !loadPage) return; - // setTimeout(() => { const firstNameButtonVal = (document.querySelector('input[name="traits.name.first"]') as HTMLInputElement)?.value; const lastNameButtonVal = (document.querySelector('input[name="traits.name.last"]') as HTMLInputElement)?.value; if (isOidc && isOidcInvitation) { @@ -171,21 +174,20 @@ const Settings: NextPage = () => { const passwordButtonVal = (document.querySelector('input[name="password"]') as HTMLInputElement)?.value; if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && firstNameButtonVal !== undefined && lastNameButtonVal !== undefined) { setShowPassword(true); - document.querySelector('button[value="profile"]')?.setAttribute("class", "hidden"); + if (flowId && !isOidc) { + document.querySelector('button[value="profile"]')?.setAttribute("class", "hidden"); + } } if (firstNameButtonVal !== "" && lastNameButtonVal !== "" && passwordButtonVal !== "" && passwordButtonVal !== undefined) { setShowAuthenticator(true); } - - console.log(firstNameButtonVal, lastNameButtonVal, emailButtonVal, passwordButtonVal, flowId); if ((firstNameButtonVal === "" || lastNameButtonVal === "" || emailButtonVal === "" || passwordButtonVal === "" || firstNameButtonVal === undefined || lastNameButtonVal === undefined || emailButtonVal === undefined || passwordButtonVal === undefined) && flowId) { setBackButtonDisabled(true); } else { setBackButtonDisabled(false); } } - // }, 0); // Wait for the page to load - }, [isOidc, isOidcInvitation, initialFlow, changedFlow, loadPage, flowId]); + }, [isOidc, isOidcInvitation, initialFlow, changedFlow, flowId, loadPage]); useEffect(() => { if (!changedFlow) return; @@ -232,16 +234,11 @@ const Settings: NextPage = () => { return Promise.reject(err) }) - useConsoleLog(showPassword, 'showPassword'); - useConsoleLog(backButtonDisabled, 'backButtonDisabled'); - useEffect(() => { - console.log('useEffect triggered for messages update', backButtonDisabled, changedFlow, flowId, isOidc, showPassword); if (backButtonDisabled || !changedFlow || !changedFlow.ui.messages || !flowId) return; const messagesCopy = [...changedFlow.ui.messages]; const messagesMapped = messagesCopy.map((message: any) => { - console.log(message.id, isOidc, showPassword, backButtonDisabled, message.id === 1060001 && !isOidc && showPassword && backButtonDisabled); if (message.id === 1050001 && !isOidc && showPassword && !backButtonDisabled) { router.push('/cognition'); return { ...message, id: '1050001ab' }; @@ -251,7 +248,6 @@ const Settings: NextPage = () => { setMessages(messagesMapped); }, [backButtonDisabled, changedFlow, flowId, isOidc, showPassword]); - return ( <> @@ -275,7 +271,7 @@ const Settings: NextPage = () => { />
- {!isOidc && <> + {(!isOidc && canShow) && <> {((flowId && showPassword) || !flowId) && (

{!flowId ? t('changePassword') : t('setPassword')}