feat: All service fields editable inline
Service cards now have full inline editing: - Backend address: editable input, updates on blur - Public/Private: toggle switch, updates immediately - Subdomains: toggle switch, updates immediately - TLS (Central TLS / Passthrough): toggle switch, updates both tls mode and backend type together - Deregister button Add form also uses toggle for TLS instead of dropdown. Removed unused Badge and Select imports. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,9 +5,7 @@ import { Button } from './ui/button';
|
|||||||
import { Input, Label } from './ui';
|
import { Input, Label } from './ui';
|
||||||
import { Alert, AlertDescription } from './ui/alert';
|
import { Alert, AlertDescription } from './ui/alert';
|
||||||
import { Textarea } from './ui/textarea';
|
import { Textarea } from './ui/textarea';
|
||||||
import { Badge } from './ui/badge';
|
|
||||||
import { Switch } from './ui/switch';
|
import { Switch } from './ui/switch';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
|
|
||||||
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from './ui/collapsible';
|
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from './ui/collapsible';
|
||||||
import {
|
import {
|
||||||
Globe, Loader2, AlertCircle, CheckCircle, Play, RotateCw,
|
Globe, Loader2, AlertCircle, CheckCircle, Play, RotateCw,
|
||||||
@@ -159,16 +157,10 @@ export function ServicesComponent() {
|
|||||||
<Switch checked={newSubdomains} onCheckedChange={setNewSubdomains} />
|
<Switch checked={newSubdomains} onCheckedChange={setNewSubdomains} />
|
||||||
Include subdomains
|
Include subdomains
|
||||||
</label>
|
</label>
|
||||||
<div className="flex items-center gap-2 text-sm">
|
<label className="flex items-center gap-2 text-sm">
|
||||||
<span className="text-muted-foreground">TLS:</span>
|
<Switch checked={newTls === 'terminate'} onCheckedChange={v => setNewTls(v ? 'terminate' : 'passthrough')} />
|
||||||
<Select value={newTls} onValueChange={setNewTls}>
|
Central handles TLS
|
||||||
<SelectTrigger className="h-8 w-36"><SelectValue /></SelectTrigger>
|
</label>
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="passthrough">Passthrough</SelectItem>
|
|
||||||
<SelectItem value="terminate">Terminate</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2 justify-end">
|
<div className="flex gap-2 justify-end">
|
||||||
<Button variant="outline" size="sm" onClick={() => setShowAddForm(false)}><X className="h-3 w-3 mr-1" />Cancel</Button>
|
<Button variant="outline" size="sm" onClick={() => setShowAddForm(false)}><X className="h-3 w-3 mr-1" />Cancel</Button>
|
||||||
@@ -237,7 +229,19 @@ export function ServicesComponent() {
|
|||||||
<div className="flex flex-wrap items-center gap-x-6 gap-y-3 py-2">
|
<div className="flex flex-wrap items-center gap-x-6 gap-y-3 py-2">
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-xs text-muted-foreground">Backend</Label>
|
<Label className="text-xs text-muted-foreground">Backend</Label>
|
||||||
<div className="font-mono text-sm mt-0.5">{service.backend.address}</div>
|
<Input
|
||||||
|
defaultValue={service.backend.address}
|
||||||
|
className="mt-0.5 h-8 font-mono text-sm w-48"
|
||||||
|
onBlur={e => {
|
||||||
|
const val = e.target.value.trim();
|
||||||
|
if (val && val !== service.backend.address) {
|
||||||
|
updateMutation.mutate({
|
||||||
|
domain: service.domain,
|
||||||
|
updates: { backend: { ...service.backend, address: val } },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -259,10 +263,18 @@ export function ServicesComponent() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Label className="text-xs text-muted-foreground">TLS</Label>
|
<Switch
|
||||||
<Badge variant={isPassthrough ? 'secondary' : 'default'} className="text-xs">
|
checked={!isPassthrough}
|
||||||
{isPassthrough ? 'Passthrough' : 'Terminate'}
|
onCheckedChange={v => updateMutation.mutate({
|
||||||
</Badge>
|
domain: service.domain,
|
||||||
|
updates: {
|
||||||
|
tls: v ? 'terminate' : 'passthrough',
|
||||||
|
backend: { ...service.backend, type: v ? 'http' : 'tcp-passthrough' },
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
disabled={updateMutation.isPending}
|
||||||
|
/>
|
||||||
|
<Label className="text-sm">{isPassthrough ? 'TLS Passthrough' : 'Central TLS'}</Label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user