feat: a calendar to subscribe to, and the backlog's corners

- Each person can subscribe their dates in Google Calendar, Outlook or
  Apple Calendar: GET /api/calendar/{token}.ics (no session) brings
  their unfinished tickets with a due date (assigned or followed), the
  planned and running sprints and the planned releases of their
  projects, as all-day events linking to the web. The token is made,
  renewed or dropped under /me/calendar (and in GraphQL); in the web,
  from «Calendario» in «Mi trabajo».
- The backlog panel keeps the selected rows' background inside its
  rounded corners.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 22:48:33 +02:00
parent 993f80b4b9
commit f45069a327
38 changed files with 1417 additions and 54 deletions

View File

@@ -256,6 +256,21 @@ secreto>`. El secreto solo se muestra al crearlo. Se reintenta a los 2 y 10 s (n
y se borran con el proyecto.
- **Checklist**: hasta 100 pasos de hasta 300 caracteres por ticket; los cambia quien puede editar el ticket.
### Calendario (iCalendar)
Cada persona puede suscribir sus fechas en Google Calendar, Outlook o Apple Calendar con una URL secreta:
`GET /api/calendar/{token}.ics` (sin sesión: las aplicaciones de calendario no pueden iniciarla). Trae, como eventos de
día completo:
- sus tickets sin terminar con fecha límite, asignados o que sigue;
- los sprints planificados o en curso de sus proyectos;
- las releases planificadas con fecha objetivo.
Cada evento enlaza a la web (`WEB_URL`). El token (32 bytes aleatorios) se crea, renueva o retira con `GET`, `POST` y
`DELETE /api/me/calendar` (GraphQL: `myCalendarFeed`, `createCalendarFeed`, `revokeCalendarFeed`); renovarlo deja sin
servicio la URL anterior. Se guarda tal cual en `calendar_feeds` para poder volver a copiar la URL: solo da lectura de
fechas y títulos que ya están en el read model.
### Notificaciones
Se derivan de los eventos (`NotificationsEventHandler`) y se guardan **por persona** en MongoDB: no son estado de