11import React , { useState , useEffect } from 'react'
2- import { Progressing , ResizableTextarea , ToastBody , noop , showError } from '@devtron-labs/devtron-fe-common-lib'
2+ import { ConditionalWrap , Progressing , ResizableTextarea , TippyTheme , ToastBody , noop , showError } from '@devtron-labs/devtron-fe-common-lib'
33import YAML from 'yaml'
44import { DEPLOYMENT_HISTORY_CONFIGURATION_LIST_MAP , PATTERNS } from '../../config'
55import { ReactComponent as Dropdown } from '../../assets/icons/ic-chevron-down.svg'
@@ -28,9 +28,10 @@ import { DeploymentHistoryDetail } from '../app/details/cdDetails/cd.type'
2828import { prepareHistoryData } from '../app/details/cdDetails/service'
2929import './ConfigMapSecret.scss'
3030import { getCMSecret , getConfigMapList , getSecretList } from './service'
31- import { useParams } from 'react-router-dom'
31+ import { useHistory , useParams , useRouteMatch } from 'react-router-dom'
3232import { toast } from 'react-toastify'
3333import Tippy from '@tippyjs/react'
34+ import { followCursor } from 'tippy.js'
3435
3536const ConfigToolbar = importComponentFromFELibrary ( 'ConfigToolbar' )
3637const ApproveRequestTippy = importComponentFromFELibrary ( 'ApproveRequestTippy' )
@@ -114,12 +115,13 @@ export function ConfigMapSecretContainer({
114115 parentName,
115116 reloadEnvironments,
116117} : ConfigMapSecretProps ) {
117- const { appId, envId } = useParams < { appId ; envId } > ( )
118- const [ collapsed , toggleCollapse ] = useState ( true )
118+ const { appId, envId, name } = useParams < { appId ; envId ; name } > ( )
119+ const history = useHistory ( )
120+ const match = useRouteMatch ( )
119121 const [ isLoader , setLoader ] = useState < boolean > ( false )
120122 const [ draftData , setDraftData ] = useState ( null )
121123 const [ selectedTab , setSelectedTab ] = useState ( data ?. draftState === 4 ? 2 : 3 )
122- const [ abortController , setAbortController ] = useState ( new AbortController ( ) ) ;
124+ const [ abortController , setAbortController ] = useState ( new AbortController ( ) )
123125
124126 let cmSecretStateLabel = ! data ?. isNew ? CM_SECRET_STATE . BASE : CM_SECRET_STATE . UNPUBLISHED
125127 if ( isOverrideView ) {
@@ -129,18 +131,32 @@ export function ConfigMapSecretContainer({
129131 cmSecretStateLabel = ! data ?. isNew ? CM_SECRET_STATE . ENV : CM_SECRET_STATE . UNPUBLISHED
130132 }
131133 }
134+
135+ useEffect ( ( ) => {
136+ if ( title !== '' && title === name ) {
137+ getData ( )
138+ }
139+ } , [ ] )
132140
133141 const getData = async ( ) => {
134142 try {
135143 abortController . abort ( )
136- const newAbortController = new AbortController ( ) ;
137- setAbortController ( newAbortController ) ;
144+ const newAbortController = new AbortController ( )
138145 setLoader ( true )
146+ setAbortController ( newAbortController )
139147 const [ _draftData , _cmSecretData ] = await Promise . allSettled ( [
140148 isProtected && getDraftByResourceName
141- ? getDraftByResourceName ( appId , envId ?? - 1 , componentType === 'secret' ? 2 : 1 , data . name , newAbortController . signal )
149+ ? getDraftByResourceName (
150+ appId ,
151+ envId ?? - 1 ,
152+ componentType === 'secret' ? 2 : 1 ,
153+ title ,
154+ newAbortController . signal ,
155+ )
156+ : null ,
157+ ! data ?. isNew
158+ ? getCMSecret ( componentType , id , appId , title , envId , newAbortController . signal )
142159 : null ,
143- ! data ?. isNew ? getCMSecret ( componentType , id , appId , data ?. name , envId , newAbortController . signal ) : null ,
144160 ] )
145161 let draftId , draftState
146162 if (
@@ -181,6 +197,7 @@ export function ConfigMapSecretContainer({
181197 } else {
182198 toast . error ( `The ${ componentType } '${ data ?. name } ' has been deleted` )
183199 update ( index , null )
200+ redirectURLToInitial ( )
184201 }
185202 } else if (
186203 cmSecretStateLabel === CM_SECRET_STATE . UNPUBLISHED &&
@@ -193,10 +210,14 @@ export function ConfigMapSecretContainer({
193210 } else if ( _draftData . value . result . draftState === 2 ) {
194211 toast . error ( `The ${ componentType } '${ data ?. name } ' has been deleted` )
195212 update ( index , null )
213+ redirectURLToInitial ( )
196214 }
197215 }
198- if ( ( _cmSecretData ?. status === 'fulfilled' && _cmSecretData ?. value !== null ) || ( _draftData ?. status === 'fulfilled' && _draftData ?. value !== null ) ) {
199- toggleCollapse ( false )
216+ if (
217+ ( _cmSecretData ?. status === 'fulfilled' && _cmSecretData ?. value !== null ) ||
218+ ( _draftData ?. status === 'fulfilled' && _draftData ?. value !== null )
219+ ) {
220+ setLoader ( true )
200221 }
201222 if (
202223 ( _cmSecretData ?. status === 'rejected' && _cmSecretData ?. reason ?. code === 403 ) ||
@@ -213,20 +234,32 @@ export function ConfigMapSecretContainer({
213234 }
214235 }
215236
237+ const redirectURLToInitial = ( urlTo : string = '' ) => {
238+ const componentTypeName = componentType === 'secret' ? 'secrets' : 'configmap'
239+ const urlPrefix = match . url . split ( componentTypeName ) [ 0 ]
240+ history . push ( `${ urlPrefix } ${ componentTypeName } /${ urlTo } ` )
241+ }
242+
216243 const updateCollapsed = ( _collapsed ?: boolean ) : void => {
217- if ( _collapsed !== undefined ) {
218- toggleCollapse ( _collapsed )
244+ if ( ! title ) {
245+ //Redirect and Add config map & secret
246+ if ( name === 'create' ) {
247+ toggleDraftComments ( null )
248+ setDraftData ( null )
249+ return redirectURLToInitial ( )
250+ }
251+ return redirectURLToInitial ( 'create' )
219252 } else {
220- if ( collapsed && data ?. name ) {
221- getData ( )
253+ //Redirect and Open existing config map & secret
254+ if ( name === title ) {
255+ toggleDraftComments ( null )
256+ setDraftData ( null )
257+ return redirectURLToInitial ( )
222258 } else {
223- toggleCollapse ( ! collapsed )
224- if ( ! collapsed ) {
225- toggleDraftComments ( null )
226- setDraftData ( null )
227- }
259+ getData ( )
260+ return redirectURLToInitial ( title )
228261 }
229- }
262+ }
230263 }
231264
232265 const handleTabSelection = ( index : number ) : void => {
@@ -255,6 +288,7 @@ export function ConfigMapSecretContainer({
255288 }
256289
257290 const renderDetails = ( ) : JSX . Element => {
291+ if ( ( name && ( ( ! title && name !== 'create' ) || ( title && name !== title ) ) ) || ! name ) return null
258292 if ( title && isProtected && draftData ?. draftId ) {
259293 return (
260294 < >
@@ -323,7 +357,7 @@ export function ConfigMapSecretContainer({
323357 }
324358
325359 const renderDraftState = ( ) : JSX . Element => {
326- if ( collapsed ) {
360+ if ( title !== name ) {
327361 if ( data . draftState === 1 ) {
328362 return < i className = "mr-10 cr-5" > In draft</ i >
329363 } else if ( data . draftState === 4 ) {
@@ -334,53 +368,77 @@ export function ConfigMapSecretContainer({
334368 return null
335369 }
336370
337- const handleCMSecretClick = ( ) => {
371+ const handleCMSecretClick = ( event ) => {
338372 if ( title && isProtected && draftData ?. draftId ) {
339373 setSelectedTab ( draftData . draftState === 4 ? 2 : 3 )
340374 }
341- updateCollapsed ( )
375+ updateCollapsed ( )
342376 }
343377
378+ const showBlurEffect = name && ( ( ! title && name !== 'create' ) || ( title && name !== title ) )
379+
344380 return (
345381 < >
346- < section
347- className = { `pt-16 dc__border bcn-0 br-8 ${ title ? 'mb-16' : 'en-3 bw-1 dashed mb-20' } ${
348- reduceOpacity ? 'dc__disable-click dc__blur-1_5' : ''
349- } `}
382+ < ConditionalWrap
383+ condition = { showBlurEffect }
384+ wrap = { ( children ) => (
385+ < Tippy
386+ theme = { TippyTheme . black }
387+ followCursor = { true }
388+ plugins = { [ followCursor ] }
389+ arrow = { true }
390+ animation = "shift-toward-subtle"
391+ placement = 'top'
392+ content = { `Collapse opened ${ componentType === 'secret' ? ' Secret' : ' ConfigMap' } first` }
393+ >
394+ < div > { children } </ div >
395+ </ Tippy >
396+ ) }
350397 >
351- < article
352- className = "dc__configuration-list pointer pr-16 pl-16 mb-16"
353- onClick = { handleCMSecretClick }
354- data-testid = "click-to-add-configmaps-secret"
398+ < div className = { `${ showBlurEffect ? 'cursor-not-allowed' : 'cursor' } ` } >
399+ < section
400+ className = { `pt-16 dc__border bcn-0 br-8 ${ title ? 'mb-16' : 'en-3 bw-1 dashed mb-20' } ${
401+ reduceOpacity || showBlurEffect ? 'dc__disable-click dc__blur-1_5' : ''
402+ } `}
355403 >
356- { renderIcon ( ) }
357- < div
358- data-testid = { `add- ${ componentType } -button` }
359- className = { `flex left lh-20 ${ ! title ? 'fw-5 fs-14 cb-5' : 'fw-5 fs-14 cn-9' } ` }
404+ < article
405+ className = "dc__configuration-list pr-16 pl-16 mb-16"
406+ onClick = { handleCMSecretClick }
407+ data-testid = "click-to-add-configmaps-secret"
360408 >
361- { title || `Add ${ componentType === 'secret' ? 'Secret' : 'ConfigMap' } ` }
362- { cmSecretStateLabel && < div className = "flex tag ml-12" > { cmSecretStateLabel } </ div > }
363- </ div >
364- { title && (
365- < div className = "flex right" >
366- { isProtected && (
367- < >
368- { renderDraftState ( ) }
369- < ProtectedIcon className = "icon-dim-20 mr-10 fcv-5" />
370- </ >
371- ) }
372- { isLoader ? (
373- < span style = { { width : '20px' } } >
374- < Progressing />
375- </ span >
376- ) : (
377- < Dropdown className = { `icon-dim-20 rotate ${ collapsed ? '' : 'dc__flip-180' } ` } />
378- ) }
409+ { renderIcon ( ) }
410+ < div
411+ data-testid = { `add-${ componentType } -button` }
412+ className = { `flex left lh-20 ${ ! title ? 'fw-5 fs-14 cb-5' : 'fw-5 fs-14 cn-9' } ` }
413+ >
414+ { title || `Add ${ componentType === 'secret' ? 'Secret' : 'ConfigMap' } ` }
415+ { cmSecretStateLabel && < div className = "flex tag ml-12" > { cmSecretStateLabel } </ div > }
379416 </ div >
380- ) }
381- </ article >
382- { ! collapsed && renderDetails ( ) }
383- </ section >
417+ { title && (
418+ < div className = "flex right" >
419+ { isProtected && (
420+ < >
421+ { renderDraftState ( ) }
422+ < ProtectedIcon className = "icon-dim-20 mr-10 fcv-5" />
423+ </ >
424+ ) }
425+ { isLoader ? (
426+ < span style = { { width : '20px' } } >
427+ < Progressing />
428+ </ span >
429+ ) : (
430+ < Dropdown
431+ className = { `icon-dim-20 rotate ${ name === title ? 'dc__flip-180' : '' } ` }
432+ />
433+ ) }
434+ </ div >
435+ ) }
436+ </ article >
437+
438+ { ! isLoader ? renderDetails ( ) : null }
439+ </ section >
440+ </ div >
441+ </ ConditionalWrap >
384442 </ >
385443 )
386444}
@@ -400,27 +458,30 @@ export function ProtectedConfigMapSecretDetails({
400458 parentName,
401459 reloadEnvironments,
402460} : ProtectedConfigMapSecretDetailsProps ) {
403- const { appId, envId } = useParams < { appId ; envId } > ( )
461+ const { appId, name } = useParams < { appId ; name } > ( )
404462 const [ isLoader , setLoader ] = useState < boolean > ( false )
405463 const [ baseData , setBaseData ] = useState ( null )
406- const [ abortController , setAbortController ] = useState ( new AbortController ( ) ) ;
407-
464+ const [ abortController , setAbortController ] = useState ( new AbortController ( ) )
408465
409466 const getBaseData = async ( ) => {
410467 try {
411468 abortController . abort ( )
412469 let newAbortController = new AbortController ( )
413470 setAbortController ( newAbortController )
414471 setLoader ( true )
415- const { result } = await ( componentType === 'secret' ? getSecretList ( appId , { signal : newAbortController . signal } ) : getConfigMapList ( appId , { signal : newAbortController . signal } ) )
472+ const { result } = await ( componentType === 'secret'
473+ ? getSecretList ( appId , { signal : newAbortController . signal } )
474+ : getConfigMapList ( appId , { signal : newAbortController . signal } ) )
416475 let _baseData
417476 if ( result ?. configData ?. length ) {
418477 _baseData = result . configData . find ( ( config ) => config . name === data . name )
419478 if ( _baseData ) {
420479 _baseData . unAuthorized = data . unAuthorized
421480 }
422481 if ( componentType === 'secret' && ! data . unAuthorized ) {
423- const { result : secretResult } = await getCMSecret ( componentType , result . id , appId , data ?. name , { signal : newAbortController . signal } )
482+ const { result : secretResult } = await getCMSecret ( componentType , result . id , appId , data ?. name , {
483+ signal : newAbortController . signal ,
484+ } )
424485 if ( secretResult ?. configData ?. length ) {
425486 _baseData = { ...secretResult . configData [ 0 ] , unAuthorized : false }
426487 }
@@ -435,7 +496,7 @@ export function ProtectedConfigMapSecretDetails({
435496
436497 useEffect ( ( ) => {
437498 if ( draftData . action === 3 && cmSecretStateLabel === CM_SECRET_STATE . OVERRIDDEN ) {
438- getBaseData ( )
499+ getBaseData ( )
439500 }
440501 } , [ ] )
441502
0 commit comments