github.com/thanos-io/thanos@v0.32.5/pkg/ui/react-app/src/pages/graph/GraphControls.tsx (about)

     1  import React, { Component } from 'react';
     2  import { Button, ButtonGroup, Form, InputGroup, InputGroupAddon, Input } from 'reactstrap';
     3  
     4  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
     5  import { faPlus, faMinus, faChartArea, faChartLine } from '@fortawesome/free-solid-svg-icons';
     6  
     7  import TimeInput from './TimeInput';
     8  import { parseDuration, formatDuration } from '../../utils';
     9  
    10  interface GraphControlsProps {
    11    range: number;
    12    endTime: number | null;
    13    useLocalTime: boolean;
    14    resolution: number | null;
    15    stacked: boolean;
    16    maxSourceResolution: string;
    17  
    18    onChangeRange: (range: number) => void;
    19    onChangeEndTime: (endTime: number | null) => void;
    20    onChangeResolution: (resolution: number | null) => void;
    21    onChangeStacking: (stacked: boolean) => void;
    22    onChangeMaxSourceResolution: (maxSourceResolution: string) => void;
    23  }
    24  
    25  class GraphControls extends Component<GraphControlsProps> {
    26    constructor(props: GraphControlsProps) {
    27      super(props);
    28  
    29      this.handleMaxSourceResChange = this.handleMaxSourceResChange.bind(this);
    30    }
    31  
    32    private rangeRef = React.createRef<HTMLInputElement>();
    33    private resolutionRef = React.createRef<HTMLInputElement>();
    34  
    35    rangeSteps = [
    36      1,
    37      10,
    38      60,
    39      5 * 60,
    40      15 * 60,
    41      30 * 60,
    42      60 * 60,
    43      2 * 60 * 60,
    44      6 * 60 * 60,
    45      12 * 60 * 60,
    46      24 * 60 * 60,
    47      48 * 60 * 60,
    48      7 * 24 * 60 * 60,
    49      14 * 24 * 60 * 60,
    50      28 * 24 * 60 * 60,
    51      56 * 24 * 60 * 60,
    52      365 * 24 * 60 * 60,
    53      730 * 24 * 60 * 60,
    54    ].map((s) => s * 1000);
    55  
    56    onChangeRangeInput = (rangeText: string): void => {
    57      const range = parseDuration(rangeText);
    58      if (range === null) {
    59        this.changeRangeInput(this.props.range);
    60      } else {
    61        this.props.onChangeRange(range);
    62      }
    63    };
    64  
    65    changeRangeInput = (range: number): void => {
    66      this.rangeRef.current!.value = formatDuration(range);
    67    };
    68  
    69    increaseRange = (): void => {
    70      for (const range of this.rangeSteps) {
    71        if (this.props.range < range) {
    72          this.changeRangeInput(range);
    73          this.props.onChangeRange(range);
    74          return;
    75        }
    76      }
    77    };
    78  
    79    decreaseRange = (): void => {
    80      for (const range of this.rangeSteps.slice().reverse()) {
    81        if (this.props.range > range) {
    82          this.changeRangeInput(range);
    83          this.props.onChangeRange(range);
    84          return;
    85        }
    86      }
    87    };
    88  
    89    componentDidUpdate(prevProps: GraphControlsProps) {
    90      if (prevProps.range !== this.props.range) {
    91        this.changeRangeInput(this.props.range);
    92      }
    93      if (prevProps.resolution !== this.props.resolution) {
    94        this.resolutionRef.current!.value = this.props.resolution !== null ? this.props.resolution.toString() : '';
    95      }
    96    }
    97  
    98    handleMaxSourceResChange(event: React.ChangeEvent<HTMLInputElement>): void {
    99      this.props.onChangeMaxSourceResolution(event.target.value);
   100    }
   101  
   102    render() {
   103      return (
   104        <Form inline className="graph-controls" onSubmit={(e) => e.preventDefault()}>
   105          <InputGroup className="range-input" size="sm">
   106            <InputGroupAddon addonType="prepend">
   107              <Button title="Decrease range" onClick={this.decreaseRange}>
   108                <FontAwesomeIcon icon={faMinus} fixedWidth />
   109              </Button>
   110            </InputGroupAddon>
   111  
   112            <Input
   113              defaultValue={formatDuration(this.props.range)}
   114              innerRef={this.rangeRef}
   115              onBlur={() => this.onChangeRangeInput(this.rangeRef.current!.value)}
   116            />
   117  
   118            <InputGroupAddon addonType="append">
   119              <Button title="Increase range" onClick={this.increaseRange}>
   120                <FontAwesomeIcon icon={faPlus} fixedWidth />
   121              </Button>
   122            </InputGroupAddon>
   123          </InputGroup>
   124  
   125          <TimeInput
   126            time={this.props.endTime}
   127            useLocalTime={this.props.useLocalTime}
   128            range={this.props.range}
   129            placeholder="End time"
   130            onChangeTime={this.props.onChangeEndTime}
   131          />
   132  
   133          <Input
   134            placeholder="Res. (s)"
   135            className="resolution-input"
   136            defaultValue={this.props.resolution !== null ? this.props.resolution.toString() : ''}
   137            innerRef={this.resolutionRef}
   138            onBlur={() => {
   139              const res = parseInt(this.resolutionRef.current!.value);
   140              this.props.onChangeResolution(res ? res : null);
   141            }}
   142            bsSize="sm"
   143          />
   144  
   145          <ButtonGroup className="stacked-input" size="sm">
   146            <Button
   147              title="Show unstacked line graph"
   148              onClick={() => this.props.onChangeStacking(false)}
   149              active={!this.props.stacked}
   150            >
   151              <FontAwesomeIcon icon={faChartLine} fixedWidth />
   152            </Button>
   153            <Button title="Show stacked graph" onClick={() => this.props.onChangeStacking(true)} active={this.props.stacked}>
   154              <FontAwesomeIcon icon={faChartArea} fixedWidth />
   155            </Button>
   156          </ButtonGroup>
   157  
   158          <Input
   159            type="select"
   160            value={this.props.maxSourceResolution}
   161            onChange={this.handleMaxSourceResChange}
   162            className="max-source-resolution-input"
   163            bsSize="sm"
   164          >
   165            <option value="auto">Auto downsampling</option>
   166            <option value="0s">Only raw data</option>
   167            <option value="5m">Max 5m downsampling</option>
   168            <option value="1h">Max 1h downsampling</option>
   169          </Input>
   170        </Form>
   171      );
   172    }
   173  }
   174  
   175  export default GraphControls;