Commit b0d6ac5f by Andrej Ocenas Committed by GitHub

Explore: Refactor live tail controls (#19328)

parent 22c64018
......@@ -14,7 +14,6 @@ import {
DataQuery,
Tooltip,
ButtonSelect,
RefreshPicker,
SetInterval,
} from '@grafana/ui';
import { RawTimeRange, TimeZone, TimeRange, SelectableValue } from '@grafana/data';
......@@ -30,7 +29,6 @@ import {
changeMode,
clearOrigin,
} from './state/actions';
import { changeRefreshIntervalAction, setPausedStateAction } from './state/actionTypes';
import { updateLocation } from 'app/core/actions';
import { getTimeZone } from '../profile/state/selectors';
import { getDashboardSrv } from '../dashboard/services/DashboardSrv';
......@@ -39,6 +37,7 @@ import { ExploreTimeControls } from './ExploreTimeControls';
import { LiveTailButton } from './LiveTailButton';
import { ResponsiveButton } from './ResponsiveButton';
import { RunButton } from './RunButton';
import { LiveTailControls } from './useLiveTailControls';
const getStyles = memoizeOne(() => {
return {
......@@ -81,8 +80,6 @@ interface DispatchProps {
changeMode: typeof changeMode;
clearOrigin: typeof clearOrigin;
updateLocation: typeof updateLocation;
changeRefreshIntervalAction: typeof changeRefreshIntervalAction;
setPausedStateAction: typeof setPausedStateAction;
}
type Props = StateProps & DispatchProps & OwnProps;
......@@ -139,29 +136,6 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
});
};
stopLive = () => {
const { exploreId } = this.props;
this.pauseLive();
// TODO referencing this from perspective of refresh picker when there is designated button for it now is not
// great. Needs another refactor.
this.props.changeRefreshIntervalAction({ exploreId, refreshInterval: RefreshPicker.offOption.value });
};
startLive = () => {
const { exploreId } = this.props;
this.props.changeRefreshIntervalAction({ exploreId, refreshInterval: RefreshPicker.liveOption.value });
};
pauseLive = () => {
const { exploreId } = this.props;
this.props.setPausedStateAction({ exploreId, isPaused: true });
};
resumeLive = () => {
const { exploreId } = this.props;
this.props.setPausedStateAction({ exploreId, isPaused: false });
};
render() {
const {
datasourceMissing,
......@@ -305,14 +279,18 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
{hasLiveOption && (
<div className={`explore-toolbar-content-item ${styles.liveTailButtons}`}>
<LiveTailButton
isLive={isLive}
isPaused={isPaused}
start={this.startLive}
pause={this.pauseLive}
resume={this.resumeLive}
stop={this.stopLive}
/>
<LiveTailControls exploreId={exploreId}>
{controls => (
<LiveTailButton
isLive={isLive}
isPaused={isPaused}
start={controls.start}
pause={controls.pause}
resume={controls.resume}
stop={controls.stop}
/>
)}
</LiveTailControls>
</div>
)}
</div>
......@@ -411,8 +389,6 @@ const mapDispatchToProps: DispatchProps = {
split: splitOpen,
changeMode: changeMode,
clearOrigin,
changeRefreshIntervalAction,
setPausedStateAction,
};
export const ExploreToolbar = hot(module)(
......
import React, { PureComponent } from 'react';
import { hot } from 'react-hot-loader';
import { connect } from 'react-redux';
import { DataSourceApi, Collapse, RefreshPicker } from '@grafana/ui';
import { DataSourceApi, Collapse } from '@grafana/ui';
import {
RawTimeRange,
......@@ -18,16 +18,13 @@ import { ExploreId, ExploreItemState } from 'app/types/explore';
import { StoreState } from 'app/types';
import { changeDedupStrategy, updateTimeRange } from './state/actions';
import {
toggleLogLevelAction,
changeRefreshIntervalAction,
setPausedStateAction,
} from 'app/features/explore/state/actionTypes';
import { toggleLogLevelAction } from 'app/features/explore/state/actionTypes';
import { deduplicatedLogsSelector, exploreItemUIStateSelector } from 'app/features/explore/state/selectors';
import { getTimeZone } from '../profile/state/selectors';
import { LiveLogsWithTheme } from './LiveLogs';
import { Logs } from './Logs';
import { LogsCrossFadeTransition } from './utils/LogsCrossFadeTransition';
import { LiveTailControls } from './useLiveTailControls';
interface LogsContainerProps {
datasourceInstance: DataSourceApi | null;
......@@ -48,11 +45,9 @@ interface LogsContainerProps {
dedupStrategy: LogsDedupStrategy;
width: number;
isLive: boolean;
stopLive: typeof changeRefreshIntervalAction;
updateTimeRange: typeof updateTimeRange;
range: TimeRange;
absoluteRange: AbsoluteTimeRange;
setPausedStateAction: typeof setPausedStateAction;
isPaused: boolean;
}
......@@ -63,22 +58,6 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
updateTimeRange({ exploreId, absoluteRange });
};
onStopLive = () => {
const { exploreId } = this.props;
this.onPause();
this.props.stopLive({ exploreId, refreshInterval: RefreshPicker.offOption.value });
};
onPause = () => {
const { exploreId } = this.props;
this.props.setPausedStateAction({ exploreId, isPaused: true });
};
onResume = () => {
const { exploreId } = this.props;
this.props.setPausedStateAction({ exploreId, isPaused: false });
};
handleDedupStrategyChange = (dedupStrategy: LogsDedupStrategy) => {
this.props.changeDedupStrategy(this.props.exploreId, dedupStrategy);
};
......@@ -116,20 +95,25 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
range,
width,
isLive,
exploreId,
} = this.props;
return (
<>
<LogsCrossFadeTransition visible={isLive}>
<Collapse label="Logs" loading={false} isOpen>
<LiveLogsWithTheme
logsResult={logsResult}
timeZone={timeZone}
stopLive={this.onStopLive}
isPaused={this.props.isPaused}
onPause={this.onPause}
onResume={this.onResume}
/>
<LiveTailControls exploreId={exploreId}>
{controls => (
<LiveLogsWithTheme
logsResult={logsResult}
timeZone={timeZone}
stopLive={controls.stop}
isPaused={this.props.isPaused}
onPause={controls.pause}
onResume={controls.resume}
/>
)}
</LiveTailControls>
</Collapse>
</LogsCrossFadeTransition>
<LogsCrossFadeTransition visible={!isLive}>
......@@ -198,9 +182,7 @@ function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }
const mapDispatchToProps = {
changeDedupStrategy,
toggleLogLevelAction,
stopLive: changeRefreshIntervalAction,
updateTimeRange,
setPausedStateAction,
};
export default hot(module)(
......
import React, { useCallback } from 'react';
import { useDispatch } from 'react-redux';
import { changeRefreshInterval } from './state/actions';
import { setPausedStateAction } from './state/actionTypes';
import { RefreshPicker } from '@grafana/ui';
import { ExploreId } from '../../types';
/**
* Hook that gives you all the functions needed to control the live tailing.
*/
export function useLiveTailControls(exploreId: ExploreId) {
const dispatch = useDispatch();
const pause = useCallback(() => {
dispatch(setPausedStateAction({ exploreId, isPaused: true }));
}, [exploreId, dispatch]);
const resume = useCallback(() => {
dispatch(setPausedStateAction({ exploreId, isPaused: false }));
}, [exploreId, dispatch]);
const stop = useCallback(() => {
// We need to pause here first because there is transition where we are not live but live logs are still shown
// to cross fade with the normal view. This will prevent reordering of the logs in the live view during the
// transition.
pause();
// TODO referencing this from perspective of refresh picker when there is designated button for it now is not
// great. Needs a bit of refactoring.
dispatch(changeRefreshInterval(exploreId, RefreshPicker.offOption.value));
}, [exploreId, dispatch, pause]);
const start = useCallback(() => {
dispatch(changeRefreshInterval(exploreId, RefreshPicker.liveOption.value));
}, [exploreId, dispatch]);
return {
pause,
resume,
stop,
start,
};
}
type Props = {
exploreId: ExploreId;
children: (controls: ReturnType<typeof useLiveTailControls>) => React.ReactElement;
};
/**
* If you can't use the hook you can use this as a render prop pattern.
*/
export function LiveTailControls(props: Props) {
const controls = useLiveTailControls(props.exploreId);
return props.children(controls);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment