M2 drag-reorder: notes.position + reorder API + native DnD
- Migration 0008: notes.position (int). Board orders pinned -> position -> updated_at; new notes created at top (max position + 1). POST /api/notes/reorder assigns positions from the given order (owner-scoped). - notes store: position on Note, position-aware sort, optimistic reorder(). - NoteCard reorderable (native HTML5 draggable + dragstart/drop); BoardView moves the dragged note before the drop target and persists. Note: drag on a CSS-columns masonry has imperfect during-drag visuals (columns reflow); order persists correctly. Candidate for a polish pass / layout tweak. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FRgehjoz7Yv8LkUfADxACm
This commit is contained in:
@@ -30,6 +30,7 @@ export interface Note {
|
||||
body: string;
|
||||
color: NoteColor;
|
||||
kind: NoteKind;
|
||||
position: number;
|
||||
pinned: boolean;
|
||||
archived: boolean;
|
||||
trashed: boolean;
|
||||
@@ -49,6 +50,7 @@ export const useNotesStore = defineStore("notes", () => {
|
||||
function sortItems(): void {
|
||||
items.value.sort((a, b) => {
|
||||
if (a.pinned !== b.pinned) return a.pinned ? -1 : 1;
|
||||
if (a.position !== b.position) return b.position - a.position;
|
||||
return (b.updated_at ?? "").localeCompare(a.updated_at ?? "");
|
||||
});
|
||||
}
|
||||
@@ -139,6 +141,18 @@ export const useNotesStore = defineStore("notes", () => {
|
||||
reconcile(await api.del<Note>(`/api/notes/${id}/attachments/${attId}`));
|
||||
}
|
||||
|
||||
async function reorder(orderedIds: string[]): Promise<void> {
|
||||
// Optimistically assign positions matching the backend (total - index), sort,
|
||||
// then persist.
|
||||
const total = orderedIds.length;
|
||||
orderedIds.forEach((id, index) => {
|
||||
const n = items.value.find((x) => x.id === id);
|
||||
if (n) n.position = total - index;
|
||||
});
|
||||
sortItems();
|
||||
await api.post("/api/notes/reorder", { ids: orderedIds });
|
||||
}
|
||||
|
||||
async function trash(id: string): Promise<void> {
|
||||
reconcile(await api.post<Note>(`/api/notes/${id}/trash`));
|
||||
}
|
||||
@@ -171,6 +185,7 @@ export const useNotesStore = defineStore("notes", () => {
|
||||
deleteItem,
|
||||
uploadAttachment,
|
||||
deleteAttachment,
|
||||
reorder,
|
||||
trash,
|
||||
restore,
|
||||
deleteForever,
|
||||
|
||||
Reference in New Issue
Block a user