diff --git a/static/app/components/events/eventReplay/replayPreviewPlayer.tsx b/static/app/components/events/eventReplay/replayPreviewPlayer.tsx index d50f079d607de6..2af075add070ff 100644 --- a/static/app/components/events/eventReplay/replayPreviewPlayer.tsx +++ b/static/app/components/events/eventReplay/replayPreviewPlayer.tsx @@ -1,6 +1,7 @@ import type {ComponentProps} from 'react'; import {useEffect, useRef, useState} from 'react'; import styled from '@emotion/styled'; +import type {Query} from 'history'; import {Alert} from 'sentry/components/core/alert'; import {Button} from 'sentry/components/core/button'; @@ -38,6 +39,7 @@ import {makeReplaysPathname} from 'sentry/views/replays/pathnames'; import type {ReplayListRecord, ReplayRecord} from 'sentry/views/replays/types'; export default function ReplayPreviewPlayer({ + query, errorBeforeReplayStart, replayId, fullReplayButtonProps, @@ -56,6 +58,7 @@ export default function ReplayPreviewPlayer({ handleForwardClick?: () => void; overlayContent?: React.ReactNode; playPausePriority?: ComponentProps['priority']; + query?: Query; showNextAndPrevious?: boolean; }) { const routes = useRoutes(); @@ -100,6 +103,7 @@ export default function ReplayPreviewPlayer({ )} ; }; export default function ReplayTable({ + query, columns, error, isPending, @@ -110,6 +113,7 @@ export default function ReplayTable({ {columns.map((column, columnIndex) => ( { + Component: ({replay, query}) => { const organization = useOrganization(); return ( - + @@ -507,9 +511,10 @@ export const ReplaySessionColumn: ReplayTableColumn = { interactive: true, sortKey: 'started_at', width: 'minmax(150px, 1fr)', - Component: ({replay}) => { + Component: ({replay, query}) => { const routes = useRoutes(); - const location = useLocation(); + const referrer = getRouteStringFromRoutes(routes); + const organization = useOrganization(); const project = useProjectFromId({project_id: replay.project_id ?? undefined}); @@ -522,50 +527,6 @@ export const ReplaySessionColumn: ReplayTableColumn = { 'For TypeScript: replay.started_at is implied because replay.is_archived is false' ); - const referrer = getRouteStringFromRoutes(routes); - const eventView = EventView.fromLocation(location); - - const {statsPeriod, start, end, ...eventViewQuery} = - eventView.generateQueryStringObject(); - - const detailsTabQuery: Query = { - referrer, - ...eventViewQuery, - }; - - if (typeof statsPeriod === 'string') { - const {start: playlistStart, end: playlistEnd} = parseStatsPeriod( - statsPeriod, - undefined, - true - ); - detailsTabQuery.playlistStart = playlistStart; - detailsTabQuery.playlistEnd = playlistEnd; - } else if (start && end) { - detailsTabQuery.playlistStart = start; - detailsTabQuery.playlistEnd = end; - } - - // Because the sort and cursor field is only generated in EventView conditionally and we - // want to avoid dirtying the URL with fields, we manually add them to the query here. - if (location.query.sort) { - detailsTabQuery.playlistSort = location.query.sort; - } - if (location.query.cursor) { - detailsTabQuery.cursor = location.query.cursor; - } - - const replayDetailsPathname = makeReplaysPathname({ - path: `/${replay.id}/`, - organization, - }); - - const detailsTab = () => { - return { - pathname: replayDetailsPathname, - query: detailsTabQuery, - }; - }; const trackNavigationEvent = () => trackAnalytics('replay.list-navigate-to-details', { project_id: project?.id, @@ -576,7 +537,13 @@ export const ReplaySessionColumn: ReplayTableColumn = { }); return ( - + ); diff --git a/static/app/components/replays/usePlaylistQuery.tsx b/static/app/components/replays/usePlaylistQuery.tsx new file mode 100644 index 00000000000000..1ab31798a5c3eb --- /dev/null +++ b/static/app/components/replays/usePlaylistQuery.tsx @@ -0,0 +1,50 @@ +import type {Query} from 'history'; + +import {parseStatsPeriod} from 'sentry/components/timeRangeSelector/utils'; +import EventView from 'sentry/utils/discover/eventView'; +import {useLocation} from 'sentry/utils/useLocation'; +import type {ReplayListQueryReferrer} from 'sentry/views/replays/types'; + +export function usePlaylistQuery( + referrer: ReplayListQueryReferrer, + eventView?: EventView +): Query { + const location = useLocation(); + if (!eventView) { + eventView = EventView.fromLocation(location); + } + + const {statsPeriod, start, end, query, project, environment} = + eventView.generateQueryStringObject(); + + const eventViewQuery: Query = { + query, + referrer, + project, + environment, + }; + + if (typeof statsPeriod === 'string') { + const {start: playlistStart, end: playlistEnd} = parseStatsPeriod( + statsPeriod, + undefined, + true + ); + eventViewQuery.playlistStart = playlistStart; + eventViewQuery.playlistEnd = playlistEnd; + } else if (start && end) { + eventViewQuery.playlistStart = start; + eventViewQuery.playlistEnd = end; + } + + // Because the sort and cursor field is only generated in EventView conditionally and we + // want to avoid dirtying the URL with fields, we manually add them to the query here. + if (location.query.sort) { + eventViewQuery.playlistSort = location.query.sort; + } + if (location.query.cursor) { + eventViewQuery.cursor = location.query.cursor; + } + eventViewQuery.referrer = referrer; + return eventViewQuery; +} diff --git a/static/app/views/issueDetails/groupReplays/groupReplays.spec.tsx b/static/app/views/issueDetails/groupReplays/groupReplays.spec.tsx index f99aa7bcda32bf..a9147d274c17ca 100644 --- a/static/app/views/issueDetails/groupReplays/groupReplays.spec.tsx +++ b/static/app/views/issueDetails/groupReplays/groupReplays.spec.tsx @@ -414,7 +414,7 @@ describe('GroupReplays', () => { expect(await screen.findAllByText('testDisplayName')).toHaveLength(2); const expectedQuery = - 'playlistEnd=2022-09-28T23%3A29%3A13&playlistStart=2022-09-14T23%3A29%3A13&query=&referrer=%2Forganizations%2F%3AorgId%2Fissues%2F%3AgroupId%2Freplays%2F&yAxis=count%28%29'; + 'playlistEnd=2022-09-28T23%3A29%3A13&playlistStart=2022-06-30T23%3A29%3A13&query=id%3A%5B346789a703f6454384f1de473b8b9fcc%2Cb05dae9b6be54d21a4d5ad9f8f02b780%5D&referrer=issueReplays'; // Expect the first row to have the correct href expect( diff --git a/static/app/views/issueDetails/groupReplays/groupReplays.tsx b/static/app/views/issueDetails/groupReplays/groupReplays.tsx index 9e16d2e8a598df..64903ab34b3a62 100644 --- a/static/app/views/issueDetails/groupReplays/groupReplays.tsx +++ b/static/app/views/issueDetails/groupReplays/groupReplays.tsx @@ -1,7 +1,7 @@ import {Fragment, useEffect, useMemo} from 'react'; import {css} from '@emotion/react'; import styled from '@emotion/styled'; -import type {Location} from 'history'; +import type {Location, Query} from 'history'; import {Button} from 'sentry/components/core/button'; import * as Layout from 'sentry/components/layouts/thirds'; @@ -22,6 +22,7 @@ import { ReplayPlayPauseColumn, ReplaySessionColumn, } from 'sentry/components/replays/table/replayTableColumns'; +import {usePlaylistQuery} from 'sentry/components/replays/usePlaylistQuery'; import {replayMobilePlatforms} from 'sentry/data/platformCategories'; import {IconPlay, IconUser} from 'sentry/icons'; import {t, tn} from 'sentry/locale'; @@ -165,6 +166,7 @@ export default function GroupReplays({group}: Props) { function SelectedReplayWrapper({ children, + query, group, replaySlug, overlayContent, @@ -175,6 +177,7 @@ function SelectedReplayWrapper({ overlayContent: React.ReactNode; replaySlug: string; replays: ReplayListRecord[] | undefined; + query?: Query; }) { const organization = useOrganization(); const readerResult = useLoadReplayReader({ @@ -195,6 +198,7 @@ function SelectedReplayWrapper({ autoStart > {replayTable} diff --git a/static/app/views/issueDetails/groupReplays/groupReplaysPlayer.tsx b/static/app/views/issueDetails/groupReplays/groupReplaysPlayer.tsx index 880d01b7a18cbe..4a12fa0b2a7f8f 100644 --- a/static/app/views/issueDetails/groupReplays/groupReplaysPlayer.tsx +++ b/static/app/views/issueDetails/groupReplays/groupReplaysPlayer.tsx @@ -1,4 +1,5 @@ import styled from '@emotion/styled'; +import type {Query} from 'history'; import NegativeSpaceContainer from 'sentry/components/container/negativeSpaceContainer'; import {REPLAY_LOADING_HEIGHT_LARGE} from 'sentry/components/events/eventReplay/constants'; @@ -21,10 +22,12 @@ interface Props { handleForwardClick: undefined | (() => void); overlayContent: React.ReactNode; replayReaderResult: ReturnType; + query?: Query; } export default function GroupReplaysPlayer({ analyticsContext, + query, handleForwardClick, handleBackClick, overlayContent, @@ -65,6 +68,7 @@ export default function GroupReplaysPlayer({ { expect(screen.getAllByText('testDisplayName')).toHaveLength(2); const expectedQuery = - 'playlistEnd=2022-09-28T23%3A29%3A13&playlistStart=2022-09-14T23%3A29%3A13&project=1&query=test&referrer=replays%2F&yAxis=count%28%29'; + 'playlistEnd=2022-09-28T23%3A29%3A13&playlistStart=2022-09-14T23%3A29%3A13&query=test&referrer=transactionReplays'; // Expect the first row to have the correct href expect( screen.getByRole('link', { diff --git a/static/app/views/performance/transactionSummary/transactionReplays/transactionReplays.tsx b/static/app/views/performance/transactionSummary/transactionReplays/transactionReplays.tsx index e4c1dd426b7c5e..8df573c86873f1 100644 --- a/static/app/views/performance/transactionSummary/transactionReplays/transactionReplays.tsx +++ b/static/app/views/performance/transactionSummary/transactionReplays/transactionReplays.tsx @@ -14,6 +14,7 @@ import { ReplaySessionColumn, ReplaySlowestTransactionColumn, } from 'sentry/components/replays/table/replayTableColumns'; +import {usePlaylistQuery} from 'sentry/components/replays/usePlaylistQuery'; import type {Organization} from 'sentry/types/organization'; import EventView from 'sentry/utils/discover/eventView'; import useReplayList from 'sentry/utils/replays/hooks/useReplayList'; @@ -89,6 +90,7 @@ function ReplaysContent({ if (!eventView.query) { eventView.query = String(location.query.query ?? ''); } + const playlistQuery = usePlaylistQuery('transactionReplays', eventView); const newLocation = useMemo( () => ({query: {}}) as Location, @@ -121,6 +123,7 @@ function ReplaysContent({ return ( @@ -121,6 +124,7 @@ export default function ReplayIndexTable({ ) : (