@@ -38,6 +38,7 @@ import {
38
38
stopPropagation ,
39
39
ButtonStyleType ,
40
40
Icon ,
41
+ SelectPicker ,
41
42
} from '@devtron-labs/devtron-fe-common-lib'
42
43
import { useParams } from 'react-router-dom'
43
44
import Tippy from '@tippyjs/react'
@@ -53,12 +54,15 @@ import { createGeneratedAPIToken } from '@Pages/GlobalConfigurations/Authorizati
53
54
import {
54
55
CURL_PREFIX ,
55
56
GENERATE_TOKEN_WITH_REQUIRED_PERMISSIONS ,
57
+ getWebhookTokenListOptions ,
56
58
PLAYGROUND_TAB_LIST ,
57
59
REQUEST_BODY_TAB_LIST ,
58
60
RESPONSE_TAB_LIST ,
61
+ SELECT_AUTO_GENERATE_TOKEN_WITH_REQUIRED_PERMISSIONS ,
62
+ TOKEN_TAB_LIST ,
59
63
} from './webhook.utils'
60
- import { SchemaType , TabDetailsType , WebhookDetailsType , WebhookDetailType } from './types'
61
- import { executeWebhookAPI , getExternalCIConfig } from './webhook.service'
64
+ import { SchemaType , TabDetailsType , TokenListOptionsType , WebhookDetailsType , WebhookDetailType } from './types'
65
+ import { executeWebhookAPI , getExternalCIConfig , getWebhookAPITokenList } from './webhook.service'
62
66
import { GENERATE_TOKEN_NAME_VALIDATION } from '../../../config/constantMessaging'
63
67
import { createUserPermissionPayload } from '@Pages/GlobalConfigurations/Authorization/utils'
64
68
import { ChartGroupPermissionsFilter } from '@Pages/GlobalConfigurations/Authorization/types'
@@ -67,6 +71,8 @@ import {
67
71
getDefaultStatusAndTimeout ,
68
72
getDefaultUserStatusAndTimeout ,
69
73
} from '@Pages/GlobalConfigurations/Authorization/libUtils'
74
+ import { getApiTokenHeader } from '@Pages/GlobalConfigurations/Authorization/APITokens/apiToken.utils'
75
+ import { TokenListType } from '@Pages/GlobalConfigurations/Authorization/APITokens/apiToken.type'
70
76
71
77
export const WebhookDetailsModal = ( { close, isTemplateView } : WebhookDetailType ) => {
72
78
const { appId, webhookId } = useParams < {
@@ -84,6 +90,7 @@ export const WebhookDetailsModal = ({ close, isTemplateView }: WebhookDetailType
84
90
const [ selectedRequestBodyTab , setRequestBodyPlaygroundTab ] = useState < string > ( REQUEST_BODY_TAB_LIST [ 0 ] . key )
85
91
const [ webhookResponse , setWebhookResponse ] = useState < Object > ( null )
86
92
const [ generatedAPIToken , setGeneratedAPIToken ] = useState < string > ( null )
93
+ const [ selectedTokenTab , setSelectedTokenTab ] = useState < string > ( TOKEN_TAB_LIST [ 0 ] . key )
87
94
const [ showTokenSection , setShowTokenSection ] = useState ( false )
88
95
const [ isSuperAdmin , setIsSuperAdmin ] = useState ( false )
89
96
const [ samplePayload , setSamplePayload ] = useState < any > ( null )
@@ -94,11 +101,14 @@ export const WebhookDetailsModal = ({ close, isTemplateView }: WebhookDetailType
94
101
const [ tryoutAPIToken , setTryoutAPIToken ] = useState < string > ( null )
95
102
const [ showTryoutAPITokenError , setTryoutAPITokenError ] = useState ( false )
96
103
const [ webhookDetails , setWebhookDetails ] = useState < WebhookDetailsType > ( null )
104
+ const [ selectedToken , setSelectedToken ] = useState < TokenListOptionsType > ( null )
105
+ const [ tokenList , setTokenList ] = useState < TokenListType [ ] > ( undefined )
97
106
const [ selectedSchema , setSelectedSchema ] = useState < string > ( '' )
98
107
const [ errorInGetData , setErrorInGetData ] = useState ( false )
99
108
const [ copyToClipboardPromise , setCopyToClipboardPromise ] = useState < ReturnType < typeof copyToClipboard > > ( null )
100
109
const schemaRef = useRef < Array < HTMLDivElement | null > > ( [ ] )
101
110
111
+
102
112
const clipboardContent = window . location . href
103
113
104
114
const handleCopyButtonClick = async ( ) => {
@@ -184,13 +194,30 @@ export const WebhookDetailsModal = ({ close, isTemplateView }: WebhookDetailType
184
194
setSampleCURL (
185
195
CURL_PREFIX . replace ( '{webhookURL}' , _webhookDetails . webhookUrl ) . replace ( '{data}' , modifiedJSONString ) ,
186
196
)
197
+ if ( _isSuperAdmin ) {
198
+ const { result } = await getWebhookAPITokenList (
199
+ _webhookDetails . projectName ,
200
+ _webhookDetails . environmentIdentifier ,
201
+ _webhookDetails . appName ,
202
+ )
203
+ const sortedResult =
204
+ result
205
+ ?. sort ( ( a , b ) => a [ 'name' ] . localeCompare ( b [ 'name' ] ) )
206
+ . map ( ( tokenData ) => {
207
+ return { label : tokenData . name , value : tokenData . id , ...tokenData }
208
+ } ) || [ ]
209
+ setTokenList ( sortedResult )
210
+ }
187
211
setLoader ( false )
188
212
} catch ( error ) {
189
213
setIsSuperAdmin ( false )
190
214
setLoader ( false )
191
215
setErrorInGetData ( true )
192
216
}
193
217
}
218
+
219
+ const hideApiToken = ! tokenList ?. [ 0 ] ?. token
220
+
194
221
const generateToken = async ( ) : Promise < void > => {
195
222
if ( ! tokenName ) {
196
223
setTokenNameError ( true )
@@ -208,6 +235,7 @@ export const WebhookDetailsModal = ({ close, isTemplateView }: WebhookDetailType
208
235
const userPermissionPayload = createUserPermissionPayload ( {
209
236
id : result . userId ,
210
237
userIdentifier : result . userIdentifier ,
238
+ hideApiToken : result . hideApiToken ,
211
239
userRoleGroups : [ ] ,
212
240
serverMode : SERVER_MODE . FULL ,
213
241
directPermission : [ ] ,
@@ -367,7 +395,7 @@ export const WebhookDetailsModal = ({ close, isTemplateView }: WebhookDetailType
367
395
return (
368
396
< div className = "mt-16" >
369
397
< InfoBlock
370
- heading = "Copy and store this token safely, you won’t be able to view it again."
398
+ heading = { getApiTokenHeader ( hideApiToken ) }
371
399
description = {
372
400
< div className = "fs-13 font-roboto flexbox dc__word-break" data-testid = "generated-api-token" >
373
401
{ token }
@@ -424,6 +452,49 @@ export const WebhookDetailsModal = ({ close, isTemplateView }: WebhookDetailType
424
452
)
425
453
}
426
454
455
+ const renderSelectTokenSection = ( ) : JSX . Element => {
456
+ const handleSelectedTokenChange = ( selectedToken ) : void => {
457
+ setSelectedToken ( selectedToken )
458
+ }
459
+
460
+ return (
461
+ < >
462
+ < div className = "w-400 h-32 mt-16" >
463
+ < SelectPicker
464
+ inputId = "select-token"
465
+ name = "select-token"
466
+ classNamePrefix = "select-token"
467
+ placeholder = "Select API token"
468
+ isClearable = { false }
469
+ options = { getWebhookTokenListOptions ( tokenList ) }
470
+ value = { selectedToken }
471
+ onChange = { handleSelectedTokenChange }
472
+ isSearchable = { false }
473
+ />
474
+ </ div >
475
+ { selectedToken ?. name && renderSelectedToken ( selectedToken . token ) }
476
+ </ >
477
+ )
478
+ }
479
+
480
+ const renderGeneratedTokenDetails = ( ) => {
481
+ if ( hideApiToken ) {
482
+ return (
483
+ < div className = "cn-9 fs-13 mb-8" >
484
+ < span className = "fs-13 lh-1-5 fw-6" > { GENERATE_TOKEN_WITH_REQUIRED_PERMISSIONS } </ span >
485
+ { renderGenerateTokenSection ( ) }
486
+ </ div >
487
+ )
488
+ }
489
+ return (
490
+ < div >
491
+ { generateTabHeader ( TOKEN_TAB_LIST , selectedTokenTab , setSelectedTokenTab ) }
492
+ { selectedTokenTab === TOKEN_TAB_LIST [ 0 ] . key && renderSelectTokenSection ( ) }
493
+ { selectedTokenTab === TOKEN_TAB_LIST [ 1 ] . key && renderGenerateTokenSection ( ) }
494
+ </ div >
495
+ )
496
+ }
497
+
427
498
const renderTokenSection = ( ) : JSX . Element | null => {
428
499
if ( ! isSuperAdmin ) {
429
500
return (
@@ -440,13 +511,10 @@ export const WebhookDetailsModal = ({ close, isTemplateView }: WebhookDetailType
440
511
dataTestId = "select-or-generate-token"
441
512
variant = { ButtonVariantType . text }
442
513
onClick = { toggleTokenSection }
443
- text = { GENERATE_TOKEN_WITH_REQUIRED_PERMISSIONS }
514
+ text = { hideApiToken ? GENERATE_TOKEN_WITH_REQUIRED_PERMISSIONS : SELECT_AUTO_GENERATE_TOKEN_WITH_REQUIRED_PERMISSIONS }
444
515
/>
445
516
) : (
446
- < div className = "cn-9 fs-13 mb-8" >
447
- < span className = "fs-13 lh-1-5 fw-6" > { GENERATE_TOKEN_WITH_REQUIRED_PERMISSIONS } </ span >
448
- { renderGenerateTokenSection ( ) }
449
- </ div >
517
+ renderGeneratedTokenDetails ( )
450
518
)
451
519
}
452
520
0 commit comments