Volver a la wiki

Página /tasks — 4 mejoras s56 (PR#11)

Página /tasks — 4 mejoras s56 (PR#11)

Conjunto de cuatro mejoras funcionales en la página /tasks del workspace, implementadas en el sprint 56 (s56) a petición de Edu (PM). Mergeado el 2026-05-11.


Resumen de cambios

#CommitÁreaDescripción
13fd6925Dashboard widgetScroll en TasksWidget + fetch 5→20 pending
21954b0fPreferencias UIFix fontSize para clases Tailwind (data-font-size)
3b6091a6TaskModal / TaskManagerMulti-select asignado (Edu/Dani/Txell toggle)
4fc6d178TaskModal + API + D1Vinculación de notas del Cuaderno (linked_note_ids)

Cambio 1 · Widget Tareas Dashboard — Scroll + Fetch ampliado

Archivo: src/components/dashboard/TasksWidget.tsx

El widget del dashboard que muestra tareas pendientes crecía indefinidamente si había muchas tareas. Se añadió:

Antes: lista sin altura máxima, mostraba solo 4 items sin scroll.
Después: hasta 20 items, scroll interno, altura máxima equivalente a 7 filas.


Cambio 2 · Fix Preferencias fontSize con Tailwind

Archivo: src/styles/globals.css

Las preferencias de tamaño de texto del workspace (data-font-size="sm|md|lg|xl") solo escalaban el font-size del body. Los componentes que usaban clases Tailwind (text-xs, text-sm, text-base, text-lg, text-xl) ignoraban la preferencia porque Tailwind genera valores estáticos.

Solución: overrides CSS explícitos por cada combinación [data-font-size] .text-{size}:

Atributotext-xstext-smtext-basetext-lgtext-xl
sm0.7rem0.8125rem0.9375rem1.05rem1.2rem
md(Tailwind default)————
lg0.825rem0.95rem1.0625rem1.225rem1.4rem
xl0.9rem1.05rem1.2rem1.4rem1.6rem

Rango ampliado: 13–19 px (antes 14–17 px). .card-title escala de forma independiente (diferencial más suave).

Feedback original de Edu: “los ajustes solo afectan a títulos, el cuerpo de tasks no cambia”.


Cambio 3 · Multi-select Asignado

Archivos: src/components/tasks/TaskModal.tsx, src/components/tasks/TaskManager.tsx, src/lib/constants.ts

Cambios en constants.ts

Cambios en TaskModal.tsx

El <select> de asignado se reemplaza por 3 botones toggle (uno por miembro del equipo):

Cambios en TaskManager.tsx

El filtro por asignado ahora soporta multi-asignación:

// Una tarea matchea 'Edu' si su campo assignee contiene ese nombre
if (filterAssignee !== 'Todos') {
  const isLegacyTeam = t.assignee === 'Equipo';
  const explicitNames = (t.assignee || '').split(',').map((s) => s.trim());
  const matches = isLegacyTeam || explicitNames.includes(filterAssignee);
  if (!matches) return false;
}

El borde derecho del último botón del filtro se calcula dinámicamente: a === TEAM_FILTER[TEAM_FILTER.length - 1].

Decisión de diseño

‘Equipo’ eliminado como opción nueva: si se quiere asignar a todos, se marcan los 3 individualmente. Legacy en BD y ASSIGNEE_COLORS se preserva. Decisión Edu (s56, punto 2).


Cambio 4 · Notas del Cuaderno vinculadas a Tareas

Archivos: src/components/tasks/TaskModal.tsx, functions/api/tasks/index.ts, functions/api/tasks/[id]/index.ts, migrations/0023_tasks_linked_notes.sql

Modelo de datos

Nueva columna en la tabla tasks de D1/SQLite:

-- migrations/0023_tasks_linked_notes.sql
ALTER TABLE tasks ADD COLUMN linked_note_ids TEXT DEFAULT '[]';

Interfaz TypeScript

// TaskModal.tsx — Task interface
linked_note_ids?: number[];  // optional, compat con tareas pre-migration 0023

// NotebookNote interface (nueva)
export interface NotebookNote {
  id: number;
  title: string;
  pinned: number;
  updated_at: string;
}

API: POST y PUT /api/tasks

Ambos endpoints (index.ts y [id]/index.ts) reciben linked_note_ids?: number[] en el body:

const linkedNoteIdsJson = JSON.stringify(
  Array.isArray(body.linked_note_ids)
    ? body.linked_note_ids.filter((n) => typeof n === 'number' && Number.isFinite(n))
    : [],
);

En el PUT, si linked_note_ids es undefined, la columna no se modifica (COALESCE(?, linked_note_ids) con null).

UX en TaskModal

Nuevo bloque “Notas del Cuaderno” en el modal:

  1. Chips de notas vinculadas: cada nota vinculada aparece como chip con enlace a /tools/notebook?id=N y botón × para desvincular.
    • Si la nota no es del usuario actual (scope user), aparece como "Nota privada #N" en cursiva y sin enlace.
  2. Select para vincular existentes: carga las notas del usuario vía GET /api/notebook al abrir el modal. En modo isLocal (tarea nueva sin ID), la lista queda vacía.
  3. Botón ”+ Crear nota nueva”: POST /api/notebook con título "Notas · {task.title}" y vinculación automática.

Privacidad de notas

Las notas son scope user: GET /api/notebook solo devuelve las del usuario autenticado, y GET /api/notebook/:id rechaza al no-propietario. Una task compartida puede tener vinculada una nota de Edu; Dani la verá como "Nota privada #N" sin acceso al contenido. Comportamiento intencional y coherente con el modelo de privacidad del Cuaderno.


Archivos modificados

ArchivoTipo de cambio
src/components/dashboard/TasksWidget.tsxUI: scroll + fetch
src/components/tasks/TaskModal.tsxUI: multi-select + notas vinculadas
src/components/tasks/TaskManager.tsxLógica: filtro multi-asignado
src/lib/constants.tsConstantes: TEAM_MEMBERS, parseAssignees
src/styles/globals.cssCSS: fontSize overrides para Tailwind
functions/api/tasks/index.tsAPI: POST con linked_note_ids
functions/api/tasks/[id]/index.tsAPI: PUT con linked_note_ids
migrations/0023_tasks_linked_notes.sqlD1: nueva columna

Véase también

Subir