diff --git a/editor/index.html b/editor/index.html index b1fc0fe8..b7ffc88b 100644 --- a/editor/index.html +++ b/editor/index.html @@ -3,6 +3,7 @@ + @@ -232,7 +233,6 @@

Musisz się zalogować

} async function renderPdf(songbook) { - notice("Generowanie PDF... Proszę czekać (może potrwać do kilkunastu sekund)", songbook); const {serialized, title} = songbook.SerializeWithChange(); const {branch} = parseParams(); @@ -244,48 +244,27 @@

Musisz się zalogować

branch: branch || "main" }; - try { - const response = await fetch("https://songbook-pdf-render-177765940460.europe-west1.run.app/api/render/song_xml", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify(payload) - }); + // Open blank window immediately to satisfy popup blocker + const pdfWindow = window.open('about:blank', '_blank'); + if (pdfWindow) { + pdfWindow.document.write("
Trwa generowanie PDF... Proszę czekać (zwykle około 10-20 sekund).
"); + } - if (!response.ok) { - alert("Błąd połączenia z serwerem PDF."); - return; + renderPdfCloudRun( + payload, + "/api/render/song_xml", + () => notice("Generowanie PDF... Proszę czekać (może potrwać do kilkunastu sekund)", songbook), + (url) => { + notice("PDF wygenerowany!", songbook); + if (pdfWindow) pdfWindow.location.href = url; + else window.open(url, '_blank'); + }, + (err, errUrl) => { + alert(err); + if (pdfWindow && errUrl) pdfWindow.location.href = errUrl; + else if (pdfWindow) pdfWindow.close(); } - - const data = await response.json(); - const jobId = data.job_id; - - // Poll for completion - const pollInterval = setInterval(async () => { - try { - const statusRes = await fetch(`https://songbook-pdf-render-177765940460.europe-west1.run.app/api/jobs/${jobId}`); - if (statusRes.ok) { - const statusData = await statusRes.json(); - if (statusData.status === "done") { - clearInterval(pollInterval); - notice("PDF wygenerowany!", songbook); - window.open(`https://songbook-pdf-render-177765940460.europe-west1.run.app${statusData.url}`, "_blank"); - } else if (statusData.status === "error") { - clearInterval(pollInterval); - alert("Błąd generowania PDF. Zobacz logi."); - window.open(`https://songbook-pdf-render-177765940460.europe-west1.run.app${statusData.url}`, "_blank"); - } - } - } catch (e) { - console.error("Polling error", e); - } - }, 2000); - - } catch (error) { - console.error("PDF render error", error); - alert("Błąd wysyłania do serwera PDF."); - } + ); } diff --git a/editor/pdf_renderer.js b/editor/pdf_renderer.js new file mode 100644 index 00000000..46e6bd1f --- /dev/null +++ b/editor/pdf_renderer.js @@ -0,0 +1,47 @@ +// Shared PDF rendering logic for Cloud Run +async function renderPdfCloudRun(payload, endpoint, onLoading, onSuccess, onError) { + onLoading(); + + try { + const response = await fetch(`https://songbook-pdf-render-177765940460.europe-west1.run.app${endpoint}`, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(payload) + }); + + if (!response.ok) { + onError("Błąd połączenia z serwerem PDF."); + return; + } + + const data = await response.json(); + const jobId = data.job_id; + + // Poll for completion + const pollInterval = setInterval(async () => { + try { + const statusRes = await fetch(`https://songbook-pdf-render-177765940460.europe-west1.run.app/api/jobs/${jobId}`); + if (statusRes.ok) { + const statusData = await statusRes.json(); + if (statusData.status === "done") { + clearInterval(pollInterval); + const finalUrl = `https://songbook-pdf-render-177765940460.europe-west1.run.app${statusData.url}`; + onSuccess(finalUrl); + } else if (statusData.status === "error") { + clearInterval(pollInterval); + const errorUrl = `https://songbook-pdf-render-177765940460.europe-west1.run.app${statusData.url}`; + onError("Błąd generowania PDF. Zobacz logi.", errorUrl); + } + } + } catch (e) { + console.error("Polling error", e); + } + }, 2000); + + } catch (error) { + console.error("PDF render error", error); + onError("Błąd wysyłania do serwera PDF."); + } +} diff --git a/src/html/index_generator.py b/src/html/index_generator.py index 058c6572..34191bde 100644 --- a/src/html/index_generator.py +++ b/src/html/index_generator.py @@ -326,6 +326,12 @@ def main(): os.remove(common_js_path) os.symlink(os.path.join(sb.repo_dir(), 'src', 'html', 'templates', "common.js"), common_js_path) + # Create symlink for pdf_renderer.js + pdf_renderer_js_path = os.path.join(target_dir, "pdf_renderer.js") + if os.path.exists(pdf_renderer_js_path): + os.remove(pdf_renderer_js_path) + os.symlink(os.path.join(sb.repo_dir(), 'editor', "pdf_renderer.js"), pdf_renderer_js_path) + # Create symlinks for songbook_edit files songbook_edit_files = ["songbook_edit.html", "songbook_edit.js", "songbook_edit.css"] for filename in songbook_edit_files: diff --git a/src/html/templates/songbook_edit/songbook_edit.html b/src/html/templates/songbook_edit/songbook_edit.html index a4263b72..6801d26a 100644 --- a/src/html/templates/songbook_edit/songbook_edit.html +++ b/src/html/templates/songbook_edit/songbook_edit.html @@ -108,22 +108,35 @@

Wybrane piosenki

- +
- + diff --git a/src/html/templates/songbook_edit/songbook_edit.js b/src/html/templates/songbook_edit/songbook_edit.js index 075eb9ea..3353a940 100644 --- a/src/html/templates/songbook_edit/songbook_edit.js +++ b/src/html/templates/songbook_edit/songbook_edit.js @@ -503,7 +503,7 @@ function renderDynamicFilters() { `}).join(''); } -function generateYAML() { +function generateYAMLString() { const songbookId = document.getElementById('songbookId').value.trim(); const songbookTitle = document.getElementById('songbookTitle').value.trim(); const songbookSubtitle = document.getElementById('songbookSubtitle').value.trim(); @@ -512,17 +512,17 @@ function generateYAML() { if (!songbookId) { alert('Proszę podać ID śpiewnika'); - return; + return null; } if (!songbookTitle) { alert('Proszę podać tytuł śpiewnika'); - return; + return null; } if (selectedSongIds.size === 0 && dynamicFilters.length === 0) { alert('Proszę wybrać przynajmniej jedną piosenkę lub dodać filtr'); - return; + return null; } // Generate UUID @@ -568,9 +568,15 @@ function generateYAML() { } }); - const yaml = JSON.stringify({ songbook }, null, 2); - document.getElementById('yamlOutput').value = yaml; - document.getElementById('outputArea').style.display = 'block'; + return JSON.stringify({ songbook }, null, 2); +} + +function generateYAML() { + const yaml = generateYAMLString(); + if (yaml) { + document.getElementById('yamlOutput').value = yaml; + document.getElementById('outputArea').style.display = 'block'; + } } function generateUUID() { @@ -612,7 +618,7 @@ function copyToClipboard() { } async function renderPDF() { - const yaml = document.getElementById('yamlOutput').value; + const yaml = generateYAMLString(); if (!yaml) return; // Get branch from URL or default to main @@ -625,64 +631,52 @@ async function renderPDF() { papersize: "a4" }; - try { - // Show loading notice - const btn = document.querySelector('button[onclick="renderPDF()"]'); - const originalText = btn.textContent; - btn.textContent = "Generowanie..."; - btn.disabled = true; - - const response = await fetch("https://songbook-pdf-render-177765940460.europe-west1.run.app/api/render/songbook_yaml", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify(payload) - }); + const btn = document.getElementById('btnRenderPdf'); + const pdfOutputArea = document.getElementById('pdfOutputArea'); + const pdfStatusText = document.getElementById('pdfStatusText'); + const pdfDownloadLink = document.getElementById('pdfDownloadLink'); + + if (pdfOutputArea) pdfOutputArea.style.display = 'block'; + if (pdfStatusText) { + pdfStatusText.style.display = 'block'; + pdfStatusText.textContent = "Trwa generowanie śpiewnika... Proszę czekać (zwykle około 15-30 sekund)."; + } + if (pdfDownloadLink) pdfDownloadLink.style.display = 'none'; - if (!response.ok) { - alert("Błąd połączenia z serwerem PDF."); - btn.textContent = originalText; - btn.disabled = false; - return; + // Open blank window immediately to satisfy popup blocker + let pdfWindow = null; + try { + pdfWindow = window.open('about:blank', '_blank'); + if (pdfWindow) { + pdfWindow.document.write("
Trwa generowanie śpiewnika PDF... Proszę czekać (zwykle około 15-30 sekund).
"); } + } catch (e) { + console.warn("Could not open new window automatically", e); + } - const data = await response.json(); - const jobId = data.job_id; - - // Poll for completion - const pollInterval = setInterval(async () => { - try { - const statusRes = await fetch(`https://songbook-pdf-render-177765940460.europe-west1.run.app/api/jobs/${jobId}`); - if (statusRes.ok) { - const statusData = await statusRes.json(); - if (statusData.status === "done") { - clearInterval(pollInterval); - btn.textContent = originalText; - btn.disabled = false; - window.open(`https://songbook-pdf-render-177765940460.europe-west1.run.app${statusData.url}`, "_blank"); - } else if (statusData.status === "error") { - clearInterval(pollInterval); - alert("Błąd generowania PDF. Sprawdź logi."); - btn.textContent = originalText; - btn.disabled = false; - window.open(`https://songbook-pdf-render-177765940460.europe-west1.run.app${statusData.url}`, "_blank"); - } - } - } catch (e) { - console.error("Polling error", e); + renderPdfCloudRun( + payload, + "/api/render/songbook_yaml", + () => { + if (btn) btn.disabled = true; + }, + (url) => { + if (btn) btn.disabled = false; + if (pdfStatusText) pdfStatusText.style.display = 'none'; + if (pdfDownloadLink) { + pdfDownloadLink.href = url; + pdfDownloadLink.style.display = 'block'; } - }, 2000); - - } catch (error) { - console.error("PDF render error", error); - alert("Błąd wysyłania do serwera PDF."); - const btn = document.querySelector('button[onclick="renderPDF()"]'); - if (btn) { - btn.textContent = "Podgląd PDF"; - btn.disabled = false; + if (pdfWindow) pdfWindow.location.href = url; + }, + (err, errUrl) => { + alert(err); + if (btn) btn.disabled = false; + if (pdfStatusText) pdfStatusText.textContent = err; + if (pdfWindow && errUrl) pdfWindow.location.href = errUrl; + else if (pdfWindow) pdfWindow.close(); } - } + ); } // Auto-generate songbook ID from title