feat: version 2.10.4 -- tarjetas de Notas arrastrables para reordenar

Nueva columna sort_order en notes (migracion 020, mismo patron que 012_sort_order.sql de
activities/tasks). Se reusa el hook useDragReorder ya existente (drag & drop nativo, sin
libreria nueva) -- el icono de agarre va solo en una esquina de la tarjeta, nunca en la
tarjeta completa, para no pisar el click que abre la edicion (mismo truco que ya usa
ListView.jsx: stopPropagation en el handle).

Solo las notas propias son arrastrables/reordenables; las compartidas conmigo quedan
siempre despues, ordenadas por fecha (el orden manual de otro usuario no tiene sentido para
mi vista). Se desactiva mientras hay un filtro de busqueda activo.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Milton Gonzalez
2026-10-12 16:17:51 -05:00
parent 2d1bfc0bfd
commit 0964ffb8a8
12 changed files with 100 additions and 17 deletions
+14 -2
View File
@@ -1,7 +1,9 @@
import { pool } from '../../config/db.js';
// Notas propias MAS las compartidas conmigo. is_owner permite al frontend decidir si se puede
// editar/borrar/compartir (siempre false para una nota compartida: el dueno nunca cambia).
// editar/borrar/compartir/arrastrar (siempre false para una nota compartida: el dueno nunca
// cambia, y el orden manual de otro usuario no tiene sentido para mi vista). Propias primero (en
// su orden manual), compartidas despues (por fecha -- nunca arrastrables).
export async function findVisibleToUser(userId) {
const [rows] = await pool.query(
`SELECT n.id, n.user_id, n.content, n.created_at, n.updated_at,
@@ -10,12 +12,22 @@ export async function findVisibleToUser(userId) {
FROM notes n
JOIN users u ON u.id = n.user_id
WHERE n.user_id = ? OR n.id IN (SELECT note_id FROM note_shares WHERE user_id = ?)
ORDER BY n.updated_at DESC`,
ORDER BY is_owner DESC, CASE WHEN is_owner THEN n.sort_order ELSE 0 END DESC, n.updated_at DESC`,
[userId, userId, userId]
);
return rows.map((r) => ({ ...r, is_owner: !!r.is_owner, share_count: Number(r.share_count) }));
}
// Posiciones SIEMPRE N..1 (nunca 0 -- ver migracion 020). El primer id del arreglo (arriba del
// todo visualmente) recibe el numero MAS ALTO porque el ORDER BY de arriba es DESC. Solo toca
// notas propias de userId, ignora cualquier id ajeno que venga en la lista.
export async function reorder(userId, ids) {
const total = ids.length;
for (let i = 0; i < total; i++) {
await pool.query('UPDATE notes SET sort_order = ? WHERE id = ? AND user_id = ?', [total - i, ids[i], userId]);
}
}
export async function findById(id) {
const [rows] = await pool.query('SELECT id, user_id, content, created_at, updated_at FROM notes WHERE id = ?', [id]);
return rows[0] || null;