listContent.tsx 3.5 KB

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