From fb34916d1e126e8ff86803481eb1ab8ee16617fc Mon Sep 17 00:00:00 2001 From: Matias Chomicki Date: Tue, 9 Jan 2024 10:49:27 +0100 Subject: [PATCH] Logs navigation: derive current page index (#80167) * Logs navigation: derive current page index * Formatting --- .../explore/Logs/LogsNavigation.test.tsx | 37 +++++++++++++++++++ .../features/explore/Logs/LogsNavigation.tsx | 18 ++++----- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/public/app/features/explore/Logs/LogsNavigation.test.tsx b/public/app/features/explore/Logs/LogsNavigation.test.tsx index d045191b060..3e0e2178745 100644 --- a/public/app/features/explore/Logs/LogsNavigation.test.tsx +++ b/public/app/features/explore/Logs/LogsNavigation.test.tsx @@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event'; import React, { ComponentProps } from 'react'; import { LogsSortOrder } from '@grafana/data'; +import { DataQuery } from '@grafana/schema'; import LogsNavigation from './LogsNavigation'; @@ -93,6 +94,42 @@ describe('LogsNavigation', () => { expect(onChangeTimeMock).toHaveBeenCalledWith({ from: 1637319338000, to: 1637322938000 }); }); + it('should correctly display the active page', async () => { + const queries: DataQuery[] = []; + const { rerender } = setup({ + absoluteRange: { from: 1704737384139, to: 1704737684139 }, + visibleRange: { from: 1704737384207, to: 1704737683316 }, + queries, + logsSortOrder: LogsSortOrder.Descending, + }); + + expect(await screen.findByTestId('page1')).toBeInTheDocument(); + expect(screen.getByTestId('page1').firstChild).toHaveClass('selectedBg'); + + expect(screen.queryByTestId('page2')).not.toBeInTheDocument(); + + await userEvent.click(screen.getByTestId('olderLogsButton')); + + rerender( + + ); + + expect(await screen.findByTestId('page1')).toBeInTheDocument(); + expect(screen.getByTestId('page1').firstChild).not.toHaveClass('selectedBg'); + + expect(await screen.findByTestId('page2')).toBeInTheDocument(); + expect(screen.getByTestId('page2').firstChild).toHaveClass('selectedBg'); + + expect(screen.queryByTestId('page3')).not.toBeInTheDocument(); + }); + it('should reset the scroll when pagination is clicked', async () => { const scrollToTopLogsMock = jest.fn(); setup({ scrollToTopLogs: scrollToTopLogsMock }); diff --git a/public/app/features/explore/Logs/LogsNavigation.tsx b/public/app/features/explore/Logs/LogsNavigation.tsx index 0c731315dd3..f9f498a566a 100644 --- a/public/app/features/explore/Logs/LogsNavigation.tsx +++ b/public/app/features/explore/Logs/LogsNavigation.tsx @@ -1,6 +1,6 @@ import { css } from '@emotion/css'; import { isEqual } from 'lodash'; -import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; +import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { AbsoluteTimeRange, GrafanaTheme2, LogsSortOrder } from '@grafana/data'; import { reportInteraction } from '@grafana/runtime'; @@ -41,7 +41,6 @@ function LogsNavigation({ addResultsToCache, }: Props) { const [pages, setPages] = useState([]); - const [currentPageIndex, setCurrentPageIndex] = useState(0); // These refs are to determine, if we want to clear up logs navigation when totally new query is run const expectedQueriesRef = useRef(); @@ -50,6 +49,14 @@ function LogsNavigation({ // e.g. if last 5 min selected, always run 5 min range const rangeSpanRef = useRef(0); + const currentPageIndex = useMemo( + () => + pages.findIndex((page) => { + return page.queryRange.to === absoluteRange.to; + }), + [absoluteRange.to, pages] + ); + const oldestLogsFirst = logsSortOrder === LogsSortOrder.Ascending; const onFirstPage = oldestLogsFirst ? currentPageIndex === pages.length - 1 : currentPageIndex === 0; const onLastPage = oldestLogsFirst ? currentPageIndex === 0 : currentPageIndex === pages.length - 1; @@ -64,7 +71,6 @@ function LogsNavigation({ if (!isEqual(expectedRangeRef.current, absoluteRange) || !isEqual(expectedQueriesRef.current, queries)) { clearCache(); setPages([newPage]); - setCurrentPageIndex(0); expectedQueriesRef.current = queries; rangeSpanRef.current = absoluteRange.to - absoluteRange.from; } else { @@ -73,14 +79,8 @@ function LogsNavigation({ newPages = pages.filter((page) => !isEqual(newPage.queryRange, page.queryRange)); // Sort pages based on logsOrder so they visually align with displayed logs newPages = [...newPages, newPage].sort((a, b) => sortPages(a, b, logsSortOrder)); - // Set new pages - return newPages; }); - - // Set current page index - const index = newPages.findIndex((page) => page.queryRange.to === absoluteRange.to); - setCurrentPageIndex(index); } addResultsToCache(); }, [visibleRange, absoluteRange, logsSortOrder, queries, clearCache, addResultsToCache]);