Repository: provectus/kafka-ui
Issue: Only content data displayed with "Save as a file" and "Copy to clipboard" the Message
Labels: type/bug
good first issue
scope/frontend
status/accepted
status/confirmed


**Describe the bug**
Only content data displayed with "Save as a file" and "Copy to clipboard" the Message

**Set up**
https://www.kafka-ui.provectus.io/

**Steps to Reproduce**
<!-- We'd like you to provide an example setup (via docker-compose, helm, etc.) 
to reproduce the problem, especially with a complex setups. -->
Steps to reproduce the behavior:

1. Navigate to Topics
2. Open the Messages tab for one Topic
3. Crete the Messages with Key, Content and Headers
4. Press the "Save as a file" / "Copy to clipboard" from menu

**Expected behavior**
All the Message's data should be copied and exist in a saved file.

**Screenshots**

https://user-images.githubusercontent.com/104780608/182073185-5aaaa867-1a56-4a2c-bbfd-e8fc242f3bc6.mov




**Additional context**
<!--
(Add any other context about the problem here)
-->


Issue comments:

Pull request review comments:

Patch that resolved the issue:
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 3cba8d058ec..3584aee7973 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
@@ -40,9 +40,18 @@ const Message: React.FC<Props> = ({
   },
 }) => {
   const [isOpen, setIsOpen] = React.useState(false);
+  const savedMessageJson = {
+    Content: content,
+    Offset: offset,
+    Key: key,
+    Partition: partition,
+    Headers: headers,
+    Timestamp: timestamp,
+  };
+  const savedMessage = JSON.stringify(savedMessageJson, null, '\t');
   const { copyToClipboard, saveFile } = useDataSaver(
     'topic-message',
-    content || ''
+    savedMessage || ''
   );
 
   const toggleIsOpen = () => setIsOpen(!isOpen);
diff --git a/kafka-ui-react-app/src/lib/hooks/__tests__/useDataSaver.spec.tsx b/kafka-ui-react-app/src/lib/hooks/__tests__/useDataSaver.spec.tsx
index 81ef81a96af..510fb955455 100644
--- a/kafka-ui-react-app/src/lib/hooks/__tests__/useDataSaver.spec.tsx
+++ b/kafka-ui-react-app/src/lib/hooks/__tests__/useDataSaver.spec.tsx
@@ -32,11 +32,7 @@ describe('useDataSaver hook', () => {
       render(<HookWrapper />);
       expect(mockCreate).toHaveBeenCalledTimes(2);
       expect(link.download).toEqual('message_1616581196000.json');
-      expect(link.href).toEqual(
-        `data:text/json;charset=utf-8,${encodeURIComponent(
-          JSON.stringify(content)
-        )}`
-      );
+      expect(link.href).toEqual(`data:text/json;charset=utf-8,${content}`);
       expect(link.click).toHaveBeenCalledTimes(1);
 
       mockCreate.mockRestore();
@@ -59,11 +55,7 @@ describe('useDataSaver hook', () => {
       render(<HookWrapper />);
       expect(mockCreate).toHaveBeenCalledTimes(2);
       expect(link.download).toEqual('message_1616581196000.txt');
-      expect(link.href).toEqual(
-        `data:text/json;charset=utf-8,${encodeURIComponent(
-          JSON.stringify('content')
-        )}`
-      );
+      expect(link.href).toEqual(`data:text/json;charset=utf-8,content`);
       expect(link.click).toHaveBeenCalledTimes(1);
 
       mockCreate.mockRestore();
diff --git a/kafka-ui-react-app/src/lib/hooks/useDataSaver.ts b/kafka-ui-react-app/src/lib/hooks/useDataSaver.ts
index 20c9cd2ac2b..6dba2700be8 100644
--- a/kafka-ui-react-app/src/lib/hooks/useDataSaver.ts
+++ b/kafka-ui-react-app/src/lib/hooks/useDataSaver.ts
@@ -20,9 +20,7 @@ const useDataSaver = (
 
   const saveFile = () => {
     const extension = isObject(data) ? 'json' : 'txt';
-    const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(
-      JSON.stringify(data)
-    )}`;
+    const dataStr = `data:text/json;charset=utf-8,${data}`;
     const downloadAnchorNode = document.createElement('a');
     downloadAnchorNode.setAttribute('href', dataStr);
     downloadAnchorNode.setAttribute(


Test patch: