import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Controller, useFieldArray, useFormContext } from "react-hook-form"; import { Button, Select, SelectOption, SelectVariant, } from "@patternfly/react-core"; import { TableComposable, Tbody, Td, Th, Thead, Tr, } from "@patternfly/react-table"; import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons"; import { camelCase } from "lodash-es"; import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation"; import { defaultContextAttributes } from "../utils"; import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput"; 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); }; const attributeValues = useMemo(() => { let values: AttributeType[] | undefined = []; if (selectableValues) { values = defaultContextAttributes.find( (attr) => attr.key === getValues().context?.[rowIndex]?.key )?.values; } return values; }, [getValues]); const renderSelectOptionType = () => { const scopeValues = resources?.find( (resource) => resource.name === getValues().resources?.[rowIndex]?.key )?.scopes; 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: "" }, false); } }, [fields]); const watchLastValue = watch(`${name}[${fields.length - 1}].value`, ""); return ( {t("key")} {t("value")} {fields.map((attribute, rowIndex) => ( ( )} /> ))} ); };