import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Controller, useFieldArray, useFormContext } from "react-hook-form"; import { Button, Select, SelectOption, SelectVariant, TextInput, } from "@patternfly/react-core"; import { TableComposable, Tbody, Td, Th, Thead, Tr, } from "@patternfly/react-table"; import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons"; import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation"; import { defaultContextAttributes } from "../utils"; import { camelCase } from "lodash-es"; import "./key-based-attribute-input.css"; export type AttributeType = { key?: string; name: string; custom?: boolean; values?: { [key: string]: string; }[]; }; type AttributeInputProps = { name: string; selectableValues?: AttributeType[]; resources?: ResourceRepresentation[]; }; type ValueInputProps = { name: string; rowIndex: number; attribute: any; selectableValues?: AttributeType[]; resources?: ResourceRepresentation[]; }; const ValueInput = ({ name, rowIndex, attribute, selectableValues, resources, }: ValueInputProps) => { const { t } = useTranslation("common"); const { control, register, getValues } = useFormContext(); const [isValueOpenArray, setIsValueOpenArray] = useState([false]); const toggleValueSelect = (rowIndex: number, open: boolean) => { const arr = [...isValueOpenArray]; arr[rowIndex] = open; setIsValueOpenArray(arr); }; let attributeValues: { key: string; name: string }[] | undefined = []; const scopeValues = resources?.find( (resource) => resource.name === getValues().resources[rowIndex]?.key )?.scopes; if (selectableValues) { attributeValues = defaultContextAttributes.find( (attr) => attr.key === getValues().context[rowIndex]?.key )?.values; } const renderSelectOptionType = () => { if (attributeValues?.length && !resources) { return attributeValues.map((attr) => ( {attr.name} )); } else if (scopeValues?.length) { return scopeValues.map((scope) => ( {scope.name} )); } }; const getMessageBundleKey = (attributeName: string) => camelCase(attributeName).replace(/\W/g, ""); return ( {resources || attributeValues?.length ? ( ( )} /> ) : ( )} ); }; export const KeyBasedAttributeInput = ({ name, selectableValues, resources, }: AttributeInputProps) => { const { t } = useTranslation("common"); const { control, watch } = useFormContext(); const { fields, append, remove } = useFieldArray({ control: control, name, }); const [isKeyOpenArray, setIsKeyOpenArray] = useState([false]); const toggleKeySelect = (rowIndex: number, open: boolean) => { const arr = [...isKeyOpenArray]; arr[rowIndex] = open; setIsKeyOpenArray(arr); }; useEffect(() => { if (!fields.length) { append({ key: "", value: "" }); } }, [fields]); const watchLastValue = watch(`${name}[${fields.length - 1}].value`, ""); return ( {t("key")} {t("value")} {fields.map((attribute, rowIndex) => ( ( )} /> ))} ); };