traceWaterfallState.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import {useRef} from 'react';
  2. import styled from '@emotion/styled';
  3. import useFeedbackWidget from 'sentry/components/feedback/widget/useFeedbackWidget';
  4. import LoadingIndicator from 'sentry/components/loadingIndicator';
  5. import {t} from 'sentry/locale';
  6. function TraceLoading() {
  7. return (
  8. // Dont flash the animation on load because it's annoying
  9. <LoadingContainer animate={false}>
  10. <NoMarginIndicator size={24}>
  11. <div>{t('Assembling the trace')}</div>
  12. </NoMarginIndicator>
  13. </LoadingContainer>
  14. );
  15. }
  16. function TraceError() {
  17. const linkref = useRef<HTMLAnchorElement>(null);
  18. const feedback = useFeedbackWidget({buttonRef: linkref});
  19. return (
  20. <LoadingContainer animate error>
  21. <div>{t('Ughhhhh, we failed to load your trace...')}</div>
  22. <div>
  23. {t('Seeing this often? Send us ')}
  24. {feedback ? (
  25. <a href="#" ref={linkref}>
  26. {t('feedback')}
  27. </a>
  28. ) : (
  29. <a href="mailto:support@sentry.io?subject=Trace%20fails%20to%20load">
  30. {t('feedback')}
  31. </a>
  32. )}
  33. </div>
  34. </LoadingContainer>
  35. );
  36. }
  37. function TraceEmpty() {
  38. const linkref = useRef<HTMLAnchorElement>(null);
  39. const feedback = useFeedbackWidget({buttonRef: linkref});
  40. return (
  41. <LoadingContainer animate>
  42. <div>{t('This trace does not contain any data?!')}</div>
  43. <div>
  44. {t('Seeing this often? Send us ')}
  45. {feedback ? (
  46. <a href="#" ref={linkref}>
  47. {t('feedback')}
  48. </a>
  49. ) : (
  50. <a href="mailto:support@sentry.io?subject=Trace%20does%20not%20contain%20data">
  51. {t('feedback')}
  52. </a>
  53. )}
  54. </div>
  55. </LoadingContainer>
  56. );
  57. }
  58. const LoadingContainer = styled('div')<{animate: boolean; error?: boolean}>`
  59. display: flex;
  60. justify-content: center;
  61. align-items: center;
  62. flex-direction: column;
  63. left: 50%;
  64. top: 50%;
  65. position: absolute;
  66. height: auto;
  67. font-size: ${p => p.theme.fontSizeMedium};
  68. color: ${p => p.theme.gray300};
  69. z-index: 30;
  70. padding: 24px;
  71. background-color: ${p => p.theme.background};
  72. border-radius: ${p => p.theme.borderRadius};
  73. border: 1px solid ${p => p.theme.border};
  74. transform-origin: 50% 50%;
  75. transform: translate(-50%, -50%);
  76. animation: ${p =>
  77. p.animate
  78. ? `${p.error ? 'showLoadingContainerShake' : 'showLoadingContainer'} 300ms cubic-bezier(0.61, 1, 0.88, 1) forwards`
  79. : 'none'};
  80. @keyframes showLoadingContainer {
  81. from {
  82. opacity: 0.6;
  83. transform: scale(0.99) translate(-50%, -50%);
  84. }
  85. to {
  86. opacity: 1;
  87. transform: scale(1) translate(-50%, -50%);
  88. }
  89. }
  90. @keyframes showLoadingContainerShake {
  91. 0% {
  92. transform: translate(-50%, -50%);
  93. }
  94. 25% {
  95. transform: translate(-51%, -50%);
  96. }
  97. 75% {
  98. transform: translate(-49%, -50%);
  99. }
  100. 100% {
  101. transform: translate(-50%, -50%);
  102. }
  103. }
  104. `;
  105. const NoMarginIndicator = styled(LoadingIndicator)`
  106. margin: 0;
  107. `;
  108. export const TraceWaterfallState = {
  109. Loading: TraceLoading,
  110. Error: TraceError,
  111. Empty: TraceEmpty,
  112. };