@@ -79,6 +79,26 @@ function AddEnvVarModal(p: EnvVarModalProps) {
7979 </ Modal >
8080}
8181
82+ function DeleteEnvVarModal ( p : { variable : UserEnvVarValue , deleteVariable : ( ) => void , onClose : ( ) => void } ) {
83+ return < Modal visible = { true } onClose = { p . onClose } >
84+ < h3 className = "mb-4" > Delete Variable?</ h3 >
85+ < div className = "border-t border-b border-gray-200 dark:border-gray-800 -mx-6 px-6 py-4 flex flex-col" >
86+ < div className = "grid grid-cols-2 gap-4 px-3 text-sm text-gray-400" >
87+ < span className = "truncate" > Name</ span >
88+ < span className = "truncate" > Scope</ span >
89+ </ div >
90+ < div className = "grid grid-cols-2 gap-4 p-3 mt-3 text-gray-400 bg-gray-100 dark:bg-gray-800 rounded-xl" >
91+ < span className = "truncate text-gray-900 dark:text-gray-50" > { p . variable . name } </ span >
92+ < span className = "truncate text-sm" > { p . variable . repositoryPattern } </ span >
93+ </ div >
94+ </ div >
95+ < div className = "flex justify-end mt-6" >
96+ < button className = "secondary" onClick = { p . onClose } > Cancel</ button >
97+ < button className = "ml-2 danger" onClick = { ( ) => { p . deleteVariable ( ) ; p . onClose ( ) ; } } > Delete Variable</ button >
98+ </ div >
99+ </ Modal > ;
100+ }
101+
82102function sortEnvVars ( a : UserEnvVarValue , b : UserEnvVarValue ) {
83103 if ( a . name === b . name ) {
84104 return a . repositoryPattern > b . repositoryPattern ? 1 : - 1 ;
@@ -90,6 +110,7 @@ export default function EnvVars() {
90110 const [ envVars , setEnvVars ] = useState ( [ ] as UserEnvVarValue [ ] ) ;
91111 const [ currentEnvVar , setCurrentEnvVar ] = useState ( { name : '' , value : '' , repositoryPattern : '' } as UserEnvVarValue ) ;
92112 const [ isAddEnvVarModalVisible , setAddEnvVarModalVisible ] = useState ( false ) ;
113+ const [ isDeleteEnvVarModalVisible , setDeleteEnvVarModalVisible ] = useState ( false ) ;
93114 const update = async ( ) => {
94115 await getGitpodService ( ) . server . getAllEnvVars ( ) . then ( r => setEnvVars ( r . sort ( sortEnvVars ) ) ) ;
95116 }
@@ -102,19 +123,27 @@ export default function EnvVars() {
102123 const add = ( ) => {
103124 setCurrentEnvVar ( { name : '' , value : '' , repositoryPattern : '' } ) ;
104125 setAddEnvVarModalVisible ( true ) ;
126+ setDeleteEnvVarModalVisible ( false ) ;
105127 }
106128
107- const edit = ( ev : UserEnvVarValue ) => {
108- setCurrentEnvVar ( ev ) ;
129+ const edit = ( variable : UserEnvVarValue ) => {
130+ setCurrentEnvVar ( variable ) ;
109131 setAddEnvVarModalVisible ( true ) ;
132+ setDeleteEnvVarModalVisible ( false ) ;
133+ }
134+
135+ const confirmDeleteVariable = ( variable : UserEnvVarValue ) => {
136+ setCurrentEnvVar ( variable ) ;
137+ setAddEnvVarModalVisible ( false ) ;
138+ setDeleteEnvVarModalVisible ( true ) ;
110139 }
111140
112141 const save = async ( variable : UserEnvVarValue ) => {
113142 await getGitpodService ( ) . server . setEnvVar ( variable ) ;
114143 await update ( ) ;
115144 } ;
116145
117- const deleteV = async ( variable : UserEnvVarValue ) => {
146+ const deleteVariable = async ( variable : UserEnvVarValue ) => {
118147 await getGitpodService ( ) . server . deleteEnvVar ( variable ) ;
119148 await update ( ) ;
120149 } ;
@@ -145,26 +174,32 @@ export default function EnvVars() {
145174 }
146175 }
147176 }
177+ if ( ! variable . id && envVars . some ( v => v . name === name && v . repositoryPattern === pattern ) ) {
178+ return 'A variable with this name and scope already exists' ;
179+ }
148180 return '' ;
149181 } ;
150182
151- return < PageWithSubMenu subMenu = { settingsMenu } title = 'Variables' subtitle = 'Configure environment variables for all workspaces.' >
152- { isAddEnvVarModalVisible ? < AddEnvVarModal
183+ return < PageWithSubMenu subMenu = { settingsMenu } title = 'Variables' subtitle = 'Configure environment variables for all workspaces.' >
184+ { isAddEnvVarModalVisible && < AddEnvVarModal
153185 save = { save }
154186 envVar = { currentEnvVar }
155187 validate = { validate }
156- onClose = { ( ) => setAddEnvVarModalVisible ( false ) } /> : null }
188+ onClose = { ( ) => setAddEnvVarModalVisible ( false ) } /> }
189+ { isDeleteEnvVarModalVisible && < DeleteEnvVarModal
190+ variable = { currentEnvVar }
191+ deleteVariable = { ( ) => deleteVariable ( currentEnvVar ) }
192+ onClose = { ( ) => setDeleteEnvVarModalVisible ( false ) } /> }
157193 < div className = "flex items-start sm:justify-between mb-2" >
158194 < div >
159195 < h3 > Environment Variables</ h3 >
160196 < h2 className = "text-gray-500" > Variables are used to store information like passwords.</ h2 >
161197 </ div >
162198 { envVars . length !== 0
163- ?
164- < div className = "mt-3 flex mt-0" >
165- < button onClick = { add } className = "ml-2" > New Variable</ button >
166- </ div >
167- : null }
199+ ? < div className = "mt-3 flex mt-0" >
200+ < button onClick = { add } className = "ml-2" > New Variable</ button >
201+ </ div >
202+ : null }
168203 </ div >
169204 { envVars . length === 0
170205 ? < div className = "bg-gray-100 dark:bg-gray-800 rounded-xl w-full h-96" >
@@ -183,22 +218,22 @@ export default function EnvVars() {
183218 </ div >
184219 </ div >
185220 < div className = "flex flex-col" >
186- { envVars . map ( ev => {
221+ { envVars . map ( variable => {
187222 return < div className = "rounded-xl whitespace-nowrap flex space-x-2 py-3 px-3 w-full justify-between hover:bg-gray-100 dark:hover:bg-gray-800 focus:bg-gitpod-kumquat-light transition ease-in-out group" >
188- < div className = "w-5/12 m-auto" > { ev . name } </ div >
189- < div className = "w-5/12 m-auto text-sm text-gray-400" > { ev . repositoryPattern } </ div >
223+ < div className = "w-5/12 m-auto" > { variable . name } </ div >
224+ < div className = "w-5/12 m-auto text-sm text-gray-400" > { variable . repositoryPattern } </ div >
190225 < div className = "w-2/12 flex justify-end" >
191226 < div className = "flex w-8 self-center hover:bg-gray-200 dark:hover:bg-gray-700 rounded-md cursor-pointer opacity-0 group-hover:opacity-100" >
192227 < ContextMenu menuEntries = { [
193228 {
194229 title : 'Edit' ,
195- onClick : ( ) => edit ( ev ) ,
230+ onClick : ( ) => edit ( variable ) ,
196231 separator : true
197232 } ,
198233 {
199234 title : 'Delete' ,
200235 customFontStyle : 'text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300' ,
201- onClick : ( ) => deleteV ( ev )
236+ onClick : ( ) => confirmDeleteVariable ( variable )
202237 } ,
203238 ] } >
204239 < svg className = "w-8 h-8 p-1 text-gray-600 dark:text-gray-300" xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" > < title > Actions</ title > < g fill = "currentColor" transform = "rotate(90 12 12)" > < circle cx = "1" cy = "1" r = "2" transform = "translate(5 11)" /> < circle cx = "1" cy = "1" r = "2" transform = "translate(11 11)" /> < circle cx = "1" cy = "1" r = "2" transform = "translate(17 11)" /> </ g > </ svg >
0 commit comments