checkInTimeline.tsx 2.6 KB

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