feat(kanban): adjuntos de archivos por card (issue 0128) #1

Merged
dataforge merged 6 commits from issue/0128-files-attachments into master 2026-05-27 09:04:38 +00:00
Owner

Issue

0128 — kanban: adjuntos de archivos

Resumen

Habilita el tab "Archivos" del CardEditPanel con tres vias de upload + render inline:

  1. Tab Archivos (CardFilesPanel): grid con thumb (imagenes) o chip + icono (PDFs/excel/csv/txt/...), botones subir y borrar.
  2. Descripcion (CardForm): drag&drop sobre el textarea → upload + inserta ![alt](url) o [name](url) en posicion del cursor.
  3. Chat (CardChatPanel): drag&drop + boton paperclip → upload + envia mensaje con la ref markdown. MessageBody renderiza la imagen inline o el link.

Backend

  • Migracion 014_card_files.sql (aditiva, idempotente): tabla con id, card_id, uploader_id, filename, mime, size, stored_path, source, created_at, deleted_at + index activo.
  • Storage: apps/kanban/uploads/<card_id>/<random>__<safe_filename> (gitignored).
  • Endpoints en backend/files.go:
    • POST /api/cards/{id}/files — multipart, max 10 MB.
    • GET /api/cards/{id}/files — lista activos.
    • GET /api/files/{id} — sirve binario, inline para image/pdf/text, attachment resto.
    • DELETE /api/files/{id} — soft delete.

Frontend

  • Nuevos componentes: CardFilesPanel, MessageBody.
  • CardForm y CardChatPanel reciben onFileUploaded + (en form) cardId para activar drop-zone solo en cards persistidas.
  • api.ts: listCardFiles, uploadCardFile (FormData), deleteCardFile.
  • types.ts: tipo CardFile.

Tests

  • e2e/files_smoke.sh (registrado en app.md::e2e_checks): build → login → crear card → upload PNG → lista → serve (verifica Content-Type) → delete → lista vacia. Verde local.
  • pnpm tsc --noEmit
  • pnpm test (3/3)
  • pnpm build (dist regenerado y commiteado).
  • go test ./... ⚠️ pre-existing failure en TestExecuteTool_MoveCard_BetweenColumns_OpensHistory (no introducido por este PR — reproducido en master limpio).

Version

apps/kanban/app.md bump 0.1.0 → 0.2.0 (minor: feature aditiva). Entrada nueva en ## Capability growth log.

DoD

  • Migracion aplicada (verificado con .schema card_files).
  • 4 endpoints responden segun spec.
  • Tab Archivos lista uploads.
  • Drag&drop funciona en desc y chat.
  • Render inline de imagenes en chat.
  • Soft delete oculta el archivo.
  • e2e/files_smoke.sh verde.

🤖 Generated with Claude Code

## Issue [0128 — kanban: adjuntos de archivos](../../../fn_registry/src/branch/master/dev/issues/0128-kanban-files-attachments.md) ## Resumen Habilita el tab "Archivos" del `CardEditPanel` con tres vias de upload + render inline: 1. **Tab Archivos** (`CardFilesPanel`): grid con thumb (imagenes) o chip + icono (PDFs/excel/csv/txt/...), botones subir y borrar. 2. **Descripcion** (`CardForm`): drag&drop sobre el textarea → upload + inserta `![alt](url)` o `[name](url)` en posicion del cursor. 3. **Chat** (`CardChatPanel`): drag&drop + boton paperclip → upload + envia mensaje con la ref markdown. `MessageBody` renderiza la imagen inline o el link. ## Backend - Migracion `014_card_files.sql` (aditiva, idempotente): tabla con `id, card_id, uploader_id, filename, mime, size, stored_path, source, created_at, deleted_at` + index activo. - Storage: `apps/kanban/uploads/<card_id>/<random>__<safe_filename>` (gitignored). - Endpoints en `backend/files.go`: - `POST /api/cards/{id}/files` — multipart, max 10 MB. - `GET /api/cards/{id}/files` — lista activos. - `GET /api/files/{id}` — sirve binario, `inline` para image/pdf/text, `attachment` resto. - `DELETE /api/files/{id}` — soft delete. ## Frontend - Nuevos componentes: `CardFilesPanel`, `MessageBody`. - `CardForm` y `CardChatPanel` reciben `onFileUploaded` + (en form) `cardId` para activar drop-zone solo en cards persistidas. - `api.ts`: `listCardFiles`, `uploadCardFile` (FormData), `deleteCardFile`. - `types.ts`: tipo `CardFile`. ## Tests - `e2e/files_smoke.sh` (registrado en `app.md::e2e_checks`): build → login → crear card → upload PNG → lista → serve (verifica Content-Type) → delete → lista vacia. ✅ Verde local. - `pnpm tsc --noEmit` ✅ - `pnpm test` ✅ (3/3) - `pnpm build` ✅ (dist regenerado y commiteado). - `go test ./...` ⚠️ pre-existing failure en `TestExecuteTool_MoveCard_BetweenColumns_OpensHistory` (no introducido por este PR — reproducido en master limpio). ## Version `apps/kanban/app.md` bump 0.1.0 → 0.2.0 (minor: feature aditiva). Entrada nueva en `## Capability growth log`. ## DoD - [x] Migracion aplicada (verificado con `.schema card_files`). - [x] 4 endpoints responden segun spec. - [x] Tab Archivos lista uploads. - [x] Drag&drop funciona en desc y chat. - [x] Render inline de imagenes en chat. - [x] Soft delete oculta el archivo. - [x] `e2e/files_smoke.sh` verde. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
dataforge added 4 commits 2026-05-27 08:53:01 +00:00
- migration 014_card_files: tabla con soft-delete + index activo
- handlers POST/GET/DELETE en backend/files.go
- routes /api/cards/{id}/files, /api/files/{id}
- limite 10MB, storage en uploads/<card_id>/<random>__<safe>
- CardFilesPanel: tab Archivos con grid thumbs + boton subir/borrar
- CardForm: drag&drop en descripcion, inserta ref markdown en cursor
- CardChatPanel: drag&drop + boton paperclip, sube y envia ref como mensaje
- MessageBody: renderer markdown minimo (img inline + link chip)
- api.ts: listCardFiles, uploadCardFile (multipart), deleteCardFile
- types.ts: CardFile
- app.md: descripcion, e2e_checks smoke_files, doc Archivos, capability growth log
- .gitignore: uploads/
- e2e/files_smoke.sh: build, login, upload PNG, list, serve, delete
dataforge added 2 commits 2026-05-27 09:04:26 +00:00
review findings:
- MessageBody: only http(s) and relative paths allowed for links;
  data:image/* allowed for inline images. Rejects javascript:,
  data:text/html, vbscript: which would execute via <a href>.
  Unsafe matches fall back to plain text.
- files.go: remove unused fileID var generated then discarded.
dataforge merged commit 87fd95314e into master 2026-05-27 09:04:38 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dataforge/kanban#1