checkInTimeline.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import styled from '@emotion/styled';
  2. import {Resizeable} from 'sentry/components/replays/resizeable';
  3. import {space} from 'sentry/styles/space';
  4. import {JobTickTooltip} from 'sentry/views/monitors/components/overviewTimeline/jobTickTooltip';
  5. import {
  6. MonitorBucketData,
  7. TimeWindow,
  8. } from 'sentry/views/monitors/components/overviewTimeline/types';
  9. import {CheckInStatus} from 'sentry/views/monitors/types';
  10. import {getColorsFromStatus} from 'sentry/views/monitors/utils';
  11. import {getAggregateStatus} from 'sentry/views/monitors/utils/getAggregateStatus';
  12. import {mergeBuckets} from 'sentry/views/monitors/utils/mergeBuckets';
  13. interface Props {
  14. bucketedData: MonitorBucketData;
  15. end: Date;
  16. start: Date;
  17. timeWindow: TimeWindow;
  18. width?: number;
  19. }
  20. function getBucketedCheckInsPosition(
  21. timestamp: number,
  22. timelineStart: Date,
  23. msPerPixel: number
  24. ) {
  25. const elapsedSinceStart = new Date(timestamp).getTime() - timelineStart.getTime();
  26. return elapsedSinceStart / msPerPixel;
  27. }
  28. export function CheckInTimeline(props: Props) {
  29. const {bucketedData, start, end, timeWindow} = props;
  30. function renderTimelineWithWidth(width: number) {
  31. const elapsedMs = end.getTime() - start.getTime();
  32. const msPerPixel = elapsedMs / width;
  33. const jobTicks = mergeBuckets(bucketedData);
  34. return (
  35. <TimelineContainer>
  36. {jobTicks.map(jobTick => {
  37. const {
  38. startTs,
  39. width: tickWidth,
  40. envMapping,
  41. roundedLeft,
  42. roundedRight,
  43. } = jobTick;
  44. const timestampMs = startTs * 1000;
  45. const left = getBucketedCheckInsPosition(timestampMs, start, msPerPixel);
  46. return (
  47. <JobTickTooltip
  48. jobTick={jobTick}
  49. timeWindow={timeWindow}
  50. skipWrapper
  51. key={startTs}
  52. >
  53. <JobTick
  54. style={{left, width: tickWidth}}
  55. status={getAggregateStatus(envMapping)}
  56. roundedLeft={roundedLeft}
  57. roundedRight={roundedRight}
  58. />
  59. </JobTickTooltip>
  60. );
  61. })}
  62. </TimelineContainer>
  63. );
  64. }
  65. if (props.width) {
  66. return renderTimelineWithWidth(props.width);
  67. }
  68. return <Resizeable>{({width}) => renderTimelineWithWidth(width)}</Resizeable>;
  69. }
  70. const TimelineContainer = styled('div')`
  71. position: relative;
  72. height: 14px;
  73. margin: ${space(2)} 0;
  74. `;
  75. const JobTick = styled('div')<{
  76. roundedLeft: boolean;
  77. roundedRight: boolean;
  78. status: CheckInStatus;
  79. }>`
  80. position: absolute;
  81. background: ${p => getColorsFromStatus(p.status, p.theme).tickColor};
  82. width: 4px;
  83. height: 14px;
  84. ${p =>
  85. p.roundedLeft &&
  86. `
  87. border-top-left-radius: 2px;
  88. border-bottom-left-radius: 2px;
  89. `}
  90. ${p =>
  91. p.roundedRight &&
  92. `
  93. border-top-right-radius: 2px;
  94. border-bottom-right-radius: 2px;
  95. `}
  96. `;