Message.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import * as React from 'react';
  2. import dayjs from 'dayjs';
  3. import { TopicMessage } from 'generated-sources';
  4. import JSONViewer from 'components/common/JSONViewer/JSONViewer';
  5. import Dropdown from 'components/common/Dropdown/Dropdown';
  6. import DropdownItem from 'components/common/Dropdown/DropdownItem';
  7. import useDataSaver from 'lib/hooks/useDataSaver';
  8. type Tab = 'key' | 'content' | 'headers';
  9. const Message: React.FC<{ message: TopicMessage }> = ({
  10. message: {
  11. timestamp,
  12. timestampType,
  13. offset,
  14. key,
  15. partition,
  16. content,
  17. headers,
  18. },
  19. }) => {
  20. const [isOpen, setIsOpen] = React.useState(false);
  21. const [activeTab, setActiveTab] = React.useState<Tab>('content');
  22. const { copyToClipboard, saveFile } = useDataSaver(
  23. 'topic-message',
  24. content || ''
  25. );
  26. const toggleIsOpen = () => setIsOpen(!isOpen);
  27. const handleKeyTabClick = (e: React.MouseEvent) => {
  28. e.preventDefault();
  29. setActiveTab('key');
  30. };
  31. const handleContentTabClick = (e: React.MouseEvent) => {
  32. e.preventDefault();
  33. setActiveTab('content');
  34. };
  35. const handleHeadersTabClick = (e: React.MouseEvent) => {
  36. e.preventDefault();
  37. setActiveTab('headers');
  38. };
  39. const activeTabContent = () => {
  40. switch (activeTab) {
  41. case 'content':
  42. return content;
  43. case 'key':
  44. return key;
  45. default:
  46. return JSON.stringify(headers);
  47. }
  48. };
  49. return (
  50. <>
  51. <tr>
  52. <td>
  53. <span
  54. className="icon has-text-link is-size-7 is-small is-clickable"
  55. onClick={toggleIsOpen}
  56. aria-hidden
  57. >
  58. <i className={`fas fa-${isOpen ? 'minus' : 'plus'}`} />
  59. </span>
  60. </td>
  61. <td>{offset}</td>
  62. <td>{partition}</td>
  63. <td
  64. className="has-text-overflow-ellipsis is-family-code"
  65. style={{ width: 80, maxWidth: 250 }}
  66. title={key}
  67. >
  68. {key}
  69. </td>
  70. <td>
  71. <div className="tag">
  72. {dayjs(timestamp).format('MM.DD.YYYY HH:mm:ss')}
  73. </div>
  74. </td>
  75. <td
  76. className="has-text-overflow-ellipsis is-family-code"
  77. style={{ width: '100%', maxWidth: 0 }}
  78. >
  79. {content}
  80. </td>
  81. <td className="has-text-right">
  82. <Dropdown
  83. label={
  84. <span className="icon">
  85. <i className="fas fa-cog" />
  86. </span>
  87. }
  88. right
  89. >
  90. <DropdownItem onClick={copyToClipboard}>
  91. Copy to clipboard
  92. </DropdownItem>
  93. <DropdownItem onClick={saveFile}>Save as a file</DropdownItem>
  94. </Dropdown>
  95. </td>
  96. </tr>
  97. {isOpen && (
  98. <tr className="has-background-light">
  99. <td />
  100. <td colSpan={3}>
  101. <div className="title is-7">Timestamp Type</div>
  102. <div className="subtitle is-7 is-spaced">{timestampType}</div>
  103. <div className="title is-7">Timestamp</div>
  104. <div className="subtitle is-7">{timestamp}</div>
  105. </td>
  106. <td colSpan={3} style={{ wordBreak: 'break-word' }}>
  107. <nav className="panel has-background-white">
  108. <p className="panel-tabs is-justify-content-start pl-5">
  109. <a
  110. href="key"
  111. onClick={handleKeyTabClick}
  112. className={activeTab === 'key' ? 'is-active' : ''}
  113. >
  114. Key
  115. </a>
  116. <a
  117. href="content"
  118. className={activeTab === 'content' ? 'is-active' : ''}
  119. onClick={handleContentTabClick}
  120. >
  121. Content
  122. </a>
  123. <a
  124. href="headers"
  125. className={activeTab === 'headers' ? 'is-active' : ''}
  126. onClick={handleHeadersTabClick}
  127. >
  128. Headers
  129. </a>
  130. </p>
  131. <div className="panel-block is-family-code">
  132. <JSONViewer data={activeTabContent() || ''} />
  133. </div>
  134. </nav>
  135. </td>
  136. </tr>
  137. )}
  138. </>
  139. );
  140. };
  141. export default Message;