New.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import React from 'react';
  2. import { useNavigate } from 'react-router-dom';
  3. import useAppParams from 'lib/hooks/useAppParams';
  4. import { Controller, FormProvider, useForm } from 'react-hook-form';
  5. import { ErrorMessage } from '@hookform/error-message';
  6. import { yupResolver } from '@hookform/resolvers/yup';
  7. import {
  8. clusterConnectConnectorPath,
  9. clusterConnectorsPath,
  10. ClusterNameRoute,
  11. } from 'lib/paths';
  12. import yup from 'lib/yupExtended';
  13. import Editor from 'components/common/Editor/Editor';
  14. import Select from 'components/common/Select/Select';
  15. import { FormError } from 'components/common/Input/Input.styled';
  16. import Input from 'components/common/Input/Input';
  17. import { Button } from 'components/common/Button/Button';
  18. import PageHeading from 'components/common/PageHeading/PageHeading';
  19. import Heading from 'components/common/heading/Heading.styled';
  20. import { useConnects, useCreateConnector } from 'lib/hooks/api/kafkaConnect';
  21. import get from 'lodash/get';
  22. import { Connect } from 'generated-sources';
  23. import * as S from './New.styled';
  24. const validationSchema = yup.object().shape({
  25. name: yup.string().required(),
  26. config: yup.string().required().isJsonObject(),
  27. });
  28. interface FormValues {
  29. connectName: Connect['name'];
  30. name: string;
  31. config: string;
  32. }
  33. const New: React.FC = () => {
  34. const { clusterName } = useAppParams<ClusterNameRoute>();
  35. const navigate = useNavigate();
  36. const { data: connects } = useConnects(clusterName);
  37. const mutation = useCreateConnector(clusterName);
  38. const methods = useForm<FormValues>({
  39. mode: 'all',
  40. resolver: yupResolver(validationSchema),
  41. defaultValues: {
  42. connectName: get(connects, '0.name', ''),
  43. name: '',
  44. config: '',
  45. },
  46. });
  47. const {
  48. handleSubmit,
  49. control,
  50. formState: { isDirty, isSubmitting, isValid, errors },
  51. getValues,
  52. setValue,
  53. } = methods;
  54. React.useEffect(() => {
  55. if (connects && connects.length > 0 && !getValues().connectName) {
  56. setValue('connectName', connects[0].name);
  57. }
  58. }, [connects, getValues, setValue]);
  59. const onSubmit = async (values: FormValues) => {
  60. const connector = await mutation.mutateAsync({
  61. connectName: values.connectName,
  62. newConnector: {
  63. name: values.name,
  64. config: JSON.parse(values.config.trim()),
  65. },
  66. });
  67. if (connector) {
  68. navigate(
  69. clusterConnectConnectorPath(
  70. clusterName,
  71. connector.connect,
  72. connector.name
  73. )
  74. );
  75. }
  76. };
  77. if (!connects || connects.length === 0) {
  78. return null;
  79. }
  80. const connectOptions = connects.map(({ name: connectName }) => ({
  81. value: connectName,
  82. label: connectName,
  83. }));
  84. return (
  85. <FormProvider {...methods}>
  86. <PageHeading
  87. text="Create new connector"
  88. backTo={clusterConnectorsPath(clusterName)}
  89. backText="Connectors"
  90. />
  91. <S.NewConnectFormStyled
  92. onSubmit={handleSubmit(onSubmit)}
  93. aria-label="Create connect form"
  94. >
  95. <S.Filed $hidden={connects.length <= 1}>
  96. <Heading level={3}>Connect *</Heading>
  97. <Controller
  98. defaultValue={connectOptions[0].value}
  99. control={control}
  100. name="connectName"
  101. render={({ field: { name, onChange } }) => (
  102. <Select
  103. selectSize="M"
  104. name={name}
  105. disabled={isSubmitting}
  106. onChange={onChange}
  107. value={connectOptions[0].value}
  108. minWidth="100%"
  109. options={connectOptions}
  110. />
  111. )}
  112. />
  113. <FormError>
  114. <ErrorMessage errors={errors} name="connectName" />
  115. </FormError>
  116. </S.Filed>
  117. <div>
  118. <Heading level={3}>Name</Heading>
  119. <Input
  120. inputSize="M"
  121. placeholder="Connector Name"
  122. name="name"
  123. autoComplete="off"
  124. disabled={isSubmitting}
  125. />
  126. <FormError>
  127. <ErrorMessage errors={errors} name="name" />
  128. </FormError>
  129. </div>
  130. <div>
  131. <Heading level={3}>Config</Heading>
  132. <Controller
  133. control={control}
  134. name="config"
  135. render={({ field }) => (
  136. <Editor {...field} readOnly={isSubmitting} />
  137. )}
  138. />
  139. <FormError>
  140. <ErrorMessage errors={errors} name="config" />
  141. </FormError>
  142. </div>
  143. <Button
  144. buttonSize="M"
  145. buttonType="primary"
  146. type="submit"
  147. disabled={!isValid || isSubmitting || !isDirty}
  148. >
  149. Submit
  150. </Button>
  151. </S.NewConnectFormStyled>
  152. </FormProvider>
  153. );
  154. };
  155. export default New;