prometheus

Форк
0
146 строк · 4.5 Кб
1
import $ from 'jquery';
2
import React, { Component } from 'react';
3
import { Button, Input, InputGroup, InputGroupAddon } from 'reactstrap';
4

5
import moment from 'moment-timezone';
6

7
import 'tempusdominus-core';
8
import 'tempusdominus-bootstrap-4';
9
import '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
  faArrowDown,
15
  faArrowUp,
16
  faCalendarCheck,
17
  faChevronLeft,
18
  faChevronRight,
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
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
  private $time: any = null;
38

39
  getBaseTime = (): number => {
40
    return this.props.time || moment().valueOf();
41
  };
42

43
  calcShiftRange = (): number => this.props.range / 2;
44

45
  increaseTime = (): void => {
46
    const time = this.getBaseTime() + this.calcShiftRange();
47
    this.props.onChangeTime(time);
48
  };
49

50
  decreaseTime = (): void => {
51
    const time = this.getBaseTime() - this.calcShiftRange();
52
    this.props.onChangeTime(time);
53
  };
54

55
  clearTime = (): void => {
56
    this.props.onChangeTime(null);
57
  };
58

59
  timezone = (): string => {
60
    return this.props.useLocalTime ? moment.tz.guess() : 'UTC';
61
  };
62

63
  componentDidMount(): void {
64
    if (!this.timeInputRef.current) {
65
      return;
66
    }
67
    this.$time = $(this.timeInputRef.current);
68

69
    this.$time.datetimepicker({
70
      icons: {
71
        today: 'fas fa-calendar-check',
72
      },
73
      buttons: {
74
        //showClear: true,
75
        showClose: true,
76
        showToday: true,
77
      },
78
      sideBySide: true,
79
      format: 'YYYY-MM-DD HH:mm:ss',
80
      locale: 'en',
81
      timeZone: this.timezone(),
82
      defaultDate: this.props.time,
83
    });
84

85
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
86
    this.$time.on('change.datetimepicker', (e: any) => {
87
      // The end time can also be set by dragging a section on the graph,
88
      // and that value will have decimal places.
89
      if (e.date && e.date.valueOf() !== Math.trunc(this.props.time?.valueOf() || NaN)) {
90
        this.props.onChangeTime(e.date.valueOf());
91
      }
92
    });
93
  }
94

95
  componentWillUnmount(): void {
96
    this.$time.datetimepicker('destroy');
97
  }
98

99
  componentDidUpdate(prevProps: TimeInputProps): void {
100
    const { time, useLocalTime } = this.props;
101
    if (prevProps.time !== time) {
102
      this.$time.datetimepicker('date', time ? moment(time) : null);
103
    }
104
    if (prevProps.useLocalTime !== useLocalTime) {
105
      this.$time.datetimepicker('options', { timeZone: this.timezone(), defaultDate: null });
106
    }
107
  }
108

109
  render(): JSX.Element {
110
    return (
111
      <InputGroup className="time-input" size="sm">
112
        <InputGroupAddon addonType="prepend">
113
          <Button title="Decrease time" onClick={this.decreaseTime}>
114
            <FontAwesomeIcon icon={faChevronLeft} fixedWidth />
115
          </Button>
116
        </InputGroupAddon>
117

118
        <Input
119
          placeholder={this.props.placeholder}
120
          innerRef={this.timeInputRef}
121
          onFocus={() => this.$time.datetimepicker('show')}
122
          onBlur={() => this.$time.datetimepicker('hide')}
123
          onKeyDown={(e) => ['Escape', 'Enter'].includes(e.key) && this.$time.datetimepicker('hide')}
124
        />
125

126
        {/* CAUTION: While the datetimepicker also has an option to show a 'clear' button,
127
            that functionality is broken, so we create an external solution instead. */}
128
        {this.props.time && (
129
          <InputGroupAddon addonType="append">
130
            <Button outline className="clear-time-btn" title="Clear time" onClick={this.clearTime}>
131
              <FontAwesomeIcon icon={faTimes} fixedWidth />
132
            </Button>
133
          </InputGroupAddon>
134
        )}
135

136
        <InputGroupAddon addonType="append">
137
          <Button title="Increase time" onClick={this.increaseTime}>
138
            <FontAwesomeIcon icon={faChevronRight} fixedWidth />
139
          </Button>
140
        </InputGroupAddon>
141
      </InputGroup>
142
    );
143
  }
144
}
145

146
export default TimeInput;
147

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.