Skip to content

Commit

Permalink
Localization > Effective message bundles tab improvements (keycloak#2…
Browse files Browse the repository at this point in the history
…6302)

* added a couple of improvements

Signed-off-by: Agnieszka Gancarczyk <[email protected]>

* fix theme and themeType

Signed-off-by: Agnieszka Gancarczyk <[email protected]>

* improved hasWords filter

Signed-off-by: Agnieszka Gancarczyk <[email protected]>

* added refresh btn

Signed-off-by: Agnieszka Gancarczyk <[email protected]>

* fixed backend

Signed-off-by: Agnieszka Gancarczyk <[email protected]>

* added validation

Signed-off-by: Agnieszka Gancarczyk <[email protected]>

* cleanup

Signed-off-by: Agnieszka Gancarczyk <[email protected]>

* replaced sort with localSort

Signed-off-by: Agnieszka Gancarczyk <[email protected]>

* improved spacing

Signed-off-by: Agnieszka Gancarczyk <[email protected]>

* added useMemo

Signed-off-by: Agnieszka Gancarczyk <[email protected]>

* removed filter on themeTypes

Signed-off-by: Agnieszka Gancarczyk <[email protected]>

---------

Signed-off-by: Agnieszka Gancarczyk <[email protected]>
Co-authored-by: Agnieszka Gancarczyk <[email protected]>
  • Loading branch information
agagancarczyk and agagancarczyk authored Jan 19, 2024
1 parent 84b2c5e commit 229cbb5
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2985,4 +2985,5 @@ readBlog=Read blog
customValue=Custom value
termsAndConditionsUserAttribute=Terms and conditions accepted timestamp
realmOverridesDescription= Realm overrides allow you to specify translations that will take effect for the entire realm. These translations will override any translation specified by a theme.
addTranslation=Add translation
addTranslation=Add translation
effectiveMessageBundlesDescription=An effective message bundle is the set of translations for a given language, theme, and theme type. It also takes into account any realm overrides, which will take precedence.
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ import {
Select,
SelectOption,
SelectVariant,
Text,
TextContent,
TextVariants,
} from "@patternfly/react-core";
import { pickBy } from "lodash-es";
import { useState } from "react";
import { useMemo, useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { adminClient } from "../../admin-client";
Expand All @@ -27,6 +30,7 @@ import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
import { useWhoAmI } from "../../context/whoami/WhoAmI";
import { DEFAULT_LOCALE } from "../../i18n/i18n";
import { localeToDisplayName } from "../../util";
import useLocaleSort, { mapByKey } from "../../utils/useLocaleSort";

type EffectiveMessageBundlesProps = {
defaultSupportedLocales: string[];
Expand All @@ -53,6 +57,7 @@ export const EffectiveMessageBundles = ({
const { realm } = useRealm();
const serverInfo = useServerInfo();
const { whoAmI } = useWhoAmI();
const localeSort = useLocaleSort();
const [searchDropdownOpen, setSearchDropdownOpen] = useState(false);
const [searchPerformed, setSearchPerformed] = useState(false);
const [selectThemesOpen, setSelectThemesOpen] = useState(false);
Expand All @@ -61,15 +66,29 @@ export const EffectiveMessageBundles = ({
const [activeFilters, setActiveFilters] = useState<
Partial<EffectiveMessageBundlesSearchForm>
>({});
const themes = serverInfo.themes;
const themeKeys = themes
? Object.keys(themes).sort((a, b) => a.localeCompare(b))
: [];
const themeTypes = Object.values(themes!)
.flatMap((theme) => theme.map((item) => item.name))
.filter((value, index, self) => self.indexOf(value) === index)
.sort((a, b) => a.localeCompare(b));
const [key, setKey] = useState(0);
const themes = serverInfo.themes;

const themeTypes = useMemo(() => {
if (!themes) {
return [];
}

return localeSort(Object.keys(themes), (key) => key);
}, [themes]);

const themeNames = useMemo(() => {
if (!themes) {
return [];
}

return localeSort(
Object.values(themes)
.flatMap((theme) => theme.map((item) => item.name))
.filter((value, index, self) => self.indexOf(value) === index),
(name) => name,
);
}, [themes]);

const filterLabels: Record<keyof EffectiveMessageBundlesSearchForm, string> =
{
Expand All @@ -82,7 +101,7 @@ export const EffectiveMessageBundles = ({
const {
getValues,
reset,
formState: { isDirty },
formState: { isDirty, isValid },
control,
} = useForm<EffectiveMessageBundlesSearchForm>({
mode: "onChange",
Expand All @@ -101,11 +120,18 @@ export const EffectiveMessageBundles = ({
},
);

return filter.hasWords.length > 0
? messages.filter((m) =>
filter.hasWords.some((f) => m.value.includes(f)),
)
: messages;
const filteredMessages =
filter.hasWords.length > 0
? messages.filter((m) =>
filter.hasWords.some(
(f) => m.value.includes(f) || m.key.includes(f),
),
)
: messages;

const sortedMessages = localeSort([...filteredMessages], mapByKey("key"));

return sortedMessages;
} catch (error) {
return [];
}
Expand Down Expand Up @@ -159,6 +185,13 @@ export const EffectiveMessageBundles = ({
direction={{ default: "column" }}
spaceItems={{ default: "spaceItemsNone" }}
>
<FlexItem>
<TextContent>
<Text className="pf-u-mb-md pf-u-mt-0" component={TextVariants.p}>
{t("effectiveMessageBundlesDescription")}
</Text>
</TextContent>
</FlexItem>
<FlexItem>
<Dropdown
id="effective-message-bundles-search-select"
Expand All @@ -175,13 +208,16 @@ export const EffectiveMessageBundles = ({
>
<Form
isHorizontal
className="pf-c-form pf-u-mx-lg pf-u-mb-lg"
className="pf-c-form pf-u-mx-lg pf-u-mb-lg pf-u-w-25vw"
data-testid="effectiveMessageBundlesSearchForm"
>
<FormGroup label={t("theme")} fieldId="kc-theme">
<FormGroup label={t("theme")} fieldId="kc-theme" isRequired>
<Controller
name="theme"
control={control}
rules={{
validate: (value) => (value || "").length > 0,
}}
render={({ field }) => (
<Select
name="theme"
Expand Down Expand Up @@ -227,18 +263,25 @@ export const EffectiveMessageBundles = ({
isDisabled
/>,
].concat(
themeKeys.map((option) => (
themeNames.map((option) => (
<SelectOption key={option} value={option} />
)),
)}
</Select>
)}
/>
</FormGroup>
<FormGroup label={t("themeType")} fieldId="kc-themeType">
<FormGroup
label={t("themeType")}
fieldId="kc-themeType"
isRequired
>
<Controller
name="themeType"
control={control}
rules={{
validate: (value) => (value || "").length > 0,
}}
render={({ field }) => (
<Select
name="themeType"
Expand Down Expand Up @@ -292,10 +335,13 @@ export const EffectiveMessageBundles = ({
)}
/>
</FormGroup>
<FormGroup label={t("language")} fieldId="kc-language">
<FormGroup label={t("language")} fieldId="kc-language" isRequired>
<Controller
name="locale"
control={control}
rules={{
validate: (value) => (value || "").length > 0,
}}
render={({ field }) => (
<Select
name="language"
Expand Down Expand Up @@ -402,7 +448,7 @@ export const EffectiveMessageBundles = ({
submitSearch();
}}
data-testid="search-effective-message-bundles-btn"
isDisabled={!isDirty}
isDisabled={!isValid}
>
{t("search")}
</Button>
Expand All @@ -417,6 +463,14 @@ export const EffectiveMessageBundles = ({
</ActionGroup>
</Form>
</Dropdown>
<Button
variant="primary"
className="pf-u-ml-md"
onClick={() => submitSearch()}
data-testid="refresh-effective-message-bundles-btn"
>
{t("refresh")}
</Button>
</FlexItem>
<FlexItem>
{Object.entries(activeFilters).length > 0 && (
Expand Down
6 changes: 3 additions & 3 deletions js/libs/keycloak-admin-client/src/resources/serverInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export class ServerInfo extends Resource {
EffectiveMessageBundleRepresentation[]
>({
method: "GET",
path: "/resources/{realm}/{theme}/{locale}",
urlParamKeys: ["realm", "theme", "locale"],
queryParamKeys: ["themeType", "source"],
path: "/resources/{realm}/{themeType}/{locale}",
urlParamKeys: ["realm", "themeType", "locale"],
queryParamKeys: ["theme", "source"],
});
}

0 comments on commit 229cbb5

Please sign in to comment.