diff --git a/public/app/features/explore/Logs/Logs.tsx b/public/app/features/explore/Logs/Logs.tsx index 0d44edaad47..5ff5719cda8 100644 --- a/public/app/features/explore/Logs/Logs.tsx +++ b/public/app/features/explore/Logs/Logs.tsx @@ -1,4 +1,4 @@ -import { css } from '@emotion/css'; +import { css, cx } from '@emotion/css'; import { capitalize } from 'lodash'; import memoizeOne from 'memoize-one'; import React, { createRef, PureComponent } from 'react'; @@ -59,7 +59,7 @@ import { changePanelState } from '../state/explorePane'; import { LogsMetaRow } from './LogsMetaRow'; import LogsNavigation from './LogsNavigation'; -import { LogsTableWrap } from './LogsTableWrap'; +import { getLogsTableHeight, LogsTableWrap } from './LogsTableWrap'; import { LogsVolumePanelList } from './LogsVolumePanelList'; import { SETTINGS_KEYS } from './utils/logs'; @@ -543,7 +543,8 @@ class UnthemedLogs extends PureComponent { contextRow, } = this.state; - const styles = getStyles(theme, wrapLogMessage); + const tableHeight = getLogsTableHeight(); + const styles = getStyles(theme, wrapLogMessage, tableHeight); const hasData = logRows && logRows.length > 0; const hasUnescapedContent = this.checkUnescapedContent(logRows); @@ -727,7 +728,9 @@ class UnthemedLogs extends PureComponent { clearDetectedFields={this.clearDetectedFields} /> -
+
{this.state.visualisationType === 'table' && hasData && (
{/* Width should be full width minus logs navigation and padding */} @@ -821,7 +824,7 @@ class UnthemedLogs extends PureComponent { export const Logs = withTheme2(UnthemedLogs); -const getStyles = (theme: GrafanaTheme2, wrapLogMessage: boolean) => { +const getStyles = (theme: GrafanaTheme2, wrapLogMessage: boolean, tableHeight: number) => { return { noData: css` > * { @@ -858,6 +861,9 @@ const getStyles = (theme: GrafanaTheme2, wrapLogMessage: boolean) => { flex-direction: row; justify-content: space-between; `, + logsTable: css({ + maxHeight: `${tableHeight}px`, + }), logRows: css` overflow-x: ${scrollableLogsContainer ? 'scroll;' : `${wrapLogMessage ? 'unset' : 'scroll'};`} overflow-y: visible; diff --git a/public/app/features/explore/Logs/LogsTableWrap.test.tsx b/public/app/features/explore/Logs/LogsTableWrap.test.tsx index c6e574dc5e6..fea39488c4f 100644 --- a/public/app/features/explore/Logs/LogsTableWrap.test.tsx +++ b/public/app/features/explore/Logs/LogsTableWrap.test.tsx @@ -139,6 +139,27 @@ describe('LogsTableWrap', () => { }); }); + it('should update selected dataframe when dataFrames update', async () => { + const initialProps = { logsFrames: [getMockLokiFrameDataPlane(undefined, 3)] }; + const render = setup(initialProps); + await waitFor(() => { + const rows = render.getAllByRole('row'); + expect(rows.length).toBe(4); + }); + + render.rerender( + getComponent({ + ...initialProps, + logsFrames: [getMockLokiFrameDataPlane(undefined, 4)], + }) + ); + + await waitFor(() => { + const rows = render.getAllByRole('row'); + expect(rows.length).toBe(5); + }); + }); + it('search input should search matching columns (dataplane)', async () => { config.featureToggles.lokiLogsDataplane = true; diff --git a/public/app/features/explore/Logs/LogsTableWrap.tsx b/public/app/features/explore/Logs/LogsTableWrap.tsx index 4fbc12ebbc7..2e898c4379e 100644 --- a/public/app/features/explore/Logs/LogsTableWrap.tsx +++ b/public/app/features/explore/Logs/LogsTableWrap.tsx @@ -52,14 +52,13 @@ export function LogsTableWrap(props: Props) { // Filtered copy of columnsWithMeta that only includes matching results const [filteredColumnsWithMeta, setFilteredColumnsWithMeta] = useState(undefined); - const height = getTableHeight(); + const height = getLogsTableHeight(); + const panelStateRefId = props?.panelState?.refId; // The current dataFrame containing the refId of the current query const [currentDataFrame, setCurrentDataFrame] = useState( - logsFrames.find((f) => f.refId === props?.panelState?.refId) ?? logsFrames[0] + logsFrames.find((f) => f.refId === panelStateRefId) ?? logsFrames[0] ); - // The refId of the current frame being displayed - const currentFrameRefId = currentDataFrame.refId; const getColumnsFromProps = useCallback( (fieldNames: fieldNameMetaStore) => { @@ -76,6 +75,16 @@ export function LogsTableWrap(props: Props) { [props.panelState?.columns] ); + /** + * When logs frame updates (e.g. query|range changes), we need to set the selected frame to state + */ + useEffect(() => { + const newFrame = logsFrames.find((f) => f.refId === panelStateRefId) ?? logsFrames[0]; + if (newFrame) { + setCurrentDataFrame(newFrame); + } + }, [logsFrames, panelStateRefId]); + /** * Keeps the filteredColumnsWithMeta state in sync with the columnsWithMeta state, * which can be updated by explore browser history state changes @@ -336,7 +345,7 @@ export function LogsTableWrap(props: Props) {