feat(calendar): vista mes/semana/día, TZ, selector de calendario, colores y CRUD de eventos
Backend (server/main.py): - GET /api/calendars: lista las colecciones de calendario bajo el calendar-home con nombre y color (compone dav_list_calendars del registry). - GET /api/calendar?cal=&from=&to=: eventos de una colección concreta (caché por colección validada por ctag). dtstart/dtend ahora en ISO con offset + tz original + all_day; parseo robusto de TZID/UTC/todo-el-día con zoneinfo. - POST/PUT/DELETE /api/event[/<uid>]: CRUD de VEVENT contra Xandikos (fuente de verdad). Construye el VCALENDAR (con VTIMEZONE para zonas con DST), reutiliza el UID al editar (idempotente), trata 404 del DELETE como idempotente, invalida la caché de la colección tras escribir. Frontend: - CalendarView reescrita: conmutador Mes/Semana/Día con rejilla horaria propia (Mantine + dayjs, sin react-big-calendar para evitar fricción con React 19), mini-calendario de navegación, selector de calendario (con color), selector de zona horaria que recoloca los eventos, colores por evento (del VEVENT o del calendario). - EventModal: alta/edición/borrado con summary, inicio/fin, todo-el-día, TZ, calendario, color, ubicación y descripción. Fechas en formato local 24h. - calendar.ts: helpers de TZ (dayjs utc+timezone), posicionado por hora, semana empezando en lunes, locale es. api.ts: tipos y funciones de eventos/calendarios. Verificado: ciclo real crear→editar→borrar contra Xandikos (cero residuo), render del calendario en navegador (React 19 + Mantine v9 montan), pnpm build verde, 40 tests verdes (+ smoke gateado). MKCALENDAR queda fuera (documentado). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
name: osint_web
|
||||
lang: py
|
||||
domain: osint
|
||||
version: 0.1.0
|
||||
description: "App web local OSINT: explora el vault de Obsidian osint (grafo sigma.js, tablas por tipo, fichas con galería de attachments) y la agenda/calendario del servidor Xandikos (CardDAV/CalDAV). Backend FastAPI que orquesta los grupos obsidian y dav del registry; escucha solo en 127.0.0.1 (datos sensibles)."
|
||||
version: 0.2.0
|
||||
description: "App web local OSINT: explora el vault de Obsidian osint (grafo sigma.js, tablas por tipo, fichas con galería de attachments), la agenda del servidor Xandikos (CardDAV) y un calendario completo (CalDAV) con vista mes/semana/día, zonas horarias, selector de calendario, colores y CRUD de eventos. Backend FastAPI que orquesta los grupos obsidian y dav del registry; escucha solo en 127.0.0.1 (datos sensibles)."
|
||||
tags: [osint, web, sigma, graph, mantine, dav, obsidian, vault, dashboard]
|
||||
uses_functions:
|
||||
- build_obsidian_graph_py_obsidian
|
||||
@@ -18,7 +18,9 @@ uses_functions:
|
||||
- search_obsidian_notes_py_obsidian
|
||||
- dav_get_collection_py_infra
|
||||
- dav_collection_ctag_py_infra
|
||||
- dav_list_calendars_py_infra
|
||||
- carddav_put_vcard_py_infra
|
||||
- caldav_put_event_py_infra
|
||||
- dav_delete_resource_py_infra
|
||||
- split_vcards_py_infra
|
||||
- pass_get_secret_py_infra
|
||||
@@ -57,13 +59,22 @@ primaria con `create_obsidian_note` / `update_obsidian_note` /
|
||||
inmediato (`carddav_put_vcard` / `dav_delete_resource`) para que se vea ya en la
|
||||
app y en el móvil sin esperar al sync periódico del dag_engine.
|
||||
|
||||
Calendario (CRUD de eventos): la app lista las colecciones de calendario, muestra
|
||||
los eventos en vista mes/semana/día (con zona horaria y color seleccionables) y
|
||||
permite crear, editar y borrar eventos. Aquí la **fuente de verdad es Xandikos
|
||||
directamente** (el calendario NO existe en el vault): cada operación escribe el
|
||||
VCALENDAR/VEVENT en la colección CalDAV (`caldav_put_event` /
|
||||
`dav_delete_resource`) e invalida la caché de esa colección.
|
||||
|
||||
Registry-first: el backend NO parsea el vault ni habla DAV a mano — orquesta las
|
||||
funciones del grupo `obsidian` (`build_obsidian_graph`, `read_obsidian_note`,
|
||||
`create_obsidian_note`, `update_obsidian_note`, `delete_obsidian_note`,
|
||||
`resolve_obsidian_embed`, ...) y del grupo `dav` (`dav_get_collection`,
|
||||
`dav_collection_ctag`, `carddav_put_vcard`, `dav_delete_resource`,
|
||||
`split_vcards`) más `pass_get_secret` para la credencial, todas declaradas en
|
||||
`uses_functions`.
|
||||
`dav_collection_ctag`, `dav_list_calendars`, `carddav_put_vcard`,
|
||||
`caldav_put_event`, `dav_delete_resource`, `split_vcards`) más `pass_get_secret`
|
||||
para la credencial, todas declaradas en `uses_functions`. La única lógica propia
|
||||
de la app sobre el calendario es el parseo robusto de VEVENT (TZID / UTC / todo el
|
||||
día → ISO con offset, vía `zoneinfo`) y la construcción del VCALENDAR de salida.
|
||||
|
||||
## Stack
|
||||
|
||||
@@ -95,7 +106,12 @@ no se cachean (se piden a Xandikos en cada llamada).
|
||||
| GET | `/api/search?q=...` | nodos cuyo contenido matchea la query |
|
||||
| GET | `/api/contacts` | contactos del addressbook Xandikos (CardDAV) a JSON |
|
||||
| GET | `/api/contact/<uid>` | un vCard concreto a JSON |
|
||||
| GET | `/api/calendar?from=&to=` | eventos del calendario Xandikos (CalDAV) en el rango |
|
||||
| POST/PUT/DELETE | `/api/contact[/<slug>]` | CRUD de contactos (ficha `.md` del vault + reflejo vCard) |
|
||||
| GET | `/api/calendars` | colecciones de calendario bajo `/enmanuel/calendars/` (nombre + color) |
|
||||
| GET | `/api/calendar?cal=&from=&to=` | eventos de una colección del calendario (CalDAV) en el rango |
|
||||
| POST | `/api/event` | crea un VEVENT (`{cal, summary, dtstart, dtend, tz, all_day, location, description, color}`) |
|
||||
| PUT | `/api/event/<uid>` | edita un VEVENT existente |
|
||||
| DELETE | `/api/event/<uid>?cal=` | borra un VEVENT |
|
||||
| POST | `/api/refresh` | re-escanea el vault y reconstruye la caché |
|
||||
|
||||
## Configuración Xandikos
|
||||
@@ -134,12 +150,19 @@ parseo vCard/iCalendar a JSON y degradación de los endpoints DAV sin red.
|
||||
|
||||
## Estado / pendiente
|
||||
|
||||
- **Hecho**: scaffold del sub-repo + backend FastAPI completo (vault + DAV) con
|
||||
13 tests verdes.
|
||||
- **Pendiente (siguiente agente)**: `frontend/` React + Vite + Mantine v9 +
|
||||
`@fn_library` con sigma.js + graphology (GraphView, TablesView, NodeCard,
|
||||
ContactsView, CalendarView). Onboarding previsto: backend en 8470 +
|
||||
`pnpm dev` en `frontend/` → abrir `http://127.0.0.1:5173`. Ver
|
||||
`frontend/README.md`.
|
||||
- **Hecho**: scaffold del sub-repo + backend FastAPI completo (vault + DAV) +
|
||||
frontend React/Vite/Mantine v9 (GraphView, TablesView, ContactsView,
|
||||
CalendarView). Suite backend verde (40 tests + 1 smoke gateado).
|
||||
- **Calendario (v0.2.0)**: vista mes/semana/día, selector de calendario (con
|
||||
color), selector de zona horaria, colores por evento y CRUD completo de
|
||||
eventos (crear en un hueco, editar/borrar). Backend con parseo robusto de
|
||||
TZID/UTC/todo-el-día y construcción de VCALENDAR (con VTIMEZONE para zonas con
|
||||
DST). Verificado con un ciclo real crear→editar→borrar contra Xandikos (cero
|
||||
residuo). Onboarding: backend en 8470 + `pnpm dev` en `frontend/` → abrir
|
||||
`http://127.0.0.1:5173` → pestaña "Calendario".
|
||||
- **Gaps conocidos**: MKCALENDAR (crear colección de calendario nueva) NO
|
||||
implementado — Xandikos tiene hoy una sola colección y la UI no lo necesita;
|
||||
documentado como pendiente. El frontend usa una rejilla Mantine propia (sin
|
||||
`react-big-calendar`) para evitar fricción de peer-deps con React 19.
|
||||
- Cuando exista el manifest de sub-repos del project (issue 0171), añadir esta
|
||||
app a `projects/osint/subrepos.yaml`.
|
||||
|
||||
Reference in New Issue
Block a user