feat: version 2.10.0 -- Notas en tarjetas, crear/editar en popup, compartir de solo lectura
Rediseno completo del modulo Notas (era lista inline, sin popup, sin compartir):
- Tarjetas con resumen del contenido en vez de lista vertical; la primera tarjeta siempre es
un "+" para crear.
- Crear y editar se hacen en un DetailPopup (antes: textarea fijo arriba + edicion inline por
tarjeta).
- Nueva tabla note_shares (migracion 019): compartir una nota con otro usuario ya registrado,
siempre de solo lectura -- el dueño sigue siendo el unico que edita/borra/comparte (mismo
patron que project_members pero sin rol ni invitacion por correo, ya que acá no hace falta).
Quien recibe la nota la ve con "Compartida por {nombre}", sin ningun control de edicion.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,18 @@
|
||||
import { pool } from '../../config/db.js';
|
||||
|
||||
export async function findByUser(userId) {
|
||||
// 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).
|
||||
export async function findVisibleToUser(userId) {
|
||||
const [rows] = await pool.query(
|
||||
'SELECT id, user_id, content, created_at, updated_at FROM notes WHERE user_id = ? ORDER BY updated_at DESC',
|
||||
[userId]
|
||||
`SELECT n.id, n.user_id, n.content, n.created_at, n.updated_at,
|
||||
(n.user_id = ?) AS is_owner, u.name AS owner_name
|
||||
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`,
|
||||
[userId, userId, userId]
|
||||
);
|
||||
return rows;
|
||||
return rows.map((r) => ({ ...r, is_owner: !!r.is_owner }));
|
||||
}
|
||||
|
||||
export async function findById(id) {
|
||||
@@ -26,3 +33,28 @@ export async function update(id, content) {
|
||||
export async function remove(id) {
|
||||
await pool.query('DELETE FROM notes WHERE id = ?', [id]);
|
||||
}
|
||||
|
||||
export async function listShares(noteId) {
|
||||
const [rows] = await pool.query(
|
||||
`SELECT ns.user_id, u.name, u.email, ns.shared_at
|
||||
FROM note_shares ns JOIN users u ON u.id = ns.user_id
|
||||
WHERE ns.note_id = ? ORDER BY u.name`,
|
||||
[noteId]
|
||||
);
|
||||
return rows;
|
||||
}
|
||||
|
||||
export async function isSharedWith(noteId, userId) {
|
||||
const [rows] = await pool.query('SELECT 1 FROM note_shares WHERE note_id = ? AND user_id = ?', [noteId, userId]);
|
||||
return rows.length > 0;
|
||||
}
|
||||
|
||||
export async function addShare(noteId, userId) {
|
||||
await pool.query('INSERT IGNORE INTO note_shares (note_id, user_id) VALUES (?, ?)', [noteId, userId]);
|
||||
return listShares(noteId);
|
||||
}
|
||||
|
||||
export async function removeShare(noteId, userId) {
|
||||
await pool.query('DELETE FROM note_shares WHERE note_id = ? AND user_id = ?', [noteId, userId]);
|
||||
return listShares(noteId);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user