Realm settings(themes): Add themes tab + tests (#544)
* wip add realm themes * get switch value from server * add tests * fix admin theme help text * remove requireSsl forlabel * update dropdown options * wip fix for locales * format * save/update locales done * expose all themes in dropdown * remove comments * remove theme types
This commit is contained in:
parent
aa7d2049d4
commit
721ed1bcaf
6 changed files with 553 additions and 41 deletions
|
@ -23,9 +23,9 @@ describe("Realm settings test", () => {
|
||||||
it("Go to general tab", function () {
|
it("Go to general tab", function () {
|
||||||
sidebarPage.goToRealmSettings();
|
sidebarPage.goToRealmSettings();
|
||||||
realmSettingsPage.toggleSwitch(managedAccessSwitch);
|
realmSettingsPage.toggleSwitch(managedAccessSwitch);
|
||||||
realmSettingsPage.save();
|
realmSettingsPage.saveGeneral();
|
||||||
realmSettingsPage.toggleSwitch(managedAccessSwitch);
|
realmSettingsPage.toggleSwitch(managedAccessSwitch);
|
||||||
realmSettingsPage.save();
|
realmSettingsPage.saveGeneral();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Go to login tab", function () {
|
it("Go to login tab", function () {
|
||||||
|
@ -36,5 +36,16 @@ describe("Realm settings test", () => {
|
||||||
realmSettingsPage.toggleSwitch(rememberMeSwitch);
|
realmSettingsPage.toggleSwitch(rememberMeSwitch);
|
||||||
realmSettingsPage.toggleSwitch(verifyEmailSwitch);
|
realmSettingsPage.toggleSwitch(verifyEmailSwitch);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Go to themes tab", function () {
|
||||||
|
sidebarPage.goToRealmSettings();
|
||||||
|
cy.getId("rs-themes-tab").click();
|
||||||
|
realmSettingsPage.selectLoginThemeType("keycloak");
|
||||||
|
realmSettingsPage.selectAccountThemeType("keycloak");
|
||||||
|
realmSettingsPage.selectAdminThemeType("keycloak.v2");
|
||||||
|
realmSettingsPage.selectEmailThemeType("base");
|
||||||
|
|
||||||
|
realmSettingsPage.saveThemes();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,28 +1,62 @@
|
||||||
export default class RealmSettingsPage {
|
export default class RealmSettingsPage {
|
||||||
saveBtn: string;
|
saveBtnGeneral: string;
|
||||||
|
saveBtnThemes: string;
|
||||||
loginTab: string;
|
loginTab: string;
|
||||||
managedAccessSwitch: string;
|
selectLoginTheme: string;
|
||||||
userRegSwitch: string;
|
loginThemeList: string;
|
||||||
forgotPwdSwitch: string;
|
selectAccountTheme: string;
|
||||||
rememberMeSwitch: string;
|
accountThemeList: string;
|
||||||
emailAsUsernameSwitch: string;
|
selectAdminTheme: string;
|
||||||
loginWithEmailSwitch: string;
|
adminThemeList: string;
|
||||||
duplicateEmailsSwitch: string;
|
selectEmailTheme: string;
|
||||||
verifyEmailSwitch: string;
|
emailThemeList: string;
|
||||||
|
selectDefaultLocale: string;
|
||||||
|
defaultLocaleList: string;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.saveBtn = "general-tab-save";
|
this.saveBtnGeneral = "general-tab-save";
|
||||||
|
this.saveBtnThemes = "themes-tab-save";
|
||||||
this.loginTab = "rs-login-tab";
|
this.loginTab = "rs-login-tab";
|
||||||
this.managedAccessSwitch = "user-managed-access-switch";
|
this.selectLoginTheme = "#kc-login-theme";
|
||||||
this.userRegSwitch = "user-reg-switch"
|
this.loginThemeList = "#kc-login-theme + ul";
|
||||||
this.forgotPwdSwitch = "forgot-password-switch"
|
this.selectAccountTheme = "#kc-account-theme";
|
||||||
this.rememberMeSwitch = "remember-me-switch"
|
this.accountThemeList = "#kc-account-theme + ul";
|
||||||
this.emailAsUsernameSwitch = "email-as-username-switch"
|
this.selectAdminTheme = "#kc-admin-console-theme";
|
||||||
this.loginWithEmailSwitch = "login-with-email-switch"
|
this.adminThemeList = "#kc-admin-console-theme + ul";
|
||||||
this.duplicateEmailsSwitch = "duplicate-emails-switch"
|
this.selectEmailTheme = "#kc-email-theme";
|
||||||
this.verifyEmailSwitch = "verify-email-switch"
|
this.emailThemeList = "#kc-email-theme + ul";
|
||||||
|
this.selectDefaultLocale = "select-default-locale";
|
||||||
|
this.defaultLocaleList = "select-default-locale + ul";
|
||||||
|
}
|
||||||
|
|
||||||
|
selectLoginThemeType(themeType: string) {
|
||||||
|
cy.get(this.selectLoginTheme).click();
|
||||||
|
cy.get(this.loginThemeList).contains(themeType).click();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectAccountThemeType(themeType: string) {
|
||||||
|
cy.get(this.selectAccountTheme).click();
|
||||||
|
cy.get(this.accountThemeList).contains(themeType).click();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectAdminThemeType(themeType: string) {
|
||||||
|
cy.get(this.selectAdminTheme).click();
|
||||||
|
cy.get(this.adminThemeList).contains(themeType).click();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectEmailThemeType(themeType: string) {
|
||||||
|
cy.get(this.selectEmailTheme).click();
|
||||||
|
cy.get(this.emailThemeList).contains(themeType).click();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDefaultLocale(locale: string) {
|
||||||
|
cy.get(this.selectDefaultLocale).click();
|
||||||
|
cy.get(this.defaultLocaleList).contains(locale).click();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSwitch(switchName: string) {
|
toggleSwitch(switchName: string) {
|
||||||
|
@ -31,10 +65,15 @@ export default class RealmSettingsPage {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
saveGeneral() {
|
||||||
cy.getId(this.saveBtn).click();
|
cy.getId(this.saveBtnGeneral).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveThemes() {
|
||||||
|
cy.getId(this.saveBtnThemes).click();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { KeycloakTabs } from "../components/keycloak-tabs/KeycloakTabs";
|
||||||
import { RealmSettingsLoginTab } from "./LoginTab";
|
import { RealmSettingsLoginTab } from "./LoginTab";
|
||||||
import { RealmSettingsGeneralTab } from "./GeneralTab";
|
import { RealmSettingsGeneralTab } from "./GeneralTab";
|
||||||
import { PartialImportDialog } from "./PartialImport";
|
import { PartialImportDialog } from "./PartialImport";
|
||||||
|
import { RealmSettingsThemesTab } from "./ThemesTab";
|
||||||
|
|
||||||
type RealmSettingsHeaderProps = {
|
type RealmSettingsHeaderProps = {
|
||||||
onChange: (value: boolean) => void;
|
onChange: (value: boolean) => void;
|
||||||
|
@ -177,6 +178,13 @@ export const RealmSettingsSection = () => {
|
||||||
>
|
>
|
||||||
<RealmSettingsLoginTab />
|
<RealmSettingsLoginTab />
|
||||||
</Tab>
|
</Tab>
|
||||||
|
<Tab
|
||||||
|
eventKey="themes"
|
||||||
|
title={<TabTitleText>{t("realm-settings:themes")}</TabTitleText>}
|
||||||
|
data-testid="rs-themes-tab"
|
||||||
|
>
|
||||||
|
<RealmSettingsThemesTab />
|
||||||
|
</Tab>
|
||||||
</KeycloakTabs>
|
</KeycloakTabs>
|
||||||
</PageSection>
|
</PageSection>
|
||||||
</>
|
</>
|
||||||
|
|
419
src/realm-settings/ThemesTab.tsx
Normal file
419
src/realm-settings/ThemesTab.tsx
Normal file
|
@ -0,0 +1,419 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
import { useErrorHandler } from "react-error-boundary";
|
||||||
|
import {
|
||||||
|
ActionGroup,
|
||||||
|
AlertVariant,
|
||||||
|
Button,
|
||||||
|
FormGroup,
|
||||||
|
PageSection,
|
||||||
|
Select,
|
||||||
|
SelectOption,
|
||||||
|
SelectVariant,
|
||||||
|
Switch,
|
||||||
|
} from "@patternfly/react-core";
|
||||||
|
|
||||||
|
import RealmRepresentation from "keycloak-admin/lib/defs/realmRepresentation";
|
||||||
|
import { useAdminClient, asyncStateFetch } from "../context/auth/AdminClient";
|
||||||
|
import { useRealm } from "../context/realm-context/RealmContext";
|
||||||
|
import { useAlerts } from "../components/alert/Alerts";
|
||||||
|
import { FormAccess } from "../components/form-access/FormAccess";
|
||||||
|
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||||
|
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||||
|
|
||||||
|
export const RealmSettingsThemesTab = () => {
|
||||||
|
const { t } = useTranslation("realm-settings");
|
||||||
|
const adminClient = useAdminClient();
|
||||||
|
const handleError = useErrorHandler();
|
||||||
|
const { realm: realmName } = useRealm();
|
||||||
|
const { addAlert } = useAlerts();
|
||||||
|
const { control, setValue, handleSubmit } = useForm();
|
||||||
|
const [realm, setRealm] = useState<RealmRepresentation>();
|
||||||
|
|
||||||
|
const [loginThemeOpen, setLoginThemeOpen] = useState(false);
|
||||||
|
const [accountThemeOpen, setAccountThemeOpen] = useState(false);
|
||||||
|
const [adminConsoleThemeOpen, setAdminConsoleThemeOpen] = useState(false);
|
||||||
|
const [emailThemeOpen, setEmailThemeOpen] = useState(false);
|
||||||
|
|
||||||
|
const [supportedLocalesOpen, setSupportedLocalesOpen] = useState(false);
|
||||||
|
const [defaultLocaleOpen, setDefaultLocaleOpen] = useState(false);
|
||||||
|
const [selections, setSelections] = useState<string[]>([]);
|
||||||
|
|
||||||
|
const [
|
||||||
|
internationalizationEnabled,
|
||||||
|
setInternationalizationEnabled,
|
||||||
|
] = useState(false);
|
||||||
|
|
||||||
|
const form = useForm();
|
||||||
|
|
||||||
|
const themeTypes = useServerInfo().themes!;
|
||||||
|
|
||||||
|
const watchSupportedLocales = form.watch(
|
||||||
|
"supportedLocales",
|
||||||
|
themeTypes?.account![0].locales
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return asyncStateFetch(
|
||||||
|
() => adminClient.realms.findOne({ realm: realmName }),
|
||||||
|
(realm) => {
|
||||||
|
setRealm(realm);
|
||||||
|
setupForm(realm);
|
||||||
|
setInternationalizationEnabled(realm.internationalizationEnabled!);
|
||||||
|
},
|
||||||
|
handleError
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setValue("supportedLocales", realm?.supportedLocales);
|
||||||
|
setValue("defaultLocale", realm?.defaultLocale);
|
||||||
|
}, [internationalizationEnabled]);
|
||||||
|
|
||||||
|
const setupForm = (realm: RealmRepresentation) => {
|
||||||
|
const { ...formValues } = realm;
|
||||||
|
|
||||||
|
form.reset(formValues);
|
||||||
|
Object.entries(realm).map((entry) => {
|
||||||
|
if (entry[0] === "internationalizationEnabled") {
|
||||||
|
setInternationalizationEnabled(realm!.internationalizationEnabled!);
|
||||||
|
}
|
||||||
|
setValue(entry[0], entry[1]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const save = async (realm: RealmRepresentation) => {
|
||||||
|
try {
|
||||||
|
await adminClient.realms.update({ realm: realmName }, realm);
|
||||||
|
setRealm({ supportedLocales: selections, ...realm });
|
||||||
|
addAlert(t("saveSuccess"), AlertVariant.success);
|
||||||
|
} catch (error) {
|
||||||
|
addAlert(t("saveError", { error }), AlertVariant.danger);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageSection variant="light">
|
||||||
|
<FormAccess
|
||||||
|
isHorizontal
|
||||||
|
role="manage-realm"
|
||||||
|
className="pf-u-mt-lg"
|
||||||
|
onSubmit={handleSubmit(save)}
|
||||||
|
>
|
||||||
|
<FormGroup
|
||||||
|
label={t("loginTheme")}
|
||||||
|
fieldId="kc-login-theme"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:loginTheme"
|
||||||
|
forLabel={t("loginTheme")}
|
||||||
|
forID="kc-login-theme"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="loginTheme"
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-login-theme"
|
||||||
|
onToggle={() => setLoginThemeOpen(!loginThemeOpen)}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setLoginThemeOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("loginTheme")}
|
||||||
|
isOpen={loginThemeOpen}
|
||||||
|
placeholderText="Select a theme"
|
||||||
|
data-testid="select-login-theme"
|
||||||
|
>
|
||||||
|
{themeTypes.login.map((theme, idx) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={theme.name === value}
|
||||||
|
key={`login-theme-${idx}`}
|
||||||
|
value={theme.name}
|
||||||
|
>
|
||||||
|
{t(`${theme.name}`)}
|
||||||
|
</SelectOption>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("accountTheme")}
|
||||||
|
fieldId="kc-account-theme"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:accountTheme"
|
||||||
|
forLabel={t("accountTheme")}
|
||||||
|
forID="kc-account-theme"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="accountTheme"
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-account-theme"
|
||||||
|
onToggle={() => setAccountThemeOpen(!accountThemeOpen)}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setAccountThemeOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("accountTheme")}
|
||||||
|
isOpen={accountThemeOpen}
|
||||||
|
placeholderText="Select a theme"
|
||||||
|
data-testid="select-account-theme"
|
||||||
|
>
|
||||||
|
{themeTypes.account.map((theme, idx) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={theme.name === value}
|
||||||
|
key={`account-theme-${idx}`}
|
||||||
|
value={theme.name}
|
||||||
|
>
|
||||||
|
{t(`${theme.name}`)}
|
||||||
|
</SelectOption>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("adminTheme")}
|
||||||
|
fieldId="kc-admin-console-theme"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:adminConsoleTheme"
|
||||||
|
forLabel={t("adminTheme")}
|
||||||
|
forID="kc-admin-console-theme"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="adminTheme"
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-admin-console-theme"
|
||||||
|
onToggle={() =>
|
||||||
|
setAdminConsoleThemeOpen(!adminConsoleThemeOpen)
|
||||||
|
}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setAdminConsoleThemeOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("adminConsoleTheme")}
|
||||||
|
isOpen={adminConsoleThemeOpen}
|
||||||
|
placeholderText="Select a theme"
|
||||||
|
data-testid="select-admin-theme"
|
||||||
|
>
|
||||||
|
{themeTypes.admin.map((theme, idx) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={theme.name === value}
|
||||||
|
key={`admin-theme-${idx}`}
|
||||||
|
value={theme.name}
|
||||||
|
>
|
||||||
|
{t(`${theme.name}`)}
|
||||||
|
</SelectOption>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("emailTheme")}
|
||||||
|
fieldId="kc-email-theme"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:emailTheme"
|
||||||
|
forLabel={t("emailTheme")}
|
||||||
|
forID="kc-email-theme"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="emailTheme"
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-email-theme"
|
||||||
|
onToggle={() => setEmailThemeOpen(!emailThemeOpen)}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setEmailThemeOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("emailTheme")}
|
||||||
|
isOpen={emailThemeOpen}
|
||||||
|
placeholderText="Select a theme"
|
||||||
|
data-testid="select-email-theme"
|
||||||
|
>
|
||||||
|
{themeTypes.email.map((theme, idx) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={theme.name === value}
|
||||||
|
key={`email-theme-${idx}`}
|
||||||
|
value={theme.name}
|
||||||
|
>
|
||||||
|
{t(`${theme.name}`)}
|
||||||
|
</SelectOption>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("internationalization")}
|
||||||
|
fieldId="kc-internationalization"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="internationalizationEnabled"
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id="kc-internationalization"
|
||||||
|
label={t("common:enabled")}
|
||||||
|
labelOff={t("common:disabled")}
|
||||||
|
isChecked={value}
|
||||||
|
data-testid={
|
||||||
|
value
|
||||||
|
? "internationalization-enabled"
|
||||||
|
: "internationalization-disabled"
|
||||||
|
}
|
||||||
|
onChange={(value) => {
|
||||||
|
onChange(value);
|
||||||
|
if (value) {
|
||||||
|
setValue("internationalizationEnabled", true);
|
||||||
|
setInternationalizationEnabled(value);
|
||||||
|
}
|
||||||
|
setInternationalizationEnabled(value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
{internationalizationEnabled && (
|
||||||
|
<>
|
||||||
|
<FormGroup
|
||||||
|
label={t("supportedLocales")}
|
||||||
|
fieldId="kc-supported-locales"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="supportedLocales"
|
||||||
|
control={control}
|
||||||
|
render={({ value, onChange }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-supported-locales"
|
||||||
|
onToggle={() =>
|
||||||
|
setSupportedLocalesOpen(!supportedLocalesOpen)
|
||||||
|
}
|
||||||
|
onSelect={(_, v) => {
|
||||||
|
const option = v as string;
|
||||||
|
if (!value) {
|
||||||
|
onChange([option]);
|
||||||
|
} else if (value!.includes(option)) {
|
||||||
|
onChange(
|
||||||
|
value.filter((item: string) => item !== option)
|
||||||
|
);
|
||||||
|
setSupportedLocalesOpen(false);
|
||||||
|
} else {
|
||||||
|
onChange([...value, option]);
|
||||||
|
setSupportedLocalesOpen(false);
|
||||||
|
}
|
||||||
|
setSelections([...value, v]);
|
||||||
|
}}
|
||||||
|
onClear={() => {
|
||||||
|
onChange(setSelections([]));
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.typeaheadMulti}
|
||||||
|
aria-label={t("supportedLocales")}
|
||||||
|
isOpen={supportedLocalesOpen}
|
||||||
|
placeholderText={"Select locales"}
|
||||||
|
>
|
||||||
|
{themeTypes?.login![0].locales.map(
|
||||||
|
(locale: string, idx: number) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={true}
|
||||||
|
key={`locale-${idx}`}
|
||||||
|
value={locale}
|
||||||
|
>
|
||||||
|
{t(`allSupportedLocales.${locale}`)}
|
||||||
|
</SelectOption>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup label={t("defaultLocale")} fieldId="kc-default-locale">
|
||||||
|
<Controller
|
||||||
|
name="defaultLocale"
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-default-locale"
|
||||||
|
onToggle={() => setDefaultLocaleOpen(!defaultLocaleOpen)}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setDefaultLocaleOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value && t(`allSupportedLocales.${value}`)}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("defaultLocale")}
|
||||||
|
isOpen={defaultLocaleOpen}
|
||||||
|
placeholderText="Select one"
|
||||||
|
data-testid="select-default-locale"
|
||||||
|
>
|
||||||
|
{selections.length !== 0
|
||||||
|
? selections.map((locale: string, idx: number) => (
|
||||||
|
<SelectOption
|
||||||
|
key={`default-locale-${idx}`}
|
||||||
|
value={locale}
|
||||||
|
>
|
||||||
|
{t(`allSupportedLocales.${locale}`)}
|
||||||
|
</SelectOption>
|
||||||
|
))
|
||||||
|
: watchSupportedLocales.map(
|
||||||
|
(locale: string, idx: number) => (
|
||||||
|
<SelectOption
|
||||||
|
key={`default-locale-${idx}`}
|
||||||
|
value={locale}
|
||||||
|
>
|
||||||
|
{t(`allSupportedLocales.${locale}`)}
|
||||||
|
</SelectOption>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<ActionGroup>
|
||||||
|
<Button
|
||||||
|
variant="primary"
|
||||||
|
type="submit"
|
||||||
|
data-testid="themes-tab-save"
|
||||||
|
>
|
||||||
|
{t("common:save")}
|
||||||
|
</Button>
|
||||||
|
<Button variant="link" onClick={() => setupForm(realm!)}>
|
||||||
|
{t("common:revert")}
|
||||||
|
</Button>
|
||||||
|
</ActionGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</PageSection>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -3,6 +3,10 @@
|
||||||
"frontendUrl": "Set the frontend URL for the realm. Use in combination with the default hostname provider to override the base URL for frontend requests for a specific realm.",
|
"frontendUrl": "Set the frontend URL for the realm. Use in combination with the default hostname provider to override the base URL for frontend requests for a specific realm.",
|
||||||
"requireSsl": "Is HTTPS required? 'None' means HTTPS is not required for any client IP address. 'External requests' means localhost and private IP addresses can access without HTTPS. 'All requests' means HTTPS is required for all IP addresses.",
|
"requireSsl": "Is HTTPS required? 'None' means HTTPS is not required for any client IP address. 'External requests' means localhost and private IP addresses can access without HTTPS. 'All requests' means HTTPS is required for all IP addresses.",
|
||||||
"userManagedAccess": "If enabled, users are allowed to manage their resources and permissions using the Account Management Console.",
|
"userManagedAccess": "If enabled, users are allowed to manage their resources and permissions using the Account Management Console.",
|
||||||
"endpoints": "Shows the configuration of the protocol endpoints"
|
"endpoints": "Shows the configuration of the protocol endpoints",
|
||||||
|
"loginTheme": "Select theme for login, OTP, grant, registration and forgot password pages.",
|
||||||
|
"accountTheme": "Select theme for user account management pages.",
|
||||||
|
"adminConsoleTheme": "Select theme for admin console.",
|
||||||
|
"emailTheme": "Select theme for emails that are sent by the server."
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
"saveError": "Realm could not be updated: {error}",
|
"saveError": "Realm could not be updated: {error}",
|
||||||
"general": "General",
|
"general": "General",
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
|
"themes": "Themes",
|
||||||
"userRegistration": "User registration",
|
"userRegistration": "User registration",
|
||||||
"userRegistrationHelpText": "Enable/disable the registration page. A link for registration will show on login page too.",
|
"userRegistrationHelpText": "Enable/disable the registration page. A link for registration will show on login page too.",
|
||||||
"forgotPassword": "Forgot password",
|
"forgotPassword": "Forgot password",
|
||||||
|
@ -37,10 +38,40 @@
|
||||||
"external": "External requests",
|
"external": "External requests",
|
||||||
"none": "None"
|
"none": "None"
|
||||||
},
|
},
|
||||||
|
"selectATheme": "Select a theme",
|
||||||
|
"allSupportedLocales": {
|
||||||
|
"ca": "Català",
|
||||||
|
"cs": "Čeština",
|
||||||
|
"da": "Dansk",
|
||||||
|
"de": "Deutsch",
|
||||||
|
"en": "English",
|
||||||
|
"es": "Español",
|
||||||
|
"fr": "Français",
|
||||||
|
"hu": "Magyar",
|
||||||
|
"it": "Italiano",
|
||||||
|
"ja": "日本語",
|
||||||
|
"lt": "Lietuvių kalba",
|
||||||
|
"nl": "Nederlands",
|
||||||
|
"no": "Norsk",
|
||||||
|
"pl": "Polski",
|
||||||
|
"pt-BR": "Português (Brasil)",
|
||||||
|
"ru": "Русский",
|
||||||
|
"sk": "Slovenčina",
|
||||||
|
"sv": "Svenska",
|
||||||
|
"tr": "Türkçe",
|
||||||
|
"zh-CN": "中文"
|
||||||
|
},
|
||||||
"userManagedAccess": "User-managed access",
|
"userManagedAccess": "User-managed access",
|
||||||
"endpoints": "Endpoints",
|
"endpoints": "Endpoints",
|
||||||
"openEndpointConfiguration": "Open Endpoint Configuration",
|
"openEndpointConfiguration": "Open Endpoint Configuration",
|
||||||
"samlIdentityProviderMetadata": "SAML 2.0 Identity Provider Metadata"
|
"samlIdentityProviderMetadata": "SAML 2.0 Identity Provider Metadata",
|
||||||
|
"loginTheme": "Login theme",
|
||||||
|
"accountTheme": "Account theme",
|
||||||
|
"adminTheme": "Admin console theme",
|
||||||
|
"emailTheme": "Email theme",
|
||||||
|
"internationalization": "Internationalization",
|
||||||
|
"supportedLocales": "Supported locales",
|
||||||
|
"defaultLocale": "Default locale"
|
||||||
},
|
},
|
||||||
"partial-import": {
|
"partial-import": {
|
||||||
"partialImportHeaderText": "Partial import allows you to import users, clients, and resources from a previously exported json file.",
|
"partialImportHeaderText": "Partial import allows you to import users, clients, and resources from a previously exported json file.",
|
||||||
|
|
Loading…
Reference in a new issue