refactor: remove legacy spaces and migrate lists to standalone resources with direct sharing
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 59s

This commit is contained in:
sandrodach committed 2026-10-25 18:17:17 +01:00
1 parent 177b69234c
commit 0d6c603e9c
9 files changed
+616 -950

No files matched your search

+42 -6
View File
@@ -8,6 +8,7 @@ import {
DocLockInfo,
KanbanColumn,
ListItem,
ListShare,
Organization,
PriorityLevel,
SharedList,
@@ -639,17 +640,36 @@ export const api = {
return ensureArray(res).map((l) => ({
...l,
items: ensureArray(l.items),
shares: ensureArray(l.shares),
}));
},
async createList(spaceId: string, title: string, icon: string, listType: 'shopping' | 'checklist' | 'vacation'): Promise<SharedList> {
const l = await request<SharedList>(`/api/v1/spaces/${spaceId}/lists`, {
async getListById(listId: string): Promise<SharedList> {
const l = await request<SharedList>(`/api/v1/lists/${listId}`);
return {
...l,
items: ensureArray(l.items),
shares: ensureArray(l.shares),
};
},
async createList(titleOrSpaceId: string, titleOrIcon?: string, iconOrType?: string, listType?: 'shopping' | 'checklist' | 'vacation'): Promise<SharedList> {
let title = titleOrSpaceId;
let icon = titleOrIcon || '🛒';
let type = (iconOrType as any) || 'shopping';
if (listType !== undefined) {
title = titleOrIcon || '';
icon = iconOrType || '🛒';
type = listType;
}
const l = await request<SharedList>('/api/v1/lists', {
method: 'POST',
body: JSON.stringify({ title, icon, listType }),
body: JSON.stringify({ title, icon, listType: type }),
});
return {
...l,
items: ensureArray(l.items),
shares: ensureArray(l.shares),
};
},
@@ -657,6 +677,22 @@ export const api = {
await request(`/api/v1/lists/${listId}`, { method: 'DELETE' });
},
async getListShares(listId: string): Promise<ListShare[]> {
const res = await request<ListShare[]>(`/api/v1/lists/${listId}/shares`);
return ensureArray(res);
},
async addListShare(listId: string, target: { targetType: 'team' | 'user'; targetId: string; role?: string }): Promise<ListShare> {
return request<ListShare>(`/api/v1/lists/${listId}/shares`, {
method: 'POST',
body: JSON.stringify(target),
});
},
async removeListShare(listId: string, shareId: string): Promise<void> {
await request(`/api/v1/lists/${listId}/shares/${shareId}`, { method: 'DELETE' });
},
async createListItem(listId: string, content: string, category = '', quantity = ''): Promise<ListItem> {
return request<ListItem>(`/api/v1/lists/${listId}/items`, {
method: 'POST',
@@ -905,11 +941,11 @@ let wsReconnectTimer: any = null;
let wsListeners: ((msg: WSMessage) => void)[] = [];
let manualDisconnect = false;
export function buildWebSocketURL(spaceId?: string): string {
export function buildWebSocketURL(listId?: string): string {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const token = getToken() || '';
if (spaceId) {
return `${protocol}//${window.location.host}/api/v1/ws/spaces/${encodeURIComponent(spaceId)}?token=${encodeURIComponent(token)}`;
if (listId) {
return `${protocol}//${window.location.host}/api/v1/ws/lists/${encodeURIComponent(listId)}?token=${encodeURIComponent(token)}`;
}
return `${protocol}//${window.location.host}/api/v1/ws?token=${encodeURIComponent(token)}`;
}
+19 -1
View File
@@ -295,13 +295,30 @@ export interface ListItem {
completedAt?: string;
}
export interface ListShare {
id: string;
listId: string;
targetType: 'team' | 'user';
targetId: string;
targetName?: string;
targetEmail?: string;
role: 'editor' | 'viewer';
createdBy?: string;
createdAt: string;
}
export interface SharedList {
id: string;
spaceId: string;
userId?: string;
ownerName?: string;
isOwner?: boolean;
role?: string;
spaceId?: string;
title: string;
icon: string;
listType: 'shopping' | 'checklist' | 'vacation';
items: ListItem[];
shares?: ListShare[];
updatedAt: string;
createdAt: string;
}
@@ -331,6 +348,7 @@ export interface WSMessage<T = any> {
event: string;
space_id?: string;
list_id?: string;
listId?: string;
payload: T;
timestamp: string;
}