grafana/public/app/features/explore/ExploreToolbar.tsx
Jack Westbrook 8d3b31ff23
Build: Upgrade Webpack 5 (#36444)
* build(webpack): bump to v5 and successful yarn start compilation

* build(webpack): update postcss dependencies

* build(webpack): silence warnings about hash renamed to fullhash

* build(webpack): enable persistent cache to store generated webpack modules / chunks

* build(webpack): prefer eslintWebpackPlugin over tschecker so eslint doesn't block typechecking

* chore(yarn): run yarn-deduplicate to clean up dependencies

* chore(yarn): refresh lock file after clean install

* build(webpack): prefer output.clean over CleanWebpackPlugin

* build(webpack): prefer esbuild over babel-loader for dev config

* build(babel): turn off cache compression to improve build performance

* build(webpack): get production builds working

* build(webpack): remove phantomJS (removed from grafana in v7) specific loader

* build(webpack): put back babel for dev builds no performance gain in using esbuild in webpack

* build(webpack): prefer terser and optimise css plugins for prod. slower but smaller bundles

* build(webpack): clean up redundant code. inform postcss about node_modules

* build(webpack): remove deprecation warnings flag

* build(webpack): bump packages, dev performance optimisations, attempt to get hot working

* chore(storybook): use webpack 5 for dev and production builds

* build(storybook): speed up dev build

* chore(yarn): refresh lock file

* chore(webpack): bump webpack and related deps to latest

* refactor(webpack): put back inline-source-map, move start scripts out of grafana toolkit

* feat(webpack): prefer react-refresh over react-hot-loader

* build(webpack): update webpack.hot to use react-refresh

* chore: remove react-hot-loader from codebase

* refactor(queryeditorrow): fix circular dependency causing react-fast-refresh errors

* revert(webpack): remove stats.errorDetails from common config

* build(webpack): bump to v5 and successful yarn start compilation

* build(webpack): update postcss dependencies

* build(webpack): silence warnings about hash renamed to fullhash

* build(webpack): enable persistent cache to store generated webpack modules / chunks

* build(webpack): prefer eslintWebpackPlugin over tschecker so eslint doesn't block typechecking

* chore(yarn): run yarn-deduplicate to clean up dependencies

* chore(yarn): refresh lock file after clean install

* build(webpack): prefer output.clean over CleanWebpackPlugin

* build(webpack): prefer esbuild over babel-loader for dev config

* build(babel): turn off cache compression to improve build performance

* build(webpack): get production builds working

* build(webpack): remove phantomJS (removed from grafana in v7) specific loader

* build(webpack): put back babel for dev builds no performance gain in using esbuild in webpack

* build(webpack): prefer terser and optimise css plugins for prod. slower but smaller bundles

* build(webpack): clean up redundant code. inform postcss about node_modules

* build(webpack): remove deprecation warnings flag

* build(webpack): bump packages, dev performance optimisations, attempt to get hot working

* chore(storybook): use webpack 5 for dev and production builds

* build(storybook): speed up dev build

* chore(yarn): refresh lock file

* chore(webpack): bump webpack and related deps to latest

* refactor(webpack): put back inline-source-map, move start scripts out of grafana toolkit

* feat(webpack): prefer react-refresh over react-hot-loader

* build(webpack): update webpack.hot to use react-refresh

* chore: remove react-hot-loader from codebase

* refactor(queryeditorrow): fix circular dependency causing react-fast-refresh errors

* revert(webpack): remove stats.errorDetails from common config

* revert(webpack): remove include from babel-loader so symlinks (enterprise) work as before

* refactor(webpack): fix deprecation warnings in prod builds

* fix(storybook): fix failing builds due to replacing css-optimise webpack plugin

* fix(storybook): use raw-loader for svg icons

* build(webpack): fix dev script colors error

* chore(webpack): bump css-loader and react-refresh-webpack-plugin to latest versions

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
2021-08-31 12:55:05 +02:00

254 lines
8.1 KiB
TypeScript

import React, { PureComponent } from 'react';
import { connect, ConnectedProps } from 'react-redux';
import classNames from 'classnames';
import { css } from '@emotion/css';
import { ExploreId, ExploreItemState } from 'app/types/explore';
import { Icon, IconButton, SetInterval, ToolbarButton, ToolbarButtonRow, Tooltip } from '@grafana/ui';
import { DataSourceInstanceSettings, RawTimeRange } from '@grafana/data';
import { DataSourcePicker } from '@grafana/runtime';
import { StoreState } from 'app/types/store';
import { createAndCopyShortLink } from 'app/core/utils/shortLinks';
import { changeDatasource } from './state/datasource';
import { splitClose, splitOpen } from './state/main';
import { syncTimes, changeRefreshInterval } from './state/time';
import { getTimeZone } from '../profile/state/selectors';
import { updateTimeZoneForSession } from '../profile/state/reducers';
import { ExploreTimeControls } from './ExploreTimeControls';
import { LiveTailButton } from './LiveTailButton';
import { RunButton } from './RunButton';
import { LiveTailControls } from './useLiveTailControls';
import { cancelQueries, clearQueries, runQueries } from './state/query';
import ReturnToDashboardButton from './ReturnToDashboardButton';
import { isSplit } from './state/selectors';
interface OwnProps {
exploreId: ExploreId;
onChangeTime: (range: RawTimeRange, changedByScanner?: boolean) => void;
}
type Props = OwnProps & ConnectedProps<typeof connector>;
export class UnConnectedExploreToolbar extends PureComponent<Props> {
onChangeDatasource = async (dsSettings: DataSourceInstanceSettings) => {
this.props.changeDatasource(this.props.exploreId, dsSettings.name, { importQueries: true });
};
onClearAll = () => {
this.props.clearAll(this.props.exploreId);
};
onRunQuery = (loading = false) => {
const { runQueries, cancelQueries, exploreId } = this.props;
if (loading) {
return cancelQueries(exploreId);
} else {
return runQueries(exploreId);
}
};
onChangeRefreshInterval = (item: string) => {
const { changeRefreshInterval, exploreId } = this.props;
changeRefreshInterval(exploreId, item);
};
onChangeTimeSync = () => {
const { syncTimes, exploreId } = this.props;
syncTimes(exploreId);
};
render() {
const {
datasourceMissing,
closeSplit,
exploreId,
loading,
range,
timeZone,
splitted,
syncedTimes,
refreshInterval,
onChangeTime,
split,
hasLiveOption,
isLive,
isPaused,
containerWidth,
onChangeTimeZone,
} = this.props;
const showSmallDataSourcePicker = (splitted ? containerWidth < 700 : containerWidth < 800) || false;
const showSmallTimePicker = splitted || containerWidth < 1210;
return (
<div className={splitted ? 'explore-toolbar splitted' : 'explore-toolbar'}>
<div className="explore-toolbar-item">
<div className="explore-toolbar-header">
<div className="explore-toolbar-header-title">
{exploreId === 'left' && (
<span className="navbar-page-btn">
<Icon
name="compass"
size="lg"
className={css`
margin-right: 6px;
margin-bottom: 3px;
`}
/>
Explore
</span>
)}
</div>
{splitted && (
<IconButton
title="Close split pane"
className="explore-toolbar-header-close"
onClick={() => closeSplit(exploreId)}
name="times"
/>
)}
</div>
</div>
<div className="explore-toolbar-item">
<div className="explore-toolbar-content">
{!datasourceMissing ? (
<div className="explore-toolbar-content-item">
<div
className={classNames(
'explore-ds-picker',
showSmallDataSourcePicker ? 'explore-ds-picker--small' : ''
)}
>
<DataSourcePicker
onChange={this.onChangeDatasource}
current={this.props.datasourceName}
hideTextValue={showSmallDataSourcePicker}
/>
</div>
</div>
) : null}
<ToolbarButtonRow>
<ReturnToDashboardButton exploreId={exploreId} />
{exploreId === 'left' && !splitted ? (
<ToolbarButton
iconOnly={splitted}
title="Split"
/* This way ToolbarButton doesn't add event as a parameter when invoking split function
* which breaks splitting functionality
*/
onClick={() => split()}
icon="columns"
disabled={isLive}
>
Split
</ToolbarButton>
) : null}
<Tooltip content={'Copy shortened link to the executed query'} placement="bottom">
<ToolbarButton icon="share-alt" onClick={() => createAndCopyShortLink(window.location.href)} />
</Tooltip>
{!isLive && (
<ExploreTimeControls
exploreId={exploreId}
range={range}
timeZone={timeZone}
onChangeTime={onChangeTime}
splitted={splitted}
syncedTimes={syncedTimes}
onChangeTimeSync={this.onChangeTimeSync}
hideText={showSmallTimePicker}
onChangeTimeZone={onChangeTimeZone}
/>
)}
{!isLive && (
<ToolbarButton title="Clear all" onClick={this.onClearAll} icon="trash-alt" iconOnly={splitted}>
Clear all
</ToolbarButton>
)}
<RunButton
refreshInterval={refreshInterval}
onChangeRefreshInterval={this.onChangeRefreshInterval}
isSmall={splitted || showSmallTimePicker}
isLive={isLive}
loading={loading || (isLive && !isPaused)}
onRun={this.onRunQuery}
showDropdown={!isLive}
/>
{refreshInterval && <SetInterval func={this.onRunQuery} interval={refreshInterval} loading={loading} />}
{hasLiveOption && (
<LiveTailControls exploreId={exploreId}>
{(controls) => (
<LiveTailButton
splitted={splitted}
isLive={isLive}
isPaused={isPaused}
start={controls.start}
pause={controls.pause}
resume={controls.resume}
stop={controls.stop}
/>
)}
</LiveTailControls>
)}
</ToolbarButtonRow>
</div>
</div>
</div>
);
}
}
const mapStateToProps = (state: StoreState, { exploreId }: OwnProps) => {
const syncedTimes = state.explore.syncedTimes;
const exploreItem: ExploreItemState = state.explore[exploreId]!;
const {
datasourceInstance,
datasourceMissing,
range,
refreshInterval,
loading,
isLive,
isPaused,
containerWidth,
} = exploreItem;
const hasLiveOption = !!datasourceInstance?.meta?.streaming;
return {
datasourceMissing,
datasourceName: datasourceInstance?.name,
loading,
range,
timeZone: getTimeZone(state.user),
splitted: isSplit(state),
refreshInterval,
hasLiveOption,
isLive,
isPaused,
syncedTimes,
containerWidth,
};
};
const mapDispatchToProps = {
changeDatasource,
changeRefreshInterval,
clearAll: clearQueries,
cancelQueries,
runQueries,
closeSplit: splitClose,
split: splitOpen,
syncTimes,
onChangeTimeZone: updateTimeZoneForSession,
};
const connector = connect(mapStateToProps, mapDispatchToProps);
export const ExploreToolbar = connector(UnConnectedExploreToolbar);