@@ -10,11 +10,13 @@ import {
10
10
InlineField ,
11
11
Input ,
12
12
Legend ,
13
+ ConfirmModal ,
13
14
} from '@grafana/ui' ;
14
15
import cn from 'classnames/bind' ;
15
16
import { observer } from 'mobx-react' ;
16
17
17
18
import { Block } from 'components/GBlock/Block' ;
19
+ import { PluginBridge , SupportedPlugin } from 'components/PluginBridge/PluginBridge' ;
18
20
import { PluginLink } from 'components/PluginLink/PluginLink' ;
19
21
import { Text } from 'components/Text/Text' ;
20
22
import { WithConfirm } from 'components/WithConfirm/WithConfirm' ;
@@ -26,9 +28,11 @@ import { PRIVATE_CHANNEL_NAME } from 'models/slack_channel/slack_channel.config'
26
28
import { SlackChannel } from 'models/slack_channel/slack_channel.types' ;
27
29
import { AppFeature } from 'state/features' ;
28
30
import { WithStoreProps } from 'state/types' ;
31
+ import { useStore } from 'state/useStore' ;
29
32
import { withMobXProviderContext } from 'state/withStore' ;
30
33
import { UserActions } from 'utils/authorization/authorization' ;
31
34
import { DOCS_SLACK_SETUP , getPluginId } from 'utils/consts' ;
35
+ import { useConfirmModal } from 'utils/hooks' ;
32
36
import { showApiError } from 'utils/utils' ;
33
37
34
38
import styles from './SlackSettings.module.css' ;
@@ -116,9 +120,12 @@ class _SlackSettings extends Component<SlackProps, SlackState> {
116
120
slackChannelStore : { items : slackChannelItems } ,
117
121
} = store ;
118
122
123
+ const isUnifiedSlackInstalled = ! currentOrganization . slack_team_identity . needs_reinstall ;
124
+
119
125
return (
120
126
< div className = { cx ( 'root' ) } >
121
127
< Legend > Slack App settings</ Legend >
128
+ { currentOrganization . slack_team_identity . needs_reinstall && < UpgradeToUnifiedSlackBanner /> }
122
129
< InlineField label = "Slack Workspace" grow disabled >
123
130
< Input value = { currentOrganization ?. slack_team_identity ?. cached_name } />
124
131
</ InlineField >
@@ -147,33 +154,58 @@ class _SlackSettings extends Component<SlackProps, SlackState> {
147
154
/>
148
155
< InlineField >
149
156
< WithPermissionControlTooltip userAction = { UserActions . ChatOpsUpdateSettings } >
150
- < WithConfirm
151
- title = "Remove Slack Integration for all of OnCall"
152
- description = {
153
- < Alert severity = "error" title = "WARNING" >
154
- < p > Are you sure to delete this Slack Integration?</ p >
155
- < p >
156
- Removing the integration will also irreverisbly remove the following data for your OnCall plugin:
157
- </ p >
158
- < ul style = { { marginLeft : '20px' } } >
159
- < li > default organization Slack channel</ li >
160
- < li > default Slack channels for OnCall Integrations</ li >
161
- < li > Slack channels & Slack user groups for OnCall Schedules </ li >
162
- < li > linked Slack usernames for OnCall Users</ li >
163
- </ ul >
164
- < br />
165
- < p >
166
- If you would like to instead remove your linked Slack username, please head{ ' ' }
167
- < PluginLink query = { { page : 'users/me' } } > here</ PluginLink > .
168
- </ p >
169
- </ Alert >
170
- }
171
- confirmationText = "DELETE"
172
- >
173
- < Button variant = "destructive" onClick = { ( ) => this . removeSlackIntegration ( ) } >
174
- Disconnect Slack App
175
- </ Button >
176
- </ WithConfirm >
157
+ { isUnifiedSlackInstalled ? (
158
+ < WithConfirm
159
+ title = "Remove IRM Slack integration"
160
+ description = {
161
+ < Alert severity = "error" title = "WARNING" >
162
+ < p > Are you sure to delete this Slack Integration? It will affect both OnCall & Incident . </ p >
163
+ < p > Removing the integration will irreverisbly remove the following data for IRM;</ p >
164
+ < ul style = { { marginLeft : '20px' } } >
165
+ < li > OnCall default Slack channel</ li >
166
+ < li > Slack channels for OnCall escalation policies</ li >
167
+ < li > Slack channels & Slack user groups for OnCall Schedules </ li >
168
+ < li > linked Slack usernames for OnCall Users</ li >
169
+ < li > Incident hooks</ li >
170
+ </ ul >
171
+ < br />
172
+ </ Alert >
173
+ }
174
+ confirmationText = "DELETE"
175
+ >
176
+ < Button variant = "destructive" onClick = { ( ) => this . removeSlackIntegration ( ) } >
177
+ Disconnect Slack App
178
+ </ Button >
179
+ </ WithConfirm >
180
+ ) : (
181
+ < WithConfirm
182
+ title = "Remove Slack Integration for all of OnCall"
183
+ description = {
184
+ < Alert severity = "error" title = "WARNING" >
185
+ < p > Are you sure to delete this Slack Integration?</ p >
186
+ < p >
187
+ Removing the integration will also irreverisbly remove the following data for your OnCall plugin:
188
+ </ p >
189
+ < ul style = { { marginLeft : '20px' } } >
190
+ < li > default organization Slack channel</ li >
191
+ < li > default Slack channels for OnCall Integrations</ li >
192
+ < li > Slack channels & Slack user groups for OnCall Schedules </ li >
193
+ < li > linked Slack usernames for OnCall Users</ li >
194
+ </ ul >
195
+ < br />
196
+ < p >
197
+ If you would like to instead remove your linked Slack username, please head{ ' ' }
198
+ < PluginLink query = { { page : 'users/me' } } > here</ PluginLink > .
199
+ </ p >
200
+ </ Alert >
201
+ }
202
+ confirmationText = "DELETE"
203
+ >
204
+ < Button variant = "destructive" onClick = { ( ) => this . removeSlackIntegration ( ) } >
205
+ Disconnect Slack App
206
+ </ Button >
207
+ </ WithConfirm >
208
+ ) }
177
209
</ WithPermissionControlTooltip >
178
210
</ InlineField >
179
211
< Legend > Additional settings</ Legend >
@@ -201,19 +233,20 @@ class _SlackSettings extends Component<SlackProps, SlackState> {
201
233
</ WithPermissionControlTooltip >
202
234
</ HorizontalGroup >
203
235
</ InlineField >
204
- { currentOrganization . slack_team_identity . needs_reinstall && (
205
- < >
206
- < Legend > Unified Slack App</ Legend >
207
- < InlineField >
208
- < WithPermissionControlTooltip userAction = { UserActions . ChatOpsUpdateSettings } >
209
- < Button onClick = { this . handleOpenSlackInstructions } >
210
- < HorizontalGroup spacing = "xs" align = "center" >
211
- < Icon name = "external-link-alt" className = { cx ( 'external-link-style' ) } /> Reinstall Slack App
212
- </ HorizontalGroup >
213
- </ Button >
214
- </ WithPermissionControlTooltip >
215
- </ InlineField >
216
- </ >
236
+ { isUnifiedSlackInstalled && (
237
+ < div className = { styles . linkToIncidentWrapper } >
238
+ < PluginBridge plugin = { SupportedPlugin . Incident } >
239
+ < Text type = "secondary" >
240
+ < a
241
+ href = { `/a/${ SupportedPlugin . Incident } /integrations/grate.irm.slack` }
242
+ target = "_blank"
243
+ rel = "noreferrer"
244
+ >
245
+ < Text type = "link" > Open Slack Incident settings</ Text >
246
+ </ a >
247
+ </ Text >
248
+ </ PluginBridge >
249
+ </ div >
217
250
) }
218
251
</ div >
219
252
) ;
@@ -251,6 +284,7 @@ class _SlackSettings extends Component<SlackProps, SlackState> {
251
284
const { store } = this . props ;
252
285
const { showENVVariablesButton } = this . state ;
253
286
const isLiveSettingAvailable = store . hasFeature ( AppFeature . LiveSettings ) && showENVVariablesButton ;
287
+ const isUnifiedSlackEnabled = store . hasFeature ( AppFeature . UnifiedSlack ) ;
254
288
255
289
return (
256
290
< VerticalGroup spacing = "lg" >
@@ -261,7 +295,9 @@ class _SlackSettings extends Component<SlackProps, SlackState> {
261
295
< SlackNewIcon />
262
296
</ div >
263
297
< Text className = { cx ( 'infoblock-text' ) } >
264
- Connecting Slack App will allow you to manage alert groups in your team Slack workspace.
298
+ { isUnifiedSlackEnabled
299
+ ? 'Connecting Slack App will allow you to manage alert groups and incidents in your team Slack workspace.'
300
+ : 'Connecting Slack App will allow you to manage alert groups in your team Slack workspace.' }
265
301
</ Text >
266
302
< Text className = { cx ( 'infoblock-text' ) } >
267
303
After a basic workspace connection your team members need to connect their personal Slack accounts in
@@ -305,4 +341,61 @@ class _SlackSettings extends Component<SlackProps, SlackState> {
305
341
} ;
306
342
}
307
343
344
+ const UpgradeToUnifiedSlackBanner = observer ( ( ) => {
345
+ const {
346
+ slackStore : { installSlackIntegration } ,
347
+ } = useStore ( ) ;
348
+ const { modalProps, openModal } = useConfirmModal ( ) ;
349
+
350
+ return (
351
+ < >
352
+ < ConfirmModal { ...modalProps } />
353
+ < Alert
354
+ className = { styles . upgradeSlackAlert }
355
+ severity = "success"
356
+ title = "Upgrade to Grafana IRM unified Slack app"
357
+ buttonContent = { < div > Upgrade</ div > }
358
+ >
359
+ We've rebranded the OnCall Slack app as the Grafana IRM Slack app, now with incident management features.
360
+ < p > Click "Upgrade" to reviewn and approve the new permissions and complete the process.</ p >
361
+ < p > For more details, check our documentation.</ p >
362
+ < Button
363
+ variant = "secondary"
364
+ className = { styles . upgradeSlackBtn }
365
+ onClick = { ( ) =>
366
+ openModal ( {
367
+ confirmText : 'Confirm' ,
368
+ onConfirm : installSlackIntegration ,
369
+ confirmButtonVariant : 'primary' ,
370
+ title : `Upgrade to Grafana IRM Slack app` ,
371
+ description : (
372
+ < div >
373
+ < p >
374
+ You will be redirected to Slack to approve additional permissions for the Grafana IRM Slack app.{ ' ' }
375
+ </ p >
376
+ < p >
377
+ These permissions are necessary for incident management. You can view the detailed list of new
378
+ permissions here.[LINK]
379
+ </ p >
380
+ < p > After the upgrade, you'll be able to manage incidents in Slack using the Grafana IRM Slack app.</ p >
381
+ < ul style = { { marginLeft : '20px' } } >
382
+ < li > Your OnCall Slack configuration will remain unchanged. </ li >
383
+ < li >
384
+ Your Incident Slack integration will be upgraded to use the Grafana IRM Slack app. Please refer to
385
+ the documentation for more details.[LINK]
386
+ </ li >
387
+ </ ul >
388
+ </ div >
389
+ ) ,
390
+ confirmVariant : 'secondary' ,
391
+ } )
392
+ }
393
+ >
394
+ Upgrade
395
+ </ Button >
396
+ </ Alert >
397
+ </ >
398
+ ) ;
399
+ } ) ;
400
+
308
401
export const SlackSettings = withMobXProviderContext ( _SlackSettings ) ;
0 commit comments