8000 Enhance theme selection by rendering custom names in dropdown selectors. by azc9673 · Pull Request #48484 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
public class ThemeInfoRepresentation {

private String name;
private String renderedName;
private String[] locales;
private String description;

Expand All @@ -37,6 +38,14 @@ public void setName(String name) {
this.name = name;
}

public String getRenderedName() {
return renderedName;
}

public void setRenderedName(String renderedName) {
this.renderedName = renderedName;
}

public String[] getLocales() {
return locales;
}
Expand Down
3 changes: 3 additions & 0 deletions docs/guides/ui-customization/themes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,14 @@ The contents of `META-INF/keycloak-themes.json` in this case would be:
{
"themes": [{
"name" : "mytheme",
"renderedName" : "My Theme",
"types": [ "login", "email" ]
}]
}
----
+
`renderedName` is optional. If present, Keycloak uses it as the user-facing label in theme selection dropdowns, while `name` remains the canonical theme id used for resolution and resource loading.

A single archive can contain multiple themes and each theme can support one or more types.

To deploy the archive to {project_name}, add it to the `providers/` directory of
Expand Down
5 changes: 4 additions & 1 deletion js/apps/admin-ui/src/clients/add/LoginSettingsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ export const LoginSettingsPanel = ({ access }: { access?: boolean }) => {
}}
options={[
{ key: "", value: t("choose") },
...loginThemes.map(({ name }) => ({ key: name, value: name })),
...loginThemes.map(({ name, renderedName }) => ({
key: name,
value: renderedName || name,
})),
]}
/>
<DefaultSwitchControl
Expand Down
5 changes: 4 additions & 1 deletion js/apps/admin-ui/src/realm-settings/themes/QuickTheme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ export const QuickTheme = ({ realm, theme }: QuickThemeProps) => {
const zip = new JSZip();

const styles = JSON.parse(realm.attributes?.style ?? "{}");
const { favicon, logo, bgimage, fileName } = realm;
const { favicon, logo, bgimage, fileName, themeName } = realm;
const themeId = "quick-theme";
const renderedThemeName = themeName?.trim() || themeId;

const logoName =
"img/logo" + logo?.name?.substring(logo?.name?.lastIndexOf("."));
Expand Down Expand Up @@ -115,6 +117,7 @@ styles=css/login.css css/theme-styles.css
`{
"themes": [{
"name" : "${themeNameClean}",
"renderedName" : ${JSON.stringify(renderedThemeName)},
"types": [ "login", "account", "admin", "common" ]
}]
}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const ThemeSettingsTab = ({ realm, save }: ThemeSettingsTabProps) => {
options={appendEmptyChoice(
themeTypes.login.map((theme) => ({
key: theme.name,
value: theme.name,
value: theme.renderedName || theme.name,
description: theme.description,
})),
)}
Expand All @@ -71,7 +71,7 @@ export const ThemeSettingsTab = ({ realm, save }: ThemeSettingsTabProps) => {
options={appendEmptyChoice(
themeTypes.account.map((theme) => ({
key: theme.name,
value: theme.name,
value: theme.renderedName || theme.name,
description: theme.description,
})),
)}
Expand All @@ -86,7 +86,7 @@ export const ThemeSettingsTab = ({ realm, save }: ThemeSettingsTabProps) => {
options={appendEmptyChoice(
themeTypes.admin.map((theme) => ({
key: theme.name,
value: theme.name,
value: theme.renderedName || theme.name,
description: theme.description,
})),
)}
Expand All @@ -101,7 +101,7 @@ export const ThemeSettingsTab = ({ realm, save }: ThemeSettingsTabProps) => {
options={appendEmptyChoice(
themeTypes.email.map((theme) => ({
key: theme.name,
value: theme.name,
value: theme.renderedName || theme.name,
description: theme.description,
})),
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface ServerInfoRepresentation {

export interface ThemeInfoRepresentation {
name: string;
renderedName?: string;
locales?: string[];
description?: string;
}
Expand Down
4 changes: 4 additions & 0 deletions server-spi/src/main/java/org/keycloak/theme/Theme.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ enum Type { LOGIN, ACCOUNT, ADMIN, EMAIL, WELCOME, COMMON };

String getName();

default String getRenderedName() {
return getName();
}

String getParentName();

String getImportName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ private void setThemes(ServerInfoRepresentation info) {
if (theme != null && name.equals(theme.getName()) && !theme.isAbstract()) {
ThemeInfoRepresentation ti = new ThemeInfoRepresentation();
ti.setName(name);
ti.setRenderedName(theme.getRenderedName());

String locales = theme.getProperties().getProperty("locales");
if (locales != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public class ClassLoaderTheme extends FileBasedTheme {

private String name;

private String renderedName;

private String parentName;

private String importName;
Expand All @@ -52,11 +54,20 @@ public class ClassLoaderTheme extends FileBasedTheme {
private Properties properties;

public ClassLoaderTheme(String name, Type type, ClassLoader classLoader) throws IOException {
init(name, type, classLoader);
this(name, name, type, classLoader);
}

public ClassLoaderTheme(String name, String renderedName, Type type, ClassLoader classLoader) throws IOException {
init(name, renderedName, type, classLoader);
}

public void init(String name, Type type, ClassLoader classLoader) throws IOException {
init(name, name, type, classLoader);
}

public void init(String name, String renderedName, Type type, ClassLoader classLoader) throws IOException {
this.name = name;
this.renderedName = renderedName == null ? name : renderedName;
this.type = type;
this.classLoader = classLoader;

Expand Down Expand Up @@ -85,6 +96,11 @@ public String getName() {
return name;
}

@Override
public String getRenderedName() {
return renderedName;
}

@Override
public String getParentName() {
return parentName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public ClasspathThemeProviderFactory(String id, ClassLoader classLoader) {

public static class ThemeRepresentation {
private String name;
private String renderedName;
private String[] types;

public String getName() {
Expand All @@ -57,6 +58,14 @@ public void setName(String name) {
this.name = name;
}

public String getRenderedName() {
return renderedName;
}

public void setRenderedName(String renderedName) {
this.renderedName = renderedName;
}

public String[] getTypes() {
return types;
}
Expand Down Expand Up @@ -116,7 +125,7 @@ protected void loadThemes(ClassLoader classLoader, ThemesRepresentation themesRe
if (!themes.containsKey(type)) {
themes.put(type, new HashMap<>());
}
themes.get(type).put(themeRep.getName(), new ClassLoaderTheme(themeRep.getName(), type, classLoader));
themes.get(type).put(themeRep.getName(), new ClassLoaderTheme(themeRep.getName(), themeRep.getRenderedName(), type, classLoader));
}
}
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ public String getName() {
return themes.get(0).getName();
}

@Override
public String getRenderedName() {
return themes.get(0).getRenderedName();
}

@Override
public String getParentName() {
return themes.get(0).getParentName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public void testServerInfo() {
Assert.assertNames(info.getThemes().get("email"), "keycloak");
Assert.assertNames(info.getThemes().get("login"), "keycloak", "keycloak.v2");
Assert.assertNames(info.getThemes().get("welcome"), "keycloak");
info.getThemes().values().forEach(themes ->
themes.forEach(theme -> assertEquals(theme.getName(), theme.getRenderedName())));

assertNotNull(info.getEnums());

Expand Down
Loading
0