22
33import { useState , FormEvent } from 'react' ;
44import { useApp } from '@/context/AppContext' ;
5+ import { SavedConnection } from '@/lib/types' ;
56import Image from 'next/image' ;
67import styles from './AddServerDialog.module.css' ;
78
@@ -11,34 +12,66 @@ interface AddServerDialogProps {
1112}
1213
1314export function AddServerDialog ( { onClose, onSuccess } : AddServerDialogProps ) {
14- const { connectServer } = useApp ( ) ;
15+ const { connectServer, saveConnection , deleteSavedConnection , connectFromSaved , state } = useApp ( ) ;
1516 const [ name , setName ] = useState ( '' ) ;
1617 const [ host , setHost ] = useState ( 'localhost' ) ;
1718 const [ port , setPort ] = useState ( 31337 ) ;
1819 const [ username , setUsername ] = useState ( '' ) ;
1920 const [ password , setPassword ] = useState ( '' ) ;
2021 const [ useTls , setUseTls ] = useState ( true ) ;
2122 const [ skipTlsVerify , setSkipTlsVerify ] = useState ( false ) ;
23+ const [ queryTimeout , setQueryTimeout ] = useState ( 0 ) ; // 0 = unlimited
24+ const [ saveThisConnection , setSaveThisConnection ] = useState ( true ) ;
25+ const [ rememberPassword , setRememberPassword ] = useState ( false ) ;
2226 const [ isConnecting , setIsConnecting ] = useState ( false ) ;
2327 const [ error , setError ] = useState < string | null > ( null ) ;
28+ const [ selectedSavedId , setSelectedSavedId ] = useState < string | null > ( null ) ;
29+
30+ const loadSavedConnection = ( saved : SavedConnection ) => {
31+ setSelectedSavedId ( saved . id ) ;
32+ setName ( saved . name ) ;
33+ setHost ( saved . host ) ;
34+ setPort ( saved . port ) ;
35+ setUsername ( saved . username || '' ) ;
36+ setPassword ( saved . password || '' ) ;
37+ setUseTls ( saved . useTls ) ;
38+ setSkipTlsVerify ( saved . skipTlsVerify ) ;
39+ setQueryTimeout ( saved . queryTimeout || 0 ) ;
40+ setRememberPassword ( ! ! saved . password ) ;
41+ } ;
42+
43+ const handleDeleteSaved = ( e : React . MouseEvent , savedId : string ) => {
44+ e . stopPropagation ( ) ;
45+ deleteSavedConnection ( savedId ) ;
46+ if ( selectedSavedId === savedId ) {
47+ setSelectedSavedId ( null ) ;
48+ }
49+ } ;
2450
2551 const handleSubmit = async ( e : FormEvent ) => {
2652 e . preventDefault ( ) ;
2753 setIsConnecting ( true ) ;
2854 setError ( null ) ;
2955
56+ const config = {
57+ host,
58+ port,
59+ username : username || undefined ,
60+ password : password || undefined ,
61+ useTls,
62+ skipTlsVerify,
63+ queryTimeout : queryTimeout || undefined ,
64+ } ;
65+ const displayName = name || `${ host } :${ port } ` ;
66+
3067 try {
31- await connectServer (
32- {
33- host,
34- port,
35- username : username || undefined ,
36- password : password || undefined ,
37- useTls,
38- skipTlsVerify,
39- } ,
40- name || `${ host } :${ port } `
41- ) ;
68+ await connectServer ( config , displayName ) ;
69+ // Save connection if checkbox is checked
70+ if ( saveThisConnection ) {
71+ // Only include password if user opted to remember it
72+ const configToSave = rememberPassword ? config : { ...config , password : undefined } ;
73+ saveConnection ( configToSave , displayName ) ;
74+ }
4275 onSuccess ( ) ;
4376 } catch ( err ) {
4477 setError ( err instanceof Error ? err . message : 'Connection failed' ) ;
@@ -70,6 +103,34 @@ export function AddServerDialog({ onClose, onSuccess }: AddServerDialogProps) {
70103 </ div >
71104 ) }
72105
106+ { state . savedConnections . length > 0 && (
107+ < div className = { styles . savedConnections } >
108+ < label > Saved Connections</ label >
109+ < div className = { styles . savedConnectionsList } >
110+ { state . savedConnections . map ( ( saved ) => (
111+ < div
112+ key = { saved . id }
113+ className = { `${ styles . savedConnectionItem } ${ selectedSavedId === saved . id ? styles . selected : '' } ` }
114+ onClick = { ( ) => loadSavedConnection ( saved ) }
115+ >
116+ < span className = { styles . savedConnectionName } > { saved . name } </ span >
117+ < span className = { styles . savedConnectionDetails } >
118+ { saved . username } @{ saved . host } :{ saved . port }
119+ </ span >
120+ < button
121+ type = "button"
122+ className = { styles . deleteSavedBtn }
123+ onClick = { ( e ) => handleDeleteSaved ( e , saved . id ) }
124+ title = "Delete saved connection"
125+ >
126+ ×
127+ </ button >
128+ </ div >
129+ ) ) }
130+ </ div >
131+ </ div >
132+ ) }
133+
73134 < div className = { styles . formGroup } >
74135 < label htmlFor = "name" > Display Name</ label >
75136 < input
@@ -151,6 +212,40 @@ export function AddServerDialog({ onClose, onSuccess }: AddServerDialogProps) {
151212 </ label >
152213 </ div >
153214
215+ < div className = { styles . formGroup } >
216+ < label htmlFor = "queryTimeout" > Query Timeout (seconds)</ label >
217+ < input
218+ type = "number"
219+ id = "queryTimeout"
220+ value = { queryTimeout }
221+ onChange = { ( e ) => setQueryTimeout ( parseInt ( e . target . value ) || 0 ) }
222+ placeholder = "0 (unlimited)"
223+ min = { 0 }
224+ />
225+ < span className = { styles . fieldHint } > 0 = unlimited (no timeout)</ span >
226+ </ div >
227+
228+ < div className = { `${ styles . formRow } ${ styles . checkboxRow } ` } >
229+ < label className = { styles . checkboxLabel } >
230+ < input
231+ type = "checkbox"
232+ checked = { saveThisConnection }
233+ onChange = { ( e ) => setSaveThisConnection ( e . target . checked ) }
234+ />
235+ < span > Save connection for later</ span >
236+ </ label >
237+ { saveThisConnection && (
238+ < label className = { styles . checkboxLabel } >
239+ < input
240+ type = "checkbox"
241+ checked = { rememberPassword }
242+ onChange = { ( e ) => setRememberPassword ( e . target . checked ) }
243+ />
244+ < span > Remember password</ span >
245+ </ label >
246+ ) }
247+ </ div >
248+
154249 < div className = { styles . dialogActions } >
155250 < button type = "button" className = "btn btn-secondary" onClick = { onClose } >
156251 Cancel
0 commit comments