import { ActionGroup, Button, Chip, ChipGroup, Divider, Dropdown, DropdownToggle, Flex, FlexItem, Form, FormGroup, Select, SelectOption, SelectVariant, } from "@patternfly/react-core"; import { pickBy } from "lodash-es"; import { useState } from "react"; import { Controller, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { adminClient } from "../../admin-client"; import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput"; import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState"; import { KeycloakDataTable } from "../../components/table-toolbar/KeycloakDataTable"; import { useRealm } from "../../context/realm-context/RealmContext"; import { useServerInfo } from "../../context/server-info/ServerInfoProvider"; import { useWhoAmI } from "../../context/whoami/WhoAmI"; import { DEFAULT_LOCALE } from "../../i18n/i18n"; import { localeToDisplayName } from "../../util"; type EffectiveMessageBundlesProps = { defaultSupportedLocales: string[]; }; type EffectiveMessageBundlesSearchForm = { theme: string; themeType: string; locale: string; hasWords: string[]; }; const defaultValues: EffectiveMessageBundlesSearchForm = { theme: "", themeType: "", locale: "", hasWords: [], }; export const EffectiveMessageBundles = ({ defaultSupportedLocales, }: EffectiveMessageBundlesProps) => { const { t } = useTranslation(); const { realm } = useRealm(); const serverInfo = useServerInfo(); const { whoAmI } = useWhoAmI(); const [searchDropdownOpen, setSearchDropdownOpen] = useState(false); const [searchPerformed, setSearchPerformed] = useState(false); const [selectThemesOpen, setSelectThemesOpen] = useState(false); const [selectThemeTypeOpen, setSelectThemeTypeOpen] = useState(false); const [selectLanguageOpen, setSelectLanguageOpen] = useState(false); const [activeFilters, setActiveFilters] = useState< Partial >({}); 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 filterLabels: Record = { theme: t("theme"), themeType: t("themeType"), locale: t("language"), hasWords: t("hasWords"), }; const { getValues, reset, formState: { isDirty }, control, } = useForm({ mode: "onChange", defaultValues, }); const loader = async () => { try { const filter = getValues(); const messages = await adminClient.serverInfo.findEffectiveMessageBundles( { realm, ...filter, locale: filter.locale || DEFAULT_LOCALE, source: true, }, ); return filter.hasWords.length > 0 ? messages.filter((m) => filter.hasWords.some((f) => m.value.includes(f)), ) : messages; } catch (error) { return []; } }; function submitSearch() { setSearchDropdownOpen(false); commitFilters(); } function resetSearch() { reset(); commitFilters(); } function removeFilter(key: keyof EffectiveMessageBundlesSearchForm) { const formValues: EffectiveMessageBundlesSearchForm = { ...getValues() }; delete formValues[key]; reset({ ...defaultValues, ...formValues }); commitFilters(); } function removeFilterValue( key: keyof EffectiveMessageBundlesSearchForm, valueToRemove: string, ) { const formValues = getValues(); const fieldValue = formValues[key]; const newFieldValue = Array.isArray(fieldValue) ? fieldValue.filter((val) => val !== valueToRemove) : fieldValue; reset({ ...formValues, [key]: newFieldValue }); commitFilters(); } function commitFilters() { const newFilters: Partial = pickBy( getValues(), (value) => value !== "" || (Array.isArray(value) && value.length > 0), ); setActiveFilters(newFilters); setKey(key + 1); } const effectiveMessageBunldesSearchFormDisplay = () => { return ( setSearchDropdownOpen(isOpen)} > {t("searchForEffectiveMessageBundles")} } isOpen={searchDropdownOpen} >
( )} /> ( )} /> ( )} /> (
{ const target = e.target as HTMLInputElement; const words = target.value .split(" ") .map((word) => word.trim()); field.onChange(words); }} /> {field.value.map((word, index) => ( { e.stopPropagation(); const newWords = field.value.filter( (_, i) => i !== index, ); field.onChange(newWords); }} > {word} ))}
)} />
{Object.entries(activeFilters).length > 0 && (
{Object.entries(activeFilters).map((filter) => { const [key, value] = filter as [ keyof EffectiveMessageBundlesSearchForm, string | string[], ]; return ( removeFilter(key)} > {typeof value === "string" ? ( {key === "locale" ? localeToDisplayName(value, whoAmI.getLocale()) : value} ) : ( value.map((entry) => ( removeFilterValue(key, entry)} > {entry} )) )} ); })}
)}
); }; if (!searchPerformed) { return ( <>
{effectiveMessageBunldesSearchFormDisplay()}
); } return ( } isSearching={Object.keys(activeFilters).length > 0} /> ); };