listContent.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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 useAllMobileProj from 'sentry/views/replays/detail/useAllMobileProj';
  15. import ReplaysFilters from 'sentry/views/replays/list/filters';
  16. import ReplayOnboardingPanel from 'sentry/views/replays/list/replayOnboardingPanel';
  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 {
  24. selection: {projects},
  25. } = usePageFilters();
  26. const rageClicksSdkVersion = useProjectSdkNeedsUpdate({
  27. minVersion: MIN_DEAD_RAGE_CLICK_SDK.minVersion,
  28. organization,
  29. projectId: projects.map(String),
  30. });
  31. const {allMobileProj} = useAllMobileProj();
  32. const [widgetIsOpen, setWidgetIsOpen] = useState(true);
  33. useRouteAnalyticsParams({
  34. hasSessionReplay,
  35. hasSentReplays: hasSentReplays.hasSentOneReplay,
  36. hasRageClickMinSDK: !rageClicksSdkVersion.needsUpdate,
  37. });
  38. if (hasSentReplays.fetching || rageClicksSdkVersion.isFetching) {
  39. return null;
  40. }
  41. if (!hasSessionReplay || !hasSentReplays.hasSentOneReplay) {
  42. return (
  43. <Fragment>
  44. <FiltersContainer>
  45. <ReplaysFilters />
  46. <ReplaysSearch />
  47. </FiltersContainer>
  48. <ReplayOnboardingPanel />
  49. </Fragment>
  50. );
  51. }
  52. if (rageClicksSdkVersion.needsUpdate) {
  53. return (
  54. <Fragment>
  55. <FiltersContainer>
  56. <ReplaysFilters />
  57. <ReplaysSearch />
  58. </FiltersContainer>
  59. <ReplayRageClickSdkVersionBanner />
  60. <ReplaysList />
  61. </Fragment>
  62. );
  63. }
  64. return (
  65. <Fragment>
  66. <FiltersContainer>
  67. <ReplaysFilters />
  68. <SearchWrapper>
  69. <ReplaysSearch />
  70. {!allMobileProj && (
  71. <Button onClick={() => setWidgetIsOpen(!widgetIsOpen)}>
  72. {widgetIsOpen ? t('Hide Widgets') : t('Show Widgets')}
  73. </Button>
  74. )}
  75. </SearchWrapper>
  76. </FiltersContainer>
  77. {widgetIsOpen && !allMobileProj ? <DeadRageSelectorCards /> : null}
  78. <ReplaysList />
  79. </Fragment>
  80. );
  81. }
  82. const FiltersContainer = styled('div')`
  83. display: flex;
  84. flex-direction: row;
  85. gap: ${space(2)};
  86. flex-wrap: wrap;
  87. `;
  88. const SearchWrapper = styled(FiltersContainer)`
  89. flex-grow: 1;
  90. flex-wrap: nowrap;
  91. `;