listContent.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import {Fragment, useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Button} from 'sentry/components/button';
  4. import ReplayRageClickSdkVersionBanner from 'sentry/components/replays/replayRageClickSdkVersionBanner';
  5. import {t} from 'sentry/locale';
  6. import {space} from 'sentry/styles/space';
  7. import {useHaveSelectedProjectsSentAnyReplayEvents} from 'sentry/utils/replays/hooks/useReplayOnboarding';
  8. import {MIN_DEAD_RAGE_CLICK_SDK} from 'sentry/utils/replays/sdkVersions';
  9. import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams';
  10. import useOrganization from 'sentry/utils/useOrganization';
  11. import usePageFilters from 'sentry/utils/usePageFilters';
  12. import useProjectSdkNeedsUpdate from 'sentry/utils/useProjectSdkNeedsUpdate';
  13. import DeadRageSelectorCards from 'sentry/views/replays/deadRageClick/deadRageSelectorCards';
  14. import ReplaysFilters from 'sentry/views/replays/list/filters';
  15. import ReplayOnboardingPanel from 'sentry/views/replays/list/replayOnboardingPanel';
  16. import ReplaysErroneousDeadRageCards from 'sentry/views/replays/list/replaysErroneousDeadRageCards';
  17. import ReplaysList from 'sentry/views/replays/list/replaysList';
  18. import ReplaysSearch from 'sentry/views/replays/list/search';
  19. export default function ListContent() {
  20. const organization = useOrganization();
  21. const hasSessionReplay = organization.features.includes('session-replay');
  22. const hasSentReplays = useHaveSelectedProjectsSentAnyReplayEvents();
  23. const hasdeadRageClickFeature = organization.features.includes(
  24. 'session-replay-rage-dead-selectors'
  25. );
  26. const {
  27. selection: {projects},
  28. } = usePageFilters();
  29. const rageClicksSdkVersion = useProjectSdkNeedsUpdate({
  30. minVersion: MIN_DEAD_RAGE_CLICK_SDK.minVersion,
  31. organization,
  32. projectId: projects.map(String),
  33. });
  34. const [widgetIsOpen, setWidgetIsOpen] = useState(true);
  35. useRouteAnalyticsParams({
  36. hasSessionReplay,
  37. hasSentReplays: hasSentReplays.hasSentOneReplay,
  38. hasRageClickMinSDK: !rageClicksSdkVersion.needsUpdate,
  39. });
  40. if (hasSentReplays.fetching || rageClicksSdkVersion.isFetching) {
  41. return null;
  42. }
  43. if (!hasSessionReplay || !hasSentReplays.hasSentOneReplay) {
  44. return (
  45. <Fragment>
  46. <FiltersContainer>
  47. <ReplaysFilters />
  48. <ReplaysSearch />
  49. </FiltersContainer>
  50. <ReplayOnboardingPanel />
  51. </Fragment>
  52. );
  53. }
  54. if (rageClicksSdkVersion.needsUpdate) {
  55. return (
  56. <Fragment>
  57. <FiltersContainer>
  58. <ReplaysFilters />
  59. <ReplaysSearch />
  60. </FiltersContainer>
  61. <ReplayRageClickSdkVersionBanner />
  62. <ReplaysList />
  63. </Fragment>
  64. );
  65. }
  66. return (
  67. <Fragment>
  68. <FiltersContainer>
  69. <ReplaysFilters />
  70. <SearchWrapper>
  71. <ReplaysSearch />
  72. {hasdeadRageClickFeature ? (
  73. <Button onClick={() => setWidgetIsOpen(!widgetIsOpen)}>
  74. {widgetIsOpen ? t('Hide Widgets') : t('Show Widgets')}
  75. </Button>
  76. ) : null}
  77. </SearchWrapper>
  78. </FiltersContainer>
  79. {hasdeadRageClickFeature ? (
  80. widgetIsOpen ? (
  81. <DeadRageSelectorCards />
  82. ) : null
  83. ) : (
  84. <ReplaysErroneousDeadRageCards />
  85. )}
  86. <ReplaysList />
  87. </Fragment>
  88. );
  89. }
  90. const FiltersContainer = styled('div')`
  91. display: flex;
  92. flex-direction: row;
  93. gap: ${space(2)};
  94. flex-wrap: wrap;
  95. `;
  96. const SearchWrapper = styled(FiltersContainer)`
  97. flex-grow: 1;
  98. flex-wrap: nowrap;
  99. `;