@@ -4,15 +4,22 @@ import styled from '@emotion/styled';
4
4
import emptyStateImg from 'sentry-images/spot/replays-empty-state.svg' ;
5
5
6
6
import Feature from 'sentry/components/acl/feature' ;
7
+ import Alert from 'sentry/components/alert' ;
7
8
import { Button } from 'sentry/components/button' ;
8
9
import ButtonBar from 'sentry/components/buttonBar' ;
9
10
import HookOrDefault from 'sentry/components/hookOrDefault' ;
11
+ import ExternalLink from 'sentry/components/links/externalLink' ;
10
12
import OnboardingPanel from 'sentry/components/onboardingPanel' ;
11
- import { t } from 'sentry/locale' ;
13
+ import { Tooltip } from 'sentry/components/tooltip' ;
14
+ import { replayPlatforms } from 'sentry/data/platformCategories' ;
15
+ import { IconInfo } from 'sentry/icons' ;
16
+ import { t , tct } from 'sentry/locale' ;
12
17
import PreferencesStore from 'sentry/stores/preferencesStore' ;
13
18
import { useLegacyStore } from 'sentry/stores/useLegacyStore' ;
14
19
import { useReplayOnboardingSidebarPanel } from 'sentry/utils/replays/hooks/useReplayOnboarding' ;
15
20
import useOrganization from 'sentry/utils/useOrganization' ;
21
+ import usePageFilters from 'sentry/utils/usePageFilters' ;
22
+ import useProjects from 'sentry/utils/useProjects' ;
16
23
17
24
type Breakpoints = {
18
25
large : string ;
@@ -28,6 +35,34 @@ const OnboardingCTAHook = HookOrDefault({
28
35
29
36
export default function ReplayOnboardingPanel ( ) {
30
37
const preferences = useLegacyStore ( PreferencesStore ) ;
38
+ const pageFilters = usePageFilters ( ) ;
39
+ const projects = useProjects ( ) ;
40
+ const organization = useOrganization ( ) ;
41
+ const canCreateProjects = organization . access . includes ( 'project:admin' ) ;
42
+
43
+ const selectedProjects = projects . projects . filter ( p =>
44
+ pageFilters . selection . projects . includes ( Number ( p . id ) )
45
+ ) ;
46
+
47
+ const hasSelectedProjects = selectedProjects . length > 0 ;
48
+
49
+ const allProjectsUnsupported = projects . projects . every (
50
+ p => ! replayPlatforms . includes ( p . platform ! )
51
+ ) ;
52
+
53
+ const allSelectedProjectsUnsupported = selectedProjects . every (
54
+ p => ! replayPlatforms . includes ( p . platform ! )
55
+ ) ;
56
+
57
+ // if all projects are unsupported we should prompt the user to create a project
58
+ // else we prompt to setup
59
+ const primaryAction = allProjectsUnsupported ? 'create' : 'setup' ;
60
+ // disable "create" if the user has insufficient permissions
61
+ // disable "setup" if the current selected pageFilters are not supported
62
+ const primaryActionDisabled =
63
+ primaryAction === 'create'
64
+ ? ! canCreateProjects
65
+ : allSelectedProjectsUnsupported && hasSelectedProjects ;
31
66
32
67
const breakpoints = preferences . collapsed
33
68
? {
@@ -43,26 +78,115 @@ export default function ReplayOnboardingPanel() {
43
78
xlarge : '1450px' ,
44
79
} ;
45
80
46
- const organization = useOrganization ( ) ;
47
-
48
81
return (
49
- < OnboardingPanel image = { < HeroImage src = { emptyStateImg } breakpoints = { breakpoints } /> } >
50
- < Feature
51
- features = { [ 'session-replay-ga' ] }
52
- organization = { organization }
53
- renderDisabled = { ( ) => < SetupReplaysCTA /> }
82
+ < Fragment >
83
+ { hasSelectedProjects && allSelectedProjectsUnsupported && (
84
+ < Alert icon = { < IconInfo /> } >
85
+ { tct (
86
+ `[projectMsg] [action] a project using our [link], or equivalent framework SDK.` ,
87
+ {
88
+ action : primaryAction === 'create' ? t ( 'Create' ) : t ( 'Select' ) ,
89
+ projectMsg : (
90
+ < strong >
91
+ { t (
92
+ `Session Replay isn't available for project %s.` ,
93
+ selectedProjects [ 0 ] . slug
94
+ ) }
95
+ </ strong >
96
+ ) ,
97
+ link : (
98
+ < ExternalLink href = "https://docs.sentry.io/platforms/javascript/session-replay/" >
99
+ { t ( 'Sentry browser SDK package' ) }
100
+ </ ExternalLink >
101
+ ) ,
102
+ }
103
+ ) }
104
+ </ Alert >
105
+ ) }
106
+ < OnboardingPanel
107
+ image = { < HeroImage src = { emptyStateImg } breakpoints = { breakpoints } /> }
54
108
>
55
- < OnboardingCTAHook organization = { organization } >
56
- < SetupReplaysCTA />
57
- </ OnboardingCTAHook >
58
- </ Feature >
59
- </ OnboardingPanel >
109
+ < Feature
110
+ features = { [ 'session-replay-ga' ] }
111
+ organization = { organization }
112
+ renderDisabled = { ( ) => (
113
+ < SetupReplaysCTA
114
+ orgSlug = { organization . slug }
115
+ primaryAction = { primaryAction }
116
+ disabled = { primaryActionDisabled }
117
+ />
118
+ ) }
119
+ >
120
+ < OnboardingCTAHook organization = { organization } >
121
+ < SetupReplaysCTA
122
+ orgSlug = { organization . slug }
123
+ primaryAction = { primaryAction }
124
+ disabled = { primaryActionDisabled }
125
+ />
126
+ </ OnboardingCTAHook >
127
+ </ Feature >
128
+ </ OnboardingPanel >
129
+ </ Fragment >
60
130
) ;
61
131
}
62
132
63
- function SetupReplaysCTA ( ) {
133
+ interface SetupReplaysCTAProps {
134
+ orgSlug : string ;
135
+ primaryAction : 'setup' | 'create' ;
136
+ disabled ?: boolean ;
137
+ }
138
+
139
+ export function SetupReplaysCTA ( {
140
+ disabled,
141
+ primaryAction = 'setup' ,
142
+ orgSlug,
143
+ } : SetupReplaysCTAProps ) {
64
144
const { activateSidebar} = useReplayOnboardingSidebarPanel ( ) ;
65
145
146
+ function renderCTA ( ) {
147
+ if ( primaryAction === 'setup' ) {
148
+ return (
149
+ < Tooltip
150
+ title = {
151
+ < span data-test-id = "setup-replays-tooltip" >
152
+ { t ( 'Select a supported project from the projects dropdown.' ) }
153
+ </ span >
154
+ }
155
+ disabled = { ! disabled } // we only want to show the tooltip when the button is disabled
156
+ >
157
+ < Button
158
+ data-test-id = "setup-replays-btn"
159
+ onClick = { activateSidebar }
160
+ priority = "primary"
161
+ disabled = { disabled }
162
+ >
163
+ { t ( 'Set Up Replays' ) }
164
+ </ Button >
165
+ </ Tooltip >
166
+ ) ;
167
+ }
168
+
169
+ return (
170
+ < Tooltip
171
+ title = {
172
+ < span data-test-id = "create-project-tooltip" >
173
+ { t ( 'Only admins, managers, and owners, can create projects.' ) }
174
+ </ span >
175
+ }
176
+ disabled = { ! disabled }
177
+ >
178
+ < Button
179
+ data-test-id = "create-project-btn"
180
+ to = { `/organizations/${ orgSlug } /projects/new/` }
181
+ priority = "primary"
182
+ disabled = { disabled }
183
+ >
184
+ { t ( 'Create Project' ) }
185
+ </ Button >
186
+ </ Tooltip >
187
+ ) ;
188
+ }
189
+
66
190
return (
67
191
< Fragment >
68
192
< h3 > { t ( 'Get to the root cause faster' ) } </ h3 >
@@ -72,9 +196,7 @@ function SetupReplaysCTA() {
72
196
) }
73
197
</ p >
74
198
< ButtonList gap = { 1 } >
75
- < Button onClick = { activateSidebar } priority = "primary" >
76
- { t ( 'Set Up Replays' ) }
77
- </ Button >
199
+ { renderCTA ( ) }
78
200
< Button
79
201
href = "https://docs.sentry.io/platforms/javascript/session-replay/"
80
202
external
0 commit comments