diff --git a/kafka-ui-react-app/src/components/Connect/New/New.tsx b/kafka-ui-react-app/src/components/Connect/New/New.tsx index 8040267661f..2effd79d3cc 100644 --- a/kafka-ui-react-app/src/components/Connect/New/New.tsx +++ b/kafka-ui-react-app/src/components/Connect/New/New.tsx @@ -13,7 +13,7 @@ import yup from 'lib/yupExtended'; import Editor from 'components/common/Editor/Editor'; import Select from 'components/common/Select/Select'; import { FormError } from 'components/common/Input/Input.styled'; -import Input from 'components/common/Input/Input'; +import ControlledInput from 'components/common/Input/ControlledInput'; import { Button } from 'components/common/Button/Button'; import PageHeading from 'components/common/PageHeading/PageHeading'; import Heading from 'components/common/heading/Heading.styled'; @@ -133,7 +133,7 @@ const New: React.FC = () => {
Name - = ({ defaultValues, partitions, topics }) => { partitionsValue.length > 0 && ( {fields.map((field, index) => ( - = ({ Stream properties: {fields.map((field, index) => ( - - = ({ Number of partitions * - = ({ Replication Factor * - = ({ )}
Display name - = ({
Value * - ) => void; } -const Checkbox: React.FC = ({ name, label, hint }) => { - const { register } = useFormContext(); - - return ( -
- - - {label} - - {hint} - - - -
- ); -}; +const Checkbox = React.forwardRef( + ({ name, label, hint, onChange }, ref) => { + return ( +
+ + + {label} + + {hint} + + + +
+ ); + } +); export default Checkbox; diff --git a/kafka-ui-react-app/src/components/common/Checkbox/ControlledCheckbox.tsx b/kafka-ui-react-app/src/components/common/Checkbox/ControlledCheckbox.tsx new file mode 100644 index 00000000000..268f508f3fb --- /dev/null +++ b/kafka-ui-react-app/src/components/common/Checkbox/ControlledCheckbox.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { Controller } from 'react-hook-form'; + +import Checkbox, { CheckboxProps } from './Checkbox'; + +const ControlledCheckbox = ({ name, label, hint }: CheckboxProps) => { + return ( + } + /> + ); +}; + +export default ControlledCheckbox; diff --git a/kafka-ui-react-app/src/components/common/Input/ControlledInput.tsx b/kafka-ui-react-app/src/components/common/Input/ControlledInput.tsx new file mode 100644 index 00000000000..8f8b1434106 --- /dev/null +++ b/kafka-ui-react-app/src/components/common/Input/ControlledInput.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { Controller } from 'react-hook-form'; + +import Input, { InputProps } from './Input'; + +const ControlledInput = ({ + name, + control, + ...restProps +}: // eslint-disable-next-line @typescript-eslint/no-explicit-any +InputProps & { control: any }) => { + return ( + } + /> + ); +}; + +export default ControlledInput; diff --git a/kafka-ui-react-app/src/components/common/Input/Input.tsx b/kafka-ui-react-app/src/components/common/Input/Input.tsx index ae76bc47178..5a7002e2dad 100644 --- a/kafka-ui-react-app/src/components/common/Input/Input.tsx +++ b/kafka-ui-react-app/src/components/common/Input/Input.tsx @@ -99,99 +99,107 @@ function pasteNumberCheck( return value; } -const Input: React.FC = ({ - name, - hookFormOptions, - search, - inputSize = 'L', - type, - positiveOnly, - integerOnly, - withError = false, - label, - hint, - ...rest -}) => { - const methods = useFormContext(); +const Input = React.forwardRef( + ( + { + name, + hookFormOptions, + search, + inputSize = 'L', + type, + positiveOnly, + integerOnly, + withError = false, + label, + hint, + ...rest + }, + ref + ) => { + const methods = useFormContext(); - const fieldId = React.useId(); + const fieldId = React.useId(); - const isHookFormField = !!name && !!methods.register; + const isHookFormField = !!name && !!methods.register; - const keyPressEventHandler = ( - event: React.KeyboardEvent - ) => { - const { key } = event; - if (type === 'number') { - // Manually prevent input of non-digit and non-minus for all number inputs - // and prevent input of negative numbers for positiveOnly inputs - if ( - !inputNumberCheck( - key, - typeof positiveOnly === 'boolean' ? positiveOnly : false, - typeof integerOnly === 'boolean' ? integerOnly : false, - methods.getValues, - typeof name === 'string' ? name : '' - ) - ) { - event.preventDefault(); + const keyPressEventHandler = ( + event: React.KeyboardEvent + ) => { + const { key } = event; + if (type === 'number') { + // Manually prevent input of non-digit and non-minus for all number inputs + // and prevent input of negative numbers for positiveOnly inputs + if ( + !inputNumberCheck( + key, + typeof positiveOnly === 'boolean' ? positiveOnly : false, + typeof integerOnly === 'boolean' ? integerOnly : false, + methods.getValues, + typeof name === 'string' ? name : '' + ) + ) { + event.preventDefault(); + } } - } - }; - const pasteEventHandler = (event: React.ClipboardEvent) => { - if (type === 'number') { - const { clipboardData } = event; - // The 'clipboardData' does not have key 'Text', but has key 'text' instead. - const text = clipboardData.getData('text'); - // Check the format of pasted text. - const value = pasteNumberCheck( - text, - typeof positiveOnly === 'boolean' ? positiveOnly : false, - typeof integerOnly === 'boolean' ? integerOnly : false - ); - // if paste value contains non-numeric characters or - // negative for positiveOnly fields then prevent paste - if (value !== text) { - event.preventDefault(); + }; + const pasteEventHandler = ( + event: React.ClipboardEvent + ) => { + if (type === 'number') { + const { clipboardData } = event; + // The 'clipboardData' does not have key 'Text', but has key 'text' instead. + const text = clipboardData.getData('text'); + // Check the format of pasted text. + const value = pasteNumberCheck( + text, + typeof positiveOnly === 'boolean' ? positiveOnly : false, + typeof integerOnly === 'boolean' ? integerOnly : false + ); + // if paste value contains non-numeric characters or + // negative for positiveOnly fields then prevent paste + if (value !== text) { + event.preventDefault(); - // for react-hook-form fields only set transformed value - if (isHookFormField) { - methods.setValue(name, value); + // for react-hook-form fields only set transformed value + if (isHookFormField) { + methods.setValue(name, value); + } } } + }; + + let inputOptions = { ...rest }; + if (isHookFormField) { + // extend input options with react-hook-form options + // if the field is a part of react-hook-form form + inputOptions = { ...rest, ...methods.register(name, hookFormOptions) }; } - }; - let inputOptions = { ...rest }; - if (isHookFormField) { - // extend input options with react-hook-form options - // if the field is a part of react-hook-form form - inputOptions = { ...rest, ...methods.register(name, hookFormOptions) }; + return ( +
+ {label && {label}} + + {search && } + + {withError && isHookFormField && ( + + + + )} + {hint && {hint}} + +
+ ); } - - return ( -
- {label && {label}} - - {search && } - - {withError && isHookFormField && ( - - - - )} - {hint && {hint}} - -
- ); -}; +); export default Input; diff --git a/kafka-ui-react-app/src/widgets/ClusterConfigForm/Sections/Authentication/AuthenticationMethods.tsx b/kafka-ui-react-app/src/widgets/ClusterConfigForm/Sections/Authentication/AuthenticationMethods.tsx index aaf2a7eae8b..6d38eb4608b 100644 --- a/kafka-ui-react-app/src/widgets/ClusterConfigForm/Sections/Authentication/AuthenticationMethods.tsx +++ b/kafka-ui-react-app/src/widgets/ClusterConfigForm/Sections/Authentication/AuthenticationMethods.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import Input from 'components/common/Input/Input'; -import Checkbox from 'components/common/Checkbox/Checkbox'; +import ControlledInput from 'components/common/Input/ControlledInput'; +import ControlledCheckbox from 'components/common/Checkbox/ControlledCheckbox'; import Fileupload from 'widgets/ClusterConfigForm/common/Fileupload'; import SSLForm from 'widgets/ClusterConfigForm/common/SSLForm'; import Credentials from 'widgets/ClusterConfigForm/common/Credentials'; @@ -10,13 +10,13 @@ const AuthenticationMethods: React.FC<{ method: string }> = ({ method }) => { case 'SASL/JAAS': return ( <> - - = ({ method }) => { case 'SASL/GSSAPI': return ( <> - - + - = ({ method }) => { ); case 'SASL/OAUTHBEARER': return ( - = ({ method }) => { case 'Delegation tokens': return ( <> - - = ({ method }) => { ); case 'SASL/AWS IAM': return ( - { {hasCustomConfig && ( <> {Object.keys(customConf).map((key) => ( - { /> {ksql && ( <> - { const { control, watch, setValue } = useFormContext(); @@ -38,14 +38,14 @@ const KafkaCluster: React.FC = () => { return ( <> Kafka Cluster - - { {fields.map((field, index) => (
- { />
- {
- { hint="Given name for the Kafka Connect cluster" withError /> - { options={METRICS_OPTIONS} /> - { /> {schemaRegistry && ( <> - = ({ return ( - + {watch(`${prefix}.isAuth`) && ( - = ({ /> - = ({ {loc ? ( - +