detailedError.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import * as React from 'react';
  2. import * as Sentry from '@sentry/react';
  3. import classNames from 'classnames';
  4. import Button from 'sentry/components/button';
  5. import {IconFlag} from 'sentry/icons';
  6. import {t} from 'sentry/locale';
  7. type DefaultProps = {
  8. /**
  9. * Hide support links in footer of error message
  10. */
  11. hideSupportLinks: boolean;
  12. };
  13. type Props = DefaultProps & {
  14. /**
  15. * Error heading
  16. */
  17. heading: React.ReactNode;
  18. className?: string;
  19. /**
  20. * Detailed error explanation
  21. */
  22. message?: React.ReactNode;
  23. /**
  24. * Retry callback
  25. */
  26. onRetry?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
  27. };
  28. function openFeedback(e: React.MouseEvent) {
  29. e.preventDefault();
  30. Sentry.showReportDialog();
  31. }
  32. class DetailedError extends React.Component<Props> {
  33. static defaultProps: DefaultProps = {
  34. hideSupportLinks: false,
  35. };
  36. componentDidMount() {
  37. // XXX(epurkhiser): Why is this here?
  38. setTimeout(() => this.forceUpdate(), 100);
  39. }
  40. render() {
  41. const {className, heading, message, onRetry, hideSupportLinks} = this.props;
  42. const cx = classNames('detailed-error', className);
  43. const showFooter = !!onRetry || !hideSupportLinks;
  44. return (
  45. <div className={cx}>
  46. <div className="detailed-error-icon">
  47. <IconFlag size="lg" />
  48. </div>
  49. <div className="detailed-error-content">
  50. <h4>{heading}</h4>
  51. <div className="detailed-error-content-body">{message}</div>
  52. {showFooter && (
  53. <div className="detailed-error-content-footer">
  54. <div>
  55. {onRetry && (
  56. <a onClick={onRetry} className="btn btn-default">
  57. {t('Retry')}
  58. </a>
  59. )}
  60. </div>
  61. {!hideSupportLinks && (
  62. <div className="detailed-error-support-links">
  63. {Sentry.lastEventId() && (
  64. <Button priority="link" onClick={openFeedback}>
  65. {t('Fill out a report')}
  66. </Button>
  67. )}
  68. <a href="https://status.sentry.io/">{t('Service status')}</a>
  69. <a href="https://sentry.io/support/">{t('Contact support')}</a>
  70. </div>
  71. )}
  72. </div>
  73. )}
  74. </div>
  75. </div>
  76. );
  77. }
  78. }
  79. export default DetailedError;