Skip to content

Commit 677ce74

Browse files
Improve git settings UI and credential management (#119)
Remove collapsible sections and batch save, implement immediate credential CRUD with toast feedback. Add default hosts for credential types and improve responsive layout in credential dialog.
1 parent abec582 commit 677ce74

2 files changed

Lines changed: 195 additions & 184 deletions

File tree

frontend/src/components/settings/GitCredentialDialog.tsx

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useState, useEffect } from 'react'
22
import { Loader2, Key, Lock, AlertTriangle } from 'lucide-react'
33
import { Button } from '@/components/ui/button'
4-
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
4+
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog'
55
import { Input } from '@/components/ui/input'
66
import { Label } from '@/components/ui/label'
77
import { Textarea } from '@/components/ui/textarea'
@@ -50,7 +50,15 @@ export function GitCredentialDialog({ open, onOpenChange, onSave, credential, is
5050
token: credential.type === 'pat' ? '' : credential.token
5151
})
5252
} else {
53-
setFormData({ name: '', host: '', type: 'pat', token: '', username: '', sshPrivateKey: '', passphrase: '' })
53+
setFormData({
54+
name: '',
55+
host: 'github.com',
56+
type: 'pat',
57+
token: '',
58+
username: '',
59+
sshPrivateKey: '',
60+
passphrase: ''
61+
})
5462
}
5563
}
5664
}, [open, credential])
@@ -151,7 +159,13 @@ export function GitCredentialDialog({ open, onOpenChange, onSave, credential, is
151159
<Button
152160
type="button"
153161
variant={formData.type === 'pat' ? 'default' : 'outline'}
154-
onClick={() => setFormData({ ...formData, type: 'pat', sshPrivateKey: '', passphrase: '' })}
162+
onClick={() => setFormData({
163+
...formData,
164+
type: 'pat',
165+
host: formData.type === 'pat' ? formData.host : 'github.com',
166+
sshPrivateKey: '',
167+
passphrase: ''
168+
})}
155169
disabled={isSaving}
156170
className="flex-1"
157171
>
@@ -161,7 +175,12 @@ export function GitCredentialDialog({ open, onOpenChange, onSave, credential, is
161175
<Button
162176
type="button"
163177
variant={formData.type === 'ssh' ? 'default' : 'outline'}
164-
onClick={() => setFormData({ ...formData, type: 'ssh', token: '' })}
178+
onClick={() => setFormData({
179+
...formData,
180+
type: 'ssh',
181+
host: formData.type === 'ssh' ? formData.host : 'git@github.com',
182+
token: ''
183+
})}
165184
disabled={isSaving}
166185
className="flex-1"
167186
>
@@ -251,24 +270,24 @@ export function GitCredentialDialog({ open, onOpenChange, onSave, credential, is
251270
</div>
252271

253272
{showPassphraseInput && (
254-
<div className="space-y-2">
255-
<Label htmlFor="cred-passphrase">Passphrase</Label>
256-
<Input
257-
id="cred-passphrase"
258-
type="password"
259-
placeholder="Enter passphrase for SSH key"
260-
value={formData.passphrase || ''}
261-
onChange={(e) => setFormData({ ...formData, passphrase: e.target.value })}
262-
disabled={isSaving}
263-
autoComplete="new-password"
264-
/>
265-
<p className="text-xs text-muted-foreground">
266-
This passphrase will be required for each git operation
267-
</p>
268-
</div>
273+
<div className="space-y-2">
274+
<Label htmlFor="cred-passphrase">Passphrase</Label>
275+
<Input
276+
id="cred-passphrase"
277+
type="password"
278+
placeholder="Enter passphrase for SSH key"
279+
value={formData.passphrase || ''}
280+
onChange={(e) => setFormData({ ...formData, passphrase: e.target.value })}
281+
disabled={isSaving}
282+
autoComplete="new-password"
283+
/>
284+
<p className="text-xs text-muted-foreground">
285+
This passphrase will be required for each git operation
286+
</p>
287+
</div>
269288
)}
270289

271-
<div className="space-y-2">
290+
<div className="space-y-2">
272291
<Label htmlFor="test-passphrase">Passphrase for Test (if protected)</Label>
273292
<Input
274293
id="test-passphrase"
@@ -304,25 +323,28 @@ export function GitCredentialDialog({ open, onOpenChange, onSave, credential, is
304323
</div>
305324
</form>
306325

307-
<div className="flex justify-end gap-2 pt-2 sm:pt-4 px-4 sm:px-6 pb-4 sm:pb-6 flex-shrink-0">
326+
<DialogFooter className="p-3 sm:p-4 border-t gap-2">
308327
<Button
309328
type="button"
310329
variant="outline"
311330
onClick={() => onOpenChange(false)}
312331
disabled={isSaving}
332+
className="flex-1 sm:flex-none"
313333
>
314334
Cancel
315335
</Button>
316336
<Button
317-
type="submit"
337+
type="button"
338+
onClick={handleSubmit}
318339
disabled={isSaving || !formData.name.trim() || !formData.host.trim() ||
319340
(formData.type === 'pat' && !formData.token?.trim()) ||
320341
(formData.type === 'ssh' && !formData.sshPrivateKey?.trim())}
342+
className="flex-1 sm:flex-none"
321343
>
322344
{isSaving && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
323345
{credential ? 'Update' : 'Add'}
324346
</Button>
325-
</div>
347+
</DialogFooter>
326348
</DialogContent>
327349
</Dialog>
328350
)

0 commit comments

Comments
 (0)