79 lines
2.9 KiB
TypeScript
79 lines
2.9 KiB
TypeScript
import type { Profile } from "./api";
|
|
|
|
export type Workspace = { id: string; slug?: string; name: string; role?: "admin" | "editor" | "viewer" };
|
|
export type Board = {
|
|
id: string;
|
|
workspace_id: string;
|
|
slug?: string;
|
|
kind: "board";
|
|
title: string;
|
|
version: number;
|
|
content?: { schema_version: number };
|
|
description?: string;
|
|
parent_board_id?: string;
|
|
frame_id?: string;
|
|
};
|
|
export function matchesRef(item: { id: string; slug?: string } | null | undefined, ref: string | undefined) { return Boolean(item && ref && (item.id === ref || item.slug === ref)); }
|
|
export const DEFAULT_BOARD_TITLE = "未命名图谱";
|
|
|
|
export function boardHref(workspace: string, board: string, demo = false) {
|
|
return `/dashboard/${encodeURIComponent(workspace)}/${encodeURIComponent(board)}${demo ? "?demo=1" : ""}`;
|
|
}
|
|
type Request = <T>(path: string, options?: RequestInit) => Promise<T>;
|
|
|
|
export async function loadWorkspaceHome(
|
|
request: Request,
|
|
signal?: AbortSignal,
|
|
) {
|
|
const [profile, result] = await Promise.all([
|
|
request<Profile>("profile", { signal }),
|
|
request<Workspace[] | { items: Workspace[] }>("workspaces", { signal }),
|
|
]);
|
|
return {
|
|
profile,
|
|
workspaces: Array.isArray(result) ? result : result.items || [],
|
|
};
|
|
}
|
|
|
|
export async function createBoard(
|
|
request: Request,
|
|
title: string,
|
|
workspaceId: string,
|
|
onWorkspaceCreated: (workspace: Workspace) => void,
|
|
) {
|
|
let id = workspaceId;
|
|
if (!id) {
|
|
const workspace = await request<Workspace>("workspaces", {
|
|
method: "POST",
|
|
body: JSON.stringify({ name: "个人空间" }),
|
|
});
|
|
id = workspace.id;
|
|
onWorkspaceCreated(workspace);
|
|
}
|
|
const name = title.trim() || DEFAULT_BOARD_TITLE;
|
|
const result = await request<{ id: string; workspace_id: string; kind: "board"; version: number; slug?: string }>("workspaces/" + id + "/materials", {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
kind: "board",
|
|
title: name,
|
|
content: { schema_version: 1 },
|
|
}),
|
|
});
|
|
return { ...result, workspace_id: result.workspace_id || id, title: name };
|
|
}
|
|
|
|
|
|
export async function renameBoard(request: Request, workspaceId: string, boardId: string, title: string): Promise<Board> {
|
|
const name = title.trim();
|
|
if (!name || new TextEncoder().encode(name).length > 300) throw new Error("invalid_title");
|
|
const path = `workspaces/${encodeURIComponent(workspaceId)}/materials/${encodeURIComponent(boardId)}`;
|
|
const current = await request<Board>(path);
|
|
if (current.kind !== "board" || !matchesRef(current, boardId) || current.workspace_id !== workspaceId) throw new Error("invalid_reference");
|
|
await request(path, {
|
|
method: "PATCH",
|
|
headers: { "If-Match": `"${current.version}"` },
|
|
body: JSON.stringify({ title: name, description: current.description || "", content: current.content || { schema_version: 1 } }),
|
|
});
|
|
return { ...current, title: name, version: current.version + 1 };
|
|
}
|