feat(collab): redesign note collaboration with REST auto-save, opt-in live session, and block locking
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 59s

This commit is contained in:
sandrodach committed 2026-10-27 14:02:38 +01:00
1 parent 50b017f387
commit 0e06cc5577
11 files changed
+1373 -239

No files matched your search

+36
View File
@@ -6,6 +6,9 @@ import {
DocumentBlock,
DocShare,
DocLockInfo,
BlockLockInfo,
LiveSessionInfo,
DocLocksResponse,
KanbanColumn,
ListItem,
ListShare,
@@ -625,6 +628,39 @@ export const api = {
await request(`/api/v1/documents/${id}`, { method: 'DELETE' });
},
async getDocLocks(docId: string): Promise<DocLocksResponse> {
const res = await request<DocLocksResponse>(`/api/v1/documents/${docId}/locks`);
return {
liveSession: res.liveSession || null,
blockLocks: ensureArray(res.blockLocks),
};
},
async lockBlock(docId: string, blockId: string, userColor?: string, ttlSeconds: number = 30): Promise<BlockLockInfo> {
return request<BlockLockInfo>(`/api/v1/documents/${docId}/blocks/${encodeURIComponent(blockId)}/lock`, {
method: 'POST',
body: JSON.stringify({ userColor, ttlSeconds }),
});
},
async unlockBlock(docId: string, blockId: string): Promise<{ status: string }> {
return request<{ status: string }>(`/api/v1/documents/${docId}/blocks/${encodeURIComponent(blockId)}/unlock`, {
method: 'POST',
});
},
async startLiveSession(docId: string): Promise<LiveSessionInfo> {
return request<LiveSessionInfo>(`/api/v1/documents/${docId}/live/start`, {
method: 'POST',
});
},
async endLiveSession(docId: string): Promise<{ status: string }> {
return request<{ status: string }>(`/api/v1/documents/${docId}/live/end`, {
method: 'POST',
});
},
async moveDocument(id: string, folderPath: string): Promise<Document> {
const d = await request<Document>(`/api/v1/documents/${id}/move`, {
method: 'PUT',