cronDetailsTimeline.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import {useRef} from 'react';
  2. import styled from '@emotion/styled';
  3. import moment from 'moment';
  4. import Panel from 'sentry/components/panels/panel';
  5. import Text from 'sentry/components/text';
  6. import {t} from 'sentry/locale';
  7. import {space} from 'sentry/styles/space';
  8. import {Organization} from 'sentry/types';
  9. import {parsePeriodToHours} from 'sentry/utils/dates';
  10. import {useApiQuery} from 'sentry/utils/queryClient';
  11. import {useDimensions} from 'sentry/utils/useDimensions';
  12. import usePageFilters from 'sentry/utils/usePageFilters';
  13. import useRouter from 'sentry/utils/useRouter';
  14. import {
  15. GridLineOverlay,
  16. GridLineTimeLabels,
  17. } from 'sentry/views/monitors/components/overviewTimeline/gridLines';
  18. import {TimelineTableRow} from 'sentry/views/monitors/components/overviewTimeline/timelineTableRow';
  19. import {MonitorBucketData} from 'sentry/views/monitors/components/overviewTimeline/types';
  20. import {getConfigFromTimeRange} from 'sentry/views/monitors/components/overviewTimeline/utils';
  21. import {Monitor} from 'sentry/views/monitors/types';
  22. interface Props {
  23. monitor: Monitor;
  24. organization: Organization;
  25. }
  26. export function CronDetailsTimeline({monitor, organization}: Props) {
  27. const {location} = useRouter();
  28. const nowRef = useRef(new Date());
  29. const {selection} = usePageFilters();
  30. const {period} = selection.datetime;
  31. let {end, start} = selection.datetime;
  32. if (!start || !end) {
  33. end = nowRef.current;
  34. start = moment(end)
  35. .subtract(parsePeriodToHours(period ?? '24h'), 'hour')
  36. .toDate();
  37. } else {
  38. start = new Date(start);
  39. end = new Date(end);
  40. }
  41. const elementRef = useRef<HTMLDivElement>(null);
  42. const {width: timelineWidth} = useDimensions<HTMLDivElement>({elementRef});
  43. const config = getConfigFromTimeRange(start, end, timelineWidth);
  44. const elapsedMinutes = config.elapsedMinutes;
  45. const rollup = Math.floor((elapsedMinutes * 60) / timelineWidth);
  46. const monitorStatsQueryKey = `/organizations/${organization.slug}/monitors-stats/`;
  47. const {data: monitorStats, isLoading} = useApiQuery<Record<string, MonitorBucketData>>(
  48. [
  49. monitorStatsQueryKey,
  50. {
  51. query: {
  52. until: Math.floor(end.getTime() / 1000),
  53. since: Math.floor(start.getTime() / 1000),
  54. monitor: monitor.slug,
  55. resolution: `${rollup}s`,
  56. ...location.query,
  57. },
  58. },
  59. ],
  60. {
  61. staleTime: 0,
  62. enabled: timelineWidth > 0,
  63. }
  64. );
  65. return (
  66. <TimelineContainer>
  67. <TimelineWidthTracker ref={elementRef} />
  68. <TimelineTitle>{t('Check-Ins')}</TimelineTitle>
  69. <StyledGridLineTimeLabels
  70. timeWindowConfig={config}
  71. start={start}
  72. end={end}
  73. width={timelineWidth}
  74. />
  75. <StyledGridLineOverlay
  76. showCursor={!isLoading}
  77. timeWindowConfig={config}
  78. start={start}
  79. end={end}
  80. width={timelineWidth}
  81. />
  82. <TimelineTableRow
  83. monitor={monitor}
  84. bucketedData={monitorStats?.[monitor.slug]}
  85. timeWindowConfig={config}
  86. end={end}
  87. start={start}
  88. width={timelineWidth}
  89. singleMonitorView
  90. />
  91. </TimelineContainer>
  92. );
  93. }
  94. const TimelineContainer = styled(Panel)`
  95. display: grid;
  96. grid-template-columns: 135px 1fr;
  97. `;
  98. const StyledGridLineTimeLabels = styled(GridLineTimeLabels)`
  99. grid-column: 2;
  100. `;
  101. const StyledGridLineOverlay = styled(GridLineOverlay)`
  102. grid-column: 2;
  103. `;
  104. const TimelineWidthTracker = styled('div')`
  105. position: absolute;
  106. width: 100%;
  107. grid-row: 1;
  108. grid-column: 2;
  109. `;
  110. const TimelineTitle = styled(Text)`
  111. ${p => p.theme.text.cardTitle};
  112. border-bottom: 1px solid ${p => p.theme.border};
  113. padding: ${space(2)};
  114. `;