eventMetaData.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import React from 'react';
  2. import styled from '@emotion/styled';
  3. import Duration from 'sentry/components/duration';
  4. import ProjectBadge from 'sentry/components/idBadge/projectBadge';
  5. import Placeholder from 'sentry/components/placeholder';
  6. import TimeSince from 'sentry/components/timeSince';
  7. import {PlatformKey} from 'sentry/data/platformCategories';
  8. import {IconCalendar, IconClock, IconFire} from 'sentry/icons';
  9. import space from 'sentry/styles/space';
  10. import type {Crumb} from 'sentry/types/breadcrumbs';
  11. import type {EventTransaction} from 'sentry/types/event';
  12. import {defined} from 'sentry/utils';
  13. type Props = {
  14. crumbs: Crumb[] | undefined;
  15. duration: number | undefined;
  16. event: EventTransaction | undefined;
  17. };
  18. function EventMetaData({crumbs, duration, event}: Props) {
  19. const errors = crumbs?.filter(crumb => crumb.type === 'error').length;
  20. return (
  21. <KeyMetrics>
  22. <ProjectBadge
  23. project={{
  24. slug: event?.projectSlug || '',
  25. id: event?.projectID,
  26. platform: event?.platform as PlatformKey,
  27. }}
  28. avatarSize={16}
  29. />
  30. <KeyMetricData>
  31. {event ? (
  32. <React.Fragment>
  33. <IconCalendar color="gray300" />
  34. <TimeSince date={event.dateReceived} shorten />
  35. </React.Fragment>
  36. ) : (
  37. <HeaderPlaceholder />
  38. )}
  39. </KeyMetricData>
  40. <KeyMetricData>
  41. {duration !== undefined ? (
  42. <React.Fragment>
  43. <IconClock color="gray300" />
  44. <Duration
  45. seconds={Math.floor(msToSec(duration || 0)) || 1}
  46. abbreviation
  47. exact
  48. />
  49. </React.Fragment>
  50. ) : (
  51. <HeaderPlaceholder />
  52. )}
  53. </KeyMetricData>
  54. <KeyMetricData>
  55. {defined(errors) ? (
  56. <React.Fragment>
  57. <IconFire color="red300" />
  58. {errors}
  59. </React.Fragment>
  60. ) : (
  61. <HeaderPlaceholder />
  62. )}
  63. </KeyMetricData>
  64. </KeyMetrics>
  65. );
  66. }
  67. function msToSec(ms: number) {
  68. return ms / 1000;
  69. }
  70. const HeaderPlaceholder = styled(function HeaderPlaceholder(
  71. props: React.ComponentProps<typeof Placeholder>
  72. ) {
  73. return <Placeholder width="100%" height="19px" {...props} />;
  74. })`
  75. background-color: ${p => p.theme.background};
  76. `;
  77. const KeyMetrics = styled('div')`
  78. display: grid;
  79. gap: ${space(3)};
  80. grid-template-columns: repeat(4, max-content);
  81. align-items: center;
  82. justify-content: end;
  83. font-size: ${p => p.theme.fontSizeMedium};
  84. `;
  85. const KeyMetricData = styled('div')`
  86. color: ${p => p.theme.textColor};
  87. font-weight: normal;
  88. display: grid;
  89. grid-template-columns: repeat(2, max-content);
  90. align-items: center;
  91. gap: ${space(1)};
  92. `;
  93. export default EventMetaData;