mirror of
https://github.com/grafana/grafana.git
synced 2025-01-27 16:57:14 -06:00
Explore: Refactor live tail controls (#19328)
This commit is contained in:
parent
22c6401867
commit
b0d6ac5f42
@ -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)(
|
||||
|
@ -1,7 +1,7 @@
|
||||
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)(
|
||||
|
57
public/app/features/explore/useLiveTailControls.ts
Normal file
57
public/app/features/explore/useLiveTailControls.ts
Normal file
@ -0,0 +1,57 @@
|
||||
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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user