clients page dialog improvements: state in url params

This commit is contained in:
Yuri Tatishchev 2024-12-25 15:35:28 -08:00
parent 62daabcd4c
commit 015bb7b05b
Signed by: CaZzzer
GPG Key ID: E0EBF441EA424369
3 changed files with 39 additions and 22 deletions

View File

@ -1,6 +1,6 @@
import type { User } from '$lib/server/db/schema';
import { ipAllocations, wgClients } from '$lib/server/db/schema';
import { db } from '$lib/server/db';
import { wgClients, ipAllocations } from '$lib/server/db/schema';
import { opnsenseAuth, opnsenseUrl, serverPublicKey, serverUuid } from '$lib/server/opnsense';
import { Address4, Address6 } from 'ip-address';
import { env } from '$env/dynamic/private';
@ -60,7 +60,7 @@ export function mapClientToDetails(
export async function createClient(params: {
name: string;
user: User;
}): Promise<Result<null, [400 | 500, string]>> {
}): Promise<Result<number, [400 | 500, string]>> {
// check if user exceeds the limit of clients
const [{ clientCount }] = await db
.select({ clientCount: count() })
@ -76,7 +76,7 @@ export async function createClient(params: {
// 2.3. update the allocation with the client id
// 3. create the client in opnsense
// 4. reconfigure opnsense to enable the new client
const error = await db.transaction(async (tx) => {
return await db.transaction(async (tx) => {
const [keys, availableAllocation, lastAllocation] = await Promise.all([
// fetch params for new client from opnsense api
getKeys(),
@ -143,10 +143,9 @@ export async function createClient(params: {
// reconfigure opnsense
await opnsenseReconfigure();
return ok(newClient.id);
});
});
if (error) return error;
return ok(null);
}
async function getKeys() {

View File

@ -1,6 +1,6 @@
import type { Actions } from './$types';
import { createClient } from '$lib/server/clients';
import { error } from '@sveltejs/kit';
import { error, redirect } from '@sveltejs/kit';
export const actions = {
create: async (event) => {
@ -15,9 +15,7 @@ export const actions = {
switch (res._tag) {
case 'ok': {
return {
status: 201,
};
return redirect(303, `/clients/${res.value}`);
}
case 'err': {
const [status, message] = res.error;

View File

@ -1,14 +1,25 @@
<script lang="ts">
import * as Table from '$lib/components/ui/table';
import * as Dialog from '$lib/components/ui/dialog';
import { Badge } from '$lib/components/ui/badge';
import { Button } from '$lib/components/ui/button';
import { Input } from '$lib/components/ui/input';
import { LucidePlus } from 'lucide-svelte';
import * as Dialog from "$lib/components/ui/dialog";
import type { PageData } from './$types';
import { Label } from '$lib/components/ui/label';
import { page } from '$app/state';
const { data }: { data: PageData } = $props();
let dialogOpen = $state(page.url.searchParams.has('add'));
let dialogVal = $state(page.url.searchParams.get('add') ?? '');
$effect(() => {
if (dialogOpen) page.url.searchParams.set('add', dialogVal);
else page.url.searchParams.delete('add');
window.history.replaceState(history.state, '', page.url);
});
</script>
<svelte:head>
@ -52,24 +63,33 @@
<!--Floating action button for adding a new client-->
<!--Not sure if this is the best place for the input field, will think about it later-->
<div class="mt-auto flex self-end pt-4">
<Dialog.Root>
<Dialog.Trigger>
<Button>
<Dialog.Root bind:open={dialogOpen}>
<Dialog.Trigger asChild let:builder>
<Button builders={[builder]}>
<LucidePlus class="mr-2 h-4 w-4" />
Add Client
</Button>
</Dialog.Trigger>
<Dialog.Content class="max-w-xs">
<form class="contents" method="post" action="?/create">
<Dialog.Header class="">
<Dialog.Title>Create a new client</Dialog.Title>
</Dialog.Header>
<div class="flex flex-wrap items-center justify-between gap-4">
<Label for="name">Name</Label>
<Input required pattern=".*[^\s]+.*" type="text" name="name" placeholder="New Client" class="max-w-[20ch]" /></div>
<Dialog.Footer>
<Button type="submit">Create</Button>
</Dialog.Footer>
<Dialog.Header class="">
<Dialog.Title>Create a new client</Dialog.Title>
</Dialog.Header>
<div class="flex flex-wrap items-center justify-between gap-4">
<Label for="name">Name</Label>
<Input
bind:value={dialogVal}
required
pattern=".*[^\s]+.*"
type="text"
name="name"
placeholder="New Client"
class="max-w-[20ch]"
/>
</div>
<Dialog.Footer>
<Button type="submit">Create</Button>
</Dialog.Footer>
</form>
</Dialog.Content>
</Dialog.Root>