keycloakify 2.2.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +156 -127
- package/bin/KeycloakVersion.js.map +1 -1
- package/bin/build-keycloak-theme/build-keycloak-theme.js +57 -54
- package/bin/build-keycloak-theme/build-keycloak-theme.js.map +1 -1
- package/bin/build-keycloak-theme/ftlValuesGlobalName.js.map +1 -1
- package/bin/build-keycloak-theme/generateDebugFiles/generateDebugFiles.js +4 -11
- package/bin/build-keycloak-theme/generateDebugFiles/generateDebugFiles.js.map +1 -1
- package/bin/build-keycloak-theme/generateFtl/common.ftl +72 -56
- package/bin/build-keycloak-theme/generateFtl/generateFtl.d.ts +1 -1
- package/bin/build-keycloak-theme/generateFtl/generateFtl.js +47 -44
- package/bin/build-keycloak-theme/generateFtl/generateFtl.js.map +1 -1
- package/bin/build-keycloak-theme/generateJavaStackFiles.js +12 -8
- package/bin/build-keycloak-theme/generateJavaStackFiles.js.map +1 -1
- package/bin/build-keycloak-theme/generateKeycloakThemeResources.js +20 -21
- package/bin/build-keycloak-theme/generateKeycloakThemeResources.js.map +1 -1
- package/bin/build-keycloak-theme/index.js.map +1 -1
- package/bin/build-keycloak-theme/replaceImportFromStatic.js +18 -30
- package/bin/build-keycloak-theme/replaceImportFromStatic.js.map +1 -1
- package/bin/download-builtin-keycloak-theme.js +2 -2
- package/bin/download-builtin-keycloak-theme.js.map +1 -1
- package/bin/generate-i18n-messages.js +9 -11
- package/bin/generate-i18n-messages.js.map +1 -1
- package/bin/link_in_test_app.js +6 -22
- package/bin/link_in_test_app.js.map +1 -1
- package/bin/tools/crawl.js.map +1 -1
- package/bin/tools/downloadAndUnzip.js +4 -5
- package/bin/tools/downloadAndUnzip.js.map +1 -1
- package/bin/tools/grant-exec-perms.js +4 -3
- package/bin/tools/grant-exec-perms.js.map +1 -1
- package/bin/tools/isInside.js.map +1 -1
- package/bin/tools/rm.js +1 -1
- package/bin/tools/rm.js.map +1 -1
- package/bin/tools/transformCodebase.js +7 -3
- package/bin/tools/transformCodebase.js.map +1 -1
- package/lib/components/Error.js +1 -2
- package/lib/components/Error.js.map +1 -1
- package/lib/components/Info.js +1 -15
- package/lib/components/Info.js.map +1 -1
- package/lib/components/KcApp.js +23 -10
- package/lib/components/KcApp.js.map +1 -1
- package/lib/components/KcProps.d.ts +4 -2
- package/lib/components/KcProps.js +10 -8
- package/lib/components/KcProps.js.map +1 -1
- package/lib/components/Login.js +20 -18
- package/lib/components/Login.js.map +1 -1
- package/lib/components/LoginIdpLinkConfirm.js.map +1 -1
- package/lib/components/LoginOtp.js +14 -15
- package/lib/components/LoginOtp.js.map +1 -1
- package/lib/components/LoginResetPassword.js +5 -7
- package/lib/components/LoginResetPassword.js.map +1 -1
- package/lib/components/LoginUpdateProfile.js +1 -5
- package/lib/components/LoginUpdateProfile.js.map +1 -1
- package/lib/components/LoginVerifyEmail.js.map +1 -1
- package/lib/components/Register.js +1 -4
- package/lib/components/Register.js.map +1 -1
- package/lib/components/RegisterUserProfile.d.ts +6 -0
- package/lib/components/RegisterUserProfile.js +78 -0
- package/lib/components/RegisterUserProfile.js.map +1 -0
- package/lib/components/Template.js +28 -43
- package/lib/components/Template.js.map +1 -1
- package/lib/components/Terms.js.map +1 -1
- package/lib/getKcContext/KcContextBase.d.ts +78 -18
- package/lib/getKcContext/KcContextBase.js +2 -3
- package/lib/getKcContext/KcContextBase.js.map +1 -1
- package/lib/getKcContext/getKcContext.d.ts +1 -3
- package/lib/getKcContext/getKcContext.js +5 -9
- package/lib/getKcContext/getKcContext.js.map +1 -1
- package/lib/getKcContext/kcContextMocks/kcContextMocks.d.ts +1 -0
- package/lib/getKcContext/kcContextMocks/kcContextMocks.js +187 -55
- package/lib/getKcContext/kcContextMocks/kcContextMocks.js.map +1 -1
- package/lib/getKcContext/kcContextMocks/urlResourcesPath.js.map +1 -1
- package/lib/i18n/KcLanguageTag.d.ts +25 -2
- package/lib/i18n/KcLanguageTag.js +27 -27
- package/lib/i18n/KcLanguageTag.js.map +1 -1
- package/lib/i18n/generated_kcMessages/11.0.3/account.js +27 -27
- package/lib/i18n/generated_kcMessages/11.0.3/account.js.map +1 -1
- package/lib/i18n/generated_kcMessages/11.0.3/admin.js +23 -23
- package/lib/i18n/generated_kcMessages/11.0.3/admin.js.map +1 -1
- package/lib/i18n/generated_kcMessages/11.0.3/email.js +97 -97
- package/lib/i18n/generated_kcMessages/11.0.3/email.js.map +1 -1
- package/lib/i18n/generated_kcMessages/11.0.3/login.js +30 -30
- package/lib/i18n/generated_kcMessages/11.0.3/login.js.map +1 -1
- package/lib/i18n/generated_kcMessages/15.0.2/account.js +29 -29
- package/lib/i18n/generated_kcMessages/15.0.2/account.js.map +1 -1
- package/lib/i18n/generated_kcMessages/15.0.2/admin.js +23 -23
- package/lib/i18n/generated_kcMessages/15.0.2/admin.js.map +1 -1
- package/lib/i18n/generated_kcMessages/15.0.2/email.js +111 -111
- package/lib/i18n/generated_kcMessages/15.0.2/email.js.map +1 -1
- package/lib/i18n/generated_kcMessages/15.0.2/login.js +32 -32
- package/lib/i18n/generated_kcMessages/15.0.2/login.js.map +1 -1
- package/lib/i18n/kcMessages/login.js +1 -1
- package/lib/i18n/kcMessages/login.js.map +1 -1
- package/lib/i18n/useKcLanguageTag.js +1 -3
- package/lib/i18n/useKcLanguageTag.js.map +1 -1
- package/lib/i18n/useKcMessage.d.ts +4 -2
- package/lib/i18n/useKcMessage.js +12 -3
- package/lib/i18n/useKcMessage.js.map +1 -1
- package/lib/keycloakJsAdapter.d.ts +6 -6
- package/lib/keycloakJsAdapter.js +10 -12
- package/lib/keycloakJsAdapter.js.map +1 -1
- package/lib/tools/ReactComponent.d.ts +2 -0
- package/lib/tools/ReactComponent.js +3 -0
- package/lib/tools/ReactComponent.js.map +1 -0
- package/lib/tools/allPropertiesValuesToUndefined.js +1 -2
- package/lib/tools/allPropertiesValuesToUndefined.js.map +1 -1
- package/lib/tools/appendHead.js +16 -12
- package/lib/tools/appendHead.js.map +1 -1
- package/lib/tools/assert.js.map +1 -1
- package/lib/tools/deepAssign.js +3 -4
- package/lib/tools/deepAssign.js.map +1 -1
- package/lib/tools/deepClone.js.map +1 -1
- package/package.json +25 -5
- package/src/bin/KeycloakVersion.ts +0 -2
- package/src/bin/build-keycloak-theme/build-keycloak-theme.ts +70 -77
- package/src/bin/build-keycloak-theme/ftlValuesGlobalName.ts +1 -2
- package/src/bin/build-keycloak-theme/generateDebugFiles/generateDebugFiles.ts +26 -37
- package/src/bin/build-keycloak-theme/generateDebugFiles/index.ts +1 -1
- package/src/bin/build-keycloak-theme/generateFtl/common.ftl +72 -56
- package/src/bin/build-keycloak-theme/generateFtl/generateFtl.ts +75 -95
- package/src/bin/build-keycloak-theme/generateFtl/index.ts +1 -1
- package/src/bin/build-keycloak-theme/generateJavaStackFiles.ts +38 -56
- package/src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts +47 -85
- package/src/bin/build-keycloak-theme/index.ts +2 -4
- package/src/bin/build-keycloak-theme/replaceImportFromStatic.ts +34 -78
- package/src/bin/download-builtin-keycloak-theme.ts +5 -19
- package/src/bin/generate-i18n-messages.ts +13 -25
- package/src/bin/link_in_test_app.ts +9 -38
- package/src/bin/tools/crawl.ts +2 -12
- package/src/bin/tools/downloadAndUnzip.ts +6 -22
- package/src/bin/tools/getProjectRoot.ts +1 -1
- package/src/bin/tools/grant-exec-perms.ts +8 -7
- package/src/bin/tools/isInside.ts +2 -9
- package/src/bin/tools/rm.ts +21 -32
- package/src/bin/tools/transformCodebase.ts +20 -43
- package/src/lib/components/Error.tsx +3 -7
- package/src/lib/components/Info.tsx +23 -47
- package/src/lib/components/KcApp.tsx +25 -13
- package/src/lib/components/KcProps.ts +94 -92
- package/src/lib/components/Login.tsx +126 -116
- package/src/lib/components/LoginIdpLinkConfirm.tsx +38 -53
- package/src/lib/components/LoginOtp.tsx +39 -76
- package/src/lib/components/LoginResetPassword.tsx +9 -26
- package/src/lib/components/LoginUpdateProfile.tsx +104 -117
- package/src/lib/components/LoginVerifyEmail.tsx +3 -12
- package/src/lib/components/Register.tsx +76 -46
- package/src/lib/components/RegisterUserProfile.tsx +201 -0
- package/src/lib/components/Template.tsx +109 -161
- package/src/lib/components/Terms.tsx +4 -13
- package/src/lib/getKcContext/KcContextBase.ts +104 -53
- package/src/lib/getKcContext/getKcContext.ts +47 -78
- package/src/lib/getKcContext/index.ts +2 -2
- package/src/lib/getKcContext/kcContextMocks/index.ts +1 -1
- package/src/lib/getKcContext/kcContextMocks/kcContextMocks.ts +362 -241
- package/src/lib/getKcContext/kcContextMocks/urlResourcesPath.ts +1 -2
- package/src/lib/i18n/KcLanguageTag.ts +34 -45
- package/src/lib/i18n/generated_kcMessages/11.0.3/account.ts +3086 -3059
- package/src/lib/i18n/generated_kcMessages/11.0.3/admin.ts +248 -239
- package/src/lib/i18n/generated_kcMessages/11.0.3/email.ts +848 -633
- package/src/lib/i18n/generated_kcMessages/11.0.3/login.ts +4466 -4359
- package/src/lib/i18n/generated_kcMessages/15.0.2/account.ts +4247 -4202
- package/src/lib/i18n/generated_kcMessages/15.0.2/admin.ts +273 -264
- package/src/lib/i18n/generated_kcMessages/15.0.2/email.ts +997 -749
- package/src/lib/i18n/generated_kcMessages/15.0.2/login.ts +5352 -5212
- package/src/lib/i18n/kcMessages/login.ts +4 -9
- package/src/lib/i18n/useKcLanguageTag.ts +2 -16
- package/src/lib/i18n/useKcMessage.tsx +26 -15
- package/src/lib/index.ts +0 -1
- package/src/lib/keycloakJsAdapter.ts +23 -53
- package/src/lib/tools/AndByDiscriminatingKey.ts +16 -30
- package/src/lib/tools/DeepPartial.ts +1 -2
- package/src/lib/tools/ReactComponent.ts +4 -0
- package/src/lib/tools/allPropertiesValuesToUndefined.ts +1 -6
- package/src/lib/tools/appendHead.ts +28 -25
- package/src/lib/tools/assert.ts +1 -2
- package/src/lib/tools/deepAssign.ts +28 -46
- package/src/lib/tools/deepClone.ts +2 -3
@@ -0,0 +1,201 @@
|
|
1
|
+
import { memo, Fragment } from "react";
|
2
|
+
import { Template } from "./Template";
|
3
|
+
import type { KcProps } from "./KcProps";
|
4
|
+
import type { KcContextBase } from "../getKcContext/KcContextBase";
|
5
|
+
import { useKcMessage } from "../i18n/useKcMessage";
|
6
|
+
import { useCssAndCx } from "tss-react";
|
7
|
+
import type { ReactComponent } from "../tools/ReactComponent";
|
8
|
+
|
9
|
+
export const RegisterUserProfile = memo(({ kcContext, ...props }: { kcContext: KcContextBase.RegisterUserProfile } & KcProps) => {
|
10
|
+
const { url, messagesPerField, realm, passwordRequired, recaptchaRequired, recaptchaSiteKey } = kcContext;
|
11
|
+
|
12
|
+
const { msg, msgStr } = useKcMessage();
|
13
|
+
|
14
|
+
const { cx } = useCssAndCx();
|
15
|
+
|
16
|
+
return (
|
17
|
+
<Template
|
18
|
+
{...{ kcContext, ...props }}
|
19
|
+
displayMessage={messagesPerField.exists("global")}
|
20
|
+
displayRequiredFields={true}
|
21
|
+
doFetchDefaultThemeResources={true}
|
22
|
+
headerNode={msg("registerTitle")}
|
23
|
+
formNode={
|
24
|
+
<form id="kc-register-form" className={cx(props.kcFormClass)} action={url.registrationAction} method="post">
|
25
|
+
<UserProfileFormFields
|
26
|
+
kcContext={kcContext}
|
27
|
+
{...props}
|
28
|
+
AfterField={({ attribute }) =>
|
29
|
+
/*render password fields just under the username or email (if used as username)*/
|
30
|
+
(passwordRequired &&
|
31
|
+
(attribute.name == "username" || (attribute.name == "email" && realm.registrationEmailAsUsername)) && (
|
32
|
+
<>
|
33
|
+
<div className={cx(props.kcFormGroupClass)}>
|
34
|
+
<div className={cx(props.kcLabelWrapperClass)}>
|
35
|
+
<label htmlFor="password" className={cx(props.kcLabelClass)}>
|
36
|
+
{msg("password")}
|
37
|
+
</label>{" "}
|
38
|
+
*
|
39
|
+
</div>
|
40
|
+
<div className={cx(props.kcInputWrapperClass)}>
|
41
|
+
<input
|
42
|
+
type="password"
|
43
|
+
id="password"
|
44
|
+
className={cx(props.kcInputClass)}
|
45
|
+
name="password"
|
46
|
+
autoComplete="new-password"
|
47
|
+
aria-invalid={
|
48
|
+
messagesPerField.existsError("password") || messagesPerField.existsError("password-confirm")
|
49
|
+
}
|
50
|
+
/>
|
51
|
+
{messagesPerField.existsError("password") && (
|
52
|
+
<span id="input-error-password" className={cx(props.kcInputErrorMessageClass)} aria-live="polite">
|
53
|
+
{messagesPerField.get("password")}
|
54
|
+
</span>
|
55
|
+
)}
|
56
|
+
</div>
|
57
|
+
</div>
|
58
|
+
<div className={cx(props.kcFormGroupClass)}>
|
59
|
+
<div className={cx(props.kcLabelWrapperClass)}>
|
60
|
+
<label htmlFor="password-confirm" className={cx(props.kcLabelClass)}>
|
61
|
+
{msg("passwordConfirm")}
|
62
|
+
</label>{" "}
|
63
|
+
*
|
64
|
+
</div>
|
65
|
+
<div className={cx(props.kcInputWrapperClass)}>
|
66
|
+
<input
|
67
|
+
type="password"
|
68
|
+
id="password-confirm"
|
69
|
+
className={cx(props.kcInputClass)}
|
70
|
+
name="password-confirm"
|
71
|
+
autoComplete="new-password"
|
72
|
+
aria-invalid={messagesPerField.existsError("password-confirm")}
|
73
|
+
/>
|
74
|
+
{messagesPerField.existsError("password-confirm") && (
|
75
|
+
<span
|
76
|
+
id="input-error-password-confirm"
|
77
|
+
className={cx(props.kcInputErrorMessageClass)}
|
78
|
+
aria-live="polite"
|
79
|
+
>
|
80
|
+
{messagesPerField.get("password-confirm")}
|
81
|
+
</span>
|
82
|
+
)}
|
83
|
+
</div>
|
84
|
+
</div>
|
85
|
+
</>
|
86
|
+
)) ||
|
87
|
+
null
|
88
|
+
}
|
89
|
+
/>
|
90
|
+
{recaptchaRequired && (
|
91
|
+
<div className="form-group">
|
92
|
+
<div className={cx(props.kcInputWrapperClass)}>
|
93
|
+
<div className="g-recaptcha" data-size="compact" data-sitekey={recaptchaSiteKey} />
|
94
|
+
</div>
|
95
|
+
</div>
|
96
|
+
)}
|
97
|
+
<div className={cx(props.kcFormGroupClass)}>
|
98
|
+
<div id="kc-form-options" className={cx(props.kcFormOptionsClass)}>
|
99
|
+
<div className={cx(props.kcFormOptionsWrapperClass)}>
|
100
|
+
<span>
|
101
|
+
<a href={url.loginUrl}>{msg("backToLogin")}</a>
|
102
|
+
</span>
|
103
|
+
</div>
|
104
|
+
</div>
|
105
|
+
|
106
|
+
<div id="kc-form-buttons" className={cx(props.kcFormButtonsClass)}>
|
107
|
+
<input
|
108
|
+
className={cx(props.kcButtonClass, props.kcButtonPrimaryClass, props.kcButtonBlockClass, props.kcButtonLargeClass)}
|
109
|
+
type="submit"
|
110
|
+
value={msgStr("doRegister")}
|
111
|
+
/>
|
112
|
+
</div>
|
113
|
+
</div>
|
114
|
+
</form>
|
115
|
+
}
|
116
|
+
/>
|
117
|
+
);
|
118
|
+
});
|
119
|
+
|
120
|
+
const UserProfileFormFields = memo(
|
121
|
+
({
|
122
|
+
kcContext,
|
123
|
+
BeforeField = () => null,
|
124
|
+
AfterField = () => null,
|
125
|
+
...props
|
126
|
+
}: { kcContext: KcContextBase.RegisterUserProfile } & KcProps &
|
127
|
+
Partial<
|
128
|
+
Record<
|
129
|
+
"BeforeField" | "AfterField",
|
130
|
+
ReactComponent<{
|
131
|
+
attribute: KcContextBase.RegisterUserProfile["profile"]["attributes"][number];
|
132
|
+
}>
|
133
|
+
>
|
134
|
+
>) => {
|
135
|
+
const { messagesPerField } = kcContext;
|
136
|
+
|
137
|
+
const { cx } = useCssAndCx();
|
138
|
+
|
139
|
+
const { advancedMsg } = useKcMessage();
|
140
|
+
|
141
|
+
let currentGroup = "";
|
142
|
+
|
143
|
+
return (
|
144
|
+
<>
|
145
|
+
{kcContext.profile.attributes
|
146
|
+
.map(attribute => [attribute, attribute])
|
147
|
+
.map(([attribute, { group = "", groupDisplayHeader = "", groupDisplayDescription = "" }], i) => (
|
148
|
+
<Fragment key={i}>
|
149
|
+
{group !== currentGroup && (currentGroup = group) !== "" && (
|
150
|
+
<div className={cx(props.kcFormGroupClass)}>
|
151
|
+
<div className={cx(props.kcContentWrapperClass)}>
|
152
|
+
<label id={`header-${group}`} className={cx(props.kcFormGroupHeader)}>
|
153
|
+
{(groupDisplayHeader !== "" && advancedMsg(groupDisplayHeader)) || currentGroup}
|
154
|
+
</label>
|
155
|
+
</div>
|
156
|
+
{groupDisplayDescription !== "" && (
|
157
|
+
<div className={cx(props.kcLabelWrapperClass)}>
|
158
|
+
<label id={`description-${group}`} className={`${cx(props.kcLabelClass)}`}>
|
159
|
+
{advancedMsg(groupDisplayDescription) ?? ""}
|
160
|
+
</label>
|
161
|
+
</div>
|
162
|
+
)}
|
163
|
+
</div>
|
164
|
+
)}
|
165
|
+
<BeforeField attribute={attribute} />
|
166
|
+
<div className={cx(props.kcFormGroupClass)}>
|
167
|
+
<div className={cx(props.kcLabelWrapperClass)}>
|
168
|
+
<label htmlFor={attribute.name} className={cx(props.kcLabelClass)}>
|
169
|
+
{advancedMsg(attribute.displayName ?? "")}
|
170
|
+
</label>
|
171
|
+
{attribute.required && <>*</>}
|
172
|
+
</div>
|
173
|
+
<div className={cx(props.kcInputWrapperClass)}>
|
174
|
+
<input
|
175
|
+
type="text"
|
176
|
+
id={attribute.name}
|
177
|
+
name={attribute.name}
|
178
|
+
defaultValue={attribute.value ?? ""}
|
179
|
+
className={cx(props.kcInputClass)}
|
180
|
+
aria-invalid={messagesPerField.existsError(attribute.name)}
|
181
|
+
disabled={attribute.readOnly}
|
182
|
+
{...(attribute.autocomplete === undefined
|
183
|
+
? {}
|
184
|
+
: {
|
185
|
+
"autoComplete": attribute.autocomplete,
|
186
|
+
})}
|
187
|
+
/>
|
188
|
+
{kcContext.messagesPerField.existsError(attribute.name) && (
|
189
|
+
<span id={`input-error-${attribute.name}`} className={cx(props.kcInputErrorMessageClass)} aria-live="polite">
|
190
|
+
{messagesPerField.get(attribute.name)}
|
191
|
+
</span>
|
192
|
+
)}
|
193
|
+
</div>
|
194
|
+
</div>
|
195
|
+
<AfterField attribute={attribute} />
|
196
|
+
</Fragment>
|
197
|
+
))}
|
198
|
+
</>
|
199
|
+
);
|
200
|
+
},
|
201
|
+
);
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
import { useReducer, useEffect, memo } from "react";
|
3
2
|
import type { ReactNode } from "react";
|
4
3
|
import { useKcMessage } from "../i18n/useKcMessage";
|
@@ -29,10 +28,9 @@ export type TemplateProps = {
|
|
29
28
|
* to avoid pulling the default theme assets.
|
30
29
|
*/
|
31
30
|
doFetchDefaultThemeResources: boolean;
|
32
|
-
} & { kcContext: KcContextBase
|
31
|
+
} & { kcContext: KcContextBase } & KcTemplateProps;
|
33
32
|
|
34
33
|
export const Template = memo((props: TemplateProps) => {
|
35
|
-
|
36
34
|
const {
|
37
35
|
displayInfo = false,
|
38
36
|
displayMessage = true,
|
@@ -44,34 +42,26 @@ export const Template = memo((props: TemplateProps) => {
|
|
44
42
|
formNode,
|
45
43
|
infoNode = null,
|
46
44
|
kcContext,
|
47
|
-
doFetchDefaultThemeResources
|
45
|
+
doFetchDefaultThemeResources,
|
48
46
|
} = props;
|
49
47
|
|
50
48
|
const { cx } = useCssAndCx();
|
51
49
|
|
52
|
-
useEffect(() => {
|
50
|
+
useEffect(() => {
|
51
|
+
console.log("Rendering this page with react using keycloakify");
|
52
|
+
}, []);
|
53
53
|
|
54
54
|
const { msg } = useKcMessage();
|
55
55
|
|
56
56
|
const { kcLanguageTag, setKcLanguageTag } = useKcLanguageTag();
|
57
57
|
|
58
|
+
const onChangeLanguageClickFactory = useCallbackFactory(([languageTag]: [KcLanguageTag]) => setKcLanguageTag(languageTag));
|
58
59
|
|
59
|
-
const
|
60
|
-
([languageTag]: [KcLanguageTag]) =>
|
61
|
-
setKcLanguageTag(languageTag)
|
62
|
-
);
|
63
|
-
|
64
|
-
const onTryAnotherWayClick = useConstCallback(() =>
|
65
|
-
(document.forms["kc-select-try-another-way-form" as never].submit(), false)
|
66
|
-
);
|
60
|
+
const onTryAnotherWayClick = useConstCallback(() => (document.forms["kc-select-try-another-way-form" as never].submit(), false));
|
67
61
|
|
68
|
-
const {
|
69
|
-
realm, locale, auth,
|
70
|
-
url, message, isAppInitiatedAction
|
71
|
-
} = kcContext;
|
62
|
+
const { realm, locale, auth, url, message, isAppInitiatedAction } = kcContext;
|
72
63
|
|
73
64
|
useEffect(() => {
|
74
|
-
|
75
65
|
if (!realm.internationalizationEnabled) {
|
76
66
|
return;
|
77
67
|
}
|
@@ -82,15 +72,12 @@ export const Template = memo((props: TemplateProps) => {
|
|
82
72
|
return;
|
83
73
|
}
|
84
74
|
|
85
|
-
window.location.href =
|
86
|
-
locale.supported.find(({ languageTag }) => languageTag === kcLanguageTag)!.url;
|
87
|
-
|
75
|
+
window.location.href = locale.supported.find(({ languageTag }) => languageTag === kcLanguageTag)!.url;
|
88
76
|
}, [kcLanguageTag]);
|
89
77
|
|
90
78
|
const [isExtraCssLoaded, setExtraCssLoaded] = useReducer(() => true, false);
|
91
79
|
|
92
80
|
useEffect(() => {
|
93
|
-
|
94
81
|
if (!doFetchDefaultThemeResources) {
|
95
82
|
setExtraCssLoaded();
|
96
83
|
return;
|
@@ -99,55 +86,48 @@ export const Template = memo((props: TemplateProps) => {
|
|
99
86
|
let isUnmounted = false;
|
100
87
|
const cleanups: (() => void)[] = [];
|
101
88
|
|
102
|
-
const toArr = (x: string | readonly string[] | undefined) =>
|
103
|
-
typeof x === "string" ? x.split(" ") : x ?? [];
|
89
|
+
const toArr = (x: string | readonly string[] | undefined) => (typeof x === "string" ? x.split(" ") : x ?? []);
|
104
90
|
|
105
91
|
Promise.all(
|
106
92
|
[
|
107
93
|
...toArr(props.stylesCommon).map(relativePath => pathJoin(url.resourcesCommonPath, relativePath)),
|
108
|
-
...toArr(props.styles).map(relativePath => pathJoin(url.resourcesPath, relativePath))
|
109
|
-
].map(href =>
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
94
|
+
...toArr(props.styles).map(relativePath => pathJoin(url.resourcesPath, relativePath)),
|
95
|
+
].map(href =>
|
96
|
+
appendHead({
|
97
|
+
"type": "css",
|
98
|
+
href,
|
99
|
+
}),
|
100
|
+
),
|
101
|
+
).then(() => {
|
102
|
+
if (isUnmounted) {
|
103
|
+
return;
|
104
|
+
}
|
119
105
|
|
120
|
-
|
106
|
+
setExtraCssLoaded();
|
107
|
+
});
|
121
108
|
|
122
|
-
toArr(props.scripts).forEach(
|
123
|
-
|
109
|
+
toArr(props.scripts).forEach(relativePath =>
|
110
|
+
appendHead({
|
124
111
|
"type": "javascript",
|
125
|
-
"src": pathJoin(url.resourcesPath, relativePath)
|
126
|
-
})
|
112
|
+
"src": pathJoin(url.resourcesPath, relativePath),
|
113
|
+
}),
|
127
114
|
);
|
128
115
|
|
129
116
|
if (props.kcHtmlClass !== undefined) {
|
117
|
+
const htmlClassList = document.getElementsByTagName("html")[0].classList;
|
130
118
|
|
131
|
-
const
|
132
|
-
document.getElementsByTagName("html")[0]
|
133
|
-
.classList;
|
134
|
-
|
135
|
-
const tokens = cx(props.kcHtmlClass).split(" ")
|
119
|
+
const tokens = cx(props.kcHtmlClass).split(" ");
|
136
120
|
|
137
121
|
htmlClassList.add(...tokens);
|
138
122
|
|
139
123
|
cleanups.push(() => htmlClassList.remove(...tokens));
|
140
|
-
|
141
124
|
}
|
142
125
|
|
143
126
|
return () => {
|
144
|
-
|
145
127
|
isUnmounted = true;
|
146
128
|
|
147
129
|
cleanups.forEach(f => f());
|
148
|
-
|
149
130
|
};
|
150
|
-
|
151
131
|
}, [props.kcHtmlClass]);
|
152
132
|
|
153
133
|
if (!isExtraCssLoaded) {
|
@@ -156,7 +136,6 @@ export const Template = memo((props: TemplateProps) => {
|
|
156
136
|
|
157
137
|
return (
|
158
138
|
<div className={cx(props.kcLoginClass)}>
|
159
|
-
|
160
139
|
<div id="kc-header" className={cx(props.kcHeaderClass)}>
|
161
140
|
<div id="kc-header-wrapper" className={cx(props.kcHeaderWrapperClass)}>
|
162
141
|
{msg("loginTitleHtml", realm.displayNameHtml)}
|
@@ -165,12 +144,7 @@ export const Template = memo((props: TemplateProps) => {
|
|
165
144
|
|
166
145
|
<div className={cx(props.kcFormCardClass, displayWide && props.kcFormCardAccountClass)}>
|
167
146
|
<header className={cx(props.kcFormHeaderClass)}>
|
168
|
-
{
|
169
|
-
(
|
170
|
-
realm.internationalizationEnabled &&
|
171
|
-
(assert(locale !== undefined), true) &&
|
172
|
-
locale.supported.length > 1
|
173
|
-
) &&
|
147
|
+
{realm.internationalizationEnabled && (assert(locale !== undefined), true) && locale.supported.length > 1 && (
|
174
148
|
<div id="kc-locale">
|
175
149
|
<div id="kc-locale-wrapper" className={cx(props.kcLocaleWrapperClass)}>
|
176
150
|
<div className="kc-dropdown" id="kc-locale-dropdown">
|
@@ -178,104 +152,77 @@ export const Template = memo((props: TemplateProps) => {
|
|
178
152
|
{getKcLanguageTagLabel(kcLanguageTag)}
|
179
153
|
</a>
|
180
154
|
<ul>
|
181
|
-
{
|
182
|
-
|
183
|
-
(
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
</li>
|
190
|
-
)
|
191
|
-
}
|
155
|
+
{locale.supported.map(({ languageTag }) => (
|
156
|
+
<li key={languageTag} className="kc-dropdown-item">
|
157
|
+
<a href="#" onClick={onChangeLanguageClickFactory(languageTag)}>
|
158
|
+
{getKcLanguageTagLabel(languageTag)}
|
159
|
+
</a>
|
160
|
+
</li>
|
161
|
+
))}
|
192
162
|
</ul>
|
193
163
|
</div>
|
194
164
|
</div>
|
195
165
|
</div>
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
<
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
<div className={cx(props.kcContentWrapperClass)}>
|
230
|
-
<div className={cx(props.kcLabelWrapperClass, "subtitle")}>
|
231
|
-
<span className="subtitle"><span className="required">*</span> {msg("requiredFields")}</span>
|
232
|
-
</div>
|
233
|
-
<div className="col-md-10">
|
234
|
-
{showUsernameNode}
|
235
|
-
<div className={cx(props.kcFormGroupClass)}>
|
236
|
-
<div id="kc-username">
|
237
|
-
<label id="kc-attempted-username">{auth?.attemptedUsername}</label>
|
238
|
-
<a id="reset-login" href={url.loginRestartFlowUrl}>
|
239
|
-
<div className="kc-login-tooltip">
|
240
|
-
<i className={cx(props.kcResetFlowIcon)}></i>
|
241
|
-
<span className="kc-tooltip-text">{msg("restartLoginTooltip")}</span>
|
242
|
-
</div>
|
243
|
-
</a>
|
244
|
-
</div>
|
166
|
+
)}
|
167
|
+
{!(auth !== undefined && auth.showUsername && !auth.showResetCredentials) ? (
|
168
|
+
displayRequiredFields ? (
|
169
|
+
<div className={cx(props.kcContentWrapperClass)}>
|
170
|
+
<div className={cx(props.kcLabelWrapperClass, "subtitle")}>
|
171
|
+
<span className="subtitle">
|
172
|
+
<span className="required">*</span>
|
173
|
+
{msg("requiredFields")}
|
174
|
+
</span>
|
175
|
+
</div>
|
176
|
+
<div className="col-md-10">
|
177
|
+
<h1 id="kc-page-title">{headerNode}</h1>
|
178
|
+
</div>
|
179
|
+
</div>
|
180
|
+
) : (
|
181
|
+
<h1 id="kc-page-title">{headerNode}</h1>
|
182
|
+
)
|
183
|
+
) : displayRequiredFields ? (
|
184
|
+
<div className={cx(props.kcContentWrapperClass)}>
|
185
|
+
<div className={cx(props.kcLabelWrapperClass, "subtitle")}>
|
186
|
+
<span className="subtitle">
|
187
|
+
<span className="required">*</span> {msg("requiredFields")}
|
188
|
+
</span>
|
189
|
+
</div>
|
190
|
+
<div className="col-md-10">
|
191
|
+
{showUsernameNode}
|
192
|
+
<div className={cx(props.kcFormGroupClass)}>
|
193
|
+
<div id="kc-username">
|
194
|
+
<label id="kc-attempted-username">{auth?.attemptedUsername}</label>
|
195
|
+
<a id="reset-login" href={url.loginRestartFlowUrl}>
|
196
|
+
<div className="kc-login-tooltip">
|
197
|
+
<i className={cx(props.kcResetFlowIcon)}></i>
|
198
|
+
<span className="kc-tooltip-text">{msg("restartLoginTooltip")}</span>
|
245
199
|
</div>
|
246
|
-
</
|
200
|
+
</a>
|
247
201
|
</div>
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
</
|
202
|
+
</div>
|
203
|
+
</div>
|
204
|
+
</div>
|
205
|
+
) : (
|
206
|
+
<>
|
207
|
+
{showUsernameNode}
|
208
|
+
<div className={cx(props.kcFormGroupClass)}>
|
209
|
+
<div id="kc-username">
|
210
|
+
<label id="kc-attempted-username">{auth?.attemptedUsername}</label>
|
211
|
+
<a id="reset-login" href={url.loginRestartFlowUrl}>
|
212
|
+
<div className="kc-login-tooltip">
|
213
|
+
<i className={cx(props.kcResetFlowIcon)}></i>
|
214
|
+
<span className="kc-tooltip-text">{msg("restartLoginTooltip")}</span>
|
261
215
|
</div>
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
216
|
+
</a>
|
217
|
+
</div>
|
218
|
+
</div>
|
219
|
+
</>
|
220
|
+
)}
|
266
221
|
</header>
|
267
222
|
<div id="kc-content">
|
268
223
|
<div id="kc-content-wrapper">
|
269
224
|
{/* App-initiated actions should not see warning messages about the need to complete the action during login. */}
|
270
|
-
{
|
271
|
-
(
|
272
|
-
displayMessage &&
|
273
|
-
message !== undefined &&
|
274
|
-
(
|
275
|
-
message.type !== "warning" ||
|
276
|
-
!isAppInitiatedAction
|
277
|
-
)
|
278
|
-
) &&
|
225
|
+
{displayMessage && message !== undefined && (message.type !== "warning" || !isAppInitiatedAction) && (
|
279
226
|
<div className={cx("alert", `alert-${message.type}`)}>
|
280
227
|
{message.type === "success" && <span className={cx(props.kcFeedbackSuccessIcon)}></span>}
|
281
228
|
{message.type === "warning" && <span className={cx(props.kcFeedbackWarningIcon)}></span>}
|
@@ -283,36 +230,37 @@ export const Template = memo((props: TemplateProps) => {
|
|
283
230
|
{message.type === "info" && <span className={cx(props.kcFeedbackInfoIcon)}></span>}
|
284
231
|
<span
|
285
232
|
className="kc-feedback-text"
|
286
|
-
dangerouslySetInnerHTML={{
|
233
|
+
dangerouslySetInnerHTML={{
|
234
|
+
"__html": message.summary,
|
235
|
+
}}
|
287
236
|
/>
|
288
237
|
</div>
|
289
|
-
}
|
238
|
+
)}
|
290
239
|
{formNode}
|
291
|
-
{
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
<div className={cx(displayWide && [props.kcFormSocialAccountContentClass, props.kcFormSocialAccountClass])} >
|
240
|
+
{auth !== undefined && auth.showTryAnotherWayLink && showAnotherWayIfPresent && (
|
241
|
+
<form
|
242
|
+
id="kc-select-try-another-way-form"
|
243
|
+
action={url.loginAction}
|
244
|
+
method="post"
|
245
|
+
className={cx(displayWide && props.kcContentWrapperClass)}
|
246
|
+
>
|
247
|
+
<div className={cx(displayWide && [props.kcFormSocialAccountContentClass, props.kcFormSocialAccountClass])}>
|
300
248
|
<div className={cx(props.kcFormGroupClass)}>
|
301
249
|
<input type="hidden" name="tryAnotherWay" value="on" />
|
302
|
-
<a href="#" id="try-another-way" onClick={onTryAnotherWayClick}>
|
250
|
+
<a href="#" id="try-another-way" onClick={onTryAnotherWayClick}>
|
251
|
+
{msg("doTryAnotherWay")}
|
252
|
+
</a>
|
303
253
|
</div>
|
304
|
-
</div
|
254
|
+
</div>
|
305
255
|
</form>
|
306
|
-
}
|
307
|
-
{
|
308
|
-
displayInfo &&
|
309
|
-
|
256
|
+
)}
|
257
|
+
{displayInfo && (
|
310
258
|
<div id="kc-info" className={cx(props.kcSignUpClass)}>
|
311
259
|
<div id="kc-info-wrapper" className={cx(props.kcInfoAreaWrapperClass)}>
|
312
260
|
{infoNode}
|
313
261
|
</div>
|
314
262
|
</div>
|
315
|
-
}
|
263
|
+
)}
|
316
264
|
</div>
|
317
265
|
</div>
|
318
266
|
</div>
|
@@ -5,8 +5,7 @@ import type { KcContextBase } from "../getKcContext/KcContextBase";
|
|
5
5
|
import { useKcMessage } from "../i18n/useKcMessage";
|
6
6
|
import { useCssAndCx } from "tss-react";
|
7
7
|
|
8
|
-
export const Terms = memo(({ kcContext, ...props }: { kcContext: KcContextBase.Terms
|
9
|
-
|
8
|
+
export const Terms = memo(({ kcContext, ...props }: { kcContext: KcContextBase.Terms } & KcProps) => {
|
10
9
|
const { msg, msgStr } = useKcMessage();
|
11
10
|
|
12
11
|
const { cx } = useCssAndCx();
|
@@ -21,9 +20,7 @@ export const Terms = memo(({ kcContext, ...props }: { kcContext: KcContextBase.T
|
|
21
20
|
headerNode={msg("termsTitle")}
|
22
21
|
formNode={
|
23
22
|
<>
|
24
|
-
<div id="kc-terms-text">
|
25
|
-
{msg("termsText")}
|
26
|
-
</div>
|
23
|
+
<div id="kc-terms-text">{msg("termsText")}</div>
|
27
24
|
<form className="form-actions" action={url.loginAction} method="POST">
|
28
25
|
<input
|
29
26
|
className={cx(
|
@@ -31,7 +28,7 @@ export const Terms = memo(({ kcContext, ...props }: { kcContext: KcContextBase.T
|
|
31
28
|
props.kcButtonClass,
|
32
29
|
props.kcButtonClass,
|
33
30
|
props.kcButtonPrimaryClass,
|
34
|
-
props.kcButtonLargeClass
|
31
|
+
props.kcButtonLargeClass,
|
35
32
|
)}
|
36
33
|
name="accept"
|
37
34
|
id="kc-accept"
|
@@ -39,11 +36,7 @@ export const Terms = memo(({ kcContext, ...props }: { kcContext: KcContextBase.T
|
|
39
36
|
value={msgStr("doAccept")}
|
40
37
|
/>
|
41
38
|
<input
|
42
|
-
className={cx(
|
43
|
-
props.kcButtonClass,
|
44
|
-
props.kcButtonDefaultClass,
|
45
|
-
props.kcButtonLargeClass
|
46
|
-
)}
|
39
|
+
className={cx(props.kcButtonClass, props.kcButtonDefaultClass, props.kcButtonLargeClass)}
|
47
40
|
name="cancel"
|
48
41
|
id="kc-decline"
|
49
42
|
type="submit"
|
@@ -56,5 +49,3 @@ export const Terms = memo(({ kcContext, ...props }: { kcContext: KcContextBase.T
|
|
56
49
|
/>
|
57
50
|
);
|
58
51
|
});
|
59
|
-
|
60
|
-
|