feat: přidáno URL pole pro bloky – klikatelný odkaz v PDF
Some checks failed
Build & Push Docker / build (push) Has been cancelled

- Block model: nové volitelné pole 'url' (Optional[str])
- Frontend: URL input v modálu pro přidání/editaci bloku
- PDF generátor: c.linkURL() – celý blok je klikatelný odkaz
- sample.json: ukázkový blok s URL
- index.html: dokumentace URL pole
- .github/copilot-instructions.md: přidány Copilot instrukce
This commit is contained in:
Martin Sukany
2026-03-14 19:10:13 +01:00
parent 5d712494a5
commit 0a694ce63a
7 changed files with 315 additions and 68 deletions

48
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,48 @@
# Copilot instructions for scenar-creator
## Big picture (read this first)
- This is a single FastAPI service that serves both API and static frontend (no separate frontend build step).
- Entry point: `app/main.py` mounts `/static` and serves `index.html` at `/`.
- API boundary is under `app/api/` (`/api/health`, `/api/validate`, `/api/sample`, `/api/generate-pdf`).
- Core domain object is `ScenarioDocument` in `app/models/event.py` (JSON-first design, no DB).
- PDF rendering is the main backend logic in `app/core/pdf_generator.py` (ReportLab canvas, A4 landscape timetable).
## Data model and domain rules (project-specific)
- Multi-day events use `event.date_from` + `event.date_to`; keep backward compatibility with legacy `event.date`.
- `blocks[].date` is always a concrete day (`YYYY-MM-DD`) even for multi-day events.
- Overnight blocks are valid: `end <= start` means crossing midnight. This rule exists in frontend canvas and backend PDF.
- `series_id` groups blocks created by “add to all days”; deleting a series removes all blocks with matching `series_id`.
- `program_types[].id` must match each `blocks[].type_id`; unknown types are validation errors.
## Frontend architecture conventions
- Frontend is vanilla JS globals loaded in order from `index.html`: `API` -> `Canvas` -> import/export helpers -> `App`.
- `App.state` is the source of truth (`event`, `program_types`, `blocks`) in `app/static/js/app.js`.
- Canvas timeline is horizontal time axis with 15-minute snapping (`Canvas.GRID_MINUTES = 15`) in `app/static/js/canvas.js`.
- Drag/resize behavior: native pointer drag for move + interact.js resize handle for duration updates.
- UI copy and date labels are Czech (e.g., `Pondělí (20.2)`), so preserve localization in new UI text.
## Backend conventions
- Keep API handlers thin; place formatting/rendering logic in `app/core/`.
- Raise `ScenarsError` from core logic and translate to HTTP 422 in API (`app/api/pdf.py`).
- PDF generator handles:
- legend from `program_types`
- optional responsible person text inside blocks
- notes as superscript markers + optional page 2 note listing
- Czech diacritics in PDFs rely on LiberationSans registration with Helvetica fallback.
## Developer workflows
- Local run: `uvicorn app.main:app --reload --port 8080`
- Tests: `python3 -m pytest tests/ -v`
- Container image includes required fonts (`fonts-liberation`) in `Dockerfile`; do not remove unless PDF text rendering is reworked.
- Health endpoint for local/container checks: `/api/health`.
## Testing patterns to preserve
- API tests use `fastapi.testclient.TestClient` (`tests/test_api.py`).
- PDF tests assert magic header `%PDF-` and page count with regex (`tests/test_pdf.py`).
- Keep coverage for overnight blocks, multi-day ranges, legacy `event.date`, and `series_id` behavior when changing models/UI.
## High-impact files
- `app/core/pdf_generator.py` — timeline layout math, fonts, notes page logic.
- `app/static/js/canvas.js` — drag/resize + time-range computation.
- `app/static/js/app.js` — modal save/delete logic, series expansion, document import/export shape.
- `app/models/event.py` — schema contract used by both API and frontend JSON.