Обновлены переводы на русский язык для компонентов, включая карточки мониторинга, сетевые панели и настройки. Исправлены описания и метки для улучшения пользовательского интерфейса, а также добавлены новые элементы для поддержки локализации в компонентах, таких как DataGrid и ResourcePage.
155 lines
4.4 KiB
TypeScript
155 lines
4.4 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import { toast } from 'sonner'
|
|
|
|
import { Button } from '@evobgp/ui/components/button'
|
|
import { Input } from '@evobgp/ui/components/input'
|
|
import { Label } from '@evobgp/ui/components/label'
|
|
|
|
import { FormDrawer } from '@/components/form-drawer'
|
|
import { LoadingButton } from '@/components/loading-button'
|
|
import {
|
|
useCreateDohProfileMutation,
|
|
useUpdateDohProfileMutation,
|
|
} from '@/queries/directories'
|
|
import type { DohProfile, DohProfileCreate, DohProfilePatch } from '@/types/api'
|
|
|
|
interface DohProfileFormDialogProps {
|
|
open: boolean
|
|
onOpenChange: (open: boolean) => void
|
|
editTarget?: DohProfile | null
|
|
}
|
|
|
|
/** @see https://reui.io/preview/base/form-7 */
|
|
export function DohProfileFormDialog({
|
|
open,
|
|
onOpenChange,
|
|
editTarget = null,
|
|
}: DohProfileFormDialogProps) {
|
|
const createMutation = useCreateDohProfileMutation()
|
|
const updateMutation = useUpdateDohProfileMutation()
|
|
const saving = createMutation.isPending || updateMutation.isPending
|
|
const [name, setName] = useState('')
|
|
const [url, setUrl] = useState('')
|
|
const [timeoutMs, setTimeoutMs] = useState('')
|
|
|
|
useEffect(() => {
|
|
if (!open) return
|
|
if (editTarget) {
|
|
setName(editTarget.name ?? '')
|
|
setUrl(editTarget.url ?? '')
|
|
setTimeoutMs(
|
|
editTarget.timeout_ms === null || editTarget.timeout_ms === undefined
|
|
? ''
|
|
: String(editTarget.timeout_ms),
|
|
)
|
|
} else {
|
|
setName('')
|
|
setUrl('')
|
|
setTimeoutMs('')
|
|
}
|
|
}, [editTarget, open])
|
|
|
|
async function save() {
|
|
const trimmedUrl = url.trim()
|
|
if (!trimmedUrl) {
|
|
toast.error('Укажите URL DoH')
|
|
return
|
|
}
|
|
let urlOk = true
|
|
try {
|
|
new URL(trimmedUrl)
|
|
} catch {
|
|
urlOk = false
|
|
}
|
|
if (!urlOk) {
|
|
toast.error('Некорректный URL')
|
|
return
|
|
}
|
|
|
|
let timeout: number | null = null
|
|
if (timeoutMs.trim() !== '') {
|
|
const ms = Number(timeoutMs)
|
|
if (!Number.isFinite(ms) || !Number.isInteger(ms) || ms <= 0) {
|
|
toast.error('Таймаут должен быть целым числом больше 0')
|
|
return
|
|
}
|
|
timeout = ms
|
|
}
|
|
|
|
const nameTrimmed = name.trim()
|
|
|
|
try {
|
|
if (editTarget) {
|
|
const body: DohProfilePatch = {
|
|
url: trimmedUrl,
|
|
name: nameTrimmed || undefined,
|
|
timeout_ms: timeout,
|
|
}
|
|
await updateMutation.mutateAsync({ id: editTarget.id, body })
|
|
} else {
|
|
const body: DohProfileCreate = { url: trimmedUrl }
|
|
if (nameTrimmed) body.name = nameTrimmed
|
|
if (timeout !== null) body.timeout_ms = timeout
|
|
await createMutation.mutateAsync(body)
|
|
}
|
|
onOpenChange(false)
|
|
} catch {
|
|
// toast in mutation
|
|
}
|
|
}
|
|
|
|
return (
|
|
<FormDrawer
|
|
open={open}
|
|
onOpenChange={onOpenChange}
|
|
title={editTarget ? 'Редактировать DoH-профиль' : 'Новый DoH-профиль'}
|
|
description="Резолвер DNS-over-HTTPS для доменных модулей"
|
|
className="sm:max-w-sm"
|
|
footer={
|
|
<>
|
|
<Button variant="outline" type="button" onClick={() => onOpenChange(false)}>
|
|
Отмена
|
|
</Button>
|
|
<LoadingButton type="button" loading={saving} onClick={() => void save()}>
|
|
{editTarget ? 'Сохранить' : 'Создать'}
|
|
</LoadingButton>
|
|
</>
|
|
}
|
|
>
|
|
<div className="flex flex-col gap-2">
|
|
<Label htmlFor="doh-name">Имя (опционально)</Label>
|
|
<Input
|
|
id="doh-name"
|
|
placeholder="Control D / AdGuard"
|
|
value={name}
|
|
onChange={(e) => setName(e.target.value)}
|
|
/>
|
|
</div>
|
|
<div className="flex flex-col gap-2">
|
|
<Label htmlFor="doh-url">URL</Label>
|
|
<Input
|
|
id="doh-url"
|
|
type="url"
|
|
placeholder="https://dns.example/dns-query"
|
|
value={url}
|
|
onChange={(e) => setUrl(e.target.value)}
|
|
/>
|
|
</div>
|
|
<div className="flex flex-col gap-2">
|
|
<Label htmlFor="doh-timeout">Таймаут, мс (необязательно)</Label>
|
|
<Input
|
|
id="doh-timeout"
|
|
type="number"
|
|
min={1}
|
|
placeholder="5000"
|
|
value={timeoutMs}
|
|
onChange={(e) => setTimeoutMs(e.target.value)}
|
|
/>
|
|
</div>
|
|
</FormDrawer>
|
|
)
|
|
}
|
|
|
|
/** @deprecated Use DohProfileFormDialog */
|
|
export const DohProfileCreateDialog = DohProfileFormDialog
|