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;