checkInTimeline.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import styled from '@emotion/styled';
  2. import {CheckInStatus} from 'sentry/views/monitors/types';
  3. import {getColorsFromStatus} from 'sentry/views/monitors/utils';
  4. import {getAggregateStatus} from 'sentry/views/monitors/utils/getAggregateStatus';
  5. import {mergeBuckets} from 'sentry/views/monitors/utils/mergeBuckets';
  6. import {JobTickTooltip} from './jobTickTooltip';
  7. import {MonitorBucketData, TimeWindowOptions} from './types';
  8. export interface CheckInTimelineProps {
  9. bucketedData: MonitorBucketData;
  10. end: Date;
  11. environment: string;
  12. start: Date;
  13. timeWindowConfig: TimeWindowOptions;
  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: CheckInTimelineProps) {
  25. const {bucketedData, start, end, timeWindowConfig, width, environment} = props;
  26. const elapsedMs = end.getTime() - start.getTime();
  27. const msPerPixel = elapsedMs / width;
  28. const jobTicks = mergeBuckets(bucketedData, environment);
  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. timeWindowConfig={timeWindowConfig}
  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: 100%;
  63. `;
  64. const JobTick = styled('div')<{
  65. roundedLeft: boolean;
  66. roundedRight: boolean;
  67. status: CheckInStatus;
  68. }>`
  69. position: absolute;
  70. top: calc(50% + 1px);
  71. transform: translateY(-50%);
  72. background: ${p => getColorsFromStatus(p.status, p.theme).tickColor};
  73. opacity: 0.7;
  74. width: 4px;
  75. height: 14px;
  76. ${p =>
  77. p.roundedLeft &&
  78. `
  79. border-top-left-radius: 2px;
  80. border-bottom-left-radius: 2px;
  81. `}
  82. ${p =>
  83. p.roundedRight &&
  84. `
  85. border-top-right-radius: 2px;
  86. border-bottom-right-radius: 2px;
  87. `}
  88. `;