Files
scenar-creator/app/static/index.html
Daneel 751ffe6f82
Some checks failed
Build & Push Docker / build (push) Has been cancelled
feat: v4.3.0 - cross-day drag (blocks can move between day rows)
2026-02-20 18:36:51 +01:00

255 lines
14 KiB
HTML

<!DOCTYPE html>
<html lang="cs">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scénář Creator</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/css/app.css">
</head>
<body>
<header class="header">
<div class="header-left">
<h1 class="header-title">Scénář Creator</h1>
<span class="header-version">v4.3</span>
</div>
<div class="header-actions">
<label class="btn btn-secondary btn-sm" id="importJsonBtn">
<input type="file" accept=".json" id="importJsonInput" hidden>
Import JSON
</label>
<button class="btn btn-secondary btn-sm" id="newScenarioBtn">Nový scénář</button>
<button class="btn btn-secondary btn-sm" id="exportJsonBtn">Export JSON</button>
<button class="btn btn-primary btn-sm" id="generatePdfBtn">Generovat PDF</button>
</div>
</header>
<div class="tabs">
<button class="tab active" data-tab="editor">Editor</button>
<button class="tab" data-tab="docs">Dokumentace</button>
</div>
<div class="tab-content" id="tab-editor">
<div class="app-layout">
<aside class="sidebar">
<section class="sidebar-section">
<h3 class="sidebar-heading">Informace o akci</h3>
<div class="form-group">
<label>Název</label>
<input type="text" id="eventTitle" placeholder="Název akce">
</div>
<div class="form-group">
<label>Podtitul</label>
<input type="text" id="eventSubtitle" placeholder="Podtitul">
</div>
<div class="form-row">
<div class="form-group">
<label>Od</label>
<input type="date" id="eventDateFrom">
</div>
<div class="form-group">
<label>Do</label>
<input type="date" id="eventDateTo">
</div>
</div>
<div class="form-group">
<label>Místo</label>
<input type="text" id="eventLocation" placeholder="Místo konání">
</div>
</section>
<section class="sidebar-section">
<h3 class="sidebar-heading">Typy programů</h3>
<div id="programTypesContainer"></div>
<button class="btn btn-secondary btn-xs" id="addTypeBtn">+ Přidat typ</button>
</section>
<section class="sidebar-section">
<button class="btn btn-primary btn-block" id="addBlockBtn">+ Přidat blok</button>
</section>
</aside>
<main class="canvas-wrapper">
<div id="canvasScrollArea" class="canvas-scroll-area">
<div id="timeAxis" class="time-axis-row"></div>
<div id="dayRows" class="day-rows"></div>
</div>
</main>
</div>
</div>
<!-- Documentation tab -->
<div class="tab-content hidden" id="tab-docs">
<div class="docs-container">
<h2>Scénář Creator — Dokumentace</h2>
<p class="docs-version">Verze 4.3.0 &nbsp;|&nbsp; <a href="/docs" target="_blank">Swagger API</a> &nbsp;|&nbsp; <a href="/api/sample">Vzorový JSON</a></p>
<h3>Jak začít</h3>
<ol>
<li><strong>Nový scénář</strong> — klikněte na „Nový scénář" v záhlaví. Vytvoří se prázdný scénář pro dnešní den.</li>
<li><strong>Import JSON</strong> — klikněte na „Import JSON" a vyberte dříve uložený .json soubor.</li>
<li><strong>Vzorový JSON</strong> — stáhněte <a href="/api/sample">sample.json</a> jako šablonu a importujte ho.</li>
</ol>
<h3>Nastavení akce (postranní panel)</h3>
<ul>
<li><strong>Název / Podtitul / Místo</strong> — zobrazí se v záhlaví PDF.</li>
<li><strong>Od / Do</strong> — rozsah dat akce. Každý den = jeden řádek v editoru. Jednodnevní kurz = stejné datum v obou polích.</li>
<li><strong>Typy programů</strong> — přidejte typ kliknutím na „+ Přidat typ", nastavte název a barvu. Každý blok patří k jednomu typu.</li>
</ul>
<h3>Práce s bloky</h3>
<ul>
<li><strong>Přidání:</strong> Klikněte na „+ Přidat blok" nebo klikněte na prázdné místo v řádku dne.</li>
<li><strong>Přidání do všech dnů:</strong> V modalu nového bloku zaškrtněte „Přidat do každého dne kurzu" — vytvoří identický blok pro každý den akce (sdílená série).</li>
<li><strong>Přesun v rámci dne:</strong> Chytněte blok a táhněte doleva/doprava. Snap na 15 minut.</li>
<li><strong>Přesun mezi dny:</strong> Táhněte blok nahoru/dolů — zvýrazní se cílový den (modrý rámeček). Pusťte na novém dni.</li>
<li><strong>Změna délky:</strong> Chytněte pravý okraj bloku a táhněte.</li>
<li><strong>Úprava:</strong> Klikněte na blok — otevře se formulář s editací jednoho bloku.</li>
<li><strong>Smazání jednoho bloku:</strong> V editačním formuláři klikněte na „Smazat jen tento".</li>
<li><strong>Smazání celé série:</strong> Pokud byl blok přidán jako součást série (zaškrtávací políčko), zobrazí se tlačítko „Smazat sérii" — smaže všechny bloky se stejným series_id.</li>
</ul>
<h3>Formulář bloku</h3>
<ul>
<li><strong>Den</strong> — výběr pouze z nastavených dní akce (ne volné datum).</li>
<li><strong>Začátek / Konec</strong> — čas HH:MM.</li>
<li><strong>Nebo trvání</strong> — zadáte hodiny a minuty → Konec se vypočítá. Funguje i opačně (zadáte Konec → trvání se aktualizuje).</li>
<li><strong>Program přes půlnoc</strong> — Konec &lt; Začátek je validní (blok přechází přes půlnoc). V editoru označen „→", v PDF správně vykreslí.</li>
<li><strong>Garant</strong> — zobrazí se v bloku v editoru i v PDF (pod názvem bloku).</li>
<li><strong>Poznámka</strong> — nezobrazuje se v editoru, pouze v PDF jako horní index (¹ ²...) u názvu bloku. Všechny poznámky jsou vypsány na 2. stránce PDF.</li>
</ul>
<h3>Export / Import</h3>
<ul>
<li><strong>Export JSON</strong> — stáhne celý scénář jako .json soubor. Uložte pro pozdější editaci.</li>
<li><strong>Import JSON</strong> — načte dříve uložený .json soubor.</li>
<li><strong>Generovat PDF</strong> — vytvoří tisknutelný harmonogram:
<ul>
<li>Stránka 1: timetable (řádky = dny, sloupce = čas, barvy dle typů, legenda)</li>
<li>Stránka 2 (pokud jsou poznámky): výpis poznámek ke scénáři s čísly</li>
</ul>
</li>
</ul>
<h3>Formát JSON</h3>
<table class="docs-table">
<thead><tr><th>Pole</th><th>Typ</th><th>Popis</th></tr></thead>
<tbody>
<tr><td>event.title</td><td>string</td><td>Název akce (povinné)</td></tr>
<tr><td>event.date_from</td><td>string</td><td>První den akce (YYYY-MM-DD)</td></tr>
<tr><td>event.date_to</td><td>string</td><td>Poslední den akce (YYYY-MM-DD)</td></tr>
<tr><td>event.subtitle</td><td>string?</td><td>Podtitul (nepovinné)</td></tr>
<tr><td>event.location</td><td>string?</td><td>Místo konání (nepovinné)</td></tr>
<tr><td>program_types[].id</td><td>string</td><td>Unikátní identifikátor typu</td></tr>
<tr><td>program_types[].name</td><td>string</td><td>Název typu (zobrazí se v legendě)</td></tr>
<tr><td>program_types[].color</td><td>string</td><td>Barva v hex formátu (#RRGGBB)</td></tr>
<tr><td>blocks[].id</td><td>string</td><td>Unikátní ID bloku (auto-generováno)</td></tr>
<tr><td>blocks[].date</td><td>string</td><td>Den bloku (YYYY-MM-DD)</td></tr>
<tr><td>blocks[].start</td><td>string</td><td>Čas začátku (HH:MM)</td></tr>
<tr><td>blocks[].end</td><td>string</td><td>Čas konce (HH:MM) — pokud end &lt; start, jde přes půlnoc</td></tr>
<tr><td>blocks[].title</td><td>string</td><td>Název bloku (povinné)</td></tr>
<tr><td>blocks[].type_id</td><td>string</td><td>ID typu programu (musí existovat v program_types)</td></tr>
<tr><td>blocks[].responsible</td><td>string?</td><td>Garant — zobrazí se v editoru i PDF</td></tr>
<tr><td>blocks[].notes</td><td>string?</td><td>Poznámka — jen v PDF, jako horní index + stránka 2</td></tr>
<tr><td>blocks[].series_id</td><td>string?</td><td>Sdílené ID série — bloky přidané přes „Přidat do všech dnů" sdílejí toto ID</td></tr>
</tbody>
</table>
<h3>Tipy</h3>
<ul>
<li>Scénář se <strong>neukládá automaticky</strong> — použijte Export JSON pro zálohování.</li>
<li>Barvy typů se projeví okamžitě v editoru i v PDF.</li>
<li>Pro tisk doporučujeme PDF v orientaci na šířku (A4 landscape).</li>
<li>Pokud blok přechází přes půlnoc, vidíte ho s šipkou „→" — v PDF se zobrazí do konce dne.</li>
</ul>
</div>
</div>
<!-- Block edit/create modal -->
<div class="modal-overlay hidden" id="blockModal">
<div class="modal">
<div class="modal-header">
<h3 id="modalTitle">Upravit blok</h3>
<button class="modal-close" id="modalClose">&times;</button>
</div>
<div class="modal-body">
<input type="hidden" id="modalBlockId">
<div class="form-group">
<label>Název bloku</label>
<input type="text" id="modalBlockTitle" placeholder="Název">
</div>
<div class="form-group">
<label>Den</label>
<select id="modalBlockDate"></select>
</div>
<div class="form-group">
<label>Typ programu</label>
<select id="modalBlockType"></select>
</div>
<div class="form-row">
<div class="form-group">
<label>Začátek</label>
<input type="text" id="modalBlockStart" placeholder="HH:MM" maxlength="5" class="time-input" autocomplete="off">
</div>
<div class="form-group">
<label>Konec</label>
<input type="text" id="modalBlockEnd" placeholder="HH:MM" maxlength="5" class="time-input" autocomplete="off">
</div>
</div>
<div class="form-group">
<label>Nebo trvání</label>
<div class="duration-row">
<div class="duration-field">
<input type="number" id="modalDurHours" min="0" max="23" placeholder="0">
<span class="duration-unit">hod</span>
</div>
<div class="duration-field">
<input type="number" id="modalDurMinutes" min="0" max="59" step="15" placeholder="0">
<span class="duration-unit">min</span>
</div>
</div>
</div>
<div class="form-group">
<label>Garant</label>
<input type="text" id="modalBlockResponsible" placeholder="Garant">
</div>
<div class="form-group">
<label>Poznámka</label>
<textarea id="modalBlockNotes" rows="3" placeholder="Poznámka"></textarea>
</div>
<!-- Shown only when creating a new block -->
<div class="form-group series-row hidden" id="seriesRow">
<label class="series-label">
<input type="checkbox" id="modalAddToAllDays">
Přidat do každého dne kurzu
</label>
<p class="series-hint">Vytvoří identický blok pro každý den akce (sdílená série).</p>
</div>
</div>
<div class="modal-footer">
<div class="modal-footer-left">
<button class="btn btn-danger btn-sm hidden" id="modalDeleteBtn">Smazat jen tento</button>
<button class="btn btn-danger-outline btn-sm hidden" id="modalDeleteSeriesBtn">Smazat sérii</button>
</div>
<button class="btn btn-primary btn-sm" id="modalSaveBtn">Uložit</button>
</div>
</div>
</div>
<!-- Status toast -->
<div class="toast hidden" id="toast"></div>
<script src="https://cdn.jsdelivr.net/npm/interactjs@1.10.27/dist/interact.min.js"></script>
<script src="/static/js/api.js"></script>
<script src="/static/js/canvas.js"></script>
<script src="/static/js/export.js"></script>
<script src="/static/js/app.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => App.init());
</script>
</body>
</html>