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

     1  import $ from 'jquery';
     2  import React, { Component } from 'react';
     3  import { Button, InputGroup, InputGroupAddon, Input } from 'reactstrap';
     4  
     5  import moment from 'moment-timezone';
     6  
     7  import 'tempusdominus-core';
     8  import 'tempusdominus-bootstrap-4';
     9  import '../../../node_modules/tempusdominus-bootstrap-4/build/css/tempusdominus-bootstrap-4.min.css';
    10  
    11  import { dom, library } from '@fortawesome/fontawesome-svg-core';
    12  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
    13  import {
    14    faChevronLeft,
    15    faChevronRight,
    16    faCalendarCheck,
    17    faArrowUp,
    18    faArrowDown,
    19    faTimes,
    20  } from '@fortawesome/free-solid-svg-icons';
    21  
    22  library.add(faChevronLeft, faChevronRight, faCalendarCheck, faArrowUp, faArrowDown, faTimes);
    23  // Sadly needed to also replace <i> within the date picker, since it's not a React component.
    24  dom.watch();
    25  
    26  interface TimeInputProps {
    27    time: number | null; // Timestamp in milliseconds.
    28    useLocalTime: boolean;
    29    range: number; // Range in seconds.
    30    placeholder: string;
    31    onChangeTime: (time: number | null) => void;
    32  }
    33  
    34  class TimeInput extends Component<TimeInputProps> {
    35    private timeInputRef = React.createRef<HTMLInputElement>();
    36    private $time: any = null;
    37  
    38    getBaseTime = (): number => {
    39      return this.props.time || moment().valueOf();
    40    };
    41  
    42    calcShiftRange = (): number => this.props.range / 2;
    43  
    44    increaseTime = (): void => {
    45      const time = this.getBaseTime() + this.calcShiftRange();
    46      this.props.onChangeTime(time);
    47    };
    48  
    49    decreaseTime = (): void => {
    50      const time = this.getBaseTime() - this.calcShiftRange();
    51      this.props.onChangeTime(time);
    52    };
    53  
    54    clearTime = (): void => {
    55      this.props.onChangeTime(null);
    56    };
    57  
    58    timezone = (): string => {
    59      return this.props.useLocalTime ? moment.tz.guess() : 'UTC';
    60    };
    61  
    62    componentDidMount(): void {
    63      this.$time = $(this.timeInputRef.current!);
    64  
    65      this.$time.datetimepicker({
    66        icons: {
    67          today: 'fas fa-calendar-check',
    68        },
    69        buttons: {
    70          //showClear: true,
    71          showClose: true,
    72          showToday: true,
    73        },
    74        sideBySide: true,
    75        format: 'YYYY-MM-DD HH:mm:ss',
    76        locale: 'en',
    77        timeZone: this.timezone(),
    78        defaultDate: this.props.time,
    79      });
    80  
    81      this.$time.on('change.datetimepicker', (e: any) => {
    82        if (e.date) {
    83          this.props.onChangeTime(e.date.valueOf());
    84        }
    85      });
    86    }
    87  
    88    componentWillUnmount(): void {
    89      this.$time.datetimepicker('destroy');
    90    }
    91  
    92    componentDidUpdate(prevProps: TimeInputProps): void {
    93      const { time, useLocalTime } = this.props;
    94      if (prevProps.time !== time) {
    95        this.$time.datetimepicker('date', time ? moment(time) : null);
    96      }
    97      if (prevProps.useLocalTime !== useLocalTime) {
    98        this.$time.datetimepicker('options', { timeZone: this.timezone(), defaultDate: null });
    99      }
   100    }
   101  
   102    render(): JSX.Element {
   103      return (
   104        <InputGroup className="time-input" size="sm">
   105          <InputGroupAddon addonType="prepend">
   106            <Button title="Decrease time" onClick={this.decreaseTime}>
   107              <FontAwesomeIcon icon={faChevronLeft} fixedWidth />
   108            </Button>
   109          </InputGroupAddon>
   110  
   111          <Input
   112            placeholder={this.props.placeholder}
   113            innerRef={this.timeInputRef}
   114            onFocus={() => this.$time.datetimepicker('show')}
   115            onBlur={() => this.$time.datetimepicker('hide')}
   116            onKeyDown={(e) => ['Escape', 'Enter'].includes(e.key) && this.$time.datetimepicker('hide')}
   117          />
   118  
   119          {/* CAUTION: While the datetimepicker also has an option to show a 'clear' button,
   120              that functionality is broken, so we create an external solution instead. */}
   121          {this.props.time && (
   122            <InputGroupAddon addonType="append">
   123              <Button outline className="clear-time-btn" title="Clear time" onClick={this.clearTime}>
   124                <FontAwesomeIcon icon={faTimes} fixedWidth />
   125              </Button>
   126            </InputGroupAddon>
   127          )}
   128  
   129          <InputGroupAddon addonType="append">
   130            <Button title="Increase time" onClick={this.increaseTime}>
   131              <FontAwesomeIcon icon={faChevronRight} fixedWidth />
   132            </Button>
   133          </InputGroupAddon>
   134        </InputGroup>
   135      );
   136    }
   137  }
   138  
   139  export default TimeInput;