Use string[] directly removed need for converstion (#2175)
This commit is contained in:
parent
ae133d675b
commit
37d1087e7e
18 changed files with 86 additions and 221 deletions
|
@ -96,7 +96,7 @@ export default class AuthorizationTab {
|
|||
if (Array.isArray(value)) {
|
||||
for (let index = 0; index < value.length; index++) {
|
||||
const v = value[index];
|
||||
cy.get(`input[name="${key}[${index}].value"]`).type(v);
|
||||
cy.get(`input[name="${key}[${index}]"]`).type(v);
|
||||
cy.findByTestId("addValue").click();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -144,11 +144,6 @@ const WebauthnSelect = ({
|
|||
);
|
||||
};
|
||||
|
||||
const MULTILINE_INPUTS = [
|
||||
"webAuthnPolicyAcceptableAaguids",
|
||||
"webAuthnPolicyPasswordlessAcceptableAaguids",
|
||||
];
|
||||
|
||||
type WebauthnPolicyProps = {
|
||||
realm: RealmRepresentation;
|
||||
realmUpdated: (realm: RealmRepresentation) => void;
|
||||
|
@ -180,12 +175,12 @@ export const WebauthnPolicy = ({
|
|||
: "webAuthnPolicy";
|
||||
|
||||
const setupForm = (realm: RealmRepresentation) =>
|
||||
convertToFormValues(realm, setValue, MULTILINE_INPUTS);
|
||||
convertToFormValues(realm, setValue);
|
||||
|
||||
useEffect(() => setupForm(realm), []);
|
||||
|
||||
const save = async (realm: RealmRepresentation) => {
|
||||
const submittedRealm = convertFormValuesToObject(realm, MULTILINE_INPUTS);
|
||||
const submittedRealm = convertFormValuesToObject(realm);
|
||||
try {
|
||||
await adminClient.realms.update({ realm: realmName }, submittedRealm);
|
||||
realmUpdated(submittedRealm);
|
||||
|
|
|
@ -9,10 +9,9 @@ import {
|
|||
ValidatedOptions,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
|
||||
import { FormAccess } from "../components/form-access/FormAccess";
|
||||
import type { ClientForm } from "./ClientDetails";
|
||||
|
||||
type ClientDescriptionProps = {
|
||||
protocol?: string;
|
||||
|
@ -20,7 +19,7 @@ type ClientDescriptionProps = {
|
|||
|
||||
export const ClientDescription = ({ protocol }: ClientDescriptionProps) => {
|
||||
const { t } = useTranslation("clients");
|
||||
const { register, errors, control } = useFormContext<ClientForm>();
|
||||
const { register, errors, control } = useFormContext<ClientRepresentation>();
|
||||
return (
|
||||
<FormAccess role="manage-clients" unWrap>
|
||||
<FormGroup
|
||||
|
|
|
@ -24,7 +24,6 @@ import {
|
|||
} from "../components/confirm-dialog/ConfirmDialog";
|
||||
import { DownloadDialog } from "../components/download-dialog/DownloadDialog";
|
||||
import {
|
||||
MultiLine,
|
||||
stringToMultiline,
|
||||
toStringValue,
|
||||
} from "../components/multi-line-input/multi-line-convert";
|
||||
|
@ -168,15 +167,6 @@ const ClientDetailHeader = ({
|
|||
);
|
||||
};
|
||||
|
||||
export type ClientForm = Omit<
|
||||
ClientRepresentation,
|
||||
"redirectUris" | "webOrigins"
|
||||
> & {
|
||||
redirectUris: MultiLine[];
|
||||
webOrigins: MultiLine[];
|
||||
requestUris?: MultiLine[];
|
||||
};
|
||||
|
||||
export type SaveOptions = {
|
||||
confirmed?: boolean;
|
||||
messageKey?: string;
|
||||
|
@ -193,7 +183,7 @@ export default function ClientDetails() {
|
|||
const [downloadDialogOpen, toggleDownloadDialogOpen] = useToggle();
|
||||
const [changeAuthenticatorOpen, toggleChangeAuthenticatorOpen] = useToggle();
|
||||
|
||||
const form = useForm<ClientForm>({ shouldUnregister: false });
|
||||
const form = useForm<ClientRepresentation>({ shouldUnregister: false });
|
||||
const { clientId } = useParams<ClientParams>();
|
||||
|
||||
const clientAuthenticatorType = useWatch({
|
||||
|
@ -226,9 +216,9 @@ export default function ClientDetails() {
|
|||
});
|
||||
|
||||
const setupForm = (client: ClientRepresentation) => {
|
||||
convertToFormValues(client, form.setValue, ["redirectUris", "webOrigins"]);
|
||||
convertToFormValues(client, form.setValue);
|
||||
form.setValue(
|
||||
"requestUris",
|
||||
"attributes.request.uris",
|
||||
stringToMultiline(client.attributes?.["request.uris"])
|
||||
);
|
||||
};
|
||||
|
@ -263,15 +253,14 @@ export default function ClientDetails() {
|
|||
|
||||
const values = form.getValues();
|
||||
|
||||
if (values.requestUris) {
|
||||
values.attributes!["request.uris"] = toStringValue(values.requestUris);
|
||||
delete values.requestUris;
|
||||
if (values.attributes?.request.uris) {
|
||||
values.attributes["request.uris"] = toStringValue(
|
||||
values.attributes.request.uris
|
||||
);
|
||||
}
|
||||
|
||||
const submittedClient = convertFormValuesToObject<
|
||||
ClientForm,
|
||||
ClientRepresentation
|
||||
>(values, ["redirectUris", "webOrigins"]);
|
||||
const submittedClient =
|
||||
convertFormValuesToObject<ClientRepresentation>(values);
|
||||
|
||||
try {
|
||||
const newClient: ClientRepresentation = {
|
||||
|
|
|
@ -24,7 +24,6 @@ import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
|||
import { SaveReset } from "./advanced/SaveReset";
|
||||
import { SamlConfig } from "./add/SamlConfig";
|
||||
import { SamlSignature } from "./add/SamlSignature";
|
||||
import type { ClientForm } from "./ClientDetails";
|
||||
import environment from "../environment";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
|
||||
|
@ -39,7 +38,8 @@ export const ClientSettings = ({
|
|||
save,
|
||||
reset,
|
||||
}: ClientSettingsProps) => {
|
||||
const { register, control, watch, errors } = useFormContext<ClientForm>();
|
||||
const { register, control, watch, errors } =
|
||||
useFormContext<ClientRepresentation>();
|
||||
const { t } = useTranslation("clients");
|
||||
const { realm } = useRealm();
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ import {
|
|||
InputGroup,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import type { ClientForm } from "../ClientDetails";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
|
||||
import "./capability-config.css";
|
||||
|
@ -26,7 +26,7 @@ export const CapabilityConfig = ({
|
|||
protocol: type,
|
||||
}: CapabilityConfigProps) => {
|
||||
const { t } = useTranslation("clients");
|
||||
const { control, watch, setValue } = useFormContext<ClientForm>();
|
||||
const { control, watch, setValue } = useFormContext<ClientRepresentation>();
|
||||
const protocol = type || watch("protocol");
|
||||
const clientAuthentication = watch("publicClient");
|
||||
const authorization = watch("authorizationServicesEnabled");
|
||||
|
|
|
@ -9,13 +9,13 @@ import {
|
|||
Switch,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import type { ClientForm } from "../ClientDetails";
|
||||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
|
||||
export const Toggle = ({ name, label }: { name: string; label: string }) => {
|
||||
const { t } = useTranslation("clients");
|
||||
const { control } = useFormContext<ClientForm>();
|
||||
const { control } = useFormContext<ClientRepresentation>();
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
|
@ -50,7 +50,7 @@ export const Toggle = ({ name, label }: { name: string; label: string }) => {
|
|||
|
||||
export const SamlConfig = () => {
|
||||
const { t } = useTranslation("clients");
|
||||
const { control } = useFormContext<ClientForm>();
|
||||
const { control } = useFormContext<ClientRepresentation>();
|
||||
|
||||
const [nameFormatOpen, setNameFormatOpen] = useState(false);
|
||||
return (
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
SelectVariant,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import type { ClientForm } from "../ClientDetails";
|
||||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { Toggle } from "./SamlConfig";
|
||||
|
@ -46,7 +46,7 @@ export const SamlSignature = () => {
|
|||
const [keyOpen, setKeyOpen] = useState(false);
|
||||
const [canOpen, setCanOpen] = useState(false);
|
||||
|
||||
const { control, watch } = useFormContext<ClientForm>();
|
||||
const { control, watch } = useFormContext<ClientRepresentation>();
|
||||
|
||||
const signDocs = watch("attributes.saml.server.signature");
|
||||
const signAssertion = watch("attributes.saml.assertion.signature");
|
||||
|
|
|
@ -486,7 +486,7 @@ export const FineGrainOpenIdConnect = ({
|
|||
}
|
||||
>
|
||||
<MultiLineInput
|
||||
name="requestUris"
|
||||
name="attributes.request.uris"
|
||||
aria-label={t("validRequestURIs")}
|
||||
addButtonLabel="clients:addRequestUri"
|
||||
/>
|
||||
|
|
|
@ -27,7 +27,6 @@ import { ViewHeader } from "../../components/view-header/ViewHeader";
|
|||
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import type { MultiLine } from "../../components/multi-line-input/multi-line-convert";
|
||||
import type { KeyValueType } from "../../components/attribute-form/attribute-convert";
|
||||
import { convertFormValuesToObject, convertToFormValues } from "../../util";
|
||||
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
|
||||
|
@ -37,9 +36,8 @@ import { AttributeInput } from "../../components/attribute-input/AttributeInput"
|
|||
|
||||
import "./resource-details.css";
|
||||
|
||||
type SubmittedResource = Omit<ResourceRepresentation, "attributes" | "uris"> & {
|
||||
type SubmittedResource = Omit<ResourceRepresentation, "attributes"> & {
|
||||
attributes: KeyValueType[];
|
||||
uris: MultiLine[];
|
||||
};
|
||||
|
||||
export default function ResourceDetails() {
|
||||
|
@ -62,7 +60,7 @@ export default function ResourceDetails() {
|
|||
const history = useHistory();
|
||||
|
||||
const setupForm = (resource: ResourceRepresentation = {}) => {
|
||||
convertToFormValues(resource, setValue, ["uris"]);
|
||||
convertToFormValues(resource, setValue);
|
||||
};
|
||||
|
||||
useFetch(
|
||||
|
@ -92,7 +90,7 @@ export default function ResourceDetails() {
|
|||
const resource = convertFormValuesToObject<
|
||||
SubmittedResource,
|
||||
ResourceRepresentation
|
||||
>(submitted, ["uris"]);
|
||||
>(submitted);
|
||||
|
||||
try {
|
||||
if (resourceId) {
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
SplitItem,
|
||||
} from "@patternfly/react-core";
|
||||
import { useFormContext } from "react-hook-form";
|
||||
import type { ClientForm } from "../ClientDetails";
|
||||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
|
||||
export type ClientSecretProps = {
|
||||
secret: string;
|
||||
|
@ -17,7 +17,7 @@ export type ClientSecretProps = {
|
|||
|
||||
export const ClientSecret = ({ secret, toggle }: ClientSecretProps) => {
|
||||
const { t } = useTranslation("clients");
|
||||
const { formState } = useFormContext<ClientForm>();
|
||||
const { formState } = useFormContext<ClientRepresentation>();
|
||||
return (
|
||||
<FormGroup label={t("clientSecret")} fieldId="kc-client-secret">
|
||||
<Split hasGutter>
|
||||
|
|
|
@ -17,12 +17,12 @@ import {
|
|||
TextInput,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import type CertificateRepresentation from "@keycloak/keycloak-admin-client/lib/defs/certificateRepresentation";
|
||||
import type KeyStoreConfig from "@keycloak/keycloak-admin-client/lib/defs/keystoreConfig";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
||||
import type { ClientForm } from "../ClientDetails";
|
||||
import { GenerateKeyDialog } from "./GenerateKeyDialog";
|
||||
import { useFetch, useAdminClient } from "../../context/auth/AdminClient";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
|
@ -43,7 +43,7 @@ export const Keys = ({ clientId, save }: KeysProps) => {
|
|||
control,
|
||||
register,
|
||||
formState: { isDirty },
|
||||
} = useFormContext<ClientForm>();
|
||||
} = useFormContext<ClientRepresentation>();
|
||||
const adminClient = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
|
|
|
@ -16,11 +16,11 @@ import {
|
|||
AlertVariant,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
|
||||
import type CertificateRepresentation from "@keycloak/keycloak-admin-client/lib/defs/certificateRepresentation";
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import type { ClientForm } from "../ClientDetails";
|
||||
import { SamlKeysDialog } from "./SamlKeysDialog";
|
||||
import { FormPanel } from "../../components/scroll-form/FormPanel";
|
||||
import { Certificate } from "./Certificate";
|
||||
|
@ -65,7 +65,7 @@ const KeySection = ({
|
|||
onImport,
|
||||
}: KeySectionProps) => {
|
||||
const { t } = useTranslation("clients");
|
||||
const { control, watch } = useFormContext<ClientForm>();
|
||||
const { control, watch } = useFormContext<ClientRepresentation>();
|
||||
const title = KEYS_MAPPING[attr].title;
|
||||
const key = KEYS_MAPPING[attr].key;
|
||||
const name = KEYS_MAPPING[attr].name;
|
||||
|
|
|
@ -1,17 +1,10 @@
|
|||
import React, { Fragment, useEffect } from "react";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFormContext } from "react-hook-form";
|
||||
import {
|
||||
Button,
|
||||
ButtonVariant,
|
||||
FormGroup,
|
||||
InputGroup,
|
||||
TextInput,
|
||||
} from "@patternfly/react-core";
|
||||
import { FormGroup } from "@patternfly/react-core";
|
||||
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import type { ComponentProps } from "./components";
|
||||
import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { MultiLineInput } from "../multi-line-input/MultiLineInput";
|
||||
|
||||
export const MultiValuedStringComponent = ({
|
||||
name,
|
||||
|
@ -22,20 +15,6 @@ export const MultiValuedStringComponent = ({
|
|||
}: ComponentProps) => {
|
||||
const { t } = useTranslation("dynamic");
|
||||
const fieldName = `config.${name}`;
|
||||
const { register, setValue, watch } = useFormContext();
|
||||
|
||||
const fields = watch(fieldName, [defaultValue]);
|
||||
|
||||
const remove = (id: number) => {
|
||||
fields.splice(id, 1);
|
||||
setValue(fieldName, [...fields]);
|
||||
};
|
||||
|
||||
const append = () => {
|
||||
setValue(fieldName, [...fields, ""]);
|
||||
};
|
||||
|
||||
useEffect(() => register(`config.${name}`), [register]);
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
|
@ -45,46 +24,14 @@ export const MultiValuedStringComponent = ({
|
|||
}
|
||||
fieldId={name!}
|
||||
>
|
||||
{fields.map((value: string, index: number) => (
|
||||
<Fragment key={index}>
|
||||
<InputGroup>
|
||||
<TextInput
|
||||
id={fieldName + index}
|
||||
onChange={(value) => {
|
||||
fields[index] = value;
|
||||
setValue(fieldName, [...fields]);
|
||||
}}
|
||||
name={`${fieldName}[${index}]`}
|
||||
value={value}
|
||||
<MultiLineInput
|
||||
name={fieldName}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
<Button
|
||||
variant={ButtonVariant.link}
|
||||
onClick={() => remove(index)}
|
||||
tabIndex={-1}
|
||||
aria-label={t("common:remove")}
|
||||
isDisabled={index === fields.length - 1}
|
||||
>
|
||||
<MinusCircleIcon />
|
||||
</Button>
|
||||
</InputGroup>
|
||||
{index === fields.length - 1 && (
|
||||
<Button
|
||||
variant={ButtonVariant.link}
|
||||
onClick={append}
|
||||
tabIndex={-1}
|
||||
aria-label={t("common:add")}
|
||||
data-testid="addValue"
|
||||
isDisabled={!value}
|
||||
>
|
||||
<PlusCircleIcon />{" "}
|
||||
{t("addMultivaluedLabel", {
|
||||
defaultValue={[defaultValue]}
|
||||
addButtonLabel={t("addMultivaluedLabel", {
|
||||
fieldLabel: t(label!).toLowerCase(),
|
||||
})}
|
||||
</Button>
|
||||
)}
|
||||
</Fragment>
|
||||
))}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Fragment } from "react";
|
||||
import { useFieldArray, useFormContext, useWatch } from "react-hook-form";
|
||||
import React, { Fragment, useEffect } from "react";
|
||||
import { useFormContext } from "react-hook-form";
|
||||
import {
|
||||
TextInput,
|
||||
Button,
|
||||
|
@ -13,32 +13,50 @@ import { useTranslation } from "react-i18next";
|
|||
export type MultiLineInputProps = Omit<TextInputProps, "form"> & {
|
||||
name: string;
|
||||
addButtonLabel?: string;
|
||||
isDisabled?: boolean;
|
||||
defaultValue?: string[];
|
||||
};
|
||||
|
||||
export const MultiLineInput = ({
|
||||
name,
|
||||
addButtonLabel,
|
||||
isDisabled = false,
|
||||
defaultValue,
|
||||
...rest
|
||||
}: MultiLineInputProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { register, control } = useFormContext();
|
||||
const { fields, append, remove } = useFieldArray({
|
||||
name,
|
||||
control,
|
||||
});
|
||||
const currentValues: { [name: string]: { value: string } } | undefined =
|
||||
useWatch({ control, name });
|
||||
const { register, watch, setValue } = useFormContext();
|
||||
|
||||
const value = watch(name, defaultValue);
|
||||
const fields = Array.isArray(value) && value.length !== 0 ? value : [""];
|
||||
|
||||
const remove = (index: number) => {
|
||||
setValue(name, [...fields.slice(0, index), ...fields.slice(index + 1)]);
|
||||
};
|
||||
|
||||
const append = () => {
|
||||
setValue(name, [...fields, ""]);
|
||||
};
|
||||
|
||||
useEffect(() => register(name), [register]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{fields.map(({ id, value }, index) => (
|
||||
<Fragment key={id}>
|
||||
{fields.map((value: string, index: number) => (
|
||||
<Fragment key={index}>
|
||||
<InputGroup>
|
||||
<TextInput
|
||||
id={id}
|
||||
ref={register()}
|
||||
name={`${name}[${index}].value`}
|
||||
defaultValue={value}
|
||||
id={name + index}
|
||||
onChange={(value) => {
|
||||
setValue(name, [
|
||||
...fields.slice(0, index),
|
||||
value,
|
||||
...fields.slice(index + 1),
|
||||
]);
|
||||
}}
|
||||
name={`${name}[${index}]`}
|
||||
value={value}
|
||||
isDisabled={isDisabled}
|
||||
{...rest}
|
||||
/>
|
||||
<Button
|
||||
|
@ -54,12 +72,11 @@ export const MultiLineInput = ({
|
|||
{index === fields.length - 1 && (
|
||||
<Button
|
||||
variant={ButtonVariant.link}
|
||||
onClick={() => append({})}
|
||||
onClick={append}
|
||||
tabIndex={-1}
|
||||
aria-label={t("common:add")}
|
||||
data-testid="addValue"
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
isDisabled={rest.isDisabled || !currentValues?.[index]?.value}
|
||||
isDisabled={!value}
|
||||
>
|
||||
<PlusCircleIcon /> {t(addButtonLabel || "common:add")}
|
||||
</Button>
|
||||
|
|
|
@ -1,19 +1,7 @@
|
|||
export type MultiLine = {
|
||||
value: string;
|
||||
};
|
||||
|
||||
export function convertToMultiline(fields: string[]): MultiLine[] {
|
||||
return (fields.length > 0 ? fields : [""]).map((field) => ({ value: field }));
|
||||
export function stringToMultiline(value?: string): string[] {
|
||||
return (value || "").split("##");
|
||||
}
|
||||
|
||||
export function stringToMultiline(value?: string): MultiLine[] {
|
||||
return (value || "").split("##").map((v) => ({ value: v }));
|
||||
}
|
||||
|
||||
export function toStringValue(formValue: MultiLine[]): string {
|
||||
return formValue.map((field) => field.value).join("##");
|
||||
}
|
||||
|
||||
export function toValue(formValue: MultiLine[]): string[] {
|
||||
return formValue.map((field) => field.value);
|
||||
export function toStringValue(formValue: string[]): string {
|
||||
return formValue.join("##");
|
||||
}
|
||||
|
|
|
@ -99,55 +99,4 @@ describe("Tests the form convert util functions", () => {
|
|||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("convert arrays to form values", () => {
|
||||
const given = {
|
||||
name: "test",
|
||||
description: "",
|
||||
redirectUris: ["http://bla.nl", "http://test.nl/bla", "http://test.nl"],
|
||||
};
|
||||
const values: { [index: string]: any } = {};
|
||||
const spy = (name: string, value: any) => (values[name] = value);
|
||||
|
||||
//when
|
||||
convertToFormValues(given, spy, ["redirectUris"]);
|
||||
|
||||
//then
|
||||
expect(values).toEqual({
|
||||
name: "test",
|
||||
description: "",
|
||||
redirectUris: [
|
||||
{ value: "http://bla.nl" },
|
||||
{ value: "http://test.nl/bla" },
|
||||
{ value: "http://test.nl" },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("convert form values to object", () => {
|
||||
const given = {
|
||||
redirectUris: [{ value: "http://bla.nl" }, { value: "http://test.nl" }],
|
||||
};
|
||||
|
||||
//when
|
||||
const values = convertFormValuesToObject(given, ["redirectUris"]);
|
||||
|
||||
//then
|
||||
expect(values).toEqual({
|
||||
redirectUris: ["http://bla.nl", "http://test.nl"],
|
||||
});
|
||||
});
|
||||
|
||||
it("convert empty multi-lines", () => {
|
||||
const values: { [index: string]: any } = {};
|
||||
const spy = (name: string, value: any) => (values[name] = value);
|
||||
|
||||
//when
|
||||
convertToFormValues({}, spy, ["redirectUris"]);
|
||||
|
||||
//then
|
||||
expect(values).toEqual({
|
||||
redirectUris: [{ value: "" }],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
21
src/util.ts
21
src/util.ts
|
@ -12,10 +12,6 @@ import {
|
|||
attributesToArray,
|
||||
KeyValueType,
|
||||
} from "./components/attribute-form/attribute-convert";
|
||||
import {
|
||||
convertToMultiline,
|
||||
toValue,
|
||||
} from "./components/multi-line-input/multi-line-convert";
|
||||
|
||||
export const sortProviders = (providers: {
|
||||
[index: string]: ProviderRepresentation;
|
||||
|
@ -84,37 +80,24 @@ const isEmpty = (obj: any) => Object.keys(obj).length === 0;
|
|||
|
||||
export const convertToFormValues = (
|
||||
obj: any,
|
||||
setValue: (name: string, value: any) => void,
|
||||
multiline?: string[]
|
||||
setValue: (name: string, value: any) => void
|
||||
) => {
|
||||
Object.entries(obj).map(([key, value]) => {
|
||||
if (key === "attributes" && isAttributesObject(value)) {
|
||||
setValue(key, attributesToArray(value as Record<string, string[]>));
|
||||
} else if (key === "config" || key === "attributes") {
|
||||
setValue(key, !isEmpty(value) ? unflatten(value) : undefined);
|
||||
} else if (multiline?.includes(key)) {
|
||||
setValue(key, convertToMultiline(value as string[]));
|
||||
} else {
|
||||
setValue(key, value);
|
||||
}
|
||||
});
|
||||
multiline?.map((line) => {
|
||||
if (!Object.keys(obj).includes(line)) {
|
||||
setValue(line, convertToMultiline([""]));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export function convertFormValuesToObject<T, G = T>(
|
||||
obj: T,
|
||||
multiline: string[] | undefined = []
|
||||
): G {
|
||||
export function convertFormValuesToObject<T, G = T>(obj: T): G {
|
||||
const result: any = {};
|
||||
Object.entries(obj).map(([key, value]) => {
|
||||
if (isAttributeArray(value)) {
|
||||
result[key] = arrayToAttributes(value as KeyValueType[]);
|
||||
} else if (multiline.includes(key)) {
|
||||
result[key] = toValue(value);
|
||||
} else if (key === "config" || key === "attributes") {
|
||||
result[key] = flatten(value as Record<string, any>, { safe: true });
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue