|
|
@@ -98,6 +98,11 @@ type Payload = { |
| 98 | 98 |
|
| 99 | 99 |
|
| 100 | 100 |
restoreBoardName?: { id: string; name: string }; |
| 101 |
|
| 102 |
|
| 103 |
|
| 104 |
|
| 105 |
label?: string; |
| 101 | 106 |
}; |
| 102 | 107 |
|
| 103 | 108 |
|
|
|
@@ -196,7 +201,7 @@ export function renameBoard(boardId: string, name: string): boolean { |
| 196 | 201 |
const before = getBoard(boardId); |
| 197 | 202 |
if (!before) return false; |
| 198 | 203 |
db.query("UPDATE board SET name = ?2 WHERE id = ?1").run(boardId, name); |
| 199 | |
logAction(boardId, { restoreBoardName: { id: boardId, name: before.name } }); |
| 204 |
logAction(boardId, { restoreBoardName: { id: boardId, name: before.name }, label: "renamed the board" }); |
| 200 | 205 |
bumpRevision(boardId); |
| 201 | 206 |
bumpRevision(BOARDS_SCOPE); |
| 202 | 207 |
return true; |
|
|
@@ -244,7 +249,7 @@ export function createColumn(boardId: string, name: string, explicitPosition?: n |
| 244 | 249 |
name, |
| 245 | 250 |
position, |
| 246 | 251 |
); |
| 247 | |
logAction(boardId, { deleteColumnIds: [id] }); |
| 252 |
logAction(boardId, { deleteColumnIds: [id], label: `added the column "${name}"` }); |
| 248 | 253 |
bumpRevision(boardId); |
| 249 | 254 |
return { id, board_id: boardId, name, position }; |
| 250 | 255 |
}).immediate(); |
|
|
@@ -261,7 +266,7 @@ export function renameColumn(boardId: string, columnId: string, name: string): b |
| 261 | 266 |
const before = getColumn(boardId, columnId); |
| 262 | 267 |
if (!before) return false; |
| 263 | 268 |
db.query("UPDATE board_column SET name = ?2 WHERE id = ?1").run(columnId, name); |
| 264 | |
logAction(boardId, { restoreColumns: [before] }); |
| 269 |
logAction(boardId, { restoreColumns: [before], label: `renamed the column "${name}"` }); |
| 265 | 270 |
bumpRevision(boardId); |
| 266 | 271 |
return true; |
| 267 | 272 |
}).immediate(); |
|
|
@@ -277,7 +282,7 @@ export function moveColumn(boardId: string, columnId: string, direction: "left" |
| 277 | 282 |
const before = [columns[i], columns[j]]; |
| 278 | 283 |
db.query("UPDATE board_column SET position = ?2 WHERE id = ?1").run(columns[i].id, columns[j].position); |
| 279 | 284 |
db.query("UPDATE board_column SET position = ?2 WHERE id = ?1").run(columns[j].id, columns[i].position); |
| 280 | |
logAction(boardId, { restoreColumns: before }); |
| 285 |
logAction(boardId, { restoreColumns: before, label: `moved the column "${columns[i].name}"` }); |
| 281 | 286 |
bumpRevision(boardId); |
| 282 | 287 |
return true; |
| 283 | 288 |
}).immediate(); |
|
|
@@ -289,7 +294,7 @@ export function deleteColumn(boardId: string, columnId: string): boolean { |
| 289 | 294 |
if (!before) return false; |
| 290 | 295 |
const cards = listCards(boardId).filter((c) => c.column_id === columnId); |
| 291 | 296 |
db.query("DELETE FROM board_column WHERE id = ?1").run(columnId); |
| 292 | |
logAction(boardId, { restoreColumns: [before], restoreCards: cards }); |
| 297 |
logAction(boardId, { restoreColumns: [before], restoreCards: cards, label: `deleted the column "${before.name}"` }); |
| 293 | 298 |
bumpRevision(boardId); |
| 294 | 299 |
return true; |
| 295 | 300 |
}).immediate(); |
|
|
@@ -309,7 +314,7 @@ export function createCard(boardId: string, columnId: string, title: string): Ca |
| 309 | 314 |
title, |
| 310 | 315 |
position, |
| 311 | 316 |
); |
| 312 | |
logAction(boardId, { deleteCardIds: [id] }); |
| 317 |
logAction(boardId, { deleteCardIds: [id], label: `added the card "${title}"` }); |
| 313 | 318 |
bumpRevision(boardId); |
| 314 | 319 |
return getCard(boardId, id)!; |
| 315 | 320 |
}).immediate(); |
|
|
@@ -329,7 +334,7 @@ export function editCard(boardId: string, cardId: string, title: string): boolea |
| 329 | 334 |
const before = getCard(boardId, cardId); |
| 330 | 335 |
if (!before) return false; |
| 331 | 336 |
db.query("UPDATE card SET title = ?2, updated_at = datetime('now') WHERE id = ?1").run(cardId, title); |
| 332 | |
logAction(boardId, { restoreCards: [before] }); |
| 337 |
logAction(boardId, { restoreCards: [before], label: `edited the card "${title}"` }); |
| 333 | 338 |
bumpRevision(boardId); |
| 334 | 339 |
return true; |
| 335 | 340 |
}).immediate(); |
|
|
@@ -359,7 +364,7 @@ export function moveCard(boardId: string, cardId: string, columnId: string, inde |
| 359 | 364 |
columnId, |
| 360 | 365 |
position, |
| 361 | 366 |
); |
| 362 | |
logAction(boardId, { restoreCards: [before] }); |
| 367 |
logAction(boardId, { restoreCards: [before], label: `moved "${before.title}"` }); |
| 363 | 368 |
bumpRevision(boardId); |
| 364 | 369 |
return true; |
| 365 | 370 |
} |
|
|
@@ -377,7 +382,7 @@ export function moveCard(boardId: string, cardId: string, columnId: string, inde |
| 377 | 382 |
columnId, |
| 378 | 383 |
at + 1, |
| 379 | 384 |
); |
| 380 | |
logAction(boardId, { restoreCards }); |
| 385 |
logAction(boardId, { restoreCards, label: `moved "${before.title}"` }); |
| 381 | 386 |
bumpRevision(boardId); |
| 382 | 387 |
return true; |
| 383 | 388 |
}).immediate(); |
|
|
@@ -388,18 +393,28 @@ export function deleteCard(boardId: string, cardId: string): boolean { |
| 388 | 393 |
const before = getCard(boardId, cardId); |
| 389 | 394 |
if (!before) return false; |
| 390 | 395 |
db.query("DELETE FROM card WHERE id = ?1").run(cardId); |
| 391 | |
logAction(boardId, { restoreCards: [before] }); |
| 396 |
logAction(boardId, { restoreCards: [before], label: `deleted the card "${before.title}"` }); |
| 392 | 397 |
bumpRevision(boardId); |
| 393 | 398 |
return true; |
| 394 | 399 |
}).immediate(); |
| 395 | 400 |
} |
| 396 | 401 |
|
| 397 | |
export function undo(boardId: string): boolean { |
| 398 | |
return db.transaction((): boolean => { |
| 402 |
|
| 403 |
export function peekUndo(boardId: string): string | null { |
| 404 |
const row = db |
| 405 |
.query<{ payload: string }, [string]>("SELECT payload FROM action WHERE board_id = ?1 ORDER BY id DESC LIMIT 1") |
| 406 |
.get(boardId); |
| 407 |
if (!row) return null; |
| 408 |
return (JSON.parse(row.payload) as Payload).label ?? "a change"; |
| 409 |
} |
| 410 |
|
| 411 |
|
| 412 |
export function undo(boardId: string): string | null { |
| 413 |
return db.transaction((): string | null => { |
| 399 | 414 |
const row = db |
| 400 | 415 |
.query<{ id: number; payload: string }, [string]>("SELECT id, payload FROM action WHERE board_id = ?1 ORDER BY id DESC LIMIT 1") |
| 401 | 416 |
.get(boardId); |
| 402 | |
if (!row) return false; |
| 417 |
if (!row) return null; |
| 403 | 418 |
const payload = JSON.parse(row.payload) as Payload; |
| 404 | 419 |
const restoreColumn = db.query( |
| 405 | 420 |
"INSERT OR REPLACE INTO board_column (id, board_id, name, position) VALUES (?1, ?2, ?3, ?4)", |
|
|
@@ -417,6 +432,6 @@ export function undo(boardId: string): boolean { |
| 417 | 432 |
} |
| 418 | 433 |
db.query("DELETE FROM action WHERE id = ?1").run(row.id); |
| 419 | 434 |
bumpRevision(boardId); |
| 420 | |
return true; |
| 435 |
return payload.label ?? "a change"; |
| 421 | 436 |
}).immediate(); |
| 422 | 437 |
} |