Edit.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import React from 'react';
  2. import {
  3. ClusterName,
  4. TopicFormDataRaw,
  5. TopicName,
  6. TopicConfigByName,
  7. TopicWithDetailedInfo,
  8. TopicFormData,
  9. } from 'redux/interfaces';
  10. import { useForm, FormProvider } from 'react-hook-form';
  11. import TopicForm from 'components/Topics/shared/Form/TopicForm';
  12. import { clusterTopicPath } from 'lib/paths';
  13. import { useHistory } from 'react-router';
  14. import { yupResolver } from '@hookform/resolvers/yup';
  15. import { topicFormValidationSchema } from 'lib/yupExtended';
  16. import { TOPIC_CUSTOM_PARAMS_PREFIX, TOPIC_CUSTOM_PARAMS } from 'lib/constants';
  17. import styled from 'styled-components';
  18. import PageHeading from 'components/common/PageHeading/PageHeading';
  19. import DangerZoneContainer from './DangerZone/DangerZoneContainer';
  20. export interface Props {
  21. clusterName: ClusterName;
  22. topicName: TopicName;
  23. topic?: TopicWithDetailedInfo;
  24. isFetched: boolean;
  25. isTopicUpdated: boolean;
  26. fetchTopicConfig: (clusterName: ClusterName, topicName: TopicName) => void;
  27. updateTopic: (
  28. clusterName: ClusterName,
  29. topicName: TopicName,
  30. form: TopicFormDataRaw
  31. ) => void;
  32. updateTopicPartitionsCount: (
  33. clusterName: string,
  34. topicname: string,
  35. partitions: number
  36. ) => void;
  37. }
  38. const EditWrapperStyled = styled.div`
  39. display: flex;
  40. justify-content: center;
  41. & > * {
  42. width: 800px;
  43. }
  44. `;
  45. const DEFAULTS = {
  46. partitions: 1,
  47. replicationFactor: 1,
  48. minInSyncReplicas: 1,
  49. cleanupPolicy: 'delete',
  50. retentionBytes: -1,
  51. maxMessageBytes: 1000012,
  52. };
  53. const topicParams = (topic: TopicWithDetailedInfo | undefined) => {
  54. if (!topic) {
  55. return DEFAULTS;
  56. }
  57. const { name, replicationFactor } = topic;
  58. return {
  59. ...DEFAULTS,
  60. name,
  61. partitions: topic.partitionCount || DEFAULTS.partitions,
  62. replicationFactor,
  63. [TOPIC_CUSTOM_PARAMS_PREFIX]: topic.config
  64. ?.filter(
  65. (el) =>
  66. el.value !== el.defaultValue &&
  67. Object.keys(TOPIC_CUSTOM_PARAMS).includes(el.name)
  68. )
  69. .map((el) => ({ name: el.name, value: el.value })),
  70. };
  71. };
  72. let formInit = false;
  73. const Edit: React.FC<Props> = ({
  74. clusterName,
  75. topicName,
  76. topic,
  77. isFetched,
  78. isTopicUpdated,
  79. fetchTopicConfig,
  80. updateTopic,
  81. }) => {
  82. const defaultValues = React.useMemo(
  83. () => topicParams(topic),
  84. [topicParams, topic]
  85. );
  86. const methods = useForm<TopicFormData>({
  87. defaultValues,
  88. resolver: yupResolver(topicFormValidationSchema),
  89. });
  90. const [isSubmitting, setIsSubmitting] = React.useState<boolean>(false);
  91. const history = useHistory();
  92. React.useEffect(() => {
  93. fetchTopicConfig(clusterName, topicName);
  94. }, [fetchTopicConfig, clusterName, topicName]);
  95. React.useEffect(() => {
  96. if (isSubmitting && isTopicUpdated) {
  97. const { name } = methods.getValues();
  98. history.push(clusterTopicPath(clusterName, name));
  99. }
  100. }, [isSubmitting, isTopicUpdated, clusterTopicPath, clusterName, methods]);
  101. if (!isFetched || !topic || !topic.config) {
  102. return null;
  103. }
  104. if (!formInit) {
  105. methods.reset(defaultValues);
  106. formInit = true;
  107. }
  108. const config: TopicConfigByName = {
  109. byName: {},
  110. };
  111. topic.config.forEach((param) => {
  112. config.byName[param.name] = param;
  113. });
  114. const onSubmit = async (data: TopicFormDataRaw) => {
  115. updateTopic(clusterName, topicName, data);
  116. setIsSubmitting(true); // Keep this action after updateTopic to prevent redirect before update.
  117. };
  118. return (
  119. <>
  120. <PageHeading text={`Edit ${topicName}`} />
  121. <EditWrapperStyled>
  122. <div>
  123. <FormProvider {...methods}>
  124. <TopicForm
  125. topicName={topicName}
  126. isSubmitting={isSubmitting}
  127. isEditing
  128. onSubmit={methods.handleSubmit(onSubmit)}
  129. />
  130. </FormProvider>
  131. {topic && (
  132. <DangerZoneContainer
  133. defaultPartitions={defaultValues.partitions}
  134. defaultReplicationFactor={
  135. defaultValues.replicationFactor || DEFAULTS.replicationFactor
  136. }
  137. />
  138. )}
  139. </div>
  140. </EditWrapperStyled>
  141. </>
  142. );
  143. };
  144. export default Edit;