8000 Fixed loading translation values for User Profile attributes by agagancarczyk · Pull Request #28408 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Closed
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
91 changes: 85 additions & 6 deletions js/apps/admin-ui/src/realm-settings/NewAttributeSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
PageSection,
} from "@patternfly/react-core";
import { flatten } from "flat";
import { useState } from "react";
import { useMemo, useState } from "react";
import { FormProvider, useForm, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom";
Expand All @@ -29,6 +29,7 @@ import { AttributeAnnotations } from "./user-profile/attribute/AttributeAnnotati
import { AttributeGeneralSettings } from "./user-profile/attribute/AttributeGeneralSettings";
import { AttributePermission } from "./user-profile/attribute/AttributePermission";
import { AttributeValidations } from "./user-profile/attribute/AttributeValidations";
import { DEFAULT_LOCALE } from "../i18n/i18n";

import "./realm-settings-section.css";

Expand Down Expand Up @@ -169,9 +170,23 @@ export default function NewAttributeSettings() {
const [generatedDisplayName, setGeneratedDisplayName] = useState<string>("");
const [realm, setRealm] = useState<RealmRepresentation>();

const defaultSupportedLocales = useMemo(() => {
return realm?.supportedLocales!.length
? realm.supportedLocales
: [DEFAULT_LOCALE];
}, [real 8000 m]);

const defaultLocales = useMemo(() => {
return realm?.defaultLocale!.length ? [realm.defaultLocale] : [];
}, [realm]);

const combinedLocales = useMemo(() => {
return Array.from(new Set([...defaultLocales, ...defaultSupportedLocales]));
}, [defaultLocales, defaultSupportedLocales]);

useFetch(
() => adminClient.realms.findOne({ realm: realmName }),
(realm) => {
async (realm) => {
if (!realm) {
throw new Error(t("notFound"));
}
Expand All @@ -180,6 +195,70 @@ export default function NewAttributeSettings() {
[],
);

useFetch(
async () => {
const translationsToSave: any[] = [];
await Promise.all(
combinedLocales.map(async (selectedLocale) => {
try {
const translations =
await adminClient.realms.getRealmLocalizationTexts({
realm: realmName,
selectedLocale,
});

const formData = form.getValues();
const formattedKey = formData.displayName?.substring(
2,
formData.displayName.length - 1,
);
const filteredTranslations: Array<{
locale: string;
value: string;
}> = [];
const allTranslations = Object.entries(translations).map(
([key, value]) => ({
key,
value,
}),
);

allTranslations.forEach((translation) => {
if (translation.key === formattedKey) {
filteredTranslations.push({
locale: selectedLocale,
value: translation.value,
});
}
});

const translationToSave: any = {
key: formattedKey,
translations: filteredTranslations,
};

translationsToSave.push(translationToSave);
} catch (error) {
console.error(
`Error fetching translations for ${selectedLocale}:`,
error,
);
}
}),
);
return translationsToSave;
},
(translationsToSaveData) => {
setTranslationsData(() => ({
key: translationsToSaveData[0].key,
translations: translationsToSaveData.flatMap(
(translationData) => translationData.translations,
),
}));
},
[combinedLocales],
);

useFetch(
() => adminClient.users.getProfile(),
(config) => {
Expand Down Expand Up @@ -228,9 +307,8 @@ export default function NewAttributeSettings() {

const saveTranslations = async () => {
try {
const nonEmptyTranslations = translationsData.translations
.filter((translation) => translation.value.trim() !== "")
.map(async (translation) => {
const nonEmptyTranslations = translationsData.translations.map(
async (translation) => {
try {
await adminClient.realms.addLocalization(
{
Expand All @@ -243,7 +321,8 @@ export default function NewAttributeSettings() {
} catch (error) {
console.error(`Error saving translation for ${translation.locale}`);
}
});
},
);
await Promise.all(nonEmptyTranslations);
} catch (error) {
console.error(`Error saving translations: ${error}`);
Expand Down
7438
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ type Translations = {

export type AddTranslationsDialogProps = {
translationKey: string;
translations: Translations;
onCancel: () => void;
toggleDialog: () => void;
onTranslationsAdded: (translations: Translations) => void;
};

export const AddTranslationsDialog = ({
translationKey,
translations,
onCancel,
toggleDialog,
onTranslationsAdded,
Expand All @@ -58,6 +60,9 @@ export const AddTranslationsDialog = ({
const [max, setMax] = useState(10);
const [first, setFirst] = useState(0);
const [filter, setFilter] = useState("");
const [defaultTranslations, setDefaultTranslations] = useState<{
[key: string]: string;
}>({});

const form = useForm<{
key: string;
Expand Down Expand Up @@ -106,19 +111,68 @@ export const AddTranslationsDialog = ({
);
}, [combinedLocales, filter, whoAmI]);

useFetch(
async () => {
const selectedLocales = combinedLocales.map((locale) => locale);

const results = await Promise.all(
selectedLocales.map((selectedLocale) =>
adminClient.realms.getRealmLocalizationTexts({
realm: realmName,
selectedLocale,
}),
),
);

const translations = results.map((result, index) => {
const locale = selectedLocales[index];
const value = result[translationKey];
return {
key: translationKey,
translations: [{ locale, value }],
};
});

const defaultValuesMap = translations.reduce((acc, translation) => {
const locale = translation.translations[0].locale;
const value = translation.translations[0].value;
return { ...acc, [locale]: value };
}, {});

return defaultValuesMap;
},
(fetchedData) => {
setDefaultTranslations((prevTranslations) => {
if (prevTranslations !== fetchedData) {
return fetchedData;
}
return prevTranslations;
});
},
[combinedLocales, translationKey, realmName],
);

useEffect(() => {
combinedLocales.forEach((locale, rowIndex) => {
setValue(`translations.${rowIndex}`, {
locale,
value: "",
});
setValue("key", translationKey);
setValue(`translations.${rowIndex}.locale`, locale);
setValue(
`translations.${rowIndex}.value`,
translations.translations.length > 0
? translations.translations[rowIndex].value
: defaultTranslations[locale] || "",
);
});
}, [combinedLocales, translationKey, setValue]);
setValue("key", translationKey);
}, [
combinedLocales,
defaultTranslations,
translationKey,
setValue,
translations,
]);

const handleOk = () => {
const formData = getValues();

const updatedTranslations = formData.translations.map((translation) => {
if (translation.locale === filter) {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,15 +171,21 @@ export const AttributeGeneralSettings = ({
handleGeneratedDisplayName(generatedDisplayName);
};

const formattedAttributeDisplayName = attributeDisplayName?.substring(
2,
attributeDisplayName.length - 1,
);

return (
<>
{addTranslationsModalOpen && (
<AddTranslationsDialog
translationKey={
editMode
? attributeDisplayName
? formattedAttributeDisplayName
: `profile.attributes.${newAttributeName}`
}
translations={translationsData}
>
toggleDialog={handleToggleDialog}
=> {
Expand Down
0