Просмотр исходного кода

Final changes to topic editing

Sergey Zakirov 5 лет назад
Родитель
Сommit
b54ac2ccdc

+ 1 - 1
kafka-ui-react-app/src/components/Topics/Edit/Edit.tsx

@@ -30,7 +30,7 @@ interface Props {
 const DEFAULTS = {
   partitions: 1,
   replicationFactor: 1,
-  minInsyncReplicas: 1,
+  minInSyncReplicas: 1,
   cleanupPolicy: CleanupPolicy.Delete,
   retentionBytes: -1,
   maxMessageBytes: 1000012,

+ 0 - 1
kafka-ui-react-app/src/components/Topics/New/New.tsx

@@ -59,7 +59,6 @@ const New: React.FC<Props> = ({
         <FormContext {...methods}>
           <TopicForm
             isSubmitting={isSubmitting}
-            isEditing
             onSubmit={methods.handleSubmit(onSubmit)}
           />
         </FormContext>

+ 57 - 0
kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamField.tsx

@@ -0,0 +1,57 @@
+import React from 'react';
+import { useFormContext, ErrorMessage } from 'react-hook-form';
+import { TopicFormCustomParam } from 'redux/interfaces';
+import CustomParamSelect from 'components/Topics/shared/Form/CustomParams/CustomParamSelect';
+import CustomParamValue from 'components/Topics/shared/Form/CustomParams/CustomParamValue';
+import CustomParamAction from 'components/Topics/shared/Form/CustomParams/CustomParamAction';
+import { INDEX_PREFIX } from './CustomParams';
+import CustomParamOptions from './CustomParamOptions';
+
+interface Props {
+  isDisabled: boolean;
+  index: string;
+  name: string;
+  existingFields: string[];
+  defaultValue: string;
+  onNameChange: (inputName: string, name: string) => void;
+  onRemove: (index: string) => void;
+}
+
+const CustomParamField: React.FC<Props> = ({
+  isDisabled,
+  index,
+  name,
+  existingFields,
+  defaultValue,
+  onNameChange,
+  onRemove,
+}) => {
+  return (
+    <div className="columns is-centered">
+      <div className="column">
+        <CustomParamSelect
+          index={index}
+          isDisabled={isDisabled}
+          name={name}
+          existingFields={existingFields}
+          onNameChange={onNameChange}
+        />
+      </div>
+
+      <div className="column">
+        <CustomParamValue
+          index={index}
+          isDisabled={isDisabled}
+          name={name}
+          defaultValue={defaultValue}
+        />
+      </div>
+
+      <div className="column is-narrow">
+        <CustomParamAction index={index} onRemove={onRemove} />
+      </div>
+    </div>
+  );
+};
+
+export default React.memo(CustomParamField);

+ 3 - 2
kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParamValue.tsx

@@ -1,5 +1,6 @@
 import React from 'react';
 import { useFormContext, ErrorMessage } from 'react-hook-form';
+import { camelCase } from 'lodash';
 import CUSTOM_PARAMS_OPTIONS from './customParamsOptions';
 
 interface Props {
@@ -21,7 +22,7 @@ const CustomParamValue: React.FC<Props> = ({
   const selectedParamName = watch(selectInputName, name);
 
   React.useEffect(() => {
-    if (selectedParamName) {
+    if (selectedParamName && !defaultValue) {
       setValue(
         valInputName,
         CUSTOM_PARAMS_OPTIONS[selectedParamName].defaultValue,
@@ -39,7 +40,7 @@ const CustomParamValue: React.FC<Props> = ({
         ref={register({
           required: 'Value is required.',
         })}
-        name={name.replace(/\./g, '_')}
+        name={valInputName}
         defaultValue={defaultValue}
         autoComplete="off"
         disabled={isDisabled}

+ 11 - 27
kafka-ui-react-app/src/components/Topics/shared/Form/CustomParams/CustomParams.tsx

@@ -2,10 +2,8 @@ import React from 'react';
 import { omit, reject, reduce, remove } from 'lodash';
 
 import { TopicFormCustomParams, TopicConfigByName } from 'redux/interfaces';
-import CustomParamSelect from './CustomParamSelect';
-import CustomParamValue from './CustomParamValue';
-import CustomParamAction from './CustomParamAction';
 import CustomParamButton, { CustomParamButtonType } from './CustomParamButton';
+import CustomParamField from './CustomParamField';
 
 export const INDEX_PREFIX = 'customParams';
 
@@ -89,30 +87,16 @@ const CustomParams: React.FC<Props> = ({ isSubmitting, config }) => {
       </div>
 
       {formCustomParams.allIndexes.map((index) => (
-        <div className="columns is-centered" key={index}>
-          <div className="column">
-            <CustomParamSelect
-              index={index}
-              isDisabled={isSubmitting}
-              name={formCustomParams.byIndex[index].name}
-              existingFields={existingFields}
-              onNameChange={onFieldNameChange}
-            />
-          </div>
-
-          <div className="column">
-            <CustomParamValue
-              index={index}
-              isDisabled={isSubmitting}
-              name={formCustomParams.byIndex[index].name}
-              defaultValue={formCustomParams.byIndex[index].value}
-            />
-          </div>
-
-          <div className="column is-narrow">
-            <CustomParamAction index={index} onRemove={onRemove} />
-          </div>
-        </div>
+        <CustomParamField
+          key={index}
+          index={index}
+          isDisabled={isSubmitting}
+          name={formCustomParams.byIndex[index].name}
+          defaultValue={formCustomParams.byIndex[index].value}
+          existingFields={existingFields}
+          onNameChange={onFieldNameChange}
+          onRemove={onRemove}
+        />
       ))}
     </>
   );

+ 1 - 1
kafka-ui-react-app/src/components/Topics/shared/Form/TopicForm.tsx

@@ -89,7 +89,7 @@ const TopicForm: React.FC<Props> = ({
             placeholder="Min In Sync Replicas"
             defaultValue="1"
             ref={register({ required: 'Min In Sync Replicas is required.' })}
-            name="minInsyncReplicas"
+            name="minInSyncReplicas"
             disabled={isSubmitting}
           />
           <p className="help is-danger">

+ 49 - 27
kafka-ui-react-app/src/redux/api/topics.ts

@@ -5,28 +5,24 @@ import {
   TopicDetails,
   TopicConfig,
   TopicFormData,
+  TopicFormCustomParam,
+  TopicFormFormattedParams,
+  TopicFormCustomParams,
 } from 'redux/interfaces';
 import { BASE_URL, BASE_PARAMS } from 'lib/constants';
-import { snakeCase } from 'lodash';
 
-interface TopicFormParams {
-  [name: string]: string;
-}
-
-const formatParams = (params: TopicFormData, omittedFields: string[] = []) => {
-  return Object.keys(params).reduce((result, paramName) => {
-    if (
-      ['name', 'partitions', 'replicationFactor', ...omittedFields].includes(
-        paramName
-      )
-    ) {
-      return result;
-    }
-    result[snakeCase(paramName).replace(/_/g, '.')] = params[
-      paramName
-    ] as string;
-    return result;
-  }, {} as TopicFormParams);
+const formatCustomParams = (
+  customParams: TopicFormCustomParams
+): TopicFormFormattedParams => {
+  return Object.values(customParams || {}).reduce(
+    (result: TopicFormFormattedParams, customParam: TopicFormCustomParam) => {
+      return {
+        ...result,
+        [customParam.name]: customParam.value,
+      };
+    },
+    {} as TopicFormFormattedParams
+  );
 };
 
 export const getTopicConfig = (
@@ -54,13 +50,29 @@ export const postTopic = (
   clusterName: ClusterName,
   form: TopicFormData
 ): Promise<Topic> => {
-  const { name, partitions, replicationFactor } = form;
+  const {
+    name,
+    partitions,
+    replicationFactor,
+    cleanupPolicy,
+    retentionBytes,
+    retentionMs,
+    maxMessageBytes,
+    minInSyncReplicas,
+  } = form;
 
   const body = JSON.stringify({
     name,
     partitions,
     replicationFactor,
-    configs: formatParams(form, ['customParams']),
+    configs: {
+      'cleanup.policy': cleanupPolicy,
+      'retention.ms': retentionMs,
+      'retention.bytes': retentionBytes,
+      'max.message.bytes': maxMessageBytes,
+      'min.insync.replicas': minInSyncReplicas,
+      ...formatCustomParams(form.customParams),
+    },
   });
 
   return fetch(`${BASE_URL}/clusters/${clusterName}/topics`, {
@@ -74,13 +86,23 @@ export const patchTopic = (
   clusterName: ClusterName,
   form: TopicFormData
 ): Promise<Topic> => {
+  const {
+    cleanupPolicy,
+    retentionBytes,
+    retentionMs,
+    maxMessageBytes,
+    minInSyncReplicas,
+  } = form;
+
   const body = JSON.stringify({
-    configs: formatParams(form, [
-      'name',
-      'partitions',
-      'replicationFactor',
-      'customParams',
-    ]),
+    configs: {
+      'cleanup.policy': cleanupPolicy,
+      'retention.ms': retentionMs,
+      'retention.bytes': retentionBytes,
+      'max.message.bytes': maxMessageBytes,
+      'min.insync.replicas': minInSyncReplicas,
+      ...formatCustomParams(form.customParams),
+    },
   });
 
   return fetch(`${BASE_URL}/clusters/${clusterName}/topics/${form.name}`, {

+ 6 - 2
kafka-ui-react-app/src/redux/interfaces/topic.ts

@@ -69,14 +69,18 @@ export interface TopicsState {
   allNames: TopicName[];
 }
 
+export interface TopicFormFormattedParams {
+  [name: string]: string;
+}
+
 export interface TopicFormData {
   name: string;
   partitions: number;
   replicationFactor: number;
-  minInsyncReplicas: number;
+  minInSyncReplicas: number;
   cleanupPolicy: string;
   retentionMs: number;
   retentionBytes: number;
   maxMessageBytes: number;
-  [name: string]: string | number;
+  customParams: TopicFormCustomParams;
 }