From d06669df276f0bacbcebc69f84723dd9e1d36938 Mon Sep 17 00:00:00 2001 From: Erik Jan de Wit Date: Tue, 29 Nov 2022 06:16:36 -0500 Subject: [PATCH] Added way to convert multi line to string (#3827) --- .../manage/clients/CreateClientPage.ts | 4 +- .../client_details/CreateResourcePage.ts | 2 +- .../client_details/tabs/SettingsTab.ts | 4 +- apps/admin-ui/src/clients/ClientDetails.tsx | 38 --------- .../src/clients/add/AccessSettings.tsx | 1 + .../src/clients/advanced/AdvancedSettings.tsx | 1 + .../advanced/FineGrainOpenIdConnect.tsx | 1 + .../dynamic/MultivaluedStringComponent.tsx | 1 + .../multi-line-input/MultiLineInput.tsx | 78 ++++++++++++++----- .../multi-line-input/multi-line-convert.ts | 7 -- 10 files changed, 66 insertions(+), 71 deletions(-) delete mode 100644 apps/admin-ui/src/components/multi-line-input/multi-line-convert.ts diff --git a/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts b/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts index 76eeed50d5..bb849ca84f 100644 --- a/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts +++ b/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts @@ -27,7 +27,7 @@ export default class CreateClientPage extends CommonPage { private rootUrlInput = "#kc-root-url"; private homeUrlInput = "#kc-home-url"; - private firstValidRedirectUrlInput = "#redirectUris0"; + private firstValidRedirectUrlInput = "redirectUris0"; private firstWebOriginsInput = "#webOrigins0"; private adminUrlInput = "#kc-admin-url"; @@ -232,7 +232,7 @@ export default class CreateClientPage extends CommonPage { cy.get(this.adminUrlInput).scrollIntoView(); cy.get(this.rootUrlInput).should("not.be.disabled"); cy.get(this.homeUrlInput).should("not.be.disabled"); - cy.get(this.firstValidRedirectUrlInput).should("not.be.disabled"); + cy.findByTestId(this.firstValidRedirectUrlInput).should("not.be.disabled"); cy.get(this.firstWebOriginsInput).should("not.be.disabled"); cy.get(this.adminUrlInput).should("not.be.disabled"); diff --git a/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/client_details/CreateResourcePage.ts b/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/client_details/CreateResourcePage.ts index e9d4c6b300..f00d0420c5 100644 --- a/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/client_details/CreateResourcePage.ts +++ b/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/client_details/CreateResourcePage.ts @@ -7,7 +7,7 @@ export default class CreateResourcePage extends CommonPage { if (Array.isArray(value)) { for (let index = 0; index < value.length; index++) { const v = value[index]; - cy.get(`input[name="${key}[${index}]"]`).type(v); + cy.findByTestId(`${key}${index}`).type(v); cy.findByTestId("addValue").click(); } } else { diff --git a/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/client_details/tabs/SettingsTab.ts b/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/client_details/tabs/SettingsTab.ts index e762abce85..70c5335179 100644 --- a/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/client_details/tabs/SettingsTab.ts +++ b/apps/admin-ui/cypress/support/pages/admin_console/manage/clients/client_details/tabs/SettingsTab.ts @@ -33,7 +33,7 @@ export default class SettingsTab extends PageObject { private saveBtn = "settingsSave"; private revertBtn = "settingsRevert"; - private redirectUris = "#redirectUris"; + private redirectUris = "redirectUris"; private postLogoutRedirectUris = "attributes.post.logout.redirect.uris"; private idpInitiatedSsoUrlName = "idpInitiatedSsoUrlName"; @@ -213,7 +213,7 @@ export default class SettingsTab extends PageObject { } public selectRedirectUriTextField(number: number, text: string) { - cy.get(this.redirectUris + number) + cy.findByTestId(this.redirectUris + number) .click() .clear() .type(text); diff --git a/apps/admin-ui/src/clients/ClientDetails.tsx b/apps/admin-ui/src/clients/ClientDetails.tsx index f004cd02d7..5bc796eec4 100644 --- a/apps/admin-ui/src/clients/ClientDetails.tsx +++ b/apps/admin-ui/src/clients/ClientDetails.tsx @@ -23,10 +23,6 @@ import { useConfirmDialog, } from "../components/confirm-dialog/ConfirmDialog"; import { DownloadDialog } from "../components/download-dialog/DownloadDialog"; -import { - stringToMultiline, - toStringValue, -} from "../components/multi-line-input/multi-line-convert"; import { ViewHeader, ViewHeaderBadge, @@ -238,10 +234,6 @@ export default function ClientDetails() { const setupForm = (client: ClientRepresentation) => { form.reset({ ...client }); convertToFormValues(client, form.setValue); - form.setValue( - convertAttributeNameToForm("attributes.request.uris"), - stringToMultiline(client.attributes?.["request.uris"]) - ); if (client.attributes?.["acr.loa.map"]) { form.setValue( convertAttributeNameToForm("attributes.acr.loa.map"), @@ -250,18 +242,6 @@ export default function ClientDetails() { ) ); } - if (client.attributes?.["default.acr.values"]) { - form.setValue( - convertAttributeNameToForm("attributes.default.acr.values"), - stringToMultiline(client.attributes["default.acr.values"]) - ); - } - if (client.attributes?.["post.logout.redirect.uris"]) { - form.setValue( - convertAttributeNameToForm("attributes.post.logout.redirect.uris"), - stringToMultiline(client.attributes["post.logout.redirect.uris"]) - ); - } }; useFetch( @@ -294,24 +274,6 @@ export default function ClientDetails() { const values = convertFormValuesToObject(form.getValues()); - if (values.attributes?.["request.uris"]) { - values.attributes["request.uris"] = toStringValue( - values.attributes["request.uris"] - ); - } - - if (values.attributes?.["default.acr.values"]) { - values.attributes["default.acr.values"] = toStringValue( - values.attributes["default.acr.values"] - ); - } - - if (values.attributes?.["post.logout.redirect.uris"]) { - values.attributes["post.logout.redirect.uris"] = toStringValue( - values.attributes["post.logout.redirect.uris"] - ); - } - const submittedClient = convertFormValuesToObject(values); diff --git a/apps/admin-ui/src/clients/add/AccessSettings.tsx b/apps/admin-ui/src/clients/add/AccessSettings.tsx index 8b4fb4244c..79b29cbcd2 100644 --- a/apps/admin-ui/src/clients/add/AccessSettings.tsx +++ b/apps/admin-ui/src/clients/add/AccessSettings.tsx @@ -105,6 +105,7 @@ export const AccessSettings = ({ )} aria-label={t("validPostLogoutRedirectUri")} addButtonLabel="clients:addPostLogoutRedirectUri" + stringify /> {protocol === "saml" && ( diff --git a/apps/admin-ui/src/clients/advanced/AdvancedSettings.tsx b/apps/admin-ui/src/clients/advanced/AdvancedSettings.tsx index 36ce0c0e98..1df2446e07 100644 --- a/apps/admin-ui/src/clients/advanced/AdvancedSettings.tsx +++ b/apps/admin-ui/src/clients/advanced/AdvancedSettings.tsx @@ -240,6 +240,7 @@ export const AdvancedSettings = ({ > diff --git a/apps/admin-ui/src/clients/advanced/FineGrainOpenIdConnect.tsx b/apps/admin-ui/src/clients/advanced/FineGrainOpenIdConnect.tsx index f099c4b30b..885dbec95c 100644 --- a/apps/admin-ui/src/clients/advanced/FineGrainOpenIdConnect.tsx +++ b/apps/admin-ui/src/clients/advanced/FineGrainOpenIdConnect.tsx @@ -460,6 +460,7 @@ export const FineGrainOpenIdConnect = ({ name={convertAttributeNameToForm("attributes.request.uris")} aria-label={t("validRequestURIs")} addButtonLabel="clients:addRequestUri" + stringify /> ); diff --git a/apps/admin-ui/src/components/multi-line-input/MultiLineInput.tsx b/apps/admin-ui/src/components/multi-line-input/MultiLineInput.tsx index c80d631360..c2acdbf1e7 100644 --- a/apps/admin-ui/src/components/multi-line-input/MultiLineInput.tsx +++ b/apps/admin-ui/src/components/multi-line-input/MultiLineInput.tsx @@ -1,20 +1,36 @@ -import { Fragment, useEffect } from "react"; -import { useFormContext } from "react-hook-form"; import { - TextInput, Button, ButtonVariant, - TextInputProps, InputGroup, + TextInput, + TextInputProps, } from "@patternfly/react-core"; import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons"; +import { Fragment, useEffect, useState } from "react"; +import { useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; +function stringToMultiline(value?: string): string[] { + return value ? value.split("##") : []; +} + +function toStringValue(formValue: string[]): string { + return formValue.join("##"); +} + +type IdValue = { + id: number; + value: string; +}; + +const generateId = () => Math.floor(Math.random() * 1000); + export type MultiLineInputProps = Omit & { name: string; addButtonLabel?: string; isDisabled?: boolean; defaultValue?: string[]; + stringify?: boolean; }; export const MultiLineInput = ({ @@ -22,39 +38,59 @@ export const MultiLineInput = ({ addButtonLabel, isDisabled = false, defaultValue, + stringify = false, ...rest }: MultiLineInputProps) => { const { t } = useTranslation(); - const { register, watch, setValue } = useFormContext(); + const { register, setValue, getValues } = useFormContext(); - const value = watch(name, defaultValue); - const fields = Array.isArray(value) && value.length !== 0 ? value : [""]; + const [fields, setFields] = useState([]); const remove = (index: number) => { - setValue(name, [...fields.slice(0, index), ...fields.slice(index + 1)]); + update([...fields.slice(0, index), ...fields.slice(index + 1)]); }; const append = () => { - setValue(name, [...fields, ""]); + update([...fields, { id: generateId(), value: "" }]); }; - useEffect(() => register(name), [register]); + const updateValue = (index: number, value: string) => { + update([ + ...fields.slice(0, index), + { ...fields[index], value }, + ...fields.slice(index + 1), + ]); + }; + + const update = (values: IdValue[]) => { + setFields(values); + const fieldValue = values.flatMap((field) => field.value); + setValue(name, stringify ? toStringValue(fieldValue) : fieldValue); + }; + + useEffect(() => { + register(name); + let values = stringify + ? stringToMultiline(getValues(name)) + : getValues(name); + + values = + Array.isArray(values) && values.length !== 0 + ? values + : defaultValue || [""]; + + setFields(values.map((value: string) => ({ value, id: generateId() }))); + }, [register, getValues]); return ( <> - {fields.map((value: string, index: number) => ( - + {fields.map(({ id, value }, index) => ( + { - setValue(name, [ - ...fields.slice(0, index), - value, - ...fields.slice(index + 1), - ]); - }} - name={`${name}[${index}]`} + data-testid={name + index} + onChange={(value) => updateValue(index, value)} + name={`${name}[${index}].value`} value={value} isDisabled={isDisabled} {...rest} diff --git a/apps/admin-ui/src/components/multi-line-input/multi-line-convert.ts b/apps/admin-ui/src/components/multi-line-input/multi-line-convert.ts deleted file mode 100644 index a2cf96745d..0000000000 --- a/apps/admin-ui/src/components/multi-line-input/multi-line-convert.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function stringToMultiline(value?: string): string[] { - return (value || "").split("##"); -} - -export function toStringValue(formValue: string[]): string { - return formValue.join("##"); -}