checkInTimeline.tsx 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import {Theme} from '@emotion/react';
  2. import styled from '@emotion/styled';
  3. import {Resizeable} from 'sentry/components/replays/resizeable';
  4. import {space} from 'sentry/styles/space';
  5. import {CheckIn, CheckInStatus} from 'sentry/views/monitors/types';
  6. interface Props {
  7. checkins: CheckIn[];
  8. end: Date;
  9. start: Date;
  10. width?: number;
  11. }
  12. function getColorFromStatus(status: CheckInStatus, theme: Theme) {
  13. const statusToColor: Record<CheckInStatus, string> = {
  14. [CheckInStatus.ERROR]: theme.red200,
  15. [CheckInStatus.TIMEOUT]: theme.red200,
  16. [CheckInStatus.OK]: theme.green200,
  17. [CheckInStatus.MISSED]: theme.yellow200,
  18. [CheckInStatus.IN_PROGRESS]: theme.disabled,
  19. };
  20. return statusToColor[status];
  21. }
  22. function getCheckInPosition(checkDate: string, timelineStart: Date, msPerPixel: number) {
  23. const elapsedSinceStart = new Date(checkDate).getTime() - timelineStart.getTime();
  24. return elapsedSinceStart / msPerPixel;
  25. }
  26. export function CheckInTimeline(props: Props) {
  27. const {checkins, start, end} = props;
  28. function renderTimelineWithWidth(width: number) {
  29. const timeWindow = end.getTime() - start.getTime();
  30. const msPerPixel = timeWindow / width;
  31. return (
  32. <TimelineContainer>
  33. {checkins.map(({id, dateCreated, status}) => {
  34. const left = getCheckInPosition(dateCreated, start, msPerPixel);
  35. if (left < 0) {
  36. return null;
  37. }
  38. return <JobTick key={id} left={left} status={status} />;
  39. })}
  40. </TimelineContainer>
  41. );
  42. }
  43. if (props.width) {
  44. return renderTimelineWithWidth(props.width);
  45. }
  46. return <Resizeable>{({width}) => renderTimelineWithWidth(width)}</Resizeable>;
  47. }
  48. const TimelineContainer = styled('div')`
  49. position: relative;
  50. height: 14px;
  51. margin: ${space(4)} 0;
  52. `;
  53. const JobTick = styled('div')<{left: number; status: CheckInStatus}>`
  54. position: absolute;
  55. width: 4px;
  56. height: 14px;
  57. border-radius: 6px;
  58. left: ${p => p.left}px;
  59. background: ${p => getColorFromStatus(p.status, p.theme)};
  60. `;