replaysList.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import {Fragment, useMemo} from 'react';
  2. import {browserHistory} from 'react-router';
  3. import {Location} from 'history';
  4. import Pagination from 'sentry/components/pagination';
  5. import type {Organization} from 'sentry/types';
  6. import trackAdvancedAnalyticsEvent from 'sentry/utils/analytics/trackAdvancedAnalyticsEvent';
  7. import EventView from 'sentry/utils/discover/eventView';
  8. import {decodeScalar} from 'sentry/utils/queryString';
  9. import {DEFAULT_SORT} from 'sentry/utils/replays/fetchReplayList';
  10. import useReplayList from 'sentry/utils/replays/hooks/useReplayList';
  11. import {useHaveSelectedProjectsSentAnyReplayEvents} from 'sentry/utils/replays/hooks/useReplayOnboarding';
  12. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  13. import {useLocation} from 'sentry/utils/useLocation';
  14. import useOrganization from 'sentry/utils/useOrganization';
  15. import ReplayOnboardingPanel from 'sentry/views/replays/list/replayOnboardingPanel';
  16. import ReplayTable from 'sentry/views/replays/replayTable';
  17. import {ReplayColumns} from 'sentry/views/replays/replayTable/types';
  18. import type {ReplayListLocationQuery} from 'sentry/views/replays/types';
  19. import {REPLAY_LIST_FIELDS} from 'sentry/views/replays/types';
  20. function ReplaysList() {
  21. const location = useLocation<ReplayListLocationQuery>();
  22. const organization = useOrganization();
  23. const eventView = useMemo(() => {
  24. const query = decodeScalar(location.query.query, '');
  25. const conditions = new MutableSearch(query);
  26. return EventView.fromNewQueryWithLocation(
  27. {
  28. id: '',
  29. name: '',
  30. version: 2,
  31. fields: REPLAY_LIST_FIELDS,
  32. projects: [],
  33. query: conditions.formatString(),
  34. orderby: decodeScalar(location.query.sort, DEFAULT_SORT),
  35. },
  36. location
  37. );
  38. }, [location]);
  39. const hasSessionReplay = organization.features.includes('session-replay');
  40. const {hasSentOneReplay, fetching} = useHaveSelectedProjectsSentAnyReplayEvents();
  41. return hasSessionReplay && !fetching && hasSentOneReplay ? (
  42. <ReplaysListTable
  43. eventView={eventView}
  44. location={location}
  45. organization={organization}
  46. />
  47. ) : (
  48. <ReplayOnboardingPanel />
  49. );
  50. }
  51. function ReplaysListTable({
  52. eventView,
  53. location,
  54. organization,
  55. }: {
  56. eventView: EventView;
  57. location: Location;
  58. organization: Organization;
  59. }) {
  60. const {replays, pageLinks, isFetching, fetchError} = useReplayList({
  61. eventView,
  62. location,
  63. organization,
  64. });
  65. return (
  66. <Fragment>
  67. <ReplayTable
  68. fetchError={fetchError}
  69. isFetching={isFetching}
  70. replays={replays}
  71. sort={eventView.sorts[0]}
  72. visibleColumns={[
  73. ReplayColumns.replay,
  74. ReplayColumns.os,
  75. ReplayColumns.browser,
  76. ReplayColumns.duration,
  77. ReplayColumns.countErrors,
  78. ReplayColumns.activity,
  79. ]}
  80. />
  81. <Pagination
  82. pageLinks={pageLinks}
  83. onCursor={(cursor, path, searchQuery) => {
  84. trackAdvancedAnalyticsEvent('replay.list-paginated', {
  85. organization,
  86. direction: cursor?.endsWith(':1') ? 'prev' : 'next',
  87. });
  88. browserHistory.push({
  89. pathname: path,
  90. query: {...searchQuery, cursor},
  91. });
  92. }}
  93. />
  94. </Fragment>
  95. );
  96. }
  97. export default ReplaysList;