Edit.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import React from 'react';
  2. import { useHistory, useParams } from 'react-router-dom';
  3. import { useForm, Controller, FormProvider } from 'react-hook-form';
  4. import {
  5. CompatibilityLevelCompatibilityEnum,
  6. SchemaType,
  7. } from 'generated-sources';
  8. import { clusterSchemaPath } from 'lib/paths';
  9. import { NewSchemaSubjectRaw } from 'redux/interfaces';
  10. import Editor from 'components/common/Editor/Editor';
  11. import Select from 'components/common/Select/Select';
  12. import { Button } from 'components/common/Button/Button';
  13. import { InputLabel } from 'components/common/Input/InputLabel.styled';
  14. import PageHeading from 'components/common/PageHeading/PageHeading';
  15. import { useAppDispatch, useAppSelector } from 'lib/hooks/redux';
  16. import {
  17. schemaAdded,
  18. schemasApiClient,
  19. fetchLatestSchema,
  20. getSchemaLatest,
  21. SCHEMA_LATEST_FETCH_ACTION,
  22. getAreSchemaLatestFulfilled,
  23. schemaUpdated,
  24. } from 'redux/reducers/schemas/schemasSlice';
  25. import { serverErrorAlertAdded } from 'redux/reducers/alerts/alertsSlice';
  26. import { getResponse } from 'lib/errorHandling';
  27. import PageLoader from 'components/common/PageLoader/PageLoader';
  28. import { resetLoaderById } from 'redux/reducers/loader/loaderSlice';
  29. import * as S from './Edit.styled';
  30. const Edit: React.FC = () => {
  31. const history = useHistory();
  32. const dispatch = useAppDispatch();
  33. const { clusterName, subject } =
  34. useParams<{ clusterName: string; subject: string }>();
  35. const methods = useForm<NewSchemaSubjectRaw>({ mode: 'onChange' });
  36. const {
  37. formState: { isDirty, isSubmitting, dirtyFields },
  38. control,
  39. handleSubmit,
  40. } = methods;
  41. React.useEffect(() => {
  42. dispatch(fetchLatestSchema({ clusterName, subject }));
  43. return () => {
  44. dispatch(resetLoaderById(SCHEMA_LATEST_FETCH_ACTION));
  45. };
  46. }, [clusterName, dispatch, subject]);
  47. const schema = useAppSelector((state) => getSchemaLatest(state));
  48. const isFetched = useAppSelector(getAreSchemaLatestFulfilled);
  49. const formatedSchema = React.useMemo(() => {
  50. return schema?.schemaType === SchemaType.PROTOBUF
  51. ? schema?.schema
  52. : JSON.stringify(JSON.parse(schema?.schema || '{}'), null, '\t');
  53. }, [schema]);
  54. const onSubmit = async (props: NewSchemaSubjectRaw) => {
  55. if (!schema) return;
  56. try {
  57. if (dirtyFields.newSchema || dirtyFields.schemaType) {
  58. const resp = await schemasApiClient.createNewSchema({
  59. clusterName,
  60. newSchemaSubject: {
  61. ...schema,
  62. schema: props.newSchema || schema.schema,
  63. schemaType: props.schemaType || schema.schemaType,
  64. },
  65. });
  66. dispatch(schemaAdded(resp));
  67. }
  68. if (dirtyFields.compatibilityLevel) {
  69. await schemasApiClient.updateSchemaCompatibilityLevel({
  70. clusterName,
  71. subject,
  72. compatibilityLevel: {
  73. compatibility: props.compatibilityLevel,
  74. },
  75. });
  76. dispatch(
  77. schemaUpdated({
  78. ...schema,
  79. compatibilityLevel: props.compatibilityLevel,
  80. })
  81. );
  82. }
  83. history.push(clusterSchemaPath(clusterName, subject));
  84. } catch (e) {
  85. const err = await getResponse(e as Response);
  86. dispatch(serverErrorAlertAdded(err));
  87. }
  88. };
  89. if (!isFetched || !schema) {
  90. return <PageLoader />;
  91. }
  92. return (
  93. <FormProvider {...methods}>
  94. <PageHeading text="Edit schema" />
  95. <S.EditWrapper>
  96. <form onSubmit={handleSubmit(onSubmit)}>
  97. <div>
  98. <div>
  99. <InputLabel>Type</InputLabel>
  100. <Controller
  101. defaultValue={schema.schemaType}
  102. control={control}
  103. rules={{ required: true }}
  104. name="schemaType"
  105. render={({ field: { name, onChange } }) => (
  106. <Select
  107. name={name}
  108. value={schema.schemaType}
  109. onChange={onChange}
  110. minWidth="100%"
  111. disabled={isSubmitting}
  112. options={Object.keys(SchemaType).map((type) => ({
  113. value: type,
  114. label: type,
  115. }))}
  116. />
  117. )}
  118. />
  119. </div>
  120. <div>
  121. <InputLabel>Compatibility level</InputLabel>
  122. <Controller
  123. defaultValue={
  124. schema.compatibilityLevel as CompatibilityLevelCompatibilityEnum
  125. }
  126. control={control}
  127. name="compatibilityLevel"
  128. render={({ field: { name, onChange } }) => (
  129. <Select
  130. name={name}
  131. value={schema.compatibilityLevel}
  132. onChange={onChange}
  133. minWidth="100%"
  134. disabled={isSubmitting}
  135. options={Object.keys(
  136. CompatibilityLevelCompatibilityEnum
  137. ).map((level) => ({ value: level, label: level }))}
  138. />
  139. )}
  140. />
  141. </div>
  142. </div>
  143. <S.EditorsWrapper>
  144. <div>
  145. <S.EditorContainer>
  146. <h4>Latest schema</h4>
  147. <Editor
  148. schemaType={schema?.schemaType}
  149. isFixedHeight
  150. readOnly
  151. height="372px"
  152. value={formatedSchema}
  153. name="latestSchema"
  154. highlightActiveLine={false}
  155. />
  156. </S.EditorContainer>
  157. </div>
  158. <div>
  159. <S.EditorContainer>
  160. <h4>New schema</h4>
  161. <Controller
  162. control={control}
  163. name="newSchema"
  164. render={({ field: { name, onChange } }) => (
  165. <Editor
  166. schemaType={schema?.schemaType}
  167. readOnly={isSubmitting}
  168. defaultValue={formatedSchema}
  169. name={name}
  170. onChange={onChange}
  171. />
  172. )}
  173. />
  174. </S.EditorContainer>
  175. <Button
  176. buttonType="primary"
  177. buttonSize="M"
  178. type="submit"
  179. disabled={!isDirty || isSubmitting}
  180. >
  181. Submit
  182. </Button>
  183. </div>
  184. </S.EditorsWrapper>
  185. </form>
  186. </S.EditWrapper>
  187. </FormProvider>
  188. );
  189. };
  190. export default Edit;