Skip to content
This repository was archived by the owner on Jan 30, 2026. It is now read-only.

Commit afdd04b

Browse files
committed
progress
1 parent 1189243 commit afdd04b

File tree

7 files changed

+148
-18
lines changed

7 files changed

+148
-18
lines changed

src/lib/api/headscale.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ export class Acl {
713713
}
714714

715715
protected static parsePolicy(policy: string) {
716-
const p: V1Policy = policy?.length ? parse(stripJsonTrailingCommas(policy)) : undefined;
716+
const p: V1Policy = policy?.length ? parse(stripJsonTrailingCommas(policy)) : {};
717717
const comments = p as unknown as V1PolicyComments;
718718

719719
return {
@@ -729,7 +729,7 @@ export class Acl {
729729
groups: Object.entries(p?.groups || {})
730730
.filter(([key]) => key !== '$$comments')
731731
.map(([name, members]) => ({
732-
name,
732+
name: name.replace(groupRegex, ''),
733733
members,
734734
comments: comments.groups?.$$comments?.[name]?.[0].map(parseComment)
735735
})),
@@ -815,7 +815,7 @@ export class Acl {
815815
groups: Object.fromEntries(
816816
this.groups.map((group, i) => {
817817
comments.groups.$$comments[i] = [group.comments?.map(stringifyComment) || []];
818-
return [group.name, group.members];
818+
return [groupRegex.test(group.name) ? group.name : 'group:' + group.name, group.members];
819819
})
820820
),
821821
tagOwners: Object.fromEntries(

src/lib/components/data/acl/EditRule.svelte

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@
4444
async onUpdate({ form }) {
4545
if (form.valid) {
4646
try {
47-
acl.acls = acl.acls.map((acl) =>
48-
acl.id === rule.id ? { ...rule, ...form.data } : rule
49-
);
47+
acl.acls = acl.acls.map((r) => (r.id === rule.id ? { ...r, ...form.data } : r));
5048
5149
const { error } = await acl.save();
5250
if (error) throw error;

src/lib/components/data/acl/RuleInfo.svelte

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
</script>
2424

2525
<div class="space-y-3 border-b pb-5 last:border-b-0 [&>div]:space-y-2">
26-
<div class="grid gap-x-2 gap-y-6 !space-y-0 sm:grid-cols-[1fr,1fr,auto]">
26+
<div class="grid gap-x-6 gap-y-6 !space-y-0 sm:grid-cols-[1fr,1fr,auto]">
2727
<div class="space-y-2">
2828
<!-- <div class="flex items-center justify-between gap-2"></div> -->
2929
<Label>Source</Label>
@@ -67,20 +67,40 @@
6767

6868
{#if prefixes}
6969
<div class="space-y-2">
70-
<Label class="gap11 flex items-center">Routes in</Label>
70+
<div>
71+
<Label>Routes</Label>
72+
73+
<Tooltip.Root>
74+
<Tooltip.Trigger tabindex={-1}>
75+
<Info class="h-2.5 w-2.5" />
76+
</Tooltip.Trigger>
77+
78+
<Tooltip.Content side="top" class="space-y-1">
79+
<div class="flex items-center gap-1.5">
80+
<ArrowLeft class="h-4 w-4" />
81+
<span> Incomming </span>
82+
</div>
83+
84+
<div class="flex items-center gap-1.5">
85+
<ArrowRight class="h-4 w-4" />
86+
<span> Outgoing </span>
87+
</div>
88+
</Tooltip.Content>
89+
</Tooltip.Root>
90+
</div>
7191

7292
<ul class="space-y-0.5">
7393
{#each prefixes.in as prefix}
74-
<li class="flex items-center gap-1.5">
75-
<ArrowLeft class="h-4 w-4" />
94+
<li class="flex items-center justify-end gap-1.5">
7695
{prefix}
96+
<ArrowLeft class="h-4 w-4" />
7797
</li>
7898
{/each}
7999
</ul>
80100
</div>
81101

82-
<div class="space-y-2">
83-
<Label class="flex items-center gap-1">Routes out</Label>
102+
<div class="space-y-2 pt-8">
103+
<!-- <Label>Routes out</Label> -->
84104

85105
<ul class="space-y-0.5">
86106
{#each prefixes.out as prefix}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<script lang="ts">
2+
import { defaults, superForm } from 'sveltekit-superforms';
3+
import { zod } from 'sveltekit-superforms/adapters';
4+
import { createEventDispatcher } from 'svelte';
5+
import { writable } from 'svelte/store';
6+
import { z } from 'zod';
7+
8+
import * as Select from '$lib/components/ui/select/index.js';
9+
import * as Sheet from '$lib/components/ui/sheet';
10+
import { Textarea } from '$lib/components/ui/textarea';
11+
12+
import * as Form from '$lib/components/form';
13+
14+
import type { Acl, AclData } from '$lib/api';
15+
16+
import { errorToast, successToast } from '$lib/utils/toast';
17+
import { formatError } from '$lib/utils/error';
18+
import Input from '$lib/components/ui/input/input.svelte';
19+
20+
export let acl: Acl;
21+
22+
const dispatch = createEventDispatcher<{ submit: undefined }>();
23+
24+
let mainSheet: InstanceType<typeof Sheet.Root>;
25+
26+
const schema: z.ZodType<Omit<AclData['hosts'][0], 'id'>> = z.object({
27+
name: z.string(),
28+
cidr: z.string(),
29+
comments: z.array(z.string()).default([])
30+
});
31+
32+
const form = superForm(defaults(zod(schema)), {
33+
SPA: true,
34+
dataType: 'json',
35+
invalidateAll: true,
36+
validators: zod(schema),
37+
async onUpdate({ form }) {
38+
if (form.valid) {
39+
try {
40+
acl.hosts.push(form.data);
41+
42+
const { error } = await acl.save();
43+
if (error) throw error;
44+
45+
successToast(`Created new host ${form.data.name}`);
46+
dispatch('submit');
47+
mainSheet.close();
48+
} catch (err) {
49+
console.error(err);
50+
errorToast(formatError(err));
51+
}
52+
}
53+
}
54+
});
55+
56+
const { form: formData } = form;
57+
58+
const description = writable<string>('');
59+
60+
description.subscribe((desc) => {
61+
formData.update((data) => ({ ...data, comments: desc.split(/\n{1,}/gm).map((i) => i.trim()) }));
62+
});
63+
</script>
64+
65+
<Sheet.Root bind:this={mainSheet}>
66+
<Sheet.Trigger asChild let:builder>
67+
<slot name="trigger" {builder} />
68+
</Sheet.Trigger>
69+
70+
<Sheet.Content side="left">
71+
<Sheet.Header>
72+
<Sheet.Title>Create host</Sheet.Title>
73+
</Sheet.Header>
74+
75+
<Form.Root {form} submitText="Create">
76+
<Form.Field {form} name="name" let:constraints>
77+
<Form.Control let:attrs>
78+
<Form.Label class="required" for={attrs.id}>Name</Form.Label>
79+
<Input {...constraints} {...attrs} bind:value={$formData.name} />
80+
<Form.FieldErrors />
81+
</Form.Control>
82+
</Form.Field>
83+
84+
<Form.Field {form} name="cidr" let:constraints>
85+
<Form.Control let:attrs>
86+
<Form.Label class="required" for={attrs.id}>CIDR</Form.Label>
87+
<Input {...constraints} {...attrs} bind:value={$formData.cidr} />
88+
<Form.FieldErrors />
89+
</Form.Control>
90+
</Form.Field>
91+
92+
<Form.Field {form} name="comments" let:constraints>
93+
<Form.Control let:attrs>
94+
<Form.Label for={attrs.id}>Description</Form.Label>
95+
<Textarea {...constraints} {...attrs} bind:value={$description} />
96+
</Form.Control>
97+
</Form.Field>
98+
</Form.Root>
99+
</Sheet.Content>
100+
</Sheet.Root>

src/lib/components/data/host/HostInfo.svelte

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import * as Sheet from '$lib/components/ui/sheet';
44
import * as Table from '$lib/components/ui/table';
55
import Plus from 'lucide-svelte/icons/plus';
6+
import CreateHost from './CreateHost.svelte';
67
78
export let acl: Acl;
89
export let machines: Machine[] | undefined;
@@ -20,10 +21,14 @@
2021

2122
<ul class="menu">
2223
<li>
23-
<button disabled>
24-
<Plus />
25-
<span> Host </span>
26-
</button>
24+
<CreateHost {acl}>
25+
<svelte:fragment slot="trigger" let:builder>
26+
<button {...builder} use:builder.action>
27+
<Plus />
28+
<span> Host </span>
29+
</button>
30+
</svelte:fragment>
31+
</CreateHost>
2732
</li>
2833
</ul>
2934

@@ -46,6 +51,12 @@
4651
{host.cidr}
4752
</Table.Cell>
4853
</Table.Row>
54+
55+
<div>
56+
{#each host.comments || [] as comment}
57+
<p>{comment}</p>
58+
{/each}
59+
</div>
4960
{/each}
5061
</Table.Body>
5162
</Table.Root>

src/lib/components/data/tag/TagInfo.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
<svelte:fragment slot="trigger" let:builder>
3232
<button {...builder} use:builder.action>
3333
<Plus />
34-
<span> Create </span>
34+
<span> Tag </span>
3535
</button>
3636
</svelte:fragment>
3737
</CreateTag>

src/lib/mock/store.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ export async function createDatabase(): Promise<IDBDatabase> {
2828

2929
async function initDatabase(db: IDBDatabase): Promise<IDBDatabase> {
3030
const seed = mockSeed();
31-
console.debug({ seed });
31+
console.debug('Mock database seed:', seed);
32+
3233
for (const key in seed) {
3334
if (!db.objectStoreNames.contains(key)) {
3435
const store = db.createObjectStore(key, mockStoreOpt[key]);

0 commit comments

Comments
 (0)