customIgnoreDurationModal.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import {Component, createRef, Fragment} from 'react';
  2. import moment from 'moment';
  3. import {sprintf} from 'sprintf-js';
  4. import {ModalRenderProps} from 'sentry/actionCreators/modal';
  5. import Alert from 'sentry/components/alert';
  6. import Button from 'sentry/components/button';
  7. import ButtonBar from 'sentry/components/buttonBar';
  8. import {t} from 'sentry/locale';
  9. import {ResolutionStatusDetails} from 'sentry/types';
  10. const defaultProps = {
  11. label: t('Ignore this issue until \u2026'),
  12. };
  13. type Props = ModalRenderProps & {
  14. onSelected: (details: ResolutionStatusDetails) => void;
  15. } & typeof defaultProps;
  16. type State = {
  17. dateWarning: boolean;
  18. };
  19. export default class CustomIgnoreDurationModal extends Component<Props, State> {
  20. static defaultProps = defaultProps;
  21. state: State = {
  22. dateWarning: false,
  23. };
  24. snoozeDateInputRef = createRef<HTMLInputElement>();
  25. snoozeTimeInputRef = createRef<HTMLInputElement>();
  26. selectedIgnoreMinutes = () => {
  27. const dateStr = this.snoozeDateInputRef.current?.value; // YYYY-MM-DD
  28. const timeStr = this.snoozeTimeInputRef.current?.value; // HH:MM
  29. if (dateStr && timeStr) {
  30. const selectedDate = moment.utc(dateStr + ' ' + timeStr);
  31. if (selectedDate.isValid()) {
  32. const now = moment.utc();
  33. return selectedDate.diff(now, 'minutes');
  34. }
  35. }
  36. return 0;
  37. };
  38. snoozeClicked = () => {
  39. const minutes = this.selectedIgnoreMinutes();
  40. this.setState({
  41. dateWarning: minutes <= 0,
  42. });
  43. if (minutes > 0) {
  44. this.props.onSelected({ignoreDuration: minutes});
  45. }
  46. this.props.closeModal();
  47. };
  48. render() {
  49. // Give the user a sane starting point to select a date
  50. // (prettier than the empty date/time inputs):
  51. const defaultDate = new Date();
  52. defaultDate.setDate(defaultDate.getDate() + 14);
  53. defaultDate.setSeconds(0);
  54. defaultDate.setMilliseconds(0);
  55. const defaultDateVal = sprintf(
  56. '%d-%02d-%02d',
  57. defaultDate.getUTCFullYear(),
  58. defaultDate.getUTCMonth() + 1,
  59. defaultDate.getUTCDate()
  60. );
  61. const defaultTimeVal = sprintf('%02d:00', defaultDate.getUTCHours());
  62. const {Header, Body, Footer, label} = this.props;
  63. return (
  64. <Fragment>
  65. <Header>{label}</Header>
  66. <Body>
  67. <form className="form-horizontal">
  68. <div className="control-group">
  69. <h6 className="nav-header">{t('Date')}</h6>
  70. <input
  71. className="form-control"
  72. type="date"
  73. id="snooze-until-date"
  74. defaultValue={defaultDateVal}
  75. ref={this.snoozeDateInputRef}
  76. required
  77. style={{padding: '0 10px'}}
  78. />
  79. </div>
  80. <div className="control-group m-b-1">
  81. <h6 className="nav-header">{t('Time (UTC)')}</h6>
  82. <input
  83. className="form-control"
  84. type="time"
  85. id="snooze-until-time"
  86. defaultValue={defaultTimeVal}
  87. ref={this.snoozeTimeInputRef}
  88. style={{padding: '0 10px'}}
  89. required
  90. />
  91. </div>
  92. </form>
  93. </Body>
  94. {this.state.dateWarning && (
  95. <Alert type="error" showIcon>
  96. {t('Please enter a valid date in the future')}
  97. </Alert>
  98. )}
  99. <Footer>
  100. <ButtonBar gap={1}>
  101. <Button type="button" priority="default" onClick={this.props.closeModal}>
  102. {t('Cancel')}
  103. </Button>
  104. <Button type="button" priority="primary" onClick={this.snoozeClicked}>
  105. {t('Ignore')}
  106. </Button>
  107. </ButtonBar>
  108. </Footer>
  109. </Fragment>
  110. );
  111. }
  112. }