fix editing records and patch mocks

This commit is contained in:
Matt Hill
2025-10-26 09:02:03 -06:00
parent 33b5f189e2
commit 124ed625d9
3 changed files with 47 additions and 23 deletions

View File

@@ -65,7 +65,7 @@ import { TunnelData, WgServer } from 'src/app/services/patch-db/data-model'
@for (device of devices(); track $index) { @for (device of devices(); track $index) {
<tr> <tr>
<td>{{ device.name }}</td> <td>{{ device.name }}</td>
<td>{{ device.subnetName }}</td> <td>{{ device.subnet.name }}</td>
<td>{{ device.ip }}</td> <td>{{ device.ip }}</td>
<td> <td>
<button <button
@@ -82,7 +82,7 @@ import { TunnelData, WgServer } from 'src/app/services/patch-db/data-model'
tuiOption tuiOption
iconStart="@tui.pencil" iconStart="@tui.pencil"
new new
(click)="onEdit(device.name)" (click)="onEdit(device)"
> >
Rename Rename
</button> </button>
@@ -156,7 +156,11 @@ import { TunnelData, WgServer } from 'src/app/services/patch-db/data-model'
/> />
} }
} }
<footer><button tuiButton (click)="onSave()">Save</button></footer> <footer>
<button tuiButton (click)="onSave()" [disabled]="form.invalid">
Save
</button>
</footer>
</form> </form>
</ng-template> </ng-template>
<ng-template [(tuiDialog)]="config"> <ng-template [(tuiDialog)]="config">
@@ -252,8 +256,10 @@ export default class Devices {
protected readonly devices = computed(() => protected readonly devices = computed(() =>
this.subnets().flatMap(subnet => this.subnets().flatMap(subnet =>
Object.entries(subnet.clients).map(([ip, { name }]) => ({ Object.entries(subnet.clients).map(([ip, { name }]) => ({
subnet: subnet.range, subnet: {
subnetName: subnet.name, name: subnet.name,
range: subnet.range,
},
ip, ip,
name, name,
})), })),
@@ -269,7 +275,7 @@ export default class Devices {
protected readonly mobile = inject(TUI_IS_MOBILE) protected readonly mobile = inject(TUI_IS_MOBILE)
protected readonly form = inject(NonNullableFormBuilder).group({ protected readonly form = inject(NonNullableFormBuilder).group({
name: ['', Validators.required], name: ['', Validators.required],
subnet: [{} as MappedSubnet, Validators.required], subnet: [{} as MappedDevice['subnet'], Validators.required],
ip: ['', Validators.required], ip: ['', Validators.required],
}) })
@@ -279,9 +285,9 @@ export default class Devices {
this.dialog.set(true) this.dialog.set(true)
} }
protected onEdit(name: string): void { protected onEdit(device: MappedDevice): void {
this.editing.set(true) this.editing.set(true)
this.form.reset({ name }) this.form.reset(device)
this.dialog.set(true) this.dialog.set(true)
} }
@@ -319,7 +325,10 @@ export default class Devices {
.subscribe(async () => { .subscribe(async () => {
const loader = this.loading.open().subscribe() const loader = this.loading.open().subscribe()
try { try {
await this.api.deleteDevice({ subnet: device.subnet, ip: device.ip }) await this.api.deleteDevice({
subnet: device.subnet.range,
ip: device.ip,
})
} catch (e) { } catch (e) {
console.log(e) console.log(e)
} finally { } finally {
@@ -337,8 +346,10 @@ type MappedSubnet = {
} }
type MappedDevice = { type MappedDevice = {
subnet: string subnet: {
subnetName: string name: string
range: string
}
ip: string ip: string
name: string name: string
} }

View File

@@ -63,7 +63,7 @@ import { TunnelData } from 'src/app/services/patch-db/data-model'
tuiOption tuiOption
iconStart="@tui.pencil" iconStart="@tui.pencil"
new new
(click)="onEdit(subnet.name)" (click)="onEdit(subnet)"
> >
Rename Rename
</button> </button>
@@ -102,7 +102,11 @@ import { TunnelData } from 'src/app/services/patch-db/data-model'
[error]="[] | tuiFieldError | async" [error]="[] | tuiFieldError | async"
/> />
} }
<footer><button tuiButton (click)="onSave()">Save</button></footer> <footer>
<button tuiButton (click)="onSave()" [disabled]="form.invalid">
Save
</button>
</footer>
</form> </form>
</ng-template> </ng-template>
`, `,
@@ -130,7 +134,7 @@ export default class Subnets {
protected readonly dialog = signal(false) protected readonly dialog = signal(false)
protected readonly editing = signal(false) protected readonly editing = signal(false)
protected readonly subnets = toSignal( protected readonly subnets = toSignal<MappedSubnet[], []>(
this.patch.watch$('wg', 'subnets').pipe( this.patch.watch$('wg', 'subnets').pipe(
map(s => map(s =>
Object.entries(s).map(([range, info]) => ({ Object.entries(s).map(([range, info]) => ({
@@ -165,9 +169,9 @@ export default class Subnets {
this.dialog.set(true) this.dialog.set(true)
} }
protected onEdit(name: string): void { protected onEdit(subnet: MappedSubnet): void {
this.editing.set(true) this.editing.set(true)
this.form.reset({ name }) this.form.reset({ subnet: subnet.range, name: subnet.name })
this.dialog.set(true) this.dialog.set(true)
} }
@@ -212,3 +216,9 @@ export default class Subnets {
}) })
} }
} }
type MappedSubnet = {
range: string
name: string
hasClients: boolean
}

View File

@@ -46,7 +46,6 @@ export class MockApiService extends ApiService {
openWebsocket$<T>(guid: string): WebSocketSubject<T> { openWebsocket$<T>(guid: string): WebSocketSubject<T> {
return this.mockWsSource$.pipe( return this.mockWsSource$.pipe(
tap(v => console.log('MOCK WS', v)),
shareReplay({ bufferSize: 1, refCount: true }), shareReplay({ bufferSize: 1, refCount: true }),
) as WebSocketSubject<T> ) as WebSocketSubject<T>
} }
@@ -80,7 +79,7 @@ export class MockApiService extends ApiService {
const patch: AddOperation<WgSubnet>[] = [ const patch: AddOperation<WgSubnet>[] = [
{ {
op: PatchOp.ADD, op: PatchOp.ADD,
path: `/wg/subnets/${params.subnet}`, path: `/wg/subnets/${replaceSlashes(params.subnet)}`,
value: { name: params.name, clients: {} }, value: { name: params.name, clients: {} },
}, },
] ]
@@ -95,7 +94,7 @@ export class MockApiService extends ApiService {
const patch: ReplaceOperation<string>[] = [ const patch: ReplaceOperation<string>[] = [
{ {
op: PatchOp.REPLACE, op: PatchOp.REPLACE,
path: `/wg/subnets/${params.subnet}/name`, path: `/wg/subnets/${replaceSlashes(params.subnet)}/name`,
value: params.name, value: params.name,
}, },
] ]
@@ -110,7 +109,7 @@ export class MockApiService extends ApiService {
const patch: RemoveOperation[] = [ const patch: RemoveOperation[] = [
{ {
op: PatchOp.REMOVE, op: PatchOp.REMOVE,
path: `/wg/subnets/${params.subnet}`, path: `/wg/subnets/${replaceSlashes(params.subnet)}`,
}, },
] ]
this.mockRevision(patch) this.mockRevision(patch)
@@ -124,7 +123,7 @@ export class MockApiService extends ApiService {
const patch: AddOperation<WgClient>[] = [ const patch: AddOperation<WgClient>[] = [
{ {
op: PatchOp.ADD, op: PatchOp.ADD,
path: `/wg/subnets/${params.subnet}/clients/${params.ip}`, path: `/wg/subnets/${replaceSlashes(params.subnet)}/clients/${params.ip}`,
value: { name: params.name }, value: { name: params.name },
}, },
] ]
@@ -139,7 +138,7 @@ export class MockApiService extends ApiService {
const patch: ReplaceOperation<string>[] = [ const patch: ReplaceOperation<string>[] = [
{ {
op: PatchOp.REPLACE, op: PatchOp.REPLACE,
path: `/wg/subnets/${params.subnet}/clients/${params.ip}/name`, path: `/wg/subnets/${replaceSlashes(params.subnet)}/clients/${params.ip}/name`,
value: params.name, value: params.name,
}, },
] ]
@@ -154,7 +153,7 @@ export class MockApiService extends ApiService {
const patch: RemoveOperation[] = [ const patch: RemoveOperation[] = [
{ {
op: PatchOp.REMOVE, op: PatchOp.REMOVE,
path: `/wg/subnets/${params.subnet}/clients/${params.ip}`, path: `/wg/subnets/${replaceSlashes(params.subnet)}/clients/${params.ip}`,
}, },
] ]
this.mockRevision(patch) this.mockRevision(patch)
@@ -199,3 +198,7 @@ export class MockApiService extends ApiService {
this.mockWsSource$.next(revision) this.mockWsSource$.next(revision)
} }
} }
function replaceSlashes(val: string) {
return val.replace(new RegExp('/', 'g'), '~1')
}