|
|
@@ -5,8 +5,17 @@ import { hot } from 'react-hot-loader';
|
|
|
import memoizeOne from 'memoize-one';
|
|
|
import classNames from 'classnames';
|
|
|
|
|
|
-import { ExploreId, ExploreMode } from 'app/types/explore';
|
|
|
-import { DataSourceSelectItem, ToggleButtonGroup, ToggleButton, DataQuery, Tooltip, ButtonSelect } from '@grafana/ui';
|
|
|
+import { ExploreId, ExploreItemState, ExploreMode } from 'app/types/explore';
|
|
|
+import {
|
|
|
+ DataSourceSelectItem,
|
|
|
+ ToggleButtonGroup,
|
|
|
+ ToggleButton,
|
|
|
+ DataQuery,
|
|
|
+ Tooltip,
|
|
|
+ ButtonSelect,
|
|
|
+ RefreshPicker,
|
|
|
+ SetInterval,
|
|
|
+} from '@grafana/ui';
|
|
|
import { RawTimeRange, TimeZone, TimeRange, SelectableValue } from '@grafana/data';
|
|
|
import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker';
|
|
|
import { StoreState } from 'app/types/store';
|
|
|
@@ -20,44 +29,15 @@ 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';
|
|
|
import kbn from '../../core/utils/kbn';
|
|
|
import { ExploreTimeControls } from './ExploreTimeControls';
|
|
|
-
|
|
|
-enum IconSide {
|
|
|
- left = 'left',
|
|
|
- right = 'right',
|
|
|
-}
|
|
|
-
|
|
|
-const createResponsiveButton = (options: {
|
|
|
- splitted: boolean;
|
|
|
- title: string;
|
|
|
- onClick: () => void;
|
|
|
- buttonClassName?: string;
|
|
|
- iconClassName?: string;
|
|
|
- iconSide?: IconSide;
|
|
|
- disabled?: boolean;
|
|
|
-}) => {
|
|
|
- const defaultOptions = {
|
|
|
- iconSide: IconSide.left,
|
|
|
- };
|
|
|
- const props = { ...options, defaultOptions };
|
|
|
- const { title, onClick, buttonClassName, iconClassName, splitted, iconSide, disabled } = props;
|
|
|
-
|
|
|
- return (
|
|
|
- <button
|
|
|
- className={`btn navbar-button ${buttonClassName ? buttonClassName : ''}`}
|
|
|
- onClick={onClick}
|
|
|
- disabled={disabled || false}
|
|
|
- >
|
|
|
- {iconClassName && iconSide === IconSide.left ? <i className={`${iconClassName}`} /> : null}
|
|
|
- <span className="btn-title">{!splitted ? title : ''}</span>
|
|
|
- {iconClassName && iconSide === IconSide.right ? <i className={`${iconClassName}`} /> : null}
|
|
|
- </button>
|
|
|
- );
|
|
|
-};
|
|
|
+import { LiveTailButton } from './LiveTailButton';
|
|
|
+import { ResponsiveButton } from './ResponsiveButton';
|
|
|
+import { RunButton } from './RunButton';
|
|
|
|
|
|
interface OwnProps {
|
|
|
exploreId: ExploreId;
|
|
|
@@ -77,6 +57,7 @@ interface StateProps {
|
|
|
selectedModeOption: SelectableValue<ExploreMode>;
|
|
|
hasLiveOption: boolean;
|
|
|
isLive: boolean;
|
|
|
+ isPaused: boolean;
|
|
|
originPanelId: number;
|
|
|
queries: DataQuery[];
|
|
|
}
|
|
|
@@ -91,6 +72,8 @@ interface DispatchProps {
|
|
|
changeMode: typeof changeMode;
|
|
|
clearOrigin: typeof clearOrigin;
|
|
|
updateLocation: typeof updateLocation;
|
|
|
+ changeRefreshIntervalAction: typeof changeRefreshIntervalAction;
|
|
|
+ setPausedStateAction: typeof setPausedStateAction;
|
|
|
}
|
|
|
|
|
|
type Props = StateProps & DispatchProps & OwnProps;
|
|
|
@@ -147,6 +130,28 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
|
|
|
});
|
|
|
};
|
|
|
|
|
|
+ stopLive = () => {
|
|
|
+ const { exploreId } = this.props;
|
|
|
+ // 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,
|
|
|
@@ -165,6 +170,7 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
|
|
|
selectedModeOption,
|
|
|
hasLiveOption,
|
|
|
isLive,
|
|
|
+ isPaused,
|
|
|
originPanelId,
|
|
|
} = this.props;
|
|
|
|
|
|
@@ -249,30 +255,25 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
|
|
|
|
|
|
{exploreId === 'left' && !splitted ? (
|
|
|
<div className="explore-toolbar-content-item">
|
|
|
- {createResponsiveButton({
|
|
|
- splitted,
|
|
|
- title: 'Split',
|
|
|
- onClick: split,
|
|
|
- iconClassName: 'fa fa-fw fa-columns icon-margin-right',
|
|
|
- iconSide: IconSide.left,
|
|
|
- disabled: isLive,
|
|
|
- })}
|
|
|
+ <ResponsiveButton
|
|
|
+ splitted={splitted}
|
|
|
+ title="Split"
|
|
|
+ onClick={split}
|
|
|
+ iconClassName="fa fa-fw fa-columns icon-margin-right"
|
|
|
+ disabled={isLive}
|
|
|
+ />
|
|
|
</div>
|
|
|
) : null}
|
|
|
- <div className="explore-toolbar-content-item">
|
|
|
- <ExploreTimeControls
|
|
|
- exploreId={exploreId}
|
|
|
- hasLiveOption={hasLiveOption}
|
|
|
- isLive={isLive}
|
|
|
- loading={loading}
|
|
|
- range={range}
|
|
|
- refreshInterval={refreshInterval}
|
|
|
- timeZone={timeZone}
|
|
|
- onChangeTime={onChangeTime}
|
|
|
- onChangeRefreshInterval={this.onChangeRefreshInterval}
|
|
|
- onRunQuery={this.onRunQuery}
|
|
|
- />
|
|
|
- </div>
|
|
|
+ {!isLive && (
|
|
|
+ <div className="explore-toolbar-content-item">
|
|
|
+ <ExploreTimeControls
|
|
|
+ exploreId={exploreId}
|
|
|
+ range={range}
|
|
|
+ timeZone={timeZone}
|
|
|
+ onChangeTime={onChangeTime}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
|
|
|
<div className="explore-toolbar-content-item">
|
|
|
<button className="btn navbar-button" onClick={this.onClearAll}>
|
|
|
@@ -280,16 +281,27 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
|
|
|
</button>
|
|
|
</div>
|
|
|
<div className="explore-toolbar-content-item">
|
|
|
- {createResponsiveButton({
|
|
|
- splitted,
|
|
|
- title: 'Run Query',
|
|
|
- onClick: this.onRunQuery,
|
|
|
- buttonClassName: 'navbar-button--secondary',
|
|
|
- iconClassName:
|
|
|
- loading && !isLive ? 'fa fa-spinner fa-fw fa-spin run-icon' : 'fa fa-level-down fa-fw run-icon',
|
|
|
- iconSide: IconSide.right,
|
|
|
- })}
|
|
|
+ <RunButton
|
|
|
+ refreshInterval={refreshInterval}
|
|
|
+ onChangeRefreshInterval={this.onChangeRefreshInterval}
|
|
|
+ splitted={splitted}
|
|
|
+ loading={loading || (isLive && !isPaused)}
|
|
|
+ onRun={this.onRunQuery}
|
|
|
+ showDropdown={!isLive}
|
|
|
+ />
|
|
|
+ {refreshInterval && <SetInterval func={this.onRunQuery} interval={refreshInterval} loading={loading} />}
|
|
|
</div>
|
|
|
+
|
|
|
+ {hasLiveOption && (
|
|
|
+ <LiveTailButton
|
|
|
+ isLive={isLive}
|
|
|
+ isPaused={isPaused}
|
|
|
+ start={this.startLive}
|
|
|
+ pause={this.pauseLive}
|
|
|
+ resume={this.resumeLive}
|
|
|
+ stop={this.stopLive}
|
|
|
+ />
|
|
|
+ )}
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -334,7 +346,7 @@ const getModeOptionsMemoized = memoizeOne(
|
|
|
|
|
|
const mapStateToProps = (state: StoreState, { exploreId }: OwnProps): StateProps => {
|
|
|
const splitted = state.explore.split;
|
|
|
- const exploreItem = state.explore[exploreId];
|
|
|
+ const exploreItem: ExploreItemState = state.explore[exploreId];
|
|
|
const {
|
|
|
datasourceInstance,
|
|
|
datasourceMissing,
|
|
|
@@ -345,6 +357,7 @@ const mapStateToProps = (state: StoreState, { exploreId }: OwnProps): StateProps
|
|
|
supportedModes,
|
|
|
mode,
|
|
|
isLive,
|
|
|
+ isPaused,
|
|
|
originPanelId,
|
|
|
queries,
|
|
|
} = exploreItem;
|
|
|
@@ -369,6 +382,7 @@ const mapStateToProps = (state: StoreState, { exploreId }: OwnProps): StateProps
|
|
|
selectedModeOption,
|
|
|
hasLiveOption,
|
|
|
isLive,
|
|
|
+ isPaused,
|
|
|
originPanelId,
|
|
|
queries,
|
|
|
};
|
|
|
@@ -384,6 +398,8 @@ const mapDispatchToProps: DispatchProps = {
|
|
|
split: splitOpen,
|
|
|
changeMode: changeMode,
|
|
|
clearOrigin,
|
|
|
+ changeRefreshIntervalAction,
|
|
|
+ setPausedStateAction,
|
|
|
};
|
|
|
|
|
|
export const ExploreToolbar = hot(module)(
|