|
@@ -1,12 +1,9 @@
|
|
import PageLoader from 'components/common/PageLoader/PageLoader';
|
|
import PageLoader from 'components/common/PageLoader/PageLoader';
|
|
import { Table } from 'components/common/table/Table/Table.styled';
|
|
import { Table } from 'components/common/table/Table/Table.styled';
|
|
import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell';
|
|
import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell';
|
|
-import { SeekDirection, TopicMessage } from 'generated-sources';
|
|
|
|
-import styled from 'styled-components';
|
|
|
|
-import { compact, concat, groupBy, map, maxBy, minBy } from 'lodash';
|
|
|
|
|
|
+import { TopicMessage } from 'generated-sources';
|
|
import React, { useContext } from 'react';
|
|
import React, { useContext } from 'react';
|
|
import { useSelector } from 'react-redux';
|
|
import { useSelector } from 'react-redux';
|
|
-import { useHistory } from 'react-router-dom';
|
|
|
|
import {
|
|
import {
|
|
getTopicMessges,
|
|
getTopicMessges,
|
|
getIsTopicMessagesFetching,
|
|
getIsTopicMessagesFetching,
|
|
@@ -14,110 +11,52 @@ import {
|
|
import TopicMessagesContext from 'components/contexts/TopicMessagesContext';
|
|
import TopicMessagesContext from 'components/contexts/TopicMessagesContext';
|
|
|
|
|
|
import Message from './Message';
|
|
import Message from './Message';
|
|
-import * as S from './MessageContent/MessageContent.styled';
|
|
|
|
-
|
|
|
|
-const MessagesPaginationWrapperStyled = styled.div`
|
|
|
|
- padding: 16px;
|
|
|
|
- display: flex;
|
|
|
|
- justify-content: flex-start;
|
|
|
|
-`;
|
|
|
|
|
|
|
|
const MessagesTable: React.FC = () => {
|
|
const MessagesTable: React.FC = () => {
|
|
- const history = useHistory();
|
|
|
|
-
|
|
|
|
- const { searchParams, isLive } = useContext(TopicMessagesContext);
|
|
|
|
|
|
+ const { isLive } = useContext(TopicMessagesContext);
|
|
|
|
|
|
const messages = useSelector(getTopicMessges);
|
|
const messages = useSelector(getTopicMessges);
|
|
const isFetching = useSelector(getIsTopicMessagesFetching);
|
|
const isFetching = useSelector(getIsTopicMessagesFetching);
|
|
|
|
|
|
- const handleNextClick = () => {
|
|
|
|
- const seekTo = searchParams.get('seekTo');
|
|
|
|
-
|
|
|
|
- if (seekTo) {
|
|
|
|
- const selectedPartitions = seekTo.split(',').map((item) => {
|
|
|
|
- const [partition] = item.split('::');
|
|
|
|
- return { offset: 0, partition: parseInt(partition, 10) };
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- const seekDirection = searchParams.get('seekDirection');
|
|
|
|
- const isBackward = seekDirection === SeekDirection.BACKWARD;
|
|
|
|
-
|
|
|
|
- const messageUniqs = map(groupBy(messages, 'partition'), (v) =>
|
|
|
|
- isBackward ? minBy(v, 'offset') : maxBy(v, 'offset')
|
|
|
|
- ).map((message) => ({
|
|
|
|
- offset: message?.offset || 0,
|
|
|
|
- partition: message?.partition || 0,
|
|
|
|
- }));
|
|
|
|
-
|
|
|
|
- const nextSeekTo = compact(
|
|
|
|
- map(
|
|
|
|
- groupBy(concat(selectedPartitions, messageUniqs), 'partition'),
|
|
|
|
- (v) => maxBy(v, 'offset')
|
|
|
|
- )
|
|
|
|
- )
|
|
|
|
- .map(({ offset, partition }) => {
|
|
|
|
- const offsetQuery = isBackward ? offset : offset + 1;
|
|
|
|
-
|
|
|
|
- return `${partition}::${offsetQuery}`;
|
|
|
|
- })
|
|
|
|
- .join(',');
|
|
|
|
-
|
|
|
|
- searchParams.set('seekTo', nextSeekTo);
|
|
|
|
-
|
|
|
|
- history.push({
|
|
|
|
- search: `?${searchParams.toString()}`,
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
return (
|
|
return (
|
|
- <>
|
|
|
|
- <Table isFullwidth>
|
|
|
|
- <thead>
|
|
|
|
|
|
+ <Table isFullwidth>
|
|
|
|
+ <thead>
|
|
|
|
+ <tr>
|
|
|
|
+ <TableHeaderCell> </TableHeaderCell>
|
|
|
|
+ <TableHeaderCell title="Offset" />
|
|
|
|
+ <TableHeaderCell title="Partition" />
|
|
|
|
+ <TableHeaderCell title="Timestamp" />
|
|
|
|
+ <TableHeaderCell title="Key" />
|
|
|
|
+ <TableHeaderCell title="Content" />
|
|
|
|
+ <TableHeaderCell> </TableHeaderCell>
|
|
|
|
+ </tr>
|
|
|
|
+ </thead>
|
|
|
|
+ <tbody>
|
|
|
|
+ {messages.map((message: TopicMessage) => (
|
|
|
|
+ <Message
|
|
|
|
+ key={[
|
|
|
|
+ message.offset,
|
|
|
|
+ message.timestamp,
|
|
|
|
+ message.key,
|
|
|
|
+ message.partition,
|
|
|
|
+ ].join('-')}
|
|
|
|
+ message={message}
|
|
|
|
+ />
|
|
|
|
+ ))}
|
|
|
|
+ {isFetching && isLive && !messages.length && (
|
|
|
|
+ <tr>
|
|
|
|
+ <td colSpan={10}>
|
|
|
|
+ <PageLoader />
|
|
|
|
+ </td>
|
|
|
|
+ </tr>
|
|
|
|
+ )}
|
|
|
|
+ {messages.length === 0 && !isFetching && (
|
|
<tr>
|
|
<tr>
|
|
- <TableHeaderCell> </TableHeaderCell>
|
|
|
|
- <TableHeaderCell title="Offset" />
|
|
|
|
- <TableHeaderCell title="Partition" />
|
|
|
|
- <TableHeaderCell title="Timestamp" />
|
|
|
|
- <TableHeaderCell title="Key" />
|
|
|
|
- <TableHeaderCell title="Content" />
|
|
|
|
- <TableHeaderCell> </TableHeaderCell>
|
|
|
|
|
|
+ <td colSpan={10}>No messages found</td>
|
|
</tr>
|
|
</tr>
|
|
- </thead>
|
|
|
|
- <tbody>
|
|
|
|
- {messages.map((message: TopicMessage) => (
|
|
|
|
- <Message
|
|
|
|
- key={[
|
|
|
|
- message.offset,
|
|
|
|
- message.timestamp,
|
|
|
|
- message.key,
|
|
|
|
- message.partition,
|
|
|
|
- ].join('-')}
|
|
|
|
- message={message}
|
|
|
|
- />
|
|
|
|
- ))}
|
|
|
|
- {isFetching && isLive && !messages.length && (
|
|
|
|
- <tr>
|
|
|
|
- <td colSpan={10}>
|
|
|
|
- <PageLoader />
|
|
|
|
- </td>
|
|
|
|
- </tr>
|
|
|
|
- )}
|
|
|
|
- {messages.length === 0 && !isFetching && (
|
|
|
|
- <tr>
|
|
|
|
- <td colSpan={10}>No messages found</td>
|
|
|
|
- </tr>
|
|
|
|
- )}
|
|
|
|
- </tbody>
|
|
|
|
- </Table>
|
|
|
|
- {!isLive && (
|
|
|
|
- <MessagesPaginationWrapperStyled>
|
|
|
|
- <S.PaginationButton onClick={handleNextClick}>
|
|
|
|
- Next
|
|
|
|
- </S.PaginationButton>
|
|
|
|
- </MessagesPaginationWrapperStyled>
|
|
|
|
- )}
|
|
|
|
- </>
|
|
|
|
|
|
+ )}
|
|
|
|
+ </tbody>
|
|
|
|
+ </Table>
|
|
);
|
|
);
|
|
};
|
|
};
|
|
|
|
|