Skip to content

Commit 33784e3

Browse files
authored
Get back messages pagination (#2862)
* 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
1 parent a0a464d commit 33784e3

File tree

4 files changed

+124
-63
lines changed

4 files changed

+124
-63
lines changed

kafka-ui-react-app/src/components/Topics/Topic/Messages/Filters/Filters.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ const Filters: React.FC<FiltersProps> = ({
9393
const navigate = useNavigate();
9494
const [searchParams] = useSearchParams();
9595

96+
const page = searchParams.get('page');
97+
9698
const { data: topic } = useTopicDetails({ clusterName, topicName });
9799

98100
const partitions = topic?.partitions || [];
@@ -202,6 +204,7 @@ const Filters: React.FC<FiltersProps> = ({
202204
filterQueryType: queryType,
203205
attempt: nextAttempt,
204206
limit: PER_PAGE,
207+
page: page || 0,
205208
seekDirection,
206209
keySerde: keySerde || (searchParams.get('keySerde') as string),
207210
valueSerde: valueSerde || (searchParams.get('valueSerde') as string),
@@ -392,6 +395,7 @@ const Filters: React.FC<FiltersProps> = ({
392395
timestamp,
393396
query,
394397
seekDirection,
398+
page,
395399
]);
396400

397401
React.useEffect(() => {

kafka-ui-react-app/src/components/Topics/Topic/Messages/Messages.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { useSerdes } from 'lib/hooks/api/topicMessages';
66
import useAppParams from 'lib/hooks/useAppParams';
77
import { RouteParamsClusterTopic } from 'lib/paths';
88
import { getDefaultSerdeName } from 'components/Topics/Topic/Messages/getDefaultSerdeName';
9+
import { MESSAGES_PER_PAGE } from 'lib/constants';
910

1011
import MessagesTable from './MessagesTable';
1112
import FiltersContainer from './Filters/FiltersContainer';
@@ -47,6 +48,9 @@ const Messages: React.FC = () => {
4748
if (!searchParams.get('valueSerde')) {
4849
searchParams.set('valueSerde', getDefaultSerdeName(serdes.value || []));
4950
}
51+
if (!searchParams.get('limit')) {
52+
searchParams.set('limit', MESSAGES_PER_PAGE);
53+
}
5054
setSearchParams(searchParams);
5155
}, [serdes]);
5256

kafka-ui-react-app/src/components/Topics/Topic/Messages/MessagesTable.tsx

Lines changed: 113 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import {
99
} from 'redux/reducers/topicMessages/selectors';
1010
import TopicMessagesContext from 'components/contexts/TopicMessagesContext';
1111
import { useAppSelector } from 'lib/hooks/redux';
12+
import { Button } from 'components/common/Button/Button';
13+
import { useSearchParams } from 'react-router-dom';
14+
import { MESSAGES_PER_PAGE } from 'lib/constants';
15+
import * as S from 'components/common/NewTable/Table.styled';
1216

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

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

2430
const messages = useAppSelector(getTopicMessges);
2531
const isFetching = useAppSelector(getIsTopicMessagesFetching);
32+
33+
const isTailing = isLive && isFetching;
34+
35+
// Pagination is disabled in live mode, also we don't want to show the button
36+
// if we are fetching the messages or if we are at the end of the topic
37+
const isPaginationDisabled = isTailing || isFetching;
38+
39+
const isNextPageButtonDisabled =
40+
isPaginationDisabled || messages.length < Number(MESSAGES_PER_PAGE);
41+
const isPrevPageButtonDisabled =
42+
isPaginationDisabled || !Number(searchParams.get('page'));
43+
44+
const handleNextPage = () => {
45+
searchParams.set('page', String(Number(page || 0) + 1));
46+
setSearchParams(searchParams);
47+
};
48+
49+
const handlePrevPage = () => {
50+
searchParams.set('page', String(Number(page || 0) - 1));
51+
setSearchParams(searchParams);
52+
};
53+
2654
return (
27-
<Table isFullwidth>
28-
<thead>
29-
<tr>
30-
<TableHeaderCell> </TableHeaderCell>
31-
<TableHeaderCell title="Offset" />
32-
<TableHeaderCell title="Partition" />
33-
<TableHeaderCell title="Timestamp" />
34-
<TableHeaderCell
35-
title="Key"
36-
previewText={`Preview ${
37-
keyFilters.length ? `(${keyFilters.length} selected)` : ''
38-
}`}
39-
onPreview={() => setPreviewFor('key')}
40-
/>
41-
<TableHeaderCell
42-
title="Value"
43-
previewText={`Preview ${
44-
contentFilters.length ? `(${contentFilters.length} selected)` : ''
45-
}`}
46-
onPreview={() => setPreviewFor('content')}
47-
/>
48-
<TableHeaderCell> </TableHeaderCell>
55+
<>
56+
<Table isFullwidth>
57+
<thead>
58+
<tr>
59+
<TableHeaderCell> </TableHeaderCell>
60+
<TableHeaderCell title="Offset" />
61+
<TableHeaderCell title="Partition" />
62+
<TableHeaderCell title="Timestamp" />
63+
<TableHeaderCell
64+
title="Key"
65+
previewText={`Preview ${
66+
keyFilters.length ? `(${keyFilters.length} selected)` : ''
67+
}`}
68+
onPreview={() => setPreviewFor('key')}
69+
/>
70+
<TableHeaderCell
71+
title="Value"
72+
previewText={`Preview ${
73+
contentFilters.length
74+
? `(${contentFilters.length} selected)`
75+
: ''
76+
}`}
77+
onPreview={() => setPreviewFor('content')}
78+
/>
79+
<TableHeaderCell> </TableHeaderCell>
4980

50-
{previewFor !== null && (
51-
<PreviewModal
52-
values={previewFor === 'key' ? keyFilters : contentFilters}
53-
toggleIsOpen={() => setPreviewFor(null)}
54-
setFilters={(payload: PreviewFilter[]) =>
55-
previewFor === 'key'
56-
? setKeyFilters(payload)
57-
: setContentFilters(payload)
58-
}
81+
{previewFor !== null && (
82+
<PreviewModal
83+
values={previewFor === 'key' ? keyFilters : contentFilters}
84+
toggleIsOpen={() => setPreviewFor(null)}
85+
setFilters={(payload: PreviewFilter[]) =>
86+
previewFor === 'key'
87+
? setKeyFilters(payload)
88+
: setContentFilters(payload)
89+
}
90+
/>
91+
)}
92+
</tr>
93+
</thead>
94+
<tbody>
95+
{messages.map((message: TopicMessage) => (
96+
<Message
97+
key={[
98+
message.offset,
99+
message.timestamp,
100+
message.key,
101+
message.partition,
102+
].join('-')}
103+
message={message}
104+
keyFilters={keyFilters}
105+
contentFilters={contentFilters}
59106
/>
107+
))}
108+
{isFetching && isLive && !messages.length && (
109+
<tr>
110+
<td colSpan={10}>
111+
<PageLoader />
112+
</td>
113+
</tr>
60114
)}
61-
</tr>
62-
</thead>
63-
<tbody>
64-
{messages.map((message: TopicMessage) => (
65-
<Message
66-
key={[
67-
message.offset,
68-
message.timestamp,
69-
message.key,
70-
message.partition,
71-
].join('-')}
72-
message={message}
73-
keyFilters={keyFilters}
74-
contentFilters={contentFilters}
75-
/>
76-
))}
77-
{isFetching && isLive && !messages.length && (
78-
<tr>
79-
<td colSpan={10}>
80-
<PageLoader />
81-
</td>
82-
</tr>
83-
)}
84-
{messages.length === 0 && !isFetching && (
85-
<tr>
86-
<td colSpan={10}>No messages found</td>
87-
</tr>
88-
)}
89-
</tbody>
90-
</Table>
115+
{messages.length === 0 && !isFetching && (
116+
<tr>
117+
<td colSpan={10}>No messages found</td>
118+
</tr>
119+
)}
120+
</tbody>
121+
</Table>
122+
<S.Pagination>
123+
<S.Pages>
124+
<Button
125+
buttonType="secondary"
126+
buttonSize="L"
127+
disabled={isPrevPageButtonDisabled}
128+
onClick={handlePrevPage}
129+
>
130+
← Back
131+
</Button>
132+
<Button
133+
buttonType="secondary"
134+
buttonSize="L"
135+
disabled={isNextPageButtonDisabled}
136+
onClick={handleNextPage}
137+
>
138+
Next →
139+
</Button>
140+
</S.Pages>
141+
</S.Pagination>
142+
</>
91143
);
92144
};
93145

kafka-ui-react-app/src/components/Topics/Topic/Messages/__test__/MessagesTable.spec.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,10 @@ describe('MessagesTable', () => {
8585
});
8686

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

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

0 commit comments

Comments
 (0)