diff --git a/cypress/integration/realm_settings_test.spec.ts b/cypress/integration/realm_settings_test.spec.ts index 9c34110e99..9a6b2a20aa 100644 --- a/cypress/integration/realm_settings_test.spec.ts +++ b/cypress/integration/realm_settings_test.spec.ts @@ -40,6 +40,19 @@ describe("Realm settings", () => { return this; }; + const addBundle = () => { + const localizationUrl = + "/auth/admin/realms/master/realm-settings/localization"; + cy.intercept(localizationUrl).as("localizationFetch"); + + realmSettingsPage.addKeyValuePair( + "key_" + (Math.random() + 1).toString(36).substring(7), + "value_" + (Math.random() + 1).toString(36).substring(7) + ); + + return this; + }; + it("Go to general tab", function () { sidebarPage.goToRealmSettings(); realmSettingsPage.toggleSwitch(realmSettingsPage.managedAccessSwitch); @@ -142,13 +155,10 @@ describe("Realm settings", () => { }); it("add Providers", () => { - cy.wait(5000); sidebarPage.goToRealmSettings(); cy.getId("rs-keys-tab").click(); - cy.wait(10000); - cy.getId("rs-providers-tab").click(); realmSettingsPage.toggleAddProviderDropdown(); @@ -182,4 +192,16 @@ describe("Realm settings", () => { realmSettingsPage.testSelectFilter(); }); + + it("add locale", () => { + sidebarPage.goToRealmSettings(); + + cy.getId("rs-localization-tab").click(); + + addBundle(); + + masthead.checkNotificationMessage( + "Success! The localization text has been created." + ); + }); }); diff --git a/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts b/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts index db84f5aa99..9353cf461b 100644 --- a/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts +++ b/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts @@ -39,6 +39,10 @@ export default class RealmSettingsPage { testConnectionButton = "test-connection-button"; modalTestConnectionButton = "modal-test-connection-button"; emailAddressInput = "email-address-input"; + addBundleButton = "no-message-bundles-empty-action"; + confirmAddBundle = "add-bundle-confirm-button"; + keyInput = "key-input"; + valueInput = "value-input"; selectLoginThemeType(themeType: string) { const themesUrl = "/auth/admin/realms/master/themes"; @@ -139,6 +143,17 @@ export default class RealmSettingsPage { return this; } + addKeyValuePair(key: string, value: string) { + cy.getId(this.addBundleButton).click(); + + cy.getId(this.keyInput).type(key); + cy.getId(this.valueInput).type(value); + + cy.getId(this.confirmAddBundle).click(); + + return this; + } + enterConsoleDisplayName(name: string) { cy.getId(this.displayName).clear().type(name); } diff --git a/src/realm-settings/AddMessageBundleModal.tsx b/src/realm-settings/AddMessageBundleModal.tsx new file mode 100644 index 0000000000..efc9da4fc7 --- /dev/null +++ b/src/realm-settings/AddMessageBundleModal.tsx @@ -0,0 +1,111 @@ +import React from "react"; +import { + Button, + ButtonVariant, + Form, + FormGroup, + Modal, + ModalVariant, + TextInput, + ValidatedOptions, +} from "@patternfly/react-core"; +import { useTranslation } from "react-i18next"; +import { useForm, UseFormMethods } from "react-hook-form"; + +type AddMessageBundleModalProps = { + id?: string; + form: UseFormMethods; + save: (model: BundleForm) => void; + handleModalToggle: () => void; +}; + +export type KeyValueType = { key: string; value: string }; + +export type BundleForm = { + messageBundle: KeyValueType; +}; + +export const AddMessageBundleModal = ({ + handleModalToggle, + save, +}: AddMessageBundleModalProps) => { + const { t } = useTranslation("groups"); + const { register, errors, handleSubmit } = useForm(); + + return ( + + {t("common:create")} + , + , + ]} + > +
+ + + + + + +
+
+ ); +}; diff --git a/src/realm-settings/KeysProvidersTab.tsx b/src/realm-settings/KeysProvidersTab.tsx index aaad319115..a70051c535 100644 --- a/src/realm-settings/KeysProvidersTab.tsx +++ b/src/realm-settings/KeysProvidersTab.tsx @@ -32,18 +32,20 @@ import type ComponentTypeRepresentation from "keycloak-admin/lib/defs/componentT import "./RealmSettingsSection.css"; import { useServerInfo } from "../context/server-info/ServerInfoProvider"; -import { AESGeneratedModal } from "./AESGeneratedModal"; -import { ECDSAGeneratedModal } from "./ECDSAGeneratedModal"; -import { HMACGeneratedModal } from "./HMACGeneratedModal"; -import { JavaKeystoreModal } from "./JavaKeystoreModal"; -import { RSAModal } from "./RSAModal"; -import { RSAGeneratedModal } from "./RSAGeneratedModal"; import { useAdminClient } from "../context/auth/AdminClient"; import { useAlerts } from "../components/alert/Alerts"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useRealm } from "../context/realm-context/RealmContext"; +import { Link, useRouteMatch } from "react-router-dom"; +import { AESGeneratedModal } from "./AESGeneratedModal"; +import { JavaKeystoreModal } from "./JavaKeystoreModal"; +import { HMACGeneratedModal } from "./HMACGeneratedModal"; +import { ECDSAGeneratedModal } from "./ECDSAGeneratedModal"; +import { RSAModal } from "./RSAModal"; +import { RSAGeneratedModal } from "./RSAGeneratedModal"; type ComponentData = KeyMetadataRepresentation & { + id?: string; providerDescription?: string; name?: string; toggleHidden?: boolean; @@ -62,6 +64,7 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => { const { addAlert } = useAlerts(); const adminClient = useAdminClient(); const { realm } = useRealm(); + const { url } = useRouteMatch(); const [id, setId] = useState(""); @@ -335,9 +338,18 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => { + <> - + + {component.name} + , diff --git a/src/realm-settings/LocalizationTab.tsx b/src/realm-settings/LocalizationTab.tsx index ba646a375c..5e1eebe991 100644 --- a/src/realm-settings/LocalizationTab.tsx +++ b/src/realm-settings/LocalizationTab.tsx @@ -1,8 +1,9 @@ import React, { useState } from "react"; import { useTranslation } from "react-i18next"; -import { Controller, useFormContext, useWatch } from "react-hook-form"; +import { Controller, useForm, useFormContext, useWatch } from "react-hook-form"; import { ActionGroup, + AlertVariant, Button, FormGroup, PageSection, @@ -20,6 +21,8 @@ import { FormPanel } from "../components/scroll-form/FormPanel"; import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; import { useAdminClient } from "../context/auth/AdminClient"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; +import { AddMessageBundleModal } from "./AddMessageBundleModal"; +import { useAlerts } from "../components/alert/Alerts"; type LocalizationTabProps = { save: (realm: RealmRepresentation) => void; @@ -28,13 +31,23 @@ type LocalizationTabProps = { realm: RealmRepresentation; }; +export type KeyValueType = { key: string; value: string }; + +export type BundleForm = { + messageBundle: KeyValueType; +}; + export const LocalizationTab = ({ save, reset, realm, + refresh, }: LocalizationTabProps) => { const { t } = useTranslation("realm-settings"); const adminClient = useAdminClient(); + const [addMessageBundleModalOpen, setAddMessageBundleModalOpen] = useState( + false + ); const [key, setKey] = useState(0); const [supportedLocalesOpen, setSupportedLocalesOpen] = useState(false); @@ -43,6 +56,10 @@ export const LocalizationTab = ({ const { getValues, control, handleSubmit } = useFormContext(); const [valueSelected, setValueSelected] = useState(false); const themeTypes = useServerInfo().themes!; + const bundleForm = useForm({ mode: "onChange" }); + const { addAlert } = useAlerts(); + + console.log(realm.supportedLocales); const watchSupportedLocales = useWatch({ control, @@ -56,19 +73,68 @@ export const LocalizationTab = ({ defaultValue: realm?.internationalizationEnabled, }); + console.log("ok", realm); + const loader = async () => { if (realm) { + // if(realm.supportedLocales?.length === 0) { + // return [[]]; + // } + // else { const result = await adminClient.realms.getRealmLocalizationTexts({ realm: realm.realm!, selectedLocale: getValues("defaultLocale") || "en", }); return Object.keys(result).map((key) => [key, result[key]]); } + + // } return [[]]; }; + const handleModalToggle = () => { + setAddMessageBundleModalOpen(!addMessageBundleModalOpen); + }; + + const addKeyValue = async (pair: KeyValueType): Promise => { + try { + adminClient.setConfig({ + requestConfig: { headers: { "Content-Type": "text/plain" } }, + }); + await adminClient.realms.addLocalization( + { + realm: realm.realm!, + selectedLocale: getValues("defaultLocale") || "en", + key: pair.key, + }, + pair.value + ); + + adminClient.setConfig({ + realmName: realm.realm, + }); + refresh(); + addAlert(t("realm-settings:pairCreatedSuccess"), AlertVariant.success); + } catch (error) { + addAlert( + t("realm-settings:pairCreatedError", { error }), + AlertVariant.danger + ); + } + }; + return ( <> + {addMessageBundleModalOpen && ( + { + addKeyValue(pair); + handleModalToggle(); + }} + form={bundleForm} + /> + )} setAddMessageBundleModalOpen(true)} + > + {t("addMessageBundle")} + + } searchPlaceholderKey=" " emptyState={ {}} + onPrimaryAction={handleModalToggle} + primaryActionText={t("addMessageBundle")} /> } canSelectAll diff --git a/src/realm-settings/RealmSettingsSection.tsx b/src/realm-settings/RealmSettingsSection.tsx index fceb9e2294..692cf8903a 100644 --- a/src/realm-settings/RealmSettingsSection.tsx +++ b/src/realm-settings/RealmSettingsSection.tsx @@ -317,6 +317,7 @@ export const RealmSettingsSection = () => { {t("localization")}} >