groupOpenPeriods.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import {useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import {DateTime} from 'sentry/components/dateTime';
  4. import Duration from 'sentry/components/duration';
  5. import GridEditable, {
  6. COL_WIDTH_UNDEFINED,
  7. type GridColumnOrder,
  8. } from 'sentry/components/gridEditable';
  9. import LoadingError from 'sentry/components/loadingError';
  10. import LoadingIndicator from 'sentry/components/loadingIndicator';
  11. import {t} from 'sentry/locale';
  12. import {useParams} from 'sentry/utils/useParams';
  13. import {EventListTable} from 'sentry/views/issueDetails/streamline/eventListTable';
  14. import {useGroup} from 'sentry/views/issueDetails/useGroup';
  15. interface OpenPeriodDisplayData {
  16. duration: React.ReactNode;
  17. end: React.ReactNode;
  18. start: React.ReactNode;
  19. title: React.ReactNode;
  20. }
  21. // TODO(snigdha): make this work for the old UI
  22. // TODO(snigdha): support pagination
  23. function IssueOpenPeriodsList() {
  24. const [now] = useState(() => new Date());
  25. const params = useParams<{groupId: string}>();
  26. const {
  27. data: group,
  28. isPending: isGroupPending,
  29. isError: isGroupError,
  30. refetch: refetchGroup,
  31. } = useGroup({groupId: params.groupId});
  32. if (isGroupError) {
  33. return <LoadingError onRetry={refetchGroup} />;
  34. }
  35. if (isGroupPending) {
  36. return <LoadingIndicator />;
  37. }
  38. // update the open periods to have date objects
  39. const openPeriods = group.openPeriods?.map(period => ({
  40. ...period,
  41. start: new Date(period.start),
  42. end: period.end ? new Date(period.end) : null,
  43. }));
  44. const getDuration = (start: Date, end?: Date) => {
  45. const duration = end
  46. ? (end.getTime() - start.getTime()) / 1000
  47. : (now.getTime() - start.getTime()) / 1000;
  48. return <Duration seconds={duration} precision="minutes" exact />;
  49. };
  50. if (!openPeriods) {
  51. return <LoadingError onRetry={refetchGroup} />;
  52. }
  53. const data: OpenPeriodDisplayData[] = openPeriods.map(period => ({
  54. title: <DateTime date={period.start} />,
  55. start: <DateTime date={period.start} />,
  56. end: period.end ? <DateTime date={period.end} /> : '—',
  57. duration: getDuration(period.start, period.end ?? undefined),
  58. }));
  59. const renderHeadCell = (col: GridColumnOrder) => {
  60. return <AlignLeft>{col.name}</AlignLeft>;
  61. };
  62. const renderBodyCell = (
  63. col: GridColumnOrder<string>,
  64. dataRow: OpenPeriodDisplayData
  65. ) => {
  66. const column = col.key as keyof OpenPeriodDisplayData;
  67. return <AlignLeft>{dataRow[column]}</AlignLeft>;
  68. };
  69. return (
  70. <EventListTable title={t('All Open Periods')} pagination={{enabled: false}}>
  71. <GridEditable
  72. isLoading={isGroupPending}
  73. data={data}
  74. columnOrder={[
  75. {key: 'title', width: COL_WIDTH_UNDEFINED, name: t('Title')},
  76. {key: 'start', width: COL_WIDTH_UNDEFINED, name: t('Start')},
  77. {key: 'end', width: COL_WIDTH_UNDEFINED, name: t('End')},
  78. {key: 'duration', width: COL_WIDTH_UNDEFINED, name: t('Duration')},
  79. ]}
  80. columnSortBy={[]}
  81. grid={{
  82. renderHeadCell,
  83. renderBodyCell,
  84. }}
  85. />
  86. </EventListTable>
  87. );
  88. }
  89. const AlignLeft = styled('span')`
  90. text-align: left;
  91. width: 100%;
  92. `;
  93. export default IssueOpenPeriodsList;