CI / changes (push) Successful in 11s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Successful in 1m3s
CI / go (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / release (push) Successful in 4m4s
Updated the ModuleDetailComponent to include new queries for communities and DoH profiles, improving data handling. Added a module type alert function for better user guidance and refined the UI to display module type in a more user-friendly manner. Removed unused components and streamlined the refresh functionality for better performance.
109 lines
3.4 KiB
TypeScript
109 lines
3.4 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import { toast } from 'sonner'
|
|
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from '@evobgp/ui/components/dialog'
|
|
import { Input } from '@evobgp/ui/components/input'
|
|
import { Label } from '@evobgp/ui/components/label'
|
|
|
|
import { LoadingButton } from '@/components/loading-button'
|
|
import { CommunitySelect } from '@/components/modules/community-select'
|
|
import { ApiError, apiMutate } from '@/lib/api-client'
|
|
import type { BgpCommunity, IpRangeEntry, IpRangeEntryCreate } from '@/types/api'
|
|
|
|
interface ModuleIpRangeEntryDialogProps {
|
|
open: boolean
|
|
moduleId: string
|
|
edit: IpRangeEntry | null
|
|
communities: BgpCommunity[]
|
|
onOpenChange: (open: boolean) => void
|
|
onSaved: () => void | Promise<void>
|
|
}
|
|
|
|
export function ModuleIpRangeEntryDialog({
|
|
open,
|
|
moduleId,
|
|
edit,
|
|
communities,
|
|
onOpenChange,
|
|
onSaved,
|
|
}: ModuleIpRangeEntryDialogProps) {
|
|
const [saving, setSaving] = useState(false)
|
|
const [form, setForm] = useState<IpRangeEntryCreate>({ prefix: '', community_id: '' })
|
|
|
|
useEffect(() => {
|
|
if (!open) return
|
|
setForm(
|
|
edit
|
|
? { prefix: edit.prefix, community_id: edit.community_id }
|
|
: { prefix: '', community_id: '' },
|
|
)
|
|
}, [open, edit])
|
|
|
|
async function save() {
|
|
if (!form.prefix.trim() || !form.community_id) {
|
|
toast.error('Укажите префикс и community')
|
|
return
|
|
}
|
|
setSaving(true)
|
|
try {
|
|
const body = { prefix: form.prefix.trim(), community_id: form.community_id }
|
|
if (edit) {
|
|
await apiMutate(`/v1/modules/${moduleId}/ip-range-entries/${edit.id}`, 'PATCH', body)
|
|
toast.success('Диапазон обновлён')
|
|
} else {
|
|
await apiMutate(`/v1/modules/${moduleId}/ip-range-entries`, 'POST', body)
|
|
toast.success('Диапазон добавлен')
|
|
}
|
|
onOpenChange(false)
|
|
await onSaved()
|
|
} catch (e) {
|
|
toast.error(e instanceof ApiError ? e.message : String(e))
|
|
} finally {
|
|
setSaving(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent className="sm:max-w-sm">
|
|
<DialogHeader>
|
|
<DialogTitle>{edit ? 'Редактировать диапазон' : 'Новый IP-диапазон'}</DialogTitle>
|
|
</DialogHeader>
|
|
<div className="space-y-4 py-2">
|
|
<div className="flex flex-col gap-1.5">
|
|
<Label htmlFor="ip-prefix">Префикс (CIDR)</Label>
|
|
<Input
|
|
id="ip-prefix"
|
|
placeholder="203.0.113.0/24"
|
|
value={form.prefix}
|
|
onChange={(e) => setForm((s) => ({ ...s, prefix: e.target.value }))}
|
|
/>
|
|
</div>
|
|
<CommunitySelect
|
|
id="ip-comm"
|
|
label="Community (обязательно)"
|
|
value={form.community_id || null}
|
|
onValueChange={(v) => setForm((s) => ({ ...s, community_id: v ?? '' }))}
|
|
communities={communities}
|
|
placeholder="Выберите community"
|
|
/>
|
|
</div>
|
|
<DialogFooter>
|
|
<LoadingButton variant="outline" onClick={() => onOpenChange(false)}>
|
|
Отмена
|
|
</LoadingButton>
|
|
<LoadingButton loading={saving} onClick={() => void save()}>
|
|
{edit ? 'Сохранить' : 'Добавить'}
|
|
</LoadingButton>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
)
|
|
}
|