CI / changes (push) Successful in 8s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Successful in 38s
CI / go (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / release (push) Successful in 4m1s
- Refactored module entry dialogs to reset forms based on edit state and improve state management. - Updated selection logic in various components to utilize derived states for active selections, enhancing bulk operations. - Improved dialog bindings for better state synchronization and user experience. - Streamlined component structure for maintainability and clarity.
116 lines
3.3 KiB
Svelte
116 lines
3.3 KiB
Svelte
<script lang="ts">
|
|
import { apiMutate } from '$lib/api/client.js';
|
|
import type { BgpCommunity, IpRangeEntry, IpRangeEntryCreate } from '$lib/api/types.js';
|
|
import { communityLabel, communityOptionLabel } from '$lib/components/modules/module-helpers.js';
|
|
import { Button } from '$lib/ui/core/button/index.js';
|
|
import { Input } from '$lib/ui/core/input/index.js';
|
|
import { Label } from '$lib/ui/core/label/index.js';
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogFooter
|
|
} from '$lib/ui/core/dialog/index.js';
|
|
import { Select, SelectContent, SelectItem, SelectTrigger } from '$lib/ui/core/select/index.js';
|
|
import { notify, notifyApiError } from '$lib/ui/app/toast.js';
|
|
|
|
type Props = {
|
|
open: boolean;
|
|
moduleId: string;
|
|
edit: IpRangeEntry | null;
|
|
communities: BgpCommunity[];
|
|
onSaved: () => void | Promise<void>;
|
|
onClose: () => void;
|
|
};
|
|
|
|
let { open = $bindable(), moduleId, edit, communities, onSaved, onClose }: Props = $props();
|
|
|
|
let saving = $state(false);
|
|
let form = $state<IpRangeEntryCreate>({ prefix: '', community_id: '' });
|
|
let initKey = $state('');
|
|
|
|
function resetForm() {
|
|
form = edit
|
|
? { prefix: edit.prefix, community_id: edit.community_id }
|
|
: { prefix: '', community_id: '' };
|
|
}
|
|
|
|
$effect(() => {
|
|
if (!open) {
|
|
initKey = '';
|
|
return;
|
|
}
|
|
const nextKey = edit?.id ?? 'new';
|
|
if (nextKey !== initKey) {
|
|
initKey = nextKey;
|
|
resetForm();
|
|
}
|
|
});
|
|
|
|
async function save() {
|
|
saving = true;
|
|
try {
|
|
if (edit) {
|
|
await apiMutate(`/v1/modules/${moduleId}/ip-range-entries/${edit.id}`, 'PATCH', form);
|
|
notify.success('Диапазон обновлён');
|
|
} else {
|
|
await apiMutate(`/v1/modules/${moduleId}/ip-range-entries`, 'POST', form);
|
|
notify.success('Диапазон добавлен');
|
|
}
|
|
open = false;
|
|
await onSaved();
|
|
} catch (e) {
|
|
notifyApiError(e);
|
|
} finally {
|
|
saving = false;
|
|
}
|
|
}
|
|
|
|
function handleOpenChange(next: boolean) {
|
|
open = next;
|
|
if (!next) onClose();
|
|
}
|
|
</script>
|
|
|
|
<Dialog bind:open onOpenChange={handleOpenChange}>
|
|
<DialogContent class="sm:max-w-sm">
|
|
<DialogHeader>
|
|
<DialogTitle>{edit ? 'Редактировать диапазон' : 'Новый IP-диапазон'}</DialogTitle>
|
|
</DialogHeader>
|
|
<div class="space-y-4 py-2">
|
|
<div class="space-y-1.5">
|
|
<Label for="ip-prefix">Префикс (CIDR)</Label>
|
|
<Input id="ip-prefix" placeholder="203.0.113.0/24" bind:value={form.prefix} />
|
|
</div>
|
|
<div class="space-y-1.5">
|
|
<Label for="ip-comm">Community (обязательно)</Label>
|
|
<Select
|
|
type="single"
|
|
value={form.community_id}
|
|
onValueChange={(v) => {
|
|
form.community_id = v;
|
|
}}
|
|
>
|
|
<SelectTrigger id="ip-comm" class="w-full">
|
|
{form.community_id
|
|
? communityLabel(form.community_id, communities)
|
|
: 'Выберите community'}
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{#each communities as c (c.id)}
|
|
<SelectItem value={c.id}>{communityOptionLabel(c)}</SelectItem>
|
|
{/each}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
</div>
|
|
<DialogFooter>
|
|
<Button variant="outline" onclick={() => handleOpenChange(false)}>Отмена</Button>
|
|
<Button onclick={save} disabled={saving}>
|
|
{saving ? 'Сохранение…' : edit ? 'Сохранить' : 'Добавить'}
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|