소스 검색

Time selection via graph

David Kaltschmidt 7 년 전
부모
커밋
c1ca1ed35e

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

@@ -898,6 +898,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
                           height={graphHeight}
                           loading={graphLoading}
                           id={`explore-graph-${position}`}
+                          onChangeTime={this.onChangeTime}
                           range={graphRange}
                           split={split}
                         />
@@ -908,7 +909,13 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
                       </div>
                     ) : null}
                     {supportsLogs && showingLogs ? (
-                      <Logs data={logsResult} loading={logsLoading} position={position} range={range} />
+                      <Logs
+                        data={logsResult}
+                        loading={logsLoading}
+                        position={position}
+                        onChangeTime={this.onChangeTime}
+                        range={range}
+                      />
                     ) : null}
                   </>
                 )}

+ 24 - 4
public/app/features/explore/Graph.tsx

@@ -5,6 +5,7 @@ import { withSize } from 'react-sizeme';
 
 import 'vendor/flot/jquery.flot';
 import 'vendor/flot/jquery.flot.time';
+import 'vendor/flot/jquery.flot.selection';
 
 import { RawTimeRange } from 'app/types/series';
 import * as dateMath from 'app/core/utils/datemath';
@@ -62,10 +63,10 @@ const FLOT_OPTIONS = {
     margin: { left: 0, right: 0 },
     labelMarginX: 0,
   },
-  // selection: {
-  //   mode: 'x',
-  //   color: '#666',
-  // },
+  selection: {
+    mode: 'x',
+    color: '#666',
+  },
   // crosshair: {
   //   mode: 'x',
   // },
@@ -80,6 +81,7 @@ interface GraphProps {
   split?: boolean;
   size?: { width: number; height: number };
   userOptions?: any;
+  onChangeTime?: (range: RawTimeRange) => void;
 }
 
 interface GraphState {
@@ -87,6 +89,8 @@ interface GraphState {
 }
 
 export class Graph extends PureComponent<GraphProps, GraphState> {
+  $el: any;
+
   state = {
     showAllTimeSeries: false,
   };
@@ -99,6 +103,8 @@ export class Graph extends PureComponent<GraphProps, GraphState> {
 
   componentDidMount() {
     this.draw();
+    this.$el = $(`#${this.props.id}`);
+    this.$el.bind('plotselected', this.onPlotSelected);
   }
 
   componentDidUpdate(prevProps: GraphProps) {
@@ -113,6 +119,20 @@ export class Graph extends PureComponent<GraphProps, GraphState> {
     }
   }
 
+  componentWillUnmount() {
+    this.$el.unbind('plotselected', this.onPlotSelected);
+  }
+
+  onPlotSelected = (event, ranges) => {
+    if (this.props.onChangeTime) {
+      const range = {
+        from: moment(ranges.xaxis.from),
+        to: moment(ranges.xaxis.to),
+      };
+      this.props.onChangeTime(range);
+    }
+  };
+
   onShowAllTimeSeries = () => {
     this.setState(
       {

+ 2 - 0
public/app/features/explore/Logs.tsx

@@ -25,6 +25,7 @@ interface LogsProps {
   loading: boolean;
   position: string;
   range?: RawTimeRange;
+  onChangeTime?: (range: RawTimeRange) => void;
 }
 
 interface LogsState {
@@ -88,6 +89,7 @@ export default class Logs extends PureComponent<LogsProps, LogsState> {
             height="100px"
             range={range}
             id={`explore-logs-graph-${position}`}
+            onChangeTime={this.props.onChangeTime}
             userOptions={graphOptions}
           />
         </div>

+ 22 - 6
public/app/features/explore/TimePicker.tsx

@@ -16,6 +16,9 @@ export const DEFAULT_RANGE = {
  * @param value Epoch or relative time
  */
 export function parseTime(value: string, isUtc = false): string {
+  if (moment.isMoment(value)) {
+    return value;
+  }
   if (value.indexOf('now') !== -1) {
     return value;
   }
@@ -39,7 +42,8 @@ interface TimePickerState {
   isOpen: boolean;
   isUtc: boolean;
   rangeString: string;
-  refreshInterval: string;
+  refreshInterval?: string;
+  initialRange: RawTimeRange;
 
   // Input-controlled text, keep these in a shape that is human-editable
   fromRaw: string;
@@ -49,11 +53,24 @@ interface TimePickerState {
 export default class TimePicker extends PureComponent<TimePickerProps, TimePickerState> {
   dropdownEl: any;
 
-  constructor(props) {
-    super(props);
+  state = {
+    isOpen: false,
+    isUtc: false,
+    rangeString: '',
+    initialRange: DEFAULT_RANGE,
+    fromRaw: '',
+    toRaw: '',
+    refreshInterval: '',
+  };
+
+  static getDerivedStateFromProps(props, state) {
+    if (state.range && state.range === props.range) {
+      return null;
+    }
 
     const from = props.range ? props.range.from : DEFAULT_RANGE.from;
     const to = props.range ? props.range.to : DEFAULT_RANGE.to;
+    const initialRange = props.range || DEFAULT_RANGE;
 
     // Ensure internal format
     const fromRaw = parseTime(from, props.isUtc);
@@ -63,13 +80,12 @@ export default class TimePicker extends PureComponent<TimePickerProps, TimePicke
       to: toRaw,
     };
 
-    this.state = {
+    return {
       fromRaw,
       toRaw,
-      isOpen: props.isOpen,
+      initialRange,
       isUtc: props.isUtc,
       rangeString: rangeUtil.describeTimeRange(range),
-      refreshInterval: '',
     };
   }