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
-
+
-
-
-
-
-
-
-
-
+
+
+
+ Opcje dla zaawansowanych (YAML)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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