Fullfør oppgave 3.5: TipTap-editor med create_node + owner-edge

Legger til owner-edge etter node-opprettelse slik at noden dukker opp
i brukerens mottak. Gjør API-klienten konfigurerbar via VITE_API_URL
for fremtidig produksjonsbruk. Legger til createEdge i API-klienten.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
vegard 2026-03-17 14:26:59 +01:00
parent daaafd34ab
commit 0756e17069
3 changed files with 42 additions and 13 deletions

View file

@ -1,10 +1,10 @@
/**
* Client for maskinrommet intentions API.
* Uses the Vite dev proxy (/api api.sidelinja.org) in development,
* and direct URL in production.
* Uses the Vite dev proxy (/api api.sidelinja.org) in development.
* In production, set VITE_API_URL to the maskinrommet URL.
*/
const BASE_URL = '/api';
const BASE_URL = import.meta.env.VITE_API_URL ?? '/api';
export interface CreateNodeRequest {
node_kind?: string;
@ -18,11 +18,20 @@ export interface CreateNodeResponse {
node_id: string;
}
export async function createNode(
accessToken: string,
data: CreateNodeRequest
): Promise<CreateNodeResponse> {
const res = await fetch(`${BASE_URL}/intentions/create_node`, {
export interface CreateEdgeRequest {
source_id: string;
target_id: string;
edge_type: string;
metadata?: Record<string, unknown>;
system?: boolean;
}
export interface CreateEdgeResponse {
edge_id: string;
}
async function post<T>(accessToken: string, path: string, data: unknown): Promise<T> {
const res = await fetch(`${BASE_URL}${path}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@ -33,8 +42,22 @@ export async function createNode(
if (!res.ok) {
const body = await res.text();
throw new Error(`create_node failed (${res.status}): ${body}`);
throw new Error(`${path} failed (${res.status}): ${body}`);
}
return res.json();
}
export function createNode(
accessToken: string,
data: CreateNodeRequest
): Promise<CreateNodeResponse> {
return post(accessToken, '/intentions/create_node', data);
}
export function createEdge(
accessToken: string,
data: CreateEdgeRequest
): Promise<CreateEdgeResponse> {
return post(accessToken, '/intentions/create_edge', data);
}

View file

@ -4,7 +4,7 @@
import { connectionState, nodeStore, edgeStore } from '$lib/spacetime';
import type { Node } from '$lib/spacetime';
import NodeEditor from '$lib/components/NodeEditor.svelte';
import { createNode } from '$lib/api';
import { createNode, createEdge } from '$lib/api';
const session = $derived($page.data.session as Record<string, unknown> | undefined);
const nodeId = $derived(session?.nodeId as string | undefined);
@ -87,13 +87,20 @@
metadata.document = data.html;
}
await createNode(accessToken, {
const { node_id } = await createNode(accessToken, {
node_kind: 'content',
title: data.title,
content: data.content,
visibility: 'hidden',
metadata
});
// Create owner edge so the node appears in the user's mottak
await createEdge(accessToken, {
source_id: nodeId!,
target_id: node_id,
edge_type: 'owner'
});
}
</script>

View file

@ -64,8 +64,7 @@ Uavhengige faser kan fortsatt plukkes.
- [x] 3.2 Authentik login: OIDC-flow (authorization code + PKCE). Session-håndtering. Redirect til login ved 401.
- [x] 3.3 STDB WebSocket-klient: abonner på noder og edges. Reaktiv Svelte-store som oppdateres ved endringer.
- [x] 3.4 Mottaksflaten v0: vis noder med edge til innlogget bruker, sortert på `created_at`. Enkel liste med tittel og utdrag.
- [~] 3.5 TipTap-editor: enkel preset (tekst, markdown, lenker). Send `create_node`-intensjon til maskinrommet ved submit.
> Påbegynt: 2026-03-17T14:19
- [x] 3.5 TipTap-editor: enkel preset (tekst, markdown, lenker). Send `create_node`-intensjon til maskinrommet ved submit.
- [ ] 3.6 Sanntidstest: åpne to faner, skriv i én, se noden dukke opp i den andre via STDB.
## Fase 4: Tilgangskontroll