TimePickerPopover.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import React, { Component, SyntheticEvent } from 'react';
  2. import { TimeRange, TimeOptions, TimeOption } from '../../types/time';
  3. import { Moment } from 'moment';
  4. import { TimePickerCalendar } from './TimePickerCalendar';
  5. import { TimePickerInput } from './TimePickerInput';
  6. import { mapTimeOptionToTimeRange } from './time';
  7. import { Timezone } from '../../utils/datemath';
  8. export interface Props {
  9. value: TimeRange;
  10. options: TimeOptions;
  11. isTimezoneUtc: boolean;
  12. timezone?: Timezone;
  13. onChange?: (timeRange: TimeRange) => void;
  14. }
  15. export interface State {
  16. value: TimeRange;
  17. isFromInputValid: boolean;
  18. isToInputValid: boolean;
  19. }
  20. export class TimePickerPopover extends Component<Props, State> {
  21. static popoverClassName = 'time-picker-popover';
  22. constructor(props: Props) {
  23. super(props);
  24. this.state = { value: props.value, isFromInputValid: true, isToInputValid: true };
  25. }
  26. onFromInputChanged = (value: string, valid: boolean) => {
  27. this.setState({
  28. value: { ...this.state.value, raw: { ...this.state.value.raw, from: value } },
  29. isFromInputValid: valid,
  30. });
  31. };
  32. onToInputChanged = (value: string, valid: boolean) => {
  33. this.setState({
  34. value: { ...this.state.value, raw: { ...this.state.value.raw, to: value } },
  35. isToInputValid: valid,
  36. });
  37. };
  38. onFromCalendarChanged = (value: Moment) => {
  39. this.setState({
  40. value: { ...this.state.value, raw: { ...this.state.value.raw, from: value } },
  41. });
  42. };
  43. onToCalendarChanged = (value: Moment) => {
  44. this.setState({
  45. value: { ...this.state.value, raw: { ...this.state.value.raw, to: value } },
  46. });
  47. };
  48. onTimeOptionClick = (timeOption: TimeOption) => {
  49. const { isTimezoneUtc, timezone, onChange } = this.props;
  50. if (onChange) {
  51. onChange(mapTimeOptionToTimeRange(timeOption, isTimezoneUtc, timezone));
  52. }
  53. };
  54. onApplyClick = () => {
  55. const { onChange } = this.props;
  56. if (onChange) {
  57. onChange(this.state.value);
  58. }
  59. };
  60. render() {
  61. const { options, isTimezoneUtc, timezone } = this.props;
  62. const { isFromInputValid, isToInputValid, value } = this.state;
  63. const isValid = isFromInputValid && isToInputValid;
  64. return (
  65. <div className={TimePickerPopover.popoverClassName}>
  66. <div className="time-picker-popover-box">
  67. <div className="time-picker-popover-box-header">
  68. <span className="time-picker-popover-box-title">Quick ranges</span>
  69. </div>
  70. <div className="time-picker-popover-box-body">
  71. {Object.keys(options).map(key => {
  72. return (
  73. <ul key={`popover-quickranges-${key}`}>
  74. {options[key].map(timeOption => (
  75. <li
  76. key={`popover-timeoption-${timeOption.from}-${timeOption.to}`}
  77. className={timeOption.active ? 'active' : ''}
  78. >
  79. <a
  80. onClick={(event: SyntheticEvent) => {
  81. event.preventDefault();
  82. this.onTimeOptionClick(timeOption);
  83. }}
  84. >
  85. {timeOption.display}
  86. </a>
  87. </li>
  88. ))}
  89. </ul>
  90. );
  91. })}
  92. </div>
  93. </div>
  94. <div className="time-picker-popover-box">
  95. <div className="time-picker-popover-box-header">
  96. <span className="time-picker-popover-box-title">Custom range</span>
  97. </div>
  98. <div className="time-picker-popover-box-body">
  99. <div className="time-picker-popover-box-body-custom-ranges">
  100. <div className="time-picker-popover-box-body-custom-ranges-input">
  101. <span>From:</span>
  102. <TimePickerInput
  103. isTimezoneUtc={isTimezoneUtc}
  104. roundup={false}
  105. timezone={timezone}
  106. value={value.raw.from}
  107. onChange={this.onFromInputChanged}
  108. />
  109. </div>
  110. <div className="time-picker-popover-box-body-custom-ranges-calendar">
  111. <TimePickerCalendar
  112. isTimezoneUtc={isTimezoneUtc}
  113. roundup={false}
  114. timezone={timezone}
  115. value={value.raw.from}
  116. onChange={this.onFromCalendarChanged}
  117. />
  118. </div>
  119. </div>
  120. <div className="time-picker-popover-box-body-custom-ranges">
  121. <div className="time-picker-popover-box-body-custom-ranges-input">
  122. <span>To:</span>
  123. <TimePickerInput
  124. isTimezoneUtc={isTimezoneUtc}
  125. roundup={true}
  126. timezone={timezone}
  127. value={value.raw.to}
  128. onChange={this.onToInputChanged}
  129. />
  130. </div>
  131. <div className="time-picker-popover-box-body-custom-ranges-calendar">
  132. <TimePickerCalendar
  133. isTimezoneUtc={isTimezoneUtc}
  134. roundup={true}
  135. timezone={timezone}
  136. value={value.raw.to}
  137. onChange={this.onToCalendarChanged}
  138. />
  139. </div>
  140. </div>
  141. </div>
  142. <div className="time-picker-popover-box-footer">
  143. <button
  144. type="submit"
  145. className="btn gf-form-btn btn-success"
  146. disabled={!isValid}
  147. onClick={this.onApplyClick}
  148. >
  149. Apply
  150. </button>
  151. </div>
  152. </div>
  153. </div>
  154. );
  155. }
  156. }