diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Messages/Filters/Filters.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Messages/Filters/Filters.tsx index 0e3d3d46614..096a714c4ee 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Messages/Filters/Filters.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Messages/Filters/Filters.tsx @@ -93,6 +93,8 @@ const Filters: React.FC = ({ const navigate = useNavigate(); const [searchParams] = useSearchParams(); + const page = searchParams.get('page'); + const { data: topic } = useTopicDetails({ clusterName, topicName }); const partitions = topic?.partitions || []; @@ -202,6 +204,7 @@ const Filters: React.FC = ({ 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), @@ -392,6 +395,7 @@ const Filters: React.FC = ({ timestamp, query, seekDirection, + page, ]); React.useEffect(() => { diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Messages/Messages.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Messages/Messages.tsx index b71e4eb8fa2..35490c627e3 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Messages/Messages.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Messages/Messages.tsx @@ -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'; @@ -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]); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessagesTable.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessagesTable.tsx index 3c5901214b0..96e9f40d73d 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessagesTable.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Messages/MessagesTable.tsx @@ -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'; @@ -19,75 +23,123 @@ const MessagesTable: React.FC = () => { const [keyFilters, setKeyFilters] = useState([]); const [contentFilters, setContentFilters] = useState([]); + 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 ( - - - - - - - - setPreviewFor('key')} - /> - setPreviewFor('content')} - /> - + <> +
+ + + + + + + setPreviewFor('key')} + /> + setPreviewFor('content')} + /> + - {previewFor !== null && ( - setPreviewFor(null)} - setFilters={(payload: PreviewFilter[]) => - previewFor === 'key' - ? setKeyFilters(payload) - : setContentFilters(payload) - } + {previewFor !== null && ( + setPreviewFor(null)} + setFilters={(payload: PreviewFilter[]) => + previewFor === 'key' + ? setKeyFilters(payload) + : setContentFilters(payload) + } + /> + )} + + + + {messages.map((message: TopicMessage) => ( + + ))} + {isFetching && isLive && !messages.length && ( + + + )} - - - - {messages.map((message: TopicMessage) => ( - - ))} - {isFetching && isLive && !messages.length && ( - - - - )} - {messages.length === 0 && !isFetching && ( - - - - )} - -
+ +
- -
No messages found
+ {messages.length === 0 && !isFetching && ( + + No messages found + + )} + + + + + + + + + ); }; diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Messages/__test__/MessagesTable.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Messages/__test__/MessagesTable.spec.tsx index 37ad28b202b..e2aeb68bbba 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Messages/__test__/MessagesTable.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Messages/__test__/MessagesTable.spec.tsx @@ -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', () => {