@@ -21,12 +21,14 @@ import space from 'app/styles/space';
21
21
import withApi from 'app/utils/withApi' ;
22
22
import withOrganization from 'app/utils/withOrganization' ;
23
23
import withTeams from 'app/utils/withTeams' ;
24
+ import IssueAlertOptions from 'app/views/projectInstall/issueAlertOptions' ;
24
25
25
26
class CreateProject extends React . Component {
26
27
static propTypes = {
27
28
api : PropTypes . object ,
28
29
teams : PropTypes . arrayOf ( SentryTypes . Team ) ,
29
30
organization : SentryTypes . Organization ,
31
+ hasIssueAlertOptionsEnabled : PropTypes . bool ,
30
32
} ;
31
33
32
34
static contextTypes = {
@@ -50,13 +52,126 @@ class CreateProject extends React.Component {
50
52
platform,
51
53
inFlight : false ,
52
54
} ;
55
+
56
+ if ( this . props . hasIssueAlertOptionsEnabled ) {
57
+ this . state = {
58
+ ...this . state ,
59
+ ...{
60
+ dataFragment : { } ,
61
+ } ,
62
+ } ;
63
+ }
53
64
}
54
65
55
- createProject = e => {
66
+ renderProjectForm = (
67
+ projectName ,
68
+ team ,
69
+ teams ,
70
+ platform ,
71
+ hasIssueAlertOptionsEnabled ,
72
+ organization ,
73
+ canSubmitForm
74
+ ) => {
75
+ const createProjectFormCaptured = (
76
+ < CreateProjectForm onSubmit = { this . createProject } >
77
+ < div >
78
+ < FormLabel >
79
+ { hasIssueAlertOptionsEnabled
80
+ ? t ( 'Project name' )
81
+ : t ( 'Give your project a name' ) }
82
+ </ FormLabel >
83
+ < ProjectNameInput >
84
+ < ProjectPlatformIcon monoTone platform = { platform } />
85
+ < input
86
+ type = "text"
87
+ name = "name"
88
+ label = { t ( 'Project Name' ) }
89
+ placeholder = { t ( 'Project name' ) }
90
+ autoComplete = "off"
91
+ value = { projectName }
92
+ onChange = { e => this . setState ( { projectName : e . target . value } ) }
93
+ />
94
+ </ ProjectNameInput >
95
+ </ div >
96
+ < div >
97
+ < FormLabel >
98
+ { hasIssueAlertOptionsEnabled ? t ( 'Name' ) : t ( 'Assign a Team' ) }
99
+ </ FormLabel >
100
+ < TeamSelectInput >
101
+ < SelectControl
102
+ deprecatedSelectControl
103
+ name = "select-team"
104
+ clearable = { false }
105
+ value = { team }
106
+ placeholder = { t ( 'Select a Team' ) }
107
+ onChange = { choice => this . setState ( { team : choice . value } ) }
108
+ options = { teams . map ( ( { slug} ) => ( {
109
+ label : `#${ slug } ` ,
110
+ value : slug ,
111
+ } ) ) }
112
+ />
113
+ < Tooltip title = { t ( 'Create a team' ) } >
114
+ < Button
115
+ borderless
116
+ data-test-id = "create-team"
117
+ type = "button"
118
+ icon = "icon-circle-add"
119
+ onClick = { ( ) =>
120
+ openCreateTeamModal ( {
121
+ organization,
122
+ onClose : ( { slug} ) => this . setState ( { team : slug } ) ,
123
+ } )
124
+ }
125
+ />
126
+ </ Tooltip >
127
+ </ TeamSelectInput >
128
+ </ div >
129
+ < div >
130
+ < Button
131
+ data-test-id = "create-project"
132
+ priority = "primary"
133
+ disabled = { ! canSubmitForm }
134
+ >
135
+ { t ( 'Create Project' ) }
136
+ </ Button >
137
+ </ div >
138
+ </ CreateProjectForm >
139
+ ) ;
140
+ return hasIssueAlertOptionsEnabled ? (
141
+ < React . Fragment >
142
+ < PageHeading withMargins > { t ( 'Give your project a name' ) } </ PageHeading >
143
+ { createProjectFormCaptured }
144
+ </ React . Fragment >
145
+ ) : (
146
+ < StickyWrapper > { createProjectFormCaptured } </ StickyWrapper >
147
+ ) ;
148
+ } ;
149
+
150
+ canSubmitForm ( inFlight , team , projectName , dataFragment , hasIssueAlertOptionsEnabled ) {
151
+ return (
152
+ ! inFlight &&
153
+ team &&
154
+ projectName !== '' &&
155
+ ( ! hasIssueAlertOptionsEnabled ||
156
+ ! dataFragment ?. shouldCreateCustomRule ||
157
+ dataFragment ?. conditions ?. every ?. ( condition => condition . value ) )
158
+ ) ;
159
+ }
160
+
161
+ createProject = async e => {
56
162
e . preventDefault ( ) ;
57
- const { organization, api} = this . props ;
58
- const { projectName, platform, team} = this . state ;
163
+ const { organization, api, hasIssueAlertOptionsEnabled } = this . props ;
164
+ const { projectName, platform, team, dataFragment } = this . state ;
59
165
const { slug} = organization ;
166
+ const {
167
+ shouldCreateCustomRule,
168
+ name,
169
+ conditions,
170
+ actions,
171
+ actionMatch,
172
+ frequency,
173
+ defaultRules,
174
+ } = hasIssueAlertOptionsEnabled ? dataFragment : { } ;
60
175
61
176
this . setState ( { inFlight : true } ) ;
62
177
@@ -68,39 +183,53 @@ class CreateProject extends React.Component {
68
183
} ) ;
69
184
}
70
185
71
- api . request ( `/teams/${ slug } /${ team } /projects/` , {
72
- method : 'POST' ,
73
- data : {
74
- name : projectName ,
75
- platform,
76
- } ,
77
- success : data => {
78
- ProjectActions . createSuccess ( data ) ;
79
-
80
- const platformKey = platform || 'other' ;
81
- const nextUrl = `/${ organization . slug } /${ data . slug } /getting-started/${ platformKey } /` ;
82
-
83
- browserHistory . push ( nextUrl ) ;
84
- } ,
85
- error : err => {
86
- this . setState ( {
87
- inFlight : false ,
88
- error : err . responseJSON . detail ,
89
- } ) ;
186
+ try {
187
+ const projectData = await api . requestPromise ( `/teams/${ slug } /${ team } /projects/` , {
188
+ method : 'POST' ,
189
+ data : {
190
+ name : projectName ,
191
+ platform,
192
+ default_rules : defaultRules ?? true ,
193
+ } ,
194
+ } ) ;
195
+
196
+ if ( shouldCreateCustomRule ) {
197
+ await api . requestPromise (
198
+ `/projects/${ organization . slug } /${ projectData . slug } /rules/` ,
199
+ {
200
+ method : 'POST' ,
201
+ data : {
202
+ name,
203
+ conditions,
204
+ actions,
205
+ actionMatch,
206
+ frequency,
207
+ } ,
208
+ }
209
+ ) ;
210
+ }
211
+ ProjectActions . createSuccess ( projectData ) ;
212
+ const platformKey = platform || 'other' ;
213
+ const nextUrl = `/${ organization . slug } /${ projectData . slug } /getting-started/${ platformKey } /` ;
214
+ browserHistory . push ( nextUrl ) ;
215
+ } catch ( err ) {
216
+ this . setState ( {
217
+ inFlight : false ,
218
+ error : err . responseJSON . detail ,
219
+ } ) ;
90
220
91
- // Only log this if the error is something other than:
92
- // * The user not having access to create a project, or,
93
- // * A project with that slug already exists
94
- if ( err . status !== 403 && err . status !== 409 ) {
95
- Sentry . withScope ( scope => {
96
- scope . setExtra ( 'err' , err ) ;
97
- scope . setExtra ( 'props' , this . props ) ;
98
- scope . setExtra ( 'state' , this . state ) ;
99
- Sentry . captureMessage ( 'Project creation failed' ) ;
100
- } ) ;
101
- }
102
- } ,
103
- } ) ;
221
+ // Only log this if the error is something other than:
222
+ // * The user not having access to create a project, or,
223
+ // * A project with that slug already exists
224
+ if ( err . status !== 403 && err . status !== 409 ) {
225
+ Sentry . withScope ( scope => {
226
+ scope . setExtra ( 'err' , err ) ;
227
+ scope . setExtra ( 'props' , this . props ) ;
228
+ scope . setExtra ( 'state' , this . state ) ;
229
+ Sentry . captureMessage ( 'Project creation failed' ) ;
230
+ } ) ;
231
+ }
232
+ }
104
233
} ;
105
234
106
235
setPlatform = platformId =>
@@ -113,10 +242,16 @@ class CreateProject extends React.Component {
113
242
} ) ) ;
114
243
115
244
render ( ) {
116
- const { organization} = this . props ;
117
- const { projectName, team, platform, error, inFlight} = this . state ;
245
+ const { organization, hasIssueAlertOptionsEnabled } = this . props ;
246
+ const { projectName, team, platform, error, inFlight, dataFragment } = this . state ;
118
247
const teams = this . props . teams . filter ( filterTeam => filterTeam . hasAccess ) ;
119
-
248
+ const canSubmitForm = this . canSubmitForm (
249
+ inFlight ,
250
+ team ,
251
+ projectName ,
252
+ dataFragment ,
253
+ hasIssueAlertOptionsEnabled
254
+ ) ;
120
255
return (
121
256
< React . Fragment >
122
257
{ error && < Alert type = "error" > { error } </ Alert > }
@@ -130,65 +265,26 @@ class CreateProject extends React.Component {
130
265
for your API server and frontend client.`
131
266
) }
132
267
</ HelpText >
133
-
268
+ { hasIssueAlertOptionsEnabled && (
269
+ < PageHeading withMargins > { t ( 'Choose a platform' ) } </ PageHeading >
270
+ ) }
134
271
< PlatformPicker platform = { platform } setPlatform = { this . setPlatform } showOther />
135
- < CreateProjectForm onSubmit = { this . createProject } >
136
- < div >
137
- < FormLabel > { t ( 'Give your project a name' ) } </ FormLabel >
138
- < ProjectNameInput >
139
- < ProjectPlatformIcon monoTone platform = { platform } />
140
- < input
141
- type = "text"
142
- name = "name"
143
- label = { t ( 'Project Name' ) }
144
- placeholder = { t ( 'Project name' ) }
145
- autoComplete = "off"
146
- value = { projectName }
147
- onChange = { e => this . setState ( { projectName : e . target . value } ) }
148
- />
149
- </ ProjectNameInput >
150
- </ div >
151
- < div >
152
- < FormLabel > { t ( 'Assign a Team' ) } </ FormLabel >
153
- < TeamSelectInput >
154
- < SelectControl
155
- deprecatedSelectControl
156
- name = "select-team"
157
- clearable = { false }
158
- value = { team }
159
- placeholder = { t ( 'Select a Team' ) }
160
- onChange = { choice => this . setState ( { team : choice . value } ) }
161
- options = { teams . map ( ( { slug} ) => ( {
162
- label : `#${ slug } ` ,
163
- value : slug ,
164
- } ) ) }
165
- />
166
- < Tooltip title = { t ( 'Create a team' ) } >
167
- < Button
168
- borderless
169
- data-test-id = "create-team"
170
- type = "button"
171
- icon = "icon-circle-add"
172
- onClick = { ( ) =>
173
- openCreateTeamModal ( {
174
- organization,
175
- onClose : ( { slug} ) => this . setState ( { team : slug } ) ,
176
- } )
177
- }
178
- />
179
- </ Tooltip >
180
- </ TeamSelectInput >
181
- </ div >
182
- < div >
183
- < Button
184
- data-test-id = "create-project"
185
- priority = "primary"
186
- disabled = { inFlight || ! team || projectName === '' }
187
- >
188
- { t ( 'Create Project' ) }
189
- </ Button >
190
- </ div >
191
- </ CreateProjectForm >
272
+ { hasIssueAlertOptionsEnabled && (
273
+ < IssueAlertOptions
274
+ onChange = { updatedData => {
275
+ this . setState ( { dataFragment : updatedData } ) ;
276
+ } }
277
+ />
278
+ ) }
279
+ { this . renderProjectForm (
280
+ projectName ,
281
+ team ,
282
+ teams ,
283
+ platform ,
284
+ hasIssueAlertOptionsEnabled ,
285
+ organization ,
286
+ canSubmitForm
287
+ ) }
192
288
</ div >
193
289
</ React . Fragment >
194
290
) ;
@@ -206,8 +302,6 @@ const CreateProjectForm = styled('form')`
206
302
padding: ${ space ( 3 ) } 0;
207
303
box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.1);
208
304
background: #fff;
209
- position: sticky;
210
- bottom: 0;
211
305
` ;
212
306
213
307
const FormLabel = styled ( 'div' ) `
@@ -243,3 +337,9 @@ const HelpText = styled('p')`
243
337
color: ${ p => p . theme . gray3 } ;
244
338
max-width: 700px;
245
339
` ;
340
+
341
+ const StickyWrapper = styled ( 'div' ) `
342
+ position: sticky;
343
+ background: #fff;
344
+ bottom: 0;
345
+ ` ;
0 commit comments