diff --git a/kafka-ui-react-app/package-lock.json b/kafka-ui-react-app/package-lock.json index 4a2ad5ff71..1ba845e9ba 100644 --- a/kafka-ui-react-app/package-lock.json +++ b/kafka-ui-react-app/package-lock.json @@ -10478,6 +10478,11 @@ "json-parse-better-errors": "^1.0.1" } }, + "parse-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", + "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==" + }, "parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", @@ -11686,6 +11691,14 @@ "react-is": "^16.8.4" } }, + "pretty-ms": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-6.0.1.tgz", + "integrity": "sha512-ke4njoVmlotekHlHyCZ3wI/c5AMT8peuHs8rKJqekj/oR5G8lND2dVpicFlUz5cbZgE290vvkMuDwfj/OcW1kw==", + "requires": { + "parse-ms": "^2.1.0" + } + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", diff --git a/kafka-ui-react-app/package.json b/kafka-ui-react-app/package.json index 9f52b99ed9..cee64d5651 100644 --- a/kafka-ui-react-app/package.json +++ b/kafka-ui-react-app/package.json @@ -22,6 +22,7 @@ "json-server": "^0.15.1", "lodash": "^4.17.15", "node-sass": "^4.13.1", + "pretty-ms": "^6.0.1", "react": "^16.12.0", "react-dom": "^16.12.0", "react-hook-form": "^4.5.5", diff --git a/kafka-ui-react-app/src/components/Topics/New/New.tsx b/kafka-ui-react-app/src/components/Topics/New/New.tsx index c5dfe688df..51b53f6078 100644 --- a/kafka-ui-react-app/src/components/Topics/New/New.tsx +++ b/kafka-ui-react-app/src/components/Topics/New/New.tsx @@ -2,12 +2,13 @@ import React from 'react'; import { ClusterName, CleanupPolicy, TopicFormData, TopicName } from 'redux/interfaces'; import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb'; import { clusterTopicsPath } from 'lib/paths'; -import { useForm, ErrorMessage } from 'react-hook-form'; +import { useForm, FormContext, ErrorMessage } from 'react-hook-form'; + import { TOPIC_NAME_VALIDATION_PATTERN, - MILLISECONDS_IN_DAY, BYTES_IN_GB, } from 'lib/constants'; +import TimeToRetain from './TimeToRetain'; interface Props { clusterName: ClusterName; @@ -24,17 +25,17 @@ const New: React.FC = ({ redirectToTopicPath, resetUploadedState }) => { - const {register, handleSubmit, errors, getValues} = useForm(); + const methods = useForm(); const [isSubmitting, setIsSubmitting] = React.useState(false); React.useEffect( () => { if (isSubmitting && isTopicCreated) { - const {name} = getValues(); + const {name} = methods.getValues(); redirectToTopicPath(clusterName, name); } }, - [isSubmitting, isTopicCreated, redirectToTopicPath, clusterName, getValues], + [isSubmitting, isTopicCreated, redirectToTopicPath, clusterName, methods.getValues], ); const onSubmit = async (data: TopicFormData) => { @@ -59,192 +60,168 @@ const New: React.FC = ({
-
-
-
- - -

- -

-
- -
- - -

- -

-
-
- -
-
- - -

- -

-
- -
- - -

- -

-
-
- -
-
- -
- - - - + /> +

+ +

+
+ +
+ + +

+ +

-
- -
- - - - - - - + /> +

+ +

+
+ +
+ + +

+ +

-
- -
- +
+
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
-
-
-
- - -

- -

+
+
+ + +

+ +

+
-
- - + + +
); diff --git a/kafka-ui-react-app/src/components/Topics/New/TimeToRetain.tsx b/kafka-ui-react-app/src/components/Topics/New/TimeToRetain.tsx new file mode 100644 index 0000000000..871ce4c3d4 --- /dev/null +++ b/kafka-ui-react-app/src/components/Topics/New/TimeToRetain.tsx @@ -0,0 +1,53 @@ +import React from 'react'; +import prettyMilliseconds from 'pretty-ms'; +import { useFormContext, ErrorMessage } from 'react-hook-form'; +import { MILLISECONDS_IN_WEEK } from 'lib/constants'; + +const MILLISECONDS_IN_SECOND = 1000; + +interface Props { + isSubmitting: boolean; +} + +const TimeToRetain: React.FC = ({ + isSubmitting, +}) => { + const { register, errors, watch } = useFormContext(); + const defaultValue = MILLISECONDS_IN_WEEK; + const name: string = 'retentionMs'; + const watchedValue: any = watch(name, defaultValue.toString()); + + const valueHint = React.useMemo(() => { + const value = parseInt(watchedValue, 10); + return value >= MILLISECONDS_IN_SECOND ? prettyMilliseconds(value) : false; + }, [watchedValue]) + + return ( + <> + + +

+ +

+ { + valueHint && +

+ {valueHint} +

+ } + + ); +} + +export default TimeToRetain; diff --git a/kafka-ui-react-app/src/lib/constants.ts b/kafka-ui-react-app/src/lib/constants.ts index 554de1b02f..ad518d4669 100644 --- a/kafka-ui-react-app/src/lib/constants.ts +++ b/kafka-ui-react-app/src/lib/constants.ts @@ -10,6 +10,6 @@ export const BASE_URL = process.env.REACT_APP_API_URL; export const TOPIC_NAME_VALIDATION_PATTERN = RegExp(/^[.,A-Za-z0-9_-]+$/); -export const MILLISECONDS_IN_DAY = 86_400_000; +export const MILLISECONDS_IN_WEEK = 604_800_000; export const BYTES_IN_GB = 1_073_741_824;