diff --git a/COMPLETION.md b/COMPLETION.md index db009e6..838635f 100644 --- a/COMPLETION.md +++ b/COMPLETION.md @@ -1,359 +1,37 @@ -# ✅ Scenar Creator — Refactoring & Features Complete +# ✅ Scenar Creator — v3.0 Complete -## Shrnutí dokončené práce +## Co je v3.0 -Projekt byl úspěšně refaktorován, otestován a nyní podporuje: +Kompletní přepis aplikace. Žádný Excel, žádný CGI/Apache. -### 🎯 Nové Features +### Stack +- **Backend:** FastAPI + Uvicorn + ReportLab +- **Frontend:** Vanilla JS + interact.js (drag-and-drop canvas) +- **Data:** JSON import/export (bez Excelu) +- **Output:** PDF timetable (A4 landscape, barvy, legenda) -1. **Inline Excel Editor** — Webový formulář s JavaScript row management - - Přidávání/odstraňování řádků programu (`+` / `Smazat`) - - Přidávání/odstraňování typů programu - - Fullcolor picker pro barvy - - Validace při submission +### Features +1. **Canvas editor** — bloky na časové ose, přetahování myší, snap na 15 min, resize +2. **JSON import/export** — uložte a načtěte scénář jako .json soubor +3. **Vzorový JSON** — GET /api/sample pro šablonu +4. **PDF generátor** — ReportLab, barevné bloky dle typů, legenda, datum +5. **Dokumentace** — záložka "Dokumentace" přímo v aplikaci +6. **API docs** — GET /docs (Swagger UI) -2. **Refactored Architecture** — Business logic oddělená od CGI - - `scenar/core.py` — 491 řádků čistého Python kódu (bez CGI/HTTP) - - `cgi-bin/scenar.py` — 450 řádků CGI wrapper + HTML rendering - - Custom exceptions: `ScenarsError`, `ValidationError`, `TemplateError` +### Endpoints +- `GET /` — hlavní UI +- `GET /api/health` — health check (vrací verzi) +- `GET /api/sample` — vzorový JSON ke stažení +- `POST /api/validate` — validace ScenarioDocument +- `POST /api/generate-pdf` — vygeneruje PDF -3. **Kompletní Test Coverage** — 10 testů, všechny ✅ procházejí - - 5 jednostkových testů pro core logiku - - 4 testy pro inline editor (schedule + types parsing) - - 1 integrace test (Docker/Podman build + HTTP) - -### 📁 Nové/Upravené Soubory - -#### Nové soubory +### JSON formát +```json +{ + "version": "1.0", + "event": { "title": "...", "subtitle": "...", "date": "YYYY-MM-DD", "location": "..." }, + "program_types": [{ "id": "...", "name": "...", "color": "#RRGGBB" }], + "blocks": [{ "id": "...", "date": "YYYY-MM-DD", "start": "HH:MM", "end": "HH:MM", + "title": "...", "type_id": "...", "responsible": "...", "notes": "..." }] +} ``` -scenar/__init__.py (package init) -scenar/core.py (491 řádků — business logic) -scripts/build_image.sh (Podman build helper) -``` - -#### Upravené soubory -``` -Dockerfile (+ COPY scenar/ + pip install -r) -cgi-bin/scenar.py (450 řádků, import z scenar.core) -tests/test_read_excel.py (9 testů — Excel + inline) -tests/test_docker_integration.py (Podman integration) -requirements.txt (openpyxl==3.1.5 fix) -README.md (+ inline editor workflow) -``` - ---- - -## 🚀 Jak funguje nový kód - -### Krok 1: Import → Validace → Parsování - -**Import z Excelu:** -1. Uživatel uploaduje `*.xlsx` (step=2) -2. `read_excel()` parsuje a detekuje overlappy -3. `get_program_types()` extrahuje unikátní typy -4. Formulář v step=2 nabídne zadání barvy a popisu pro každý typ - -**Inline Editor:** -1. Uživatel vyplní tabelu řádkami (step=builder) -2. JavaScript: `addScheduleRow()` / `removeScheduleRow()` manipulují DOM -3. `parse_inline_schedule()` validuje vstupní data -4. `parse_inline_types()` extrahuje definice typů z formuláře - -### Krok 2: Generování Timetablu - -```python -# oba workflow vedou k: -wb = create_timetable( - data, # DataFrame s programem - title, detail, - program_descriptions, # {typ: popis} - program_colors # {typ: AARRGGBB} -) -wb.save(file_path) # Excel soubor -``` - -Výstup: Profesionální Excel timetable s: -- Nadpis + detail v záhlaví -- Datum × Čas tabulka s programy -- Barevné výraznění typů -- Legenda s popisem typů - ---- - -## 🧪 Test Coverage - -### Unit Tests (9 testů) - -``` -✅ test_read_excel_happy_path — Excel parsing s validními daty -✅ test_read_excel_invalid_time — Chyba na neplatný čas -✅ test_get_program_types — Extrakce typů ze formuláře -✅ test_create_timetable — Generování Excelu -✅ test_create_timetable_with_color_dict — Timetable s vlastními barvami -✅ test_parse_inline_schedule — Parsing inline řádků (9 řádků) -✅ test_parse_inline_schedule_missing — Validace povinných polí -✅ test_parse_inline_types — Parsing definic typů -✅ test_inline_workflow_integration — End-to-end: form → Excel -``` - -### Integration Test (1 test) - -``` -✅ test_build_run_and_cleanup_podman — Build image, run container, HTTP test, cleanup -``` - -**Spuštění:** -```bash -# Všechny testy -pytest -v # 10/10 ✅ - -# Jen unit testy (bez Podman) -pytest -q -m "not integration" # 9/9 ✅ - -# Specifický test -pytest tests/test_read_excel.py::test_parse_inline_schedule -v -``` - ---- - -## 📋 Key Changes Detail - -### `scenar/core.py` (NEW — 491 řádků) - -**Funkce:** -- `read_excel(file_content)` → (valid_df, error_rows) -- `create_timetable(data, title, detail, descriptions, colors)` → Workbook -- `get_program_types(form_data)` → (descriptions, colors) tuple -- `validate_inputs(title, detail, file_size)` — Kontrola bezpečnosti -- `parse_inline_schedule(form)` → DataFrame (NOVÉ) -- `parse_inline_types(form)` → (descriptions, colors) tuple (NOVÉ) - -**Custom Exceptions:** -```python -class ScenarsError(Exception): # Base -class ValidationError(ScenarsError): # Validační chyby -class TemplateError(ScenarsError): # Excel struktura -``` - -**Helpers:** -- `normalize_time()` — Parse HH:MM nebo HH:MM:SS -- `calculate_row_height()` — Auto-sizing řádků -- `calculate_column_width()` — Auto-sizing sloupců -- `validate_excel_template()` — Kontrola sloupců - -### `cgi-bin/scenar.py` (REFACTORED — 450 řádků) - -**Nově:** -```python -# sys.path fallback pro CGI kontext -import sys -if DOCROOT not in sys.path: - sys.path.insert(0, DOCROOT) - -from scenar.core import read_excel, create_timetable, ... -``` - -**HTML Tabs:** -- Tab 1: "Importovat Excel" — klasický workflow -- Tab 2: "Vytvořit inline" — nový JS editor (NOVÝ) - -**JavaScript Functions:** -```javascript -addScheduleRow() // Přidá řádek v tabulce -removeScheduleRow(id) // Smaže řádek -addTypeRow() // Přidá def. typu -removeTypeRow(id) // Smaže def. typu -switchTab(e, tabId) // Tab switching -``` - -**HTTP Handlers:** -- `step='1'` — Render home (import + inline tabs) -- `step='2'` — Load Excel, show type input form -- `step='3'` — Generate timetable (Excel import workflow) -- `step='builder'` — Generate from inline data (NOVÝ) - -### `Dockerfile` (FIXED) - -**Změny:** -```dockerfile -# Přidat scenar package do kontejneru -COPY scenar ./scenar -COPY requirements.txt ./requirements.txt - -# Usar requirements.txt místo hardcodované verze -RUN pip install --no-cache-dir -r requirements.txt -``` - -**Výsledek:** Container má přístup k `scenar.core` při CGI spuštění - -### `requirements.txt` (FIXED) - -``` -pandas==2.1.3 -openpyxl==3.1.5 # Byla 3.11.0 (neexistuje!) → Fixed -pytest==7.4.3 -``` - ---- - -## 🎨 Workflow Diagrams - -### Import Excel Workflow -``` -Home (step=1) - ↓ upload file -Step 2: Load Excel → Detect Types - ↓ fill descriptions + colors -Step 3: Generate Timetable - ↓ Download Excel -Done ✅ -``` - -### Inline Editor Workflow -``` -Home (step=1) - ↓ click "Vytvořit inline" tab -Fill Form + JS Row Management - ↓ submit (step=builder) -Parse Form → Generate Timetable - ↓ Download Excel -Done ✅ -``` - ---- - -## 🔍 Validation Logic - -### Input Validation -```python -validate_inputs(title, detail, file_size) -# Checks: -# - title: required, 1-200 chars -# - detail: required, 1-500 chars -# - file_size: max 10 MB -``` - -### Excel Parsing -```python -read_excel(file_content) -# Checks: -# - Required columns: Datum, Zacatek, Konec, Program, Typ, Garant, Poznamka -# - Date format: YYYY-MM-DD -# - Time format: HH:MM or HH:MM:SS -# - Time overlaps: Detects and errors -# Returns: (valid_data, error_rows) -``` - -### Inline Schedule Parsing -```python -parse_inline_schedule(form) -# Checks: -# - Each row: all required fields filled -# - Dates valid (YYYY-MM-DD) -# - Times valid (HH:MM or HH:MM:SS) -# - Skips empty rows -# Raises: ValidationError if invalid -``` - ---- - -## 🐳 Container & Deployment - -### Local Testing (bez Dockeru) -```bash -python -m http.server --cgi 8000 -# http://localhost:8000/cgi-bin/scenar.py -``` - -### Podman/Docker (produkce) -```bash -# Build -podman build -t scenar-creator:latest . - -# Run -podman run -d -p 8080:8080 \ - -v $(pwd)/tmp:/var/www/htdocs/tmp \ - scenar-creator:latest - -# Visit: http://localhost:8080/ -``` - -### Pre-commit Hooks -```bash -./scripts/install_hooks.sh -git commit -m "..." # Runs pytest automatically -``` - ---- - -## 📊 Architecture Summary - -``` -┌─────────────────────────────────────────────────────┐ -│ Browser (HTML + JavaScript) │ -│ - Form: Title, Detail, File/Inline Data │ -│ - JS: Row add/remove (DOM manipulation) │ -└────────────────┬────────────────────────────────────┘ - │ HTTP POST -┌────────────────▼────────────────────────────────────┐ -│ cgi-bin/scenar.py (CGI Wrapper — 450 lines) │ -│ - Form parsing (cgi.FieldStorage) │ -│ - Step routing (1, 2, 3, builder) │ -│ - HTML rendering │ -│ - Imports from scenar.core │ -└────────────────┬────────────────────────────────────┘ - │ -┌────────────────▼────────────────────────────────────┐ -│ scenar/core.py (Business Logic — 491 lines) │ -│ - read_excel() → validate & parse Excel │ -│ - parse_inline_schedule() → validate form data │ -│ - parse_inline_types() → extract type definitions│ -│ - create_timetable() → generate OpenPyXL │ -│ - Custom exceptions & validation │ -└────────────────┬────────────────────────────────────┘ - │ -┌────────────────▼────────────────────────────────────┐ -│ Dependencies: pandas, openpyxl, Python 3.12 │ -│ Testing: pytest (9 units + 1 integration) │ -│ Container: Podman/Docker (port 8080) │ -└──────────────────────────────────────────────────────┘ -``` - ---- - -## ✨ Highlights - -- ✅ **No 500 errors** — sys.path fix + Dockerfile fix -- ✅ **Full test coverage** — 10 tests, all passing -- ✅ **Two workflows** — Excel import OR inline editor -- ✅ **JavaScript row management** — DOM manipulation for schedule/types -- ✅ **Professional Excel output** — Styling, colors, legend, auto-sizing -- ✅ **Clean architecture** — Core logic separated from CGI -- ✅ **Validated inputs** — Security checks for file size, string lengths -- ✅ **Comprehensive error handling** — Custom exceptions, user-friendly messages - ---- - -## 📝 Next Steps (Optional Enhancements) - -1. **Database** — Store scenarios in DB instead of tmp files -2. **Export to PDF** — Generate PDF instead of just Excel -3. **Collaborative editing** — Real-time sync between users -4. **Authentication** — User accounts & access control -5. **More type validation** — Email, phone numbers in Garant field -6. **Duplicate detection** — Warn if same program at same time -7. **Template library** — Save & reuse scenarios - ---- - -## 📚 Documentation - -- **README.md** — User guide + installation -- **`.github/copilot-instructions.md`** — AI agent instructions -- **This file** — Technical summary & architecture - ---- - -**Date:** November 13, 2025 -**Status:** ✅ **COMPLETE & TESTED** -**Test Result:** 10/10 ✅ passing diff --git a/tmp/F.A.K.A.P.xlsx b/tmp/F.A.K.A.P.xlsx deleted file mode 100644 index 7bfaabb..0000000 Binary files a/tmp/F.A.K.A.P.xlsx and /dev/null differ diff --git a/tmp/FAKAP.xlsx b/tmp/FAKAP.xlsx deleted file mode 100644 index 3305759..0000000 Binary files a/tmp/FAKAP.xlsx and /dev/null differ diff --git a/tmp/FAKAP2.xlsx b/tmp/FAKAP2.xlsx deleted file mode 100644 index 8759658..0000000 Binary files a/tmp/FAKAP2.xlsx and /dev/null differ diff --git a/tmp/FAKAP3.xlsx b/tmp/FAKAP3.xlsx deleted file mode 100644 index 6a87886..0000000 Binary files a/tmp/FAKAP3.xlsx and /dev/null differ diff --git a/tmp/TRABANT.xlsx b/tmp/TRABANT.xlsx deleted file mode 100644 index b7b39c2..0000000 Binary files a/tmp/TRABANT.xlsx and /dev/null differ diff --git a/tmp/Zazitkovy kurz TRABANT.xlsx b/tmp/Zazitkovy kurz TRABANT.xlsx deleted file mode 100644 index a9505e7..0000000 Binary files a/tmp/Zazitkovy kurz TRABANT.xlsx and /dev/null differ diff --git a/tmp/Zazitkovy kurz trabant.xlsx b/tmp/Zazitkovy kurz trabant.xlsx deleted file mode 100644 index a9505e7..0000000 Binary files a/tmp/Zazitkovy kurz trabant.xlsx and /dev/null differ diff --git a/tmp/Zážitkový kurz TRABANT.xlsx b/tmp/Zážitkový kurz TRABANT.xlsx deleted file mode 100644 index 017c3ba..0000000 Binary files a/tmp/Zážitkový kurz TRABANT.xlsx and /dev/null differ diff --git a/tmp/a.xlsx b/tmp/a.xlsx deleted file mode 100644 index 04dba36..0000000 Binary files a/tmp/a.xlsx and /dev/null differ diff --git a/tmp/test.xlsx b/tmp/test.xlsx deleted file mode 100644 index 924e458..0000000 Binary files a/tmp/test.xlsx and /dev/null differ diff --git a/tmp/x.xlsx b/tmp/x.xlsx deleted file mode 100644 index 48586c0..0000000 Binary files a/tmp/x.xlsx and /dev/null differ