New.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. try {
  61. const connector = await mutation.createResource({
  62. connectName: values.connectName,
  63. newConnector: {
  64. name: values.name,
  65. config: JSON.parse(values.config.trim()),
  66. },
  67. });
  68. if (connector) {
  69. navigate(
  70. clusterConnectConnectorPath(
  71. clusterName,
  72. connector.connect,
  73. connector.name
  74. )
  75. );
  76. }
  77. } catch (e) {
  78. // do nothing
  79. }
  80. };
  81. const connectOptions = connects.map(({ name: connectName }) => ({
  82. value: connectName,
  83. label: connectName,
  84. }));
  85. return (
  86. <FormProvider {...methods}>
  87. <PageHeading
  88. text="Create new connector"
  89. backTo={clusterConnectorsPath(clusterName)}
  90. backText="Connectors"
  91. />
  92. <S.NewConnectFormStyled
  93. onSubmit={handleSubmit(onSubmit)}
  94. aria-label="Create connect form"
  95. >
  96. <S.Filed $hidden={connects?.length <= 1}>
  97. <Heading level={3}>Connect *</Heading>
  98. <Controller
  99. defaultValue={connectOptions[0]?.value}
  100. control={control}
  101. name="connectName"
  102. render={({ field: { name, onChange } }) => (
  103. <Select
  104. selectSize="M"
  105. name={name}
  106. disabled={isSubmitting}
  107. onChange={onChange}
  108. value={connectOptions[0]?.value}
  109. minWidth="100%"
  110. options={connectOptions}
  111. />
  112. )}
  113. />
  114. <FormError>
  115. <ErrorMessage errors={errors} name="connectName" />
  116. </FormError>
  117. </S.Filed>
  118. <div>
  119. <Heading level={3}>Name</Heading>
  120. <Input
  121. inputSize="M"
  122. placeholder="Connector Name"
  123. name="name"
  124. autoFocus
  125. autoComplete="off"
  126. disabled={isSubmitting}
  127. />
  128. <FormError>
  129. <ErrorMessage errors={errors} name="name" />
  130. </FormError>
  131. </div>
  132. <div>
  133. <Heading level={3}>Config</Heading>
  134. <Controller
  135. control={control}
  136. name="config"
  137. render={({ field }) => (
  138. <Editor {...field} readOnly={isSubmitting} ref={null} />
  139. )}
  140. />
  141. <FormError>
  142. <ErrorMessage errors={errors} name="config" />
  143. </FormError>
  144. </div>
  145. <Button
  146. buttonSize="M"
  147. buttonType="primary"
  148. type="submit"
  149. disabled={!isValid || isSubmitting || !isDirty}
  150. >
  151. Submit
  152. </Button>
  153. </S.NewConnectFormStyled>
  154. </FormProvider>
  155. );
  156. };
  157. export default New;