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:
parent
daaafd34ab
commit
0756e17069
3 changed files with 42 additions and 13 deletions
|
|
@ -1,10 +1,10 @@
|
||||||
/**
|
/**
|
||||||
* Client for maskinrommet intentions API.
|
* Client for maskinrommet intentions API.
|
||||||
* Uses the Vite dev proxy (/api → api.sidelinja.org) in development,
|
* Uses the Vite dev proxy (/api → api.sidelinja.org) in development.
|
||||||
* and direct URL in production.
|
* 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 {
|
export interface CreateNodeRequest {
|
||||||
node_kind?: string;
|
node_kind?: string;
|
||||||
|
|
@ -18,11 +18,20 @@ export interface CreateNodeResponse {
|
||||||
node_id: string;
|
node_id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createNode(
|
export interface CreateEdgeRequest {
|
||||||
accessToken: string,
|
source_id: string;
|
||||||
data: CreateNodeRequest
|
target_id: string;
|
||||||
): Promise<CreateNodeResponse> {
|
edge_type: string;
|
||||||
const res = await fetch(`${BASE_URL}/intentions/create_node`, {
|
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',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
|
@ -33,8 +42,22 @@ export async function createNode(
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const body = await res.text();
|
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();
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
import { connectionState, nodeStore, edgeStore } from '$lib/spacetime';
|
import { connectionState, nodeStore, edgeStore } from '$lib/spacetime';
|
||||||
import type { Node } from '$lib/spacetime';
|
import type { Node } from '$lib/spacetime';
|
||||||
import NodeEditor from '$lib/components/NodeEditor.svelte';
|
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 session = $derived($page.data.session as Record<string, unknown> | undefined);
|
||||||
const nodeId = $derived(session?.nodeId as string | undefined);
|
const nodeId = $derived(session?.nodeId as string | undefined);
|
||||||
|
|
@ -87,13 +87,20 @@
|
||||||
metadata.document = data.html;
|
metadata.document = data.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
await createNode(accessToken, {
|
const { node_id } = await createNode(accessToken, {
|
||||||
node_kind: 'content',
|
node_kind: 'content',
|
||||||
title: data.title,
|
title: data.title,
|
||||||
content: data.content,
|
content: data.content,
|
||||||
visibility: 'hidden',
|
visibility: 'hidden',
|
||||||
metadata
|
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>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
3
tasks.md
3
tasks.md
|
|
@ -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.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.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.
|
- [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.
|
- [x] 3.5 TipTap-editor: enkel preset (tekst, markdown, lenker). Send `create_node`-intensjon til maskinrommet ved submit.
|
||||||
> Påbegynt: 2026-03-17T14:19
|
|
||||||
- [ ] 3.6 Sanntidstest: åpne to faner, skriv i én, se noden dukke opp i den andre via STDB.
|
- [ ] 3.6 Sanntidstest: åpne to faner, skriv i én, se noden dukke opp i den andre via STDB.
|
||||||
|
|
||||||
## Fase 4: Tilgangskontroll
|
## Fase 4: Tilgangskontroll
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue