feat: preserve tabs on sync disconnect/reconnect
Disconnecting a synced list (Google/Outlook/Synology) now uses a soft-disconnect: tasks are soft-deleted and the external link is cleared, but the SomedayList record is kept with its tab assignment intact. When the user reconnects, the import route finds the list by title, re-links the external provider, and restores tasks (clearing deletedAt). Tabs survive the full disconnect/reconnect cycle without the user needing to drag lists back to tabs. Also clears deletedAt on task re-import so previously disconnected tasks become visible again on reconnect. v1.89.0
This commit is contained in:
parent
d8d1003e78
commit
0a84bf3114
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "my-weekly-todo-list",
|
||||
"version": "1.88.2",
|
||||
"version": "1.89.0",
|
||||
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -121,6 +121,8 @@ export async function DELETE(request: NextRequest) {
|
||||
|
||||
const { searchParams } = new URL(request.url);
|
||||
const id = searchParams.get('id');
|
||||
// tasksOnly=true: soft-disconnect (keep list record with tab, just remove tasks + external link)
|
||||
const tasksOnly = searchParams.get('tasksOnly') === 'true';
|
||||
|
||||
if (!id) {
|
||||
return NextResponse.json(
|
||||
@ -147,6 +149,16 @@ export async function DELETE(request: NextRequest) {
|
||||
data: { deletedAt: new Date(), somedayListId: null }
|
||||
});
|
||||
|
||||
if (tasksOnly) {
|
||||
// Soft-disconnect: keep list record (preserves tab assignment) but clear external link
|
||||
await prisma.somedayList.update({
|
||||
where: { id },
|
||||
data: { externalId: null, externalProvider: null, lastSyncedAt: null }
|
||||
});
|
||||
notifyUser(userId, "list-changed", { action: "disconnected" });
|
||||
return NextResponse.json({ success: true, kept: true });
|
||||
}
|
||||
|
||||
await prisma.somedayList.delete({
|
||||
where: { id }
|
||||
});
|
||||
|
||||
@ -293,7 +293,8 @@ export async function POST(req: NextRequest) {
|
||||
where: { id: existingTask.id },
|
||||
data: {
|
||||
somedayListId: somedayList.id,
|
||||
lastSyncedAt: new Date()
|
||||
lastSyncedAt: new Date(),
|
||||
deletedAt: null, // clear soft-delete from a previous disconnect
|
||||
}
|
||||
});
|
||||
externalToLocalId.set(task.externalId, existingTask.id);
|
||||
|
||||
@ -3672,10 +3672,13 @@ export default function WeeklyView() {
|
||||
);
|
||||
if (!existing) { setUnsyncConfirm(null); return; }
|
||||
try {
|
||||
const res = await fetch(`/api/someday-lists?id=${existing.id}`, {
|
||||
// tasksOnly=true: soft-disconnect — removes tasks but keeps list record with its tab assignment
|
||||
// so when the user reconnects, the tab is restored automatically without re-dragging
|
||||
const res = await fetch(`/api/someday-lists?id=${existing.id}&tasksOnly=true`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
if (res.ok) {
|
||||
// Remove from local state (clean UI); DB record is kept for tab restoration on reconnect
|
||||
setSomedayLists((prev) => prev.filter((l) => l.id !== existing.id));
|
||||
setImportStatusMsg({
|
||||
type: "success",
|
||||
@ -3683,7 +3686,7 @@ export default function WeeklyView() {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to delete list", error);
|
||||
console.error("Failed to unsync list", error);
|
||||
setImportStatusMsg({
|
||||
type: "error",
|
||||
text: "Failed to stop syncing list.",
|
||||
@ -3717,7 +3720,8 @@ export default function WeeklyView() {
|
||||
);
|
||||
if (!existing) continue;
|
||||
try {
|
||||
const res = await fetch(`/api/someday-lists?id=${existing.id}`, {
|
||||
// tasksOnly=true: soft-disconnect — keeps list record with tab for reconnect restoration
|
||||
const res = await fetch(`/api/someday-lists?id=${existing.id}&tasksOnly=true`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
if (res.ok) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user