Browse Source

Made ExplorerToolbar connected and refactored away responsabilities from Explore

Hugo Häggmark 7 years ago
parent
commit
1e6d50df7a

+ 1 - 68
public/app/features/explore/Explore.tsx

@@ -9,7 +9,6 @@ import { AutoSizer } from 'react-virtualized';
 import store from 'app/core/store';
 
 // Components
-import { DataSourceSelectItem } from '@grafana/ui/src/types';
 import { Alert } from './Error';
 import ErrorBoundary from './ErrorBoundary';
 import GraphContainer from './GraphContainer';
@@ -20,18 +19,13 @@ import TimePicker, { parseTime } from './TimePicker';
 
 // Actions
 import {
-  changeDatasource,
   changeSize,
   changeTime,
-  clearQueries,
   initializeExplore,
   modifyQueries,
-  runQueries,
   scanStart,
   scanStop,
   setQueries,
-  splitClose,
-  splitOpen,
 } from './state/actions';
 
 // Types
@@ -44,24 +38,19 @@ import { ExploreToolbar } from './ExploreToolbar';
 
 interface ExploreProps {
   StartPage?: any;
-  changeDatasource: typeof changeDatasource;
   changeSize: typeof changeSize;
   changeTime: typeof changeTime;
-  clearQueries: typeof clearQueries;
   datasourceError: string;
   datasourceInstance: any;
   datasourceLoading: boolean | null;
   datasourceMissing: boolean;
-  exploreDatasources: DataSourceSelectItem[];
   exploreId: ExploreId;
   initialDatasource?: string;
   initialQueries: DataQuery[];
   initializeExplore: typeof initializeExplore;
   initialized: boolean;
-  loading: boolean;
   modifyQueries: typeof modifyQueries;
   range: RawTimeRange;
-  runQueries: typeof runQueries;
   scanner?: RangeScanner;
   scanning?: boolean;
   scanRange?: RawTimeRange;
@@ -69,8 +58,6 @@ interface ExploreProps {
   scanStop: typeof scanStop;
   setQueries: typeof setQueries;
   split: boolean;
-  splitClose: typeof splitClose;
-  splitOpen: typeof splitOpen;
   showingStartPage?: boolean;
   supportsGraph: boolean | null;
   supportsLogs: boolean | null;
@@ -145,10 +132,6 @@ export class Explore extends React.PureComponent<ExploreProps> {
     this.el = el;
   };
 
-  onChangeDatasource = async option => {
-    this.props.changeDatasource(this.props.exploreId, option.value);
-  };
-
   onChangeTime = (range: TimeRange, changedByScanner?: boolean) => {
     if (this.props.scanning && !changedByScanner) {
       this.onStopScanning();
@@ -156,23 +139,11 @@ export class Explore extends React.PureComponent<ExploreProps> {
     this.props.changeTime(this.props.exploreId, range);
   };
 
-  onClickClear = () => {
-    this.props.clearQueries(this.props.exploreId);
-  };
-
-  onClickCloseSplit = () => {
-    this.props.splitClose();
-  };
-
   // Use this in help pages to set page to a single query
   onClickExample = (query: DataQuery) => {
     this.props.setQueries(this.props.exploreId, [query]);
   };
 
-  onClickSplit = () => {
-    this.props.splitOpen();
-  };
-
   onClickLabel = (key: string, value: string) => {
     this.onModifyQueries({ type: 'ADD_FILTER', key, value });
   };
@@ -204,10 +175,6 @@ export class Explore extends React.PureComponent<ExploreProps> {
     this.props.scanStop(this.props.exploreId);
   };
 
-  onSubmit = () => {
-    this.props.runQueries(this.props.exploreId);
-  };
-
   render() {
     const {
       StartPage,
@@ -215,11 +182,8 @@ export class Explore extends React.PureComponent<ExploreProps> {
       datasourceError,
       datasourceLoading,
       datasourceMissing,
-      exploreDatasources,
       exploreId,
-      loading,
       initialQueries,
-      range,
       showingStartPage,
       split,
       supportsGraph,
@@ -227,30 +191,10 @@ export class Explore extends React.PureComponent<ExploreProps> {
       supportsTable,
     } = this.props;
     const exploreClass = split ? 'explore explore-split' : 'explore';
-    const selectedDatasource = datasourceInstance
-      ? exploreDatasources.find(d => d.name === datasourceInstance.name)
-      : undefined;
-
-    const timepicker = <TimePicker ref={this.timepickerRef} range={range} onChangeTime={this.onChangeTime} />;
 
     return (
       <div className={exploreClass} ref={this.getRef}>
-        <ExploreToolbar
-          datasourceMissing={datasourceMissing}
-          exploreDatasources={exploreDatasources}
-          exploreId={exploreId}
-          loading={loading}
-          range={range}
-          selectedDatasource={selectedDatasource}
-          splitted={split}
-          timepicker={timepicker}
-          onChangeDatasource={this.onChangeDatasource}
-          onClearAll={this.onClickClear}
-          onCloseSplit={this.onClickCloseSplit}
-          onChangeTime={this.onChangeTime}
-          onRunQuery={this.onSubmit}
-          onSplit={this.onClickSplit}
-        />
+        <ExploreToolbar exploreId={exploreId} timepickerRef={this.timepickerRef} onChangeTime={this.onChangeTime} />
         {datasourceLoading ? <div className="explore-container">Loading datasource...</div> : null}
         {datasourceMissing ? (
           <div className="explore-container">Please add a datasource that supports Explore (e.g., Prometheus).</div>
@@ -307,30 +251,24 @@ function mapStateToProps(state: StoreState, { exploreId }) {
     datasourceInstance,
     datasourceLoading,
     datasourceMissing,
-    exploreDatasources,
     initialDatasource,
     initialQueries,
     initialized,
-    queryTransactions,
     range,
     showingStartPage,
     supportsGraph,
     supportsLogs,
     supportsTable,
   } = item;
-  const loading = queryTransactions.some(qt => !qt.done);
   return {
     StartPage,
     datasourceError,
     datasourceInstance,
     datasourceLoading,
     datasourceMissing,
-    exploreDatasources,
     initialDatasource,
     initialQueries,
     initialized,
-    loading,
-    queryTransactions,
     range,
     showingStartPage,
     split,
@@ -341,18 +279,13 @@ function mapStateToProps(state: StoreState, { exploreId }) {
 }
 
 const mapDispatchToProps = {
-  changeDatasource,
   changeSize,
   changeTime,
-  clearQueries,
   initializeExplore,
   modifyQueries,
-  runQueries,
   scanStart,
   scanStop,
   setQueries,
-  splitClose,
-  splitOpen,
 };
 
 export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(Explore));

+ 75 - 17
public/app/features/explore/ExploreToolbar.tsx

@@ -1,7 +1,13 @@
 import React, { PureComponent } from 'react';
+import { connect } from 'react-redux';
+import { hot } from 'react-hot-loader';
+
 import { ExploreId } from 'app/types/explore';
 import { DataSourceSelectItem, RawTimeRange, TimeRange } from '@grafana/ui';
 import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker';
+import { StoreState } from 'app/types/store';
+import { changeDatasource, clearQueries, splitClose, runQueries, splitOpen } from './state/actions';
+import TimePicker from './TimePicker';
 
 const createResponsiveButton = (options: {
   splitted: boolean;
@@ -20,37 +26,58 @@ const createResponsiveButton = (options: {
   );
 };
 
-interface Props {
+interface OwnProps {
+  exploreId: ExploreId;
+  timepickerRef: React.RefObject<TimePicker>;
+  onChangeTime: (range: TimeRange, changedByScanner?: boolean) => void;
+}
+
+interface StateProps {
   datasourceMissing: boolean;
   exploreDatasources: DataSourceSelectItem[];
-  exploreId: ExploreId;
   loading: boolean;
   range: RawTimeRange;
   selectedDatasource: DataSourceSelectItem;
   splitted: boolean;
-  timepicker: JSX.Element;
-  onChangeDatasource: (option) => void;
-  onClearAll: () => void;
-  onCloseSplit: () => void;
-  onChangeTime: (range: TimeRange, changedByScanner?: boolean) => void;
-  onRunQuery: () => void;
-  onSplit: () => void;
 }
 
-export class ExploreToolbar extends PureComponent<Props, {}> {
+interface DispatchProps {
+  changeDatasource: typeof changeDatasource;
+  clearAll: typeof clearQueries;
+  runQuery: typeof runQueries;
+  closeSplit: typeof splitClose;
+  split: typeof splitOpen;
+}
+
+type Props = StateProps & DispatchProps & OwnProps;
+
+export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
   constructor(props) {
     super(props);
   }
 
+  onChangeDatasource = async option => {
+    this.props.changeDatasource(this.props.exploreId, option.value);
+  };
+
+  onClearAll = () => {
+    this.props.clearAll(this.props.exploreId);
+  };
+
+  onRunQuery = () => {
+    this.props.runQuery(this.props.exploreId);
+  };
+
   render() {
     const {
       datasourceMissing,
       exploreDatasources,
       exploreId,
       loading,
+      range,
       selectedDatasource,
       splitted,
-      timepicker,
+      timepickerRef,
     } = this.props;
 
     return (
@@ -67,7 +94,7 @@ export class ExploreToolbar extends PureComponent<Props, {}> {
             </div>
             <div className="toolbar-header-close">
               {exploreId === 'right' && (
-                <a onClick={this.props.onCloseSplit}>
+                <a onClick={this.props.closeSplit}>
                   <i className="fa fa-window-close fa-fw" />
                 </a>
               )}
@@ -80,7 +107,7 @@ export class ExploreToolbar extends PureComponent<Props, {}> {
               <div className="toolbar-content-item">
                 <div className="datasource-picker">
                   <DataSourcePicker
-                    onChange={this.props.onChangeDatasource}
+                    onChange={this.onChangeDatasource}
                     datasources={exploreDatasources}
                     current={selectedDatasource}
                   />
@@ -92,14 +119,16 @@ export class ExploreToolbar extends PureComponent<Props, {}> {
                 {createResponsiveButton({
                   splitted,
                   title: 'Split',
-                  onClick: this.props.onSplit,
+                  onClick: this.props.split,
                   iconClassName: 'fa fa-fw fa-columns',
                 })}
               </div>
             ) : null}
-            <div className="toolbar-content-item timepicker">{timepicker}</div>
+            <div className="toolbar-content-item timepicker">
+              <TimePicker ref={timepickerRef} range={range} onChangeTime={this.props.onChangeTime} />
+            </div>
             <div className="toolbar-content-item">
-              <button className="btn navbar-button navbar-button--no-icon" onClick={this.props.onClearAll}>
+              <button className="btn navbar-button navbar-button--no-icon" onClick={this.onClearAll}>
                 Clear All
               </button>
             </div>
@@ -107,7 +136,7 @@ export class ExploreToolbar extends PureComponent<Props, {}> {
               {createResponsiveButton({
                 splitted,
                 title: 'Run Query',
-                onClick: this.props.onRunQuery,
+                onClick: this.onRunQuery,
                 buttonClassName: 'navbar-button--primary',
                 iconClassName: loading ? 'fa fa-spinner fa-fw fa-spin run-icon' : 'fa fa-level-down fa-fw run-icon',
               })}
@@ -118,3 +147,32 @@ export class ExploreToolbar extends PureComponent<Props, {}> {
     );
   }
 }
+
+const mapStateToProps = (state: StoreState, { exploreId }: OwnProps): StateProps => {
+  const splitted = state.explore.split;
+  const exploreItem = state.explore[exploreId];
+  const { datasourceInstance, datasourceMissing, exploreDatasources, queryTransactions, range } = exploreItem;
+  const selectedDatasource = datasourceInstance
+    ? exploreDatasources.find(datasource => datasource.name === datasourceInstance.name)
+    : undefined;
+  const loading = queryTransactions.some(qt => !qt.done);
+
+  return {
+    datasourceMissing,
+    exploreDatasources,
+    loading,
+    range,
+    selectedDatasource,
+    splitted,
+  };
+};
+
+const mapDispatchToProps: DispatchProps = {
+  changeDatasource,
+  clearAll: clearQueries,
+  runQuery: runQueries,
+  closeSplit: splitClose,
+  split: splitOpen,
+};
+
+export const ExploreToolbar = hot(module)(connect(mapStateToProps, mapDispatchToProps)(UnConnectedExploreToolbar));