feat(tasks): persist list_id/effort/notes + update_task_cmd — close Task 2 metadata gap
This commit is contained in:
@@ -244,6 +244,7 @@ function mapTaskRow(row) {
|
||||
bucket: row.bucket ?? "inbox",
|
||||
listId: row.listId ?? null,
|
||||
effort: row.effort ?? "",
|
||||
notes: row.notes ?? "",
|
||||
done: !!row.done,
|
||||
doneAt: row.doneAt ?? null,
|
||||
createdAt: row.createdAt ?? new Date().toISOString(),
|
||||
@@ -294,6 +295,11 @@ export async function addTask(task) {
|
||||
text: task.text,
|
||||
bucket: task.bucket || "inbox",
|
||||
sourceTranscriptId: task.sourceTranscriptId || null,
|
||||
// Task 2.6: forward list_id / effort so the SQLite row carries the
|
||||
// metadata callers pass in. Callers that omit these get server
|
||||
// defaults (NULL for list_id/effort, '' for notes at the column).
|
||||
listId: task.listId ?? null,
|
||||
effort: task.effort ?? null,
|
||||
},
|
||||
});
|
||||
tasks.unshift(mapTaskRow(row));
|
||||
@@ -303,7 +309,16 @@ export async function addTask(task) {
|
||||
}
|
||||
}
|
||||
|
||||
export function updateTask(id, updates) {
|
||||
/**
|
||||
* Apply a partial update to an in-memory task and broadcast the change.
|
||||
* Used by `completeTask` / `uncompleteTask` after their dedicated server
|
||||
* commands succeed. Not exported — external callers go through `updateTask`
|
||||
* which persists via `update_task_cmd`.
|
||||
*
|
||||
* @param {string} id
|
||||
* @param {Record<string, any>} updates
|
||||
*/
|
||||
function applyLocalTaskUpdate(id, updates) {
|
||||
const idx = tasks.findIndex((t) => t.id === id);
|
||||
if (idx >= 0) {
|
||||
Object.assign(tasks[idx], updates);
|
||||
@@ -311,6 +326,47 @@ export function updateTask(id, updates) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist a patch to an existing task and refresh the in-memory copy with
|
||||
* the server's canonical row. `updates` may contain any of
|
||||
* `{ text, bucket, listId, effort, notes }`; omitted fields are preserved
|
||||
* server-side via COALESCE. `done` / `doneAt` are ignored by the server's
|
||||
* UpdateTaskRequest — use `completeTask` / `uncompleteTask` for those.
|
||||
*
|
||||
* Closes the Task 2.6 gap: before this, updateTask was a session-only
|
||||
* mutation, so bucket / effort / listId edits vanished on restart.
|
||||
*
|
||||
* @param {string} id
|
||||
* @param {Record<string, any>} updates
|
||||
*/
|
||||
export async function updateTask(id, updates) {
|
||||
if (!hasTauriRuntime()) {
|
||||
// Browser preview: fall back to the local-only path so the UI still
|
||||
// reflects edits during Vite dev runs outside the Tauri shell.
|
||||
applyLocalTaskUpdate(id, updates);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const row = await invoke("update_task_cmd", {
|
||||
id,
|
||||
patch: {
|
||||
text: updates.text ?? null,
|
||||
bucket: updates.bucket ?? null,
|
||||
listId: updates.listId ?? null,
|
||||
effort: updates.effort ?? null,
|
||||
notes: updates.notes ?? null,
|
||||
},
|
||||
});
|
||||
const idx = tasks.findIndex((t) => t.id === id);
|
||||
if (idx >= 0) {
|
||||
tasks[idx] = mapTaskRow(row);
|
||||
broadcastTasks();
|
||||
}
|
||||
} catch (err) {
|
||||
toasts.error("Couldn't update task", err?.message ?? String(err));
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteTask(id) {
|
||||
if (!hasTauriRuntime()) return;
|
||||
try {
|
||||
@@ -329,7 +385,10 @@ export async function completeTask(id) {
|
||||
if (!hasTauriRuntime()) return;
|
||||
try {
|
||||
await invoke("complete_task_cmd", { id });
|
||||
updateTask(id, { done: true, doneAt: new Date().toISOString() });
|
||||
// Local-only mirror: complete_task_cmd already stamped done/done_at
|
||||
// server-side, so we just mirror the state here. Going through the
|
||||
// persisting `updateTask` path would be a wasted round-trip.
|
||||
applyLocalTaskUpdate(id, { done: true, doneAt: new Date().toISOString() });
|
||||
} catch (err) {
|
||||
toasts.error("Couldn't complete task", err?.message ?? String(err));
|
||||
}
|
||||
@@ -339,7 +398,7 @@ export async function uncompleteTask(id) {
|
||||
if (!hasTauriRuntime()) return;
|
||||
try {
|
||||
await invoke("uncomplete_task_cmd", { id });
|
||||
updateTask(id, { done: false, doneAt: null });
|
||||
applyLocalTaskUpdate(id, { done: false, doneAt: null });
|
||||
} catch (err) {
|
||||
toasts.error("Couldn't uncomplete task", err?.message ?? String(err));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user