Build, Test, and Push CFDM Docker Image / test (push) Successful in 3m55s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Successful in 2m14s
Build, Test, and Push CFDM Docker Image / update-wiki (push) Successful in 7s
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped
197 lines
6.2 KiB
TypeScript
197 lines
6.2 KiB
TypeScript
import { useEffect, useMemo, useState } from 'react'
|
|
import type { CertMonitoring } from '@cfdm/shared'
|
|
import type { ServiceView, SubdomainRecord } from '@/lib/schemas'
|
|
import { certMonitoringOptions } from '@/lib/cert-monitoring'
|
|
import { formatServiceGroupLabel } from '@/lib/service-utils'
|
|
import { FormFieldSimple } from '@/components/form-field'
|
|
import { LoadingButton } from '@/components/loading-button'
|
|
import { AppInput } from '@/components/app-input'
|
|
import { AppFieldDescription, AppFieldGroup } from '@/components/app-field'
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from '@cfdm/ui/components/select'
|
|
import {
|
|
Sheet,
|
|
SheetContent,
|
|
SheetDescription,
|
|
SheetFooter,
|
|
SheetHeader,
|
|
SheetTitle,
|
|
} from '@cfdm/ui/components/sheet'
|
|
|
|
export interface SubdomainEditValues {
|
|
name: string
|
|
serviceId: string
|
|
certMonitoring: CertMonitoring
|
|
}
|
|
|
|
interface SubdomainEditSheetProps {
|
|
mode: 'create' | 'edit'
|
|
subdomain: SubdomainRecord | null
|
|
zoneName: string
|
|
services: ServiceView[]
|
|
serviceGroupById: Map<number, string | null>
|
|
currentServiceId: string
|
|
open: boolean
|
|
isSaving: boolean
|
|
onOpenChange: (open: boolean) => void
|
|
onSubmit: (values: SubdomainEditValues) => void
|
|
}
|
|
|
|
export function SubdomainEditSheet({
|
|
mode,
|
|
subdomain,
|
|
zoneName,
|
|
services,
|
|
serviceGroupById,
|
|
currentServiceId,
|
|
open,
|
|
isSaving,
|
|
onOpenChange,
|
|
onSubmit,
|
|
}: SubdomainEditSheetProps) {
|
|
const [name, setName] = useState('')
|
|
const [serviceId, setServiceId] = useState('none')
|
|
const [certMonitoring, setCertMonitoring] = useState<CertMonitoring>('auto')
|
|
|
|
const serviceItems = useMemo(
|
|
() => [
|
|
{ label: 'Без сервиса', value: 'none' },
|
|
...services.map((service) => ({
|
|
label: formatServiceGroupLabel(
|
|
serviceGroupById.get(service.id),
|
|
service.name,
|
|
),
|
|
value: String(service.id),
|
|
})),
|
|
],
|
|
[services, serviceGroupById],
|
|
)
|
|
|
|
const certMonitoringItems = useMemo(
|
|
() =>
|
|
certMonitoringOptions.map((option) => ({
|
|
label: option.label,
|
|
value: option.value,
|
|
})),
|
|
[],
|
|
)
|
|
|
|
useEffect(() => {
|
|
if (!open) return
|
|
if (mode === 'edit' && subdomain) {
|
|
setName(subdomain.name)
|
|
setServiceId(currentServiceId || 'none')
|
|
setCertMonitoring(subdomain.cert_monitoring)
|
|
return
|
|
}
|
|
setName('')
|
|
setServiceId('none')
|
|
setCertMonitoring('auto')
|
|
}, [open, mode, subdomain, currentServiceId])
|
|
|
|
function handleSubmit(event: React.FormEvent) {
|
|
event.preventDefault()
|
|
const trimmed = name.trim()
|
|
if (!trimmed) return
|
|
onSubmit({ name: trimmed, serviceId, certMonitoring })
|
|
}
|
|
|
|
return (
|
|
<Sheet open={open} onOpenChange={onOpenChange}>
|
|
<SheetContent>
|
|
<SheetHeader>
|
|
<SheetTitle>
|
|
{mode === 'create' ? 'Создать поддомен' : 'Редактировать поддомен'}
|
|
</SheetTitle>
|
|
<SheetDescription>
|
|
{mode === 'create'
|
|
? `Имя записи в зоне ${zoneName} (например, www или api)`
|
|
: `Изменение поддомена в зоне ${zoneName}`}
|
|
</SheetDescription>
|
|
</SheetHeader>
|
|
<form onSubmit={handleSubmit} className="flex flex-col gap-4 px-4">
|
|
<AppFieldGroup>
|
|
<FormFieldSimple label="Имя" htmlFor="subdomain_name">
|
|
<AppInput
|
|
id="subdomain_name"
|
|
placeholder="www"
|
|
value={name}
|
|
onChange={(event) => setName(event.target.value)}
|
|
className="font-mono"
|
|
aria-invalid={!name.trim() && name.length > 0}
|
|
/>
|
|
</FormFieldSimple>
|
|
{mode === 'edit' && (
|
|
<>
|
|
<FormFieldSimple label="Сервис" htmlFor="subdomain_service">
|
|
<Select
|
|
items={serviceItems}
|
|
value={serviceId}
|
|
onValueChange={(value) => setServiceId(value ?? 'none')}
|
|
>
|
|
<SelectTrigger id="subdomain_service" className="w-full">
|
|
<SelectValue placeholder="Без сервиса" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{serviceItems.map((item) => (
|
|
<SelectItem key={item.value} value={item.value}>
|
|
{item.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</FormFieldSimple>
|
|
<FormFieldSimple
|
|
label="Мониторинг SSL"
|
|
htmlFor="subdomain_cert_monitoring"
|
|
>
|
|
<Select
|
|
items={certMonitoringItems}
|
|
value={certMonitoring}
|
|
onValueChange={(value) =>
|
|
setCertMonitoring((value ?? 'auto') as CertMonitoring)
|
|
}
|
|
>
|
|
<SelectTrigger id="subdomain_cert_monitoring" className="w-full">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{certMonitoringOptions.map((option) => (
|
|
<SelectItem key={option.value} value={option.value}>
|
|
{option.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
<AppFieldDescription>
|
|
{
|
|
certMonitoringOptions.find((o) => o.value === certMonitoring)
|
|
?.description
|
|
}
|
|
</AppFieldDescription>
|
|
</FormFieldSimple>
|
|
</>
|
|
)}
|
|
</AppFieldGroup>
|
|
<SheetFooter>
|
|
<LoadingButton
|
|
type="submit"
|
|
className="w-full"
|
|
disabled={!name.trim()}
|
|
isLoading={isSaving}
|
|
loadingLabel="Сохранение…"
|
|
>
|
|
{mode === 'create' ? 'Создать' : 'Сохранить'}
|
|
</LoadingButton>
|
|
</SheetFooter>
|
|
</form>
|
|
</SheetContent>
|
|
</Sheet>
|
|
)
|
|
}
|