datePageFilter.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import {updateDateTime} from 'sentry/actionCreators/pageFilters';
  4. import Datetime from 'sentry/components/dateTime';
  5. import PageFilterDropdownButton from 'sentry/components/organizations/pageFilters/pageFilterDropdownButton';
  6. import PageFilterPinIndicator from 'sentry/components/organizations/pageFilters/pageFilterPinIndicator';
  7. import TimeRangeSelector, {
  8. ChangeData,
  9. } from 'sentry/components/organizations/timeRangeSelector';
  10. import {IconCalendar} from 'sentry/icons';
  11. import {space} from 'sentry/styles/space';
  12. import {
  13. DEFAULT_DAY_END_TIME,
  14. DEFAULT_DAY_START_TIME,
  15. getFormattedDate,
  16. } from 'sentry/utils/dates';
  17. import useOrganization from 'sentry/utils/useOrganization';
  18. import usePageFilters from 'sentry/utils/usePageFilters';
  19. import useRouter from 'sentry/utils/useRouter';
  20. type Props = Omit<
  21. React.ComponentProps<typeof TimeRangeSelector>,
  22. 'organization' | 'start' | 'end' | 'utc' | 'relative' | 'onUpdate'
  23. > & {
  24. /**
  25. * Reset these URL params when we fire actions (custom routing only)
  26. */
  27. resetParamsOnChange?: string[];
  28. };
  29. function DatePageFilter({resetParamsOnChange, disabled, ...props}: Props) {
  30. const router = useRouter();
  31. const {selection, desyncedFilters} = usePageFilters();
  32. const organization = useOrganization();
  33. const {start, end, period, utc} = selection.datetime;
  34. const handleUpdate = (timePeriodUpdate: ChangeData) => {
  35. const {relative, ...startEndUtc} = timePeriodUpdate;
  36. const newTimePeriod = {
  37. period: relative,
  38. ...startEndUtc,
  39. };
  40. updateDateTime(newTimePeriod, router, {save: true, resetParams: resetParamsOnChange});
  41. };
  42. const customDropdownButton = ({getActorProps, isOpen}) => {
  43. let label;
  44. if (start && end) {
  45. const startTimeFormatted = getFormattedDate(start, 'HH:mm:ss', {local: true});
  46. const endTimeFormatted = getFormattedDate(end, 'HH:mm:ss', {local: true});
  47. const showDateOnly =
  48. startTimeFormatted === DEFAULT_DAY_START_TIME &&
  49. endTimeFormatted === DEFAULT_DAY_END_TIME;
  50. label = (
  51. <Fragment>
  52. <Datetime date={start} dateOnly={showDateOnly} />
  53. {' – '}
  54. <Datetime date={end} dateOnly={showDateOnly} />
  55. </Fragment>
  56. );
  57. } else {
  58. label = period?.toUpperCase();
  59. }
  60. return (
  61. <PageFilterDropdownButton
  62. detached
  63. disabled={disabled}
  64. hideBottomBorder={false}
  65. isOpen={isOpen}
  66. highlighted={desyncedFilters.has('datetime')}
  67. data-test-id="page-filter-timerange-selector"
  68. {...getActorProps()}
  69. >
  70. <DropdownTitle>
  71. <PageFilterPinIndicator filter="datetime">
  72. <IconCalendar />
  73. </PageFilterPinIndicator>
  74. <TitleContainer>{label}</TitleContainer>
  75. </DropdownTitle>
  76. </PageFilterDropdownButton>
  77. );
  78. };
  79. return (
  80. <TimeRangeSelector
  81. organization={organization}
  82. start={start}
  83. end={end}
  84. relative={period}
  85. utc={utc}
  86. onUpdate={handleUpdate}
  87. customDropdownButton={customDropdownButton}
  88. disabled={disabled}
  89. showPin
  90. detached
  91. {...props}
  92. />
  93. );
  94. }
  95. const TitleContainer = styled('div')`
  96. flex: 1 1 0%;
  97. margin-left: ${space(1)};
  98. text-align: left;
  99. ${p => p.theme.overflowEllipsis}
  100. `;
  101. const DropdownTitle = styled('div')`
  102. display: flex;
  103. align-items: center;
  104. flex: 1;
  105. width: max-content;
  106. min-width: 0;
  107. `;
  108. export default DatePageFilter;