// BackPRO - Frontend Scripts (function () { 'use strict'; var confirmQueue = Promise.resolve(); var confirmUi = null; function getToastClass(type) { if (type === 'success') return 'text-bg-success'; if (type === 'danger' || type === 'error') return 'text-bg-danger'; if (type === 'warning') return 'text-bg-warning'; return 'text-bg-primary'; } function getToastTitle(type) { if (type === 'success') return 'Sukces'; if (type === 'danger' || type === 'error') return 'Blad'; if (type === 'warning') return 'Uwaga'; return 'Informacja'; } function ensureToastContainer() { var container = document.getElementById('bpToastContainer'); if (container) return container; container = document.createElement('div'); container.id = 'bpToastContainer'; container.className = 'toast-container position-fixed top-0 end-0 p-3 bp-toast-container'; document.body.appendChild(container); return container; } function showToast(message, type, options) { if (!message) return; if (!window.bootstrap || !window.bootstrap.Toast) { var fallbackContainer = ensureToastContainer(); var fallbackToast = document.createElement('div'); fallbackToast.className = 'bp-toast-fallback'; fallbackToast.textContent = message; fallbackContainer.appendChild(fallbackToast); setTimeout(function () { fallbackToast.remove(); }, 4000); return; } var opts = options || {}; var container = ensureToastContainer(); var toast = document.createElement('div'); var toastClass = getToastClass(type || 'info'); var title = opts.title || getToastTitle(type || 'info'); var delay = typeof opts.delay === 'number' ? opts.delay : 5000; toast.className = 'toast border-0 shadow-sm bp-toast ' + toastClass; toast.setAttribute('role', 'alert'); toast.setAttribute('aria-live', 'assertive'); toast.setAttribute('aria-atomic', 'true'); toast.innerHTML = '
' + '
' + '' + title + ': ' + message + '
' + '' + '
'; container.appendChild(toast); var bsToast = new bootstrap.Toast(toast, { delay: delay }); toast.addEventListener('hidden.bs.toast', function () { toast.remove(); }); bsToast.show(); } function ensureConfirmUi() { if (confirmUi) return confirmUi; var existing = document.getElementById('bpConfirmModal'); if (!existing) { var modal = document.createElement('div'); modal.className = 'modal fade bp-confirm-modal'; modal.id = 'bpConfirmModal'; modal.tabIndex = -1; modal.setAttribute('aria-hidden', 'true'); modal.innerHTML = ''; document.body.appendChild(modal); existing = modal; } confirmUi = { el: existing, modal: window.bootstrap && window.bootstrap.Modal ? new bootstrap.Modal(existing, { backdrop: 'static', keyboard: false }) : null, titleEl: existing.querySelector('#bpConfirmTitle'), messageEl: existing.querySelector('#bpConfirmMessage'), cancelBtn: existing.querySelector('[data-role="cancel"]'), confirmBtn: existing.querySelector('[data-role="confirm"]') }; return confirmUi; } function showConfirmDialog(message, options) { var opts = options || {}; if (!window.bootstrap || !window.bootstrap.Modal) { showToast('Brak komponentu potwierdzenia. Operacja zostala wstrzymana.', 'warning'); return Promise.resolve(false); } var ui = ensureConfirmUi(); ui.titleEl.textContent = opts.title || 'Potwierdzenie'; ui.messageEl.textContent = message || 'Czy na pewno?'; ui.cancelBtn.textContent = opts.cancelText || 'Anuluj'; ui.confirmBtn.textContent = opts.confirmText || 'Potwierdz'; ui.confirmBtn.className = 'btn ' + (opts.confirmClass || 'btn-danger'); return new Promise(function (resolve) { var confirmed = false; function cleanup() { ui.confirmBtn.removeEventListener('click', onConfirm); ui.cancelBtn.removeEventListener('click', onCancel); ui.el.removeEventListener('hidden.bs.modal', onHidden); } function onConfirm() { confirmed = true; ui.modal.hide(); } function onCancel() { ui.modal.hide(); } function onHidden() { cleanup(); resolve(confirmed); } ui.confirmBtn.addEventListener('click', onConfirm); ui.cancelBtn.addEventListener('click', onCancel); ui.el.addEventListener('hidden.bs.modal', onHidden); ui.modal.show(); }); } function queueConfirm(message, options) { var run = function () { return showConfirmDialog(message, options); }; var pending = confirmQueue.then(run, run); confirmQueue = pending.catch(function () { return false; }); return pending; } function installConfirmForForms() { document.addEventListener('submit', function (event) { var form = event.target; if (!(form instanceof HTMLFormElement)) return; if (!form.matches('form[data-confirm]')) return; if (form.dataset.confirmBypass === '1') { form.dataset.confirmBypass = ''; return; } event.preventDefault(); queueConfirm(form.getAttribute('data-confirm'), { title: form.dataset.confirmTitle || 'Potwierdzenie', confirmText: form.dataset.confirmOk || 'Potwierdz', cancelText: form.dataset.confirmCancel || 'Anuluj', confirmClass: form.dataset.confirmClass || 'btn-danger' }).then(function (ok) { if (!ok) return; form.dataset.confirmBypass = '1'; form.submit(); }); }, true); } function initTestConnectionButtons() { document.querySelectorAll('.btn-test-connection').forEach(function (btn) { btn.addEventListener('click', function () { var siteId = this.dataset.siteId; var button = this; var originalHtml = button.innerHTML; button.innerHTML = ''; button.disabled = true; fetch('/sites/' + siteId + '/test', { method: 'POST' }) .then(function (r) { return r.json(); }) .then(function (data) { if (data.success) { button.innerHTML = ''; button.classList.remove('btn-outline-success'); button.classList.add('btn-success'); showToast(data.message || 'Polaczenie poprawne.', 'success', { delay: 3500 }); } else { button.innerHTML = ''; button.classList.remove('btn-outline-success'); button.classList.add('btn-danger'); showToast('Blad polaczenia: ' + (data.message || 'Nieznany blad'), 'danger'); } }) .catch(function () { button.innerHTML = ''; button.classList.add('btn-danger'); showToast('Blad sieci podczas testu polaczenia.', 'danger'); }) .finally(function () { button.disabled = false; setTimeout(function () { button.innerHTML = originalHtml; button.className = button.className.replace('btn-success', 'btn-outline-success').replace('btn-danger', 'btn-outline-success'); }, 3000); }); }); }); } function initTopicEditButtons() { document.querySelectorAll('.btn-edit-topic').forEach(function (btn) { btn.addEventListener('click', function () { var id = this.dataset.id; var form = document.getElementById('topicForm'); var title = document.getElementById('topicFormTitle'); var submit = document.getElementById('topicFormSubmit'); if (!form || !title || !submit) return; form.action = '/topics/' + id + '/update'; title.textContent = 'Edytuj temat'; submit.textContent = 'Zapisz zmiany'; document.getElementById('topic_name').value = this.dataset.name; document.getElementById('topic_description').value = this.dataset.description; document.getElementById('topic_wp_category').value = this.dataset.wpCategory || ''; document.getElementById('topic_is_active').checked = this.dataset.active === '1'; var globalSelect = document.getElementById('topic_global_id'); if (globalSelect) { globalSelect.value = this.dataset.globalTopic || ''; } }); }); } function highlightActiveSidebarLink() { var currentPath = window.location.pathname; document.querySelectorAll('.sidebar .nav-link').forEach(function (link) { var href = link.getAttribute('href'); if (currentPath === href || (href !== '/' && currentPath.startsWith(href))) { link.classList.add('active'); } }); } window.BackProUI = { toast: showToast, confirm: queueConfirm }; window.backproNotify = function (message, type, options) { showToast(message, type || 'info', options); }; window.backproConfirm = function (message, options) { return queueConfirm(message, options); }; document.addEventListener('DOMContentLoaded', function () { installConfirmForForms(); initTestConnectionButtons(); initTopicEditButtons(); highlightActiveSidebarLink(); }); })();