diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/serdes/ConsumerRecordDeserializer.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/serdes/ConsumerRecordDeserializer.java index 8c7a3024ed..f5b7018034 100644 --- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/serdes/ConsumerRecordDeserializer.java +++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/serdes/ConsumerRecordDeserializer.java @@ -123,11 +123,11 @@ public class ConsumerRecordDeserializer { } private static Long getKeySize(ConsumerRecord consumerRecord) { - return consumerRecord.key() != null ? (long) consumerRecord.key().get().length : null; + return consumerRecord.key() != null ? (long) consumerRecord.serializedKeySize() : null; } private static Long getValueSize(ConsumerRecord consumerRecord) { - return consumerRecord.value() != null ? (long) consumerRecord.value().get().length : null; + return consumerRecord.value() != null ? (long) consumerRecord.serializedValueSize() : null; } private static int headerSize(Header header) { diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/serdes/SerdesInitializer.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/serdes/SerdesInitializer.java index 40ea320b2e..66692894a6 100644 --- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/serdes/SerdesInitializer.java +++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/serdes/SerdesInitializer.java @@ -122,8 +122,6 @@ public class SerdesInitializer { registeredSerdes, Optional.ofNullable(clusterProperties.getDefaultKeySerde()) .map(name -> Preconditions.checkNotNull(registeredSerdes.get(name), "Default key serde not found")) - .or(() -> Optional.ofNullable(registeredSerdes.get(SchemaRegistrySerde.name()))) - .or(() -> Optional.ofNullable(registeredSerdes.get(ProtobufFileSerde.name()))) .orElse(null), Optional.ofNullable(clusterProperties.getDefaultValueSerde()) .map(name -> Preconditions.checkNotNull(registeredSerdes.get(name), "Default value serde not found")) diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/KafkaConnectService.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/KafkaConnectService.java index d07ef7ed2d..98b61541c5 100644 --- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/KafkaConnectService.java +++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/KafkaConnectService.java @@ -109,6 +109,7 @@ public class KafkaConnectService { private Stream getStringsForSearch(FullConnectorInfoDTO fullConnectorInfo) { return Stream.of( fullConnectorInfo.getName(), + fullConnectorInfo.getConnect(), fullConnectorInfo.getStatus().getState().getValue(), fullConnectorInfo.getType().getValue()); } diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/analyze/TopicAnalysisStats.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/analyze/TopicAnalysisStats.java index d5b4400807..f36d3bec4d 100644 --- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/analyze/TopicAnalysisStats.java +++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/analyze/TopicAnalysisStats.java @@ -43,8 +43,7 @@ class TopicAnalysisStats { Long max; final UpdateDoublesSketch sizeSketch = DoublesSketch.builder().build(); - void apply(byte[] bytes) { - int len = bytes.length; + void apply(int len) { sum += len; min = minNullable(min, len); max = maxNullable(max, len); @@ -98,7 +97,7 @@ class TopicAnalysisStats { if (rec.key() != null) { byte[] keyBytes = rec.key().get(); - keysSize.apply(keyBytes); + keysSize.apply(rec.serializedKeySize()); uniqKeys.update(keyBytes); } else { nullKeys++; @@ -106,7 +105,7 @@ class TopicAnalysisStats { if (rec.value() != null) { byte[] valueBytes = rec.value().get(); - valuesSize.apply(valueBytes); + valuesSize.apply(rec.serializedValueSize()); uniqValues.update(valueBytes); } else { nullValues++; diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Messages/Message.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Messages/Message.tsx index fb4e258cca..dd5cfae748 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Messages/Message.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Messages/Message.tsx @@ -142,6 +142,8 @@ const Message: React.FC = ({ timestampType={timestampType} keySize={keySize} contentSize={valueSize} + keySerde={keySerde} + valueSerde={valueSerde} /> )} diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/MessageContent.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/MessageContent.tsx index 93616ca432..d1237ba0d4 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/MessageContent.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/MessageContent.tsx @@ -3,7 +3,6 @@ import EditorViewer from 'components/common/EditorViewer/EditorViewer'; import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted'; import { SchemaType, TopicMessageTimestampTypeEnum } from 'generated-sources'; import { formatTimestamp } from 'lib/dateTimeHelpers'; -import { useSearchParams } from 'react-router-dom'; import * as S from './MessageContent.styled'; @@ -17,6 +16,8 @@ export interface MessageContentProps { timestampType?: TopicMessageTimestampTypeEnum; keySize?: number; contentSize?: number; + keySerde?: string; + valueSerde?: string; } const MessageContent: React.FC = ({ @@ -27,12 +28,10 @@ const MessageContent: React.FC = ({ timestampType, keySize, contentSize, + keySerde, + valueSerde, }) => { const [activeTab, setActiveTab] = React.useState('content'); - const [searchParams] = useSearchParams(); - const keyFormat = searchParams.get('keySerde') || ''; - const valueFormat = searchParams.get('valueSerde') || ''; - const activeTabContent = () => { switch (activeTab) { case 'content': @@ -110,7 +109,7 @@ const MessageContent: React.FC = ({ Key Serde - {keyFormat} + {keySerde} Size: @@ -120,7 +119,7 @@ const MessageContent: React.FC = ({ Value Serde - {valueFormat} + {valueSerde} Size: diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/__tests__/MessageContent.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/__tests__/MessageContent.spec.tsx index 91310a30e4..d76455242c 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/__tests__/MessageContent.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessageContent/__tests__/MessageContent.spec.tsx @@ -20,6 +20,8 @@ const setupWrapper = (props?: Partial) => { headers={{ header: 'test' }} timestamp={new Date(0)} timestampType={TopicMessageTimestampTypeEnum.CREATE_TIME} + keySerde="SchemaRegistry" + valueSerde="Avro" {...props} /> @@ -27,42 +29,20 @@ const setupWrapper = (props?: Partial) => { ); }; -const proto = - 'syntax = "proto3";\npackage com.provectus;\n\nmessage TestProtoRecord {\n string f1 = 1;\n int32 f2 = 2;\n}\n'; - global.TextEncoder = TextEncoder; -const searchParamsContentAVRO = new URLSearchParams({ - keySerde: 'SchemaRegistry', - valueSerde: 'AVRO', - limit: '100', -}); - -const searchParamsContentJSON = new URLSearchParams({ - keySerde: 'SchemaRegistry', - valueSerde: 'JSON', - limit: '100', -}); - -const searchParamsContentPROTOBUF = new URLSearchParams({ - keySerde: 'SchemaRegistry', - valueSerde: 'PROTOBUF', - limit: '100', -}); describe('MessageContent screen', () => { beforeEach(() => { - render(setupWrapper(), { - initialEntries: [`/messages?${searchParamsContentAVRO}`], - }); + render(setupWrapper()); }); - describe('renders', () => { - it('key format in document', () => { + describe('Checking keySerde and valueSerde', () => { + it('keySerde in document', () => { expect(screen.getByText('SchemaRegistry')).toBeInTheDocument(); }); - it('content format in document', () => { - expect(screen.getByText('AVRO')).toBeInTheDocument(); + it('valueSerde in document', () => { + expect(screen.getByText('Avro')).toBeInTheDocument(); }); }); @@ -98,42 +78,3 @@ describe('MessageContent screen', () => { }); }); }); - -describe('checking content type depend on message type', () => { - it('renders component with message having JSON type', () => { - render( - setupWrapper({ - messageContent: '{"data": "test"}', - }), - { initialEntries: [`/messages?${searchParamsContentJSON}`] } - ); - expect(screen.getByText('JSON')).toBeInTheDocument(); - }); - it('renders component with message having AVRO type', () => { - render( - setupWrapper({ - messageContent: '{"data": "test"}', - }), - { initialEntries: [`/messages?${searchParamsContentAVRO}`] } - ); - expect(screen.getByText('AVRO')).toBeInTheDocument(); - }); - it('renders component with message having PROTOBUF type', () => { - render( - setupWrapper({ - messageContent: proto, - }), - { initialEntries: [`/messages?${searchParamsContentPROTOBUF}`] } - ); - expect(screen.getByText('PROTOBUF')).toBeInTheDocument(); - }); - it('renders component with message having no type which is equal to having PROTOBUF type', () => { - render( - setupWrapper({ - messageContent: '', - }), - { initialEntries: [`/messages?${searchParamsContentPROTOBUF}`] } - ); - expect(screen.getByText('PROTOBUF')).toBeInTheDocument(); - }); -}); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.styled.tsx b/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.styled.tsx index 483c41d053..d2750abf7d 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.styled.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.styled.tsx @@ -8,15 +8,29 @@ export const Wrapper = styled.div` export const Columns = styled.div` margin: -0.75rem; margin-bottom: 0.75rem; + display: flex; + flex-direction: column; + padding: 0.75rem; + gap: 8px; @media screen and (min-width: 769px) { display: flex; } `; - -export const Column = styled.div` - flex-basis: 0; - flex-grow: 1; - flex-shrink: 1; - padding: 0.75rem; +export const Flex = styled.div` + display: flex; + flex-direction: row; + gap: 8px; + @media screen and (max-width: 1200px) { + flex-direction: column; + } +`; +export const FlexItem = styled.div` + width: 18rem; + @media screen and (max-width: 1450px) { + width: 50%; + } + @media screen and (max-width: 1200px) { + width: 100%; + } `; diff --git a/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.tsx b/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.tsx index 9450e512ad..bacfa76c93 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/SendMessage/SendMessage.tsx @@ -4,6 +4,7 @@ import { RouteParamsClusterTopic } from 'lib/paths'; import { Button } from 'components/common/Button/Button'; import Editor from 'components/common/Editor/Editor'; import Select, { SelectOption } from 'components/common/Select/Select'; +import Switch from 'components/common/Switch/Switch'; import useAppParams from 'lib/hooks/useAppParams'; import { showAlert } from 'lib/errorHandling'; import { useSendMessage, useTopicDetails } from 'lib/hooks/api/topics'; @@ -26,9 +27,12 @@ interface FormType { partition: number; keySerde: string; valueSerde: string; + keepContents: boolean; } -const SendMessage: React.FC<{ onSubmit: () => void }> = ({ onSubmit }) => { +const SendMessage: React.FC<{ closeSidebar: () => void }> = ({ + closeSidebar, +}) => { const { clusterName, topicName } = useAppParams(); const { data: topic } = useTopicDetails({ clusterName, topicName }); const { data: serdes = {} } = useSerdes({ @@ -47,11 +51,13 @@ const SendMessage: React.FC<{ onSubmit: () => void }> = ({ onSubmit }) => { handleSubmit, formState: { isSubmitting }, control, + setValue, } = useForm({ mode: 'onChange', defaultValues: { ...defaultValues, partition: Number(partitionOptions[0].value), + keepContents: false, }, }); @@ -62,6 +68,7 @@ const SendMessage: React.FC<{ onSubmit: () => void }> = ({ onSubmit }) => { content, headers, partition, + keepContents, }: FormType) => { let errors: string[] = []; @@ -110,7 +117,11 @@ const SendMessage: React.FC<{ onSubmit: () => void }> = ({ onSubmit }) => { keySerde, valueSerde, }); - onSubmit(); + if (!keepContents) { + setValue('key', ''); + setValue('content', ''); + closeSidebar(); + } } catch (e) { // do nothing } @@ -120,7 +131,7 @@ const SendMessage: React.FC<{ onSubmit: () => void }> = ({ onSubmit }) => {
- + Partition void }> = ({ onSubmit }) => { /> )} /> - - - Key Serde + + + + Key Serde + ( + + )} + /> + + +
( - - )} - /> - + Keep contents +
- - +
Key void }> = ({ onSubmit }) => { /> )} /> - - +
+
Value void }> = ({ onSubmit }) => { /> )} /> - +
- +
Headers void }> = ({ onSubmit }) => { /> )} /> - +