Edit.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import React from 'react';
  2. import {
  3. ClusterName,
  4. TopicFormDataRaw,
  5. TopicName,
  6. TopicConfigByName,
  7. TopicWithDetailedInfo,
  8. CleanupPolicy,
  9. } from 'redux/interfaces';
  10. import { TopicConfig } from 'generated-sources';
  11. import { useForm, FormContext } from 'react-hook-form';
  12. import { camelCase } from 'lodash';
  13. import TopicForm from '../shared/Form/TopicForm';
  14. import FormBreadcrumbs from '../shared/Form/FormBreadcrumbs';
  15. interface Props {
  16. clusterName: ClusterName;
  17. topicName: TopicName;
  18. topic?: TopicWithDetailedInfo;
  19. isFetched: boolean;
  20. isTopicDetailsFetched: boolean;
  21. isTopicUpdated: boolean;
  22. fetchTopicDetails: (clusterName: ClusterName, topicName: TopicName) => void;
  23. fetchTopicConfig: (clusterName: ClusterName, topicName: TopicName) => void;
  24. updateTopic: (clusterName: ClusterName, form: TopicFormDataRaw) => void;
  25. redirectToTopicPath: (clusterName: ClusterName, topicName: TopicName) => void;
  26. resetUploadedState: () => void;
  27. }
  28. const DEFAULTS = {
  29. partitions: 1,
  30. replicationFactor: 1,
  31. minInSyncReplicas: 1,
  32. cleanupPolicy: CleanupPolicy.Delete,
  33. retentionBytes: -1,
  34. maxMessageBytes: 1000012,
  35. };
  36. const topicParams = (topic: TopicWithDetailedInfo | undefined) => {
  37. if (!topic) {
  38. return DEFAULTS;
  39. }
  40. const { name, replicationFactor } = topic;
  41. const configs = topic.config?.reduce(
  42. (result: { [key: string]: TopicConfig['value'] }, param) => ({
  43. ...result,
  44. [camelCase(param.name)]: param.value || param.defaultValue,
  45. }),
  46. {}
  47. );
  48. return {
  49. ...DEFAULTS,
  50. name,
  51. partitions: topic.partitionCount || DEFAULTS.partitions,
  52. replicationFactor,
  53. ...configs,
  54. };
  55. };
  56. let formInit = false;
  57. const Edit: React.FC<Props> = ({
  58. clusterName,
  59. topicName,
  60. topic,
  61. isFetched,
  62. isTopicDetailsFetched,
  63. isTopicUpdated,
  64. fetchTopicDetails,
  65. fetchTopicConfig,
  66. updateTopic,
  67. redirectToTopicPath,
  68. }) => {
  69. const defaultValues = topicParams(topic);
  70. const methods = useForm<TopicFormDataRaw>({ defaultValues });
  71. const [isSubmitting, setIsSubmitting] = React.useState<boolean>(false);
  72. React.useEffect(() => {
  73. fetchTopicConfig(clusterName, topicName);
  74. fetchTopicDetails(clusterName, topicName);
  75. }, [fetchTopicConfig, fetchTopicDetails, clusterName, topicName]);
  76. React.useEffect(() => {
  77. if (isSubmitting && isTopicUpdated) {
  78. const { name } = methods.getValues();
  79. redirectToTopicPath(clusterName, name);
  80. }
  81. }, [isSubmitting, isTopicUpdated, redirectToTopicPath, clusterName, methods]);
  82. if (!isFetched || !isTopicDetailsFetched || !topic || !topic.config) {
  83. return null;
  84. }
  85. if (!formInit) {
  86. methods.reset(defaultValues);
  87. formInit = true;
  88. }
  89. const config: TopicConfigByName = {
  90. byName: {},
  91. };
  92. topic.config.forEach((param) => {
  93. config.byName[param.name] = param;
  94. });
  95. const onSubmit = async (data: TopicFormDataRaw) => {
  96. updateTopic(clusterName, data);
  97. setIsSubmitting(true); // Keep this action after updateTopic to prevent redirect before update.
  98. };
  99. return (
  100. <div className="section">
  101. <div className="level">
  102. <FormBreadcrumbs
  103. clusterName={clusterName}
  104. topicName={topicName}
  105. current="Edit Topic"
  106. />
  107. </div>
  108. <div className="box">
  109. {/* eslint-disable-next-line react/jsx-props-no-spreading */}
  110. <FormContext {...methods}>
  111. <TopicForm
  112. topicName={topicName}
  113. config={config}
  114. isSubmitting={isSubmitting}
  115. isEditing
  116. onSubmit={methods.handleSubmit(onSubmit)}
  117. />
  118. </FormContext>
  119. </div>
  120. </div>
  121. );
  122. };
  123. export default Edit;