Skip to content

Commit

Permalink
Get back messages pagination (#2862)
Browse files Browse the repository at this point in the history
* initial messages pagination , modification in v2

add minor test in messages table component

Add Messages pagination

add next feature in the Advanced Filters

Messages Table add Back button navigation

remove un-necessary code from the messages table

minor code refactors to remove unnecessary codes

page parameter fix in the query of the advanced Filters

minor change in the test file to keep uniformity of the project

set default table limit for first request messages v1

* pagination fix the initial disable
  • Loading branch information
Mgrdich authored Dec 23, 2022
1 parent a0a464d commit 33784e3
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ const Filters: React.FC<FiltersProps> = ({
const navigate = useNavigate();
const [searchParams] = useSearchParams();

const page = searchParams.get('page');

const { data: topic } = useTopicDetails({ clusterName, topicName });

const partitions = topic?.partitions || [];
Expand Down Expand Up @@ -202,6 +204,7 @@ const Filters: React.FC<FiltersProps> = ({
filterQueryType: queryType,
attempt: nextAttempt,
limit: PER_PAGE,
page: page || 0,
seekDirection,
keySerde: keySerde || (searchParams.get('keySerde') as string),
valueSerde: valueSerde || (searchParams.get('valueSerde') as string),
Expand Down Expand Up @@ -392,6 +395,7 @@ const Filters: React.FC<FiltersProps> = ({
timestamp,
query,
seekDirection,
page,
]);

React.useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useSerdes } from 'lib/hooks/api/topicMessages';
import useAppParams from 'lib/hooks/useAppParams';
import { RouteParamsClusterTopic } from 'lib/paths';
import { getDefaultSerdeName } from 'components/Topics/Topic/Messages/getDefaultSerdeName';
import { MESSAGES_PER_PAGE } from 'lib/constants';

import MessagesTable from './MessagesTable';
import FiltersContainer from './Filters/FiltersContainer';
Expand Down Expand Up @@ -47,6 +48,9 @@ const Messages: React.FC = () => {
if (!searchParams.get('valueSerde')) {
searchParams.set('valueSerde', getDefaultSerdeName(serdes.value || []));
}
if (!searchParams.get('limit')) {
searchParams.set('limit', MESSAGES_PER_PAGE);
}
setSearchParams(searchParams);
}, [serdes]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import {
} from 'redux/reducers/topicMessages/selectors';
import TopicMessagesContext from 'components/contexts/TopicMessagesContext';
import { useAppSelector } from 'lib/hooks/redux';
import { Button } from 'components/common/Button/Button';
import { useSearchParams } from 'react-router-dom';
import { MESSAGES_PER_PAGE } from 'lib/constants';
import * as S from 'components/common/NewTable/Table.styled';

import PreviewModal from './PreviewModal';
import Message, { PreviewFilter } from './Message';
Expand All @@ -19,75 +23,123 @@ const MessagesTable: React.FC = () => {
const [keyFilters, setKeyFilters] = useState<PreviewFilter[]>([]);
const [contentFilters, setContentFilters] = useState<PreviewFilter[]>([]);

const [searchParams, setSearchParams] = useSearchParams();
const page = searchParams.get('page');
const { isLive } = useContext(TopicMessagesContext);

const messages = useAppSelector(getTopicMessges);
const isFetching = useAppSelector(getIsTopicMessagesFetching);

const isTailing = isLive && isFetching;

// Pagination is disabled in live mode, also we don't want to show the button
// if we are fetching the messages or if we are at the end of the topic
const isPaginationDisabled = isTailing || isFetching;

const isNextPageButtonDisabled =
isPaginationDisabled || messages.length < Number(MESSAGES_PER_PAGE);
const isPrevPageButtonDisabled =
isPaginationDisabled || !Number(searchParams.get('page'));

const handleNextPage = () => {
searchParams.set('page', String(Number(page || 0) + 1));
setSearchParams(searchParams);
};

const handlePrevPage = () => {
searchParams.set('page', String(Number(page || 0) - 1));
setSearchParams(searchParams);
};

return (
<Table isFullwidth>
<thead>
<tr>
<TableHeaderCell> </TableHeaderCell>
<TableHeaderCell title="Offset" />
<TableHeaderCell title="Partition" />
<TableHeaderCell title="Timestamp" />
<TableHeaderCell
title="Key"
previewText={`Preview ${
keyFilters.length ? `(${keyFilters.length} selected)` : ''
}`}
onPreview={() => setPreviewFor('key')}
/>
<TableHeaderCell
title="Value"
previewText={`Preview ${
contentFilters.length ? `(${contentFilters.length} selected)` : ''
}`}
onPreview={() => setPreviewFor('content')}
/>
<TableHeaderCell> </TableHeaderCell>
<>
<Table isFullwidth>
<thead>
<tr>
<TableHeaderCell> </TableHeaderCell>
<TableHeaderCell title="Offset" />
<TableHeaderCell title="Partition" />
<TableHeaderCell title="Timestamp" />
<TableHeaderCell
title="Key"
previewText={`Preview ${
keyFilters.length ? `(${keyFilters.length} selected)` : ''
}`}
onPreview={() => setPreviewFor('key')}
/>
<TableHeaderCell
title="Value"
previewText={`Preview ${
contentFilters.length
? `(${contentFilters.length} selected)`
: ''
}`}
onPreview={() => setPreviewFor('content')}
/>
<TableHeaderCell> </TableHeaderCell>

{previewFor !== null && (
<PreviewModal
values={previewFor === 'key' ? keyFilters : contentFilters}
toggleIsOpen={() => setPreviewFor(null)}
setFilters={(payload: PreviewFilter[]) =>
previewFor === 'key'
? setKeyFilters(payload)
: setContentFilters(payload)
}
{previewFor !== null && (
<PreviewModal
values={previewFor === 'key' ? keyFilters : contentFilters}
toggleIsOpen={() => setPreviewFor(null)}
setFilters={(payload: PreviewFilter[]) =>
previewFor === 'key'
? setKeyFilters(payload)
: setContentFilters(payload)
}
/>
)}
</tr>
</thead>
<tbody>
{messages.map((message: TopicMessage) => (
<Message
key={[
message.offset,
message.timestamp,
message.key,
message.partition,
].join('-')}
message={message}
keyFilters={keyFilters}
contentFilters={contentFilters}
/>
))}
{isFetching && isLive && !messages.length && (
<tr>
<td colSpan={10}>
<PageLoader />
</td>
</tr>
)}
</tr>
</thead>
<tbody>
{messages.map((message: TopicMessage) => (
<Message
key={[
message.offset,
message.timestamp,
message.key,
message.partition,
].join('-')}
message={message}
keyFilters={keyFilters}
contentFilters={contentFilters}
/>
))}
{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>
{messages.length === 0 && !isFetching && (
<tr>
<td colSpan={10}>No messages found</td>
</tr>
)}
</tbody>
</Table>
<S.Pagination>
<S.Pages>
<Button
buttonType="secondary"
buttonSize="L"
disabled={isPrevPageButtonDisabled}
onClick={handlePrevPage}
>
← Back
</Button>
<Button
buttonType="secondary"
buttonSize="L"
disabled={isNextPageButtonDisabled}
onClick={handleNextPage}
>
Next →
</Button>
</S.Pages>
</S.Pagination>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@ describe('MessagesTable', () => {
});

describe('Custom Setup with different props value', () => {
it('should check if next click is gone during isLive Param', () => {
it('should check if next button and previous is disabled isLive Param', () => {
setUpComponent(searchParams, { ...contextValue, isLive: true });
expect(screen.queryByText(/next/i)).not.toBeInTheDocument();
expect(screen.queryByText(/next/i)).toBeDisabled();
expect(screen.queryByText(/back/i)).toBeDisabled();
});

it('should check the display of the loader element', () => {
Expand Down

0 comments on commit 33784e3

Please sign in to comment.