diff --git a/api-docs/dump.rdb b/api-docs/dump.rdb deleted file mode 100644 index ffe6bb5953f188..00000000000000 Binary files a/api-docs/dump.rdb and /dev/null differ diff --git a/static/app/views/issueDetails/groupReplays/groupReplays.spec.tsx b/static/app/views/issueDetails/groupReplays/groupReplays.spec.tsx index 9fa0e54ff103d7..ca9318fd63d12e 100644 --- a/static/app/views/issueDetails/groupReplays/groupReplays.spec.tsx +++ b/static/app/views/issueDetails/groupReplays/groupReplays.spec.tsx @@ -51,6 +51,11 @@ function init({organizationProps = {features: ['session-replay']}}: InitializeOr describe('GroupReplays', () => { beforeEach(() => { MockApiClient.clearMockResponses(); + MockApiClient.addMockResponse({ + method: 'GET', + url: `/organizations/org-slug/sdk-updates/`, + body: [], + }); }); describe('Replay Feature Disabled', () => { diff --git a/static/app/views/performance/transactionSummary/transactionReplays/index.spec.tsx b/static/app/views/performance/transactionSummary/transactionReplays/index.spec.tsx index b3b5b592a418c9..9bc188ab43aba8 100644 --- a/static/app/views/performance/transactionSummary/transactionReplays/index.spec.tsx +++ b/static/app/views/performance/transactionSummary/transactionReplays/index.spec.tsx @@ -89,6 +89,11 @@ describe('TransactionReplays', () => { let eventsMockApi: jest.Mock; let replaysMockApi: jest.Mock; beforeEach(() => { + MockApiClient.addMockResponse({ + method: 'GET', + url: `/organizations/org-slug/sdk-updates/`, + body: [], + }); MockApiClient.addMockResponse({ url: '/organizations/org-slug/events-has-measurements/', body: {measurements: false}, diff --git a/static/app/views/replays/list/replaysList.tsx b/static/app/views/replays/list/replaysList.tsx index 9bebea4cb2b1cc..c01a86a361ff41 100644 --- a/static/app/views/replays/list/replaysList.tsx +++ b/static/app/views/replays/list/replaysList.tsx @@ -83,7 +83,7 @@ function ReplaysListTable({ const {needsUpdate: allSelectedProjectsNeedUpdates} = useProjectSdkNeedsUpdate({ minVersion: MIN_REPLAY_CLICK_SDK, organization, - projectId: projects.map(p => String(p)), + projectId: projects.map(String), }); const conditions = useMemo(() => { diff --git a/static/app/views/replays/replayTable/index.tsx b/static/app/views/replays/replayTable/index.tsx index 4e55719f4ea3dd..a38b43bd12f233 100644 --- a/static/app/views/replays/replayTable/index.tsx +++ b/static/app/views/replays/replayTable/index.tsx @@ -3,14 +3,17 @@ import styled from '@emotion/styled'; import {Location} from 'history'; import {Alert} from 'sentry/components/alert'; +import ExternalLink from 'sentry/components/links/externalLink'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import PanelTable from 'sentry/components/panels/panelTable'; -import {t} from 'sentry/locale'; +import {t, tct} from 'sentry/locale'; import EventView from 'sentry/utils/discover/eventView'; import type {Sort} from 'sentry/utils/discover/fields'; import getRouteStringFromRoutes from 'sentry/utils/getRouteStringFromRoutes'; import {useLocation} from 'sentry/utils/useLocation'; import useOrganization from 'sentry/utils/useOrganization'; +import usePageFilters from 'sentry/utils/usePageFilters'; +import useProjectSdkNeedsUpdate from 'sentry/utils/useProjectSdkNeedsUpdate'; import {useRoutes} from 'sentry/utils/useRoutes'; import type {ReplayListRecordWithTx} from 'sentry/views/performance/transactionSummary/transactionReplays/useReplaysWithTxData'; import HeaderCell from 'sentry/views/replays/replayTable/headerCell'; @@ -28,6 +31,8 @@ import { import {ReplayColumn} from 'sentry/views/replays/replayTable/types'; import type {ReplayListRecord} from 'sentry/views/replays/types'; +const MIN_DEAD_RAGE_CLICK_SDK = '7.60.1'; + type Props = { fetchError: undefined | Error; isFetching: boolean; @@ -53,6 +58,18 @@ function ReplayTable({ const newLocation = useLocation(); const organization = useOrganization(); + const { + selection: {projects}, + } = usePageFilters(); + + const needSDKUpgrade = useProjectSdkNeedsUpdate({ + minVersion: MIN_DEAD_RAGE_CLICK_SDK, + organization, + projectId: projects.map(String), + }); + + const showBottomBorder = visibleColumns.includes(ReplayColumn.MOST_RAGE_CLICKS); + const location: Location = saveLocation ? { pathname: '', @@ -78,7 +95,7 @@ function ReplayTable({ data-test-id="replay-table" gridRows={undefined} > - + {typeof fetchError === 'string' ? fetchError : t( @@ -89,6 +106,32 @@ function ReplayTable({ ); } + if ( + needSDKUpgrade.needsUpdate && + visibleColumns.includes(ReplayColumn.COUNT_DEAD_CLICKS) + ) { + return ( + } + disablePadding + > + + {tct('[data] requires [sdkPrompt]. [link:Upgrade now.]', { + data: Rage and dead clicks, + sdkPrompt: {t('SDK version >= 7.60.1')}, + link: ( + + ), + })} + + + ); + } + const referrer = getRouteStringFromRoutes(routes); const eventView = EventView.fromLocation(location); @@ -207,14 +250,18 @@ const StyledPanelTable = styled(PanelTable)<{ ) .join(' ')}; - ${props => (props.gridRows ? `grid-template-rows: ${props.gridRows};` : '')} + ${props => + props.gridRows + ? `grid-template-rows: ${props.gridRows};` + : `grid-template-rows: 44px max-content;`} `; -const StyledAlert = styled(Alert)` +const StyledAlert = styled(Alert)<{showBottomBorder?: boolean}>` border-radius: 0; - border-width: 1px 0 0 0; grid-column: 1/-1; margin-bottom: 0; + ${props => + props.showBottomBorder ? `border-width: 1px 0 1px 0;` : `border-width: 1px 0 0 0;`} `; export default ReplayTable;