/* BreznFlow — Admin JS (vanilla ES2020, no dependencies) */ /* global breznflowAdmin */ (function () { 'use strict'; // ── AJAX helpers ────────────────────────────────────────────────────────── function post(action, data, callback) { const params = new URLSearchParams(); params.append('action', action); params.append('nonce', breznflowAdmin.nonce); for (const [k, v] of Object.entries(data)) { params.append(k, v); } fetch(breznflowAdmin.ajaxUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params.toString(), }) .then(function(r) { return r.json(); }) .then(callback) .catch(function(err) { callback({ success: false, data: { message: String(err) } }); }); } // ── Step 1: Validation ──────────────────────────────────────────────────── const jsonTextarea = document.getElementById('breznflow-json'); const validateBtn = document.getElementById('breznflow-validate-btn'); const submitBtn = document.getElementById('breznflow-step1-submit'); const resultDiv = document.getElementById('breznflow-validation-result'); function showResult(success, message) { if (!resultDiv) return; resultDiv.removeAttribute('hidden'); resultDiv.className = success ? 'success' : 'error'; resultDiv.textContent = message; } if (validateBtn && jsonTextarea) { validateBtn.addEventListener('click', function () { const json = jsonTextarea.value.trim(); if (!json) { showResult(false, breznflowAdmin.i18n.pasteFirst || 'Please paste a workflow JSON first.'); return; } validateBtn.disabled = true; validateBtn.textContent = breznflowAdmin.i18n.validating || 'Validating...'; post('breznflow_validate_json', { json: json }, function(resp) { validateBtn.disabled = false; validateBtn.textContent = breznflowAdmin.i18n.validateJson || 'Validate JSON'; if (resp.success) { const msg = (breznflowAdmin.i18n.valid || 'Valid n8n workflow') + ': ' + resp.data.name + ' \u2014 ' + resp.data.nodes + ' ' + (breznflowAdmin.i18n.nodes || 'nodes'); showResult(true, msg); if (submitBtn) submitBtn.disabled = false; } else { showResult(false, (breznflowAdmin.i18n.invalid || 'Invalid') + ': ' + (resp.data && resp.data.message ? resp.data.message : 'Unknown error')); if (submitBtn) submitBtn.disabled = true; } }); }); } // ── Step 1: File upload → textarea ──────────────────────────────────────── const fileInput = document.getElementById('breznflow-file'); if (fileInput && jsonTextarea) { fileInput.addEventListener('change', function () { const file = this.files && this.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(e) { jsonTextarea.value = e.target.result; if (resultDiv) { resultDiv.setAttribute('hidden', ''); resultDiv.className = ''; resultDiv.textContent = ''; } if (submitBtn) submitBtn.disabled = true; }; reader.readAsText(file); }); } // ── Step 1: URL fetch ───────────────────────────────────────────────────── const urlInput = document.getElementById('breznflow-url'); const fetchBtn = document.getElementById('breznflow-fetch-url'); if (fetchBtn && urlInput && jsonTextarea) { fetchBtn.addEventListener('click', function () { const url = urlInput.value.trim(); if (!url) return; fetchBtn.disabled = true; fetchBtn.textContent = breznflowAdmin.i18n.fetching || 'Fetching...'; post('breznflow_fetch_url', { url: url }, function(resp) { fetchBtn.disabled = false; fetchBtn.textContent = breznflowAdmin.i18n.fetch || 'Fetch'; if (resp.success && resp.data && resp.data.json) { jsonTextarea.value = resp.data.json; if (submitBtn) submitBtn.disabled = true; if (resultDiv) { resultDiv.setAttribute('hidden', ''); resultDiv.textContent = ''; } } else { showResult(false, resp.data && resp.data.message ? resp.data.message : (breznflowAdmin.i18n.fetchFailed || 'Fetch failed')); } }); }); } // ── Copy Shortcode buttons ──────────────────────────────────────────────── function attachCopyButtons() { document.querySelectorAll('.breznflow-copy-sc').forEach(function(btn) { btn.addEventListener('click', function () { const sc = btn.getAttribute('data-sc') || ''; const label = btn.textContent; if (!sc) return; if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(sc).then(function() { btn.textContent = breznflowAdmin.i18n.copied || 'Copied!'; setTimeout(function() { btn.textContent = label; }, 2000); }).catch(function() { fallbackCopy(sc, btn, label); }); } else { fallbackCopy(sc, btn, label); } }); }); } function fallbackCopy(text, btn, label) { const ta = document.createElement('textarea'); ta.value = text; ta.style.position = 'fixed'; ta.style.opacity = '0'; document.body.appendChild(ta); ta.focus(); ta.select(); try { document.execCommand('copy'); btn.textContent = breznflowAdmin.i18n.copied || 'Copied!'; setTimeout(function() { btn.textContent = label; }, 2000); } catch (e) { // silently ignore } document.body.removeChild(ta); } attachCopyButtons(); // ── Step 2: Live shortcode preview ──────────────────────────────────────── const scLive = document.getElementById('breznflow-shortcode-live'); if (scLive) { const postIdInput = document.querySelector('input[name="breznflow_post_id"]'); const postId = postIdInput ? postIdInput.value : ''; const modeRadios = document.querySelectorAll('input[name="default_mode"]'); const showTitleCb = document.querySelector('input[name="show_title"]'); const showInfoCb = document.querySelector('input[name="show_infobox"]'); const showDlCb = document.querySelector('input[name="show_download"]'); const zoomInput = document.querySelector('input[name="default_zoom"]'); function updatePreview() { let sc = '[breznflow id="' + postId + '"'; const modeVal = document.querySelector('input[name="default_mode"]:checked'); if (modeVal && modeVal.value !== 'visual') sc += ' mode="' + modeVal.value + '"'; if (zoomInput && zoomInput.value !== '100') sc += ' zoom="' + zoomInput.value + '"'; if (showTitleCb && !showTitleCb.checked) sc += ' show_title="0"'; if (showInfoCb && !showInfoCb.checked) sc += ' show_infobox="0"'; if (showDlCb && showDlCb.checked) sc += ' show_download="1"'; sc += ']'; scLive.textContent = sc; // Update copy button data attribute const copyBtn = scLive.nextElementSibling; if (copyBtn && copyBtn.classList.contains('breznflow-copy-sc')) { copyBtn.setAttribute('data-sc', sc); } } modeRadios.forEach(function(r) { r.addEventListener('change', updatePreview); }); if (showTitleCb) showTitleCb.addEventListener('change', updatePreview); if (showInfoCb) showInfoCb.addEventListener('change', updatePreview); if (showDlCb) showDlCb.addEventListener('change', updatePreview); if (zoomInput) zoomInput.addEventListener('input', updatePreview); } }());