document.addEventListener("DOMContentLoaded", function(e) { // Tabs functionality for settings pages let tabs = document.querySelectorAll('.jvb-settings-tab'); tabs.forEach(tab => { tab.addEventListener('click', (e) => { removeActiveTab(tabs); tab.classList.add('active'); setActiveSection(tab); }); }); // Check for hash in URL and activate corresponding tab if (window.location.hash) { var hash = window.location.hash.substring(1); document.querySelector('.jvb-settings-tab[data-tab="' + hash + '"]')?.click(); } else { // Activate first tab by default document.querySelector('.jvb-settings-tab')?.click(); } let confirm = document.querySelector('.jvb-confirm-action'); if (confirm) { confirm.addEventListener('click', (e) => { if (!window.confirm(confirm.dataset.confirm || 'Are you sure?')) { e.preventDefault(); return false; } }); } // Initialize admin actions initAdminActions(); initCacheActions(); initIconActions(); }); function removeActiveTab(tabs) { let active = document.querySelectorAll('.active'); active.forEach(tab => { tab.classList.remove('active'); if (tab.dataset.tab) { setActiveSection(tab, false); window.location.hash = tab.dataset.tab; } }); } function setActiveSection(tab, set = true) { let id = tab.dataset.tab; if (!id) return; let section = document.querySelector('#' + id); if (!section) return; if (set) { section.classList.add('active'); } else { section.classList.remove('active'); } } /** * Initialize admin action buttons (dashboard quick actions) */ function initAdminActions() { document.querySelectorAll('a[data-action]').forEach(action => { action.addEventListener('click', (e) => { e.preventDefault(); let loader = action.querySelector('.loader'); loader.classList.add('loading'); let a = action.dataset.action; makeAdminRequest('admin-action', { action: a }) .then(data => { if (data.success === true) { loader.classList.remove('loading'); loader.classList.add('loaded'); setTimeout(() => { loader.classList.remove('loaded'); }, 3000); } else { throw new Error(data.message || 'Action failed'); } }) .catch(error => { console.error('Error:', error); loader.classList.remove('loading'); alert('Error: ' + error.message); }); }); }); } /** * Initialize cache management actions */ function initCacheActions() { const flushAllBtn = document.querySelector('[data-cache-action="flush-all"]'); if (flushAllBtn) { flushAllBtn.addEventListener('click', function() { const originalText = this.innerHTML; this.disabled = true; this.innerHTML = 'Flushing...'; makeAdminRequest('admin-cache', { action: 'flush-all' }) .then(data => handleActionResponse(data, this, originalText)) .catch(error => handleActionError(error, this, originalText)); }); } document.querySelectorAll('[data-cache-action="flush-cache"]').forEach(btn => { btn.addEventListener('click', function() { const group = this.getAttribute('data-group'); const originalText = this.innerHTML; this.disabled = true; this.innerHTML = 'Flushing...'; makeAdminRequest('admin-cache', { action: 'flush-cache', group: group }) .then(data => handleActionResponse(data, this, originalText)) .catch(error => handleActionError(error, this, originalText)); }); }); } /** * Initialize icon management actions */ function initIconActions() { const currentSource = document.getElementById('icon-source-select')?.value || 'icons'; // Select all checkbox const selectAll = document.getElementById('select-all-versions'); if (selectAll) { selectAll.addEventListener('change', function() { document.querySelectorAll('.version-checkbox').forEach(checkbox => { checkbox.checked = this.checked; checkbox.dispatchEvent(new Event('change')); }); }); } // Enable/disable merge button based on selection document.querySelectorAll('.version-checkbox').forEach(checkbox => { checkbox.addEventListener('change', updateMergeButtonState); }); // Toggle icon list view document.querySelectorAll('.view-icon-list-btn').forEach(btn => { btn.addEventListener('click', function() { const timestamp = this.getAttribute('data-timestamp'); const row = document.getElementById('icon-list-' + timestamp); if (row) { row.style.display = row.style.display === 'none' ? '' : 'none'; this.textContent = row.style.display === 'none' ? '(view)' : '(hide)'; } }); }); // Force refresh button const refreshBtn = document.querySelector('[data-icon-action="refresh-icons"]'); if (refreshBtn) { refreshBtn.addEventListener('click', function() { const originalText = this.innerHTML; this.disabled = true; this.innerHTML = 'Regenerating...'; const source = this.getAttribute('data-source') || currentSource; makeAdminRequest('admin-icons', { action: 'refresh-icons', source: source }) .then(data => { handleActionResponse(data, this, originalText); }) .catch(error => { handleActionError(error, this, originalText); }); }); } // Merge versions button const mergeBtn = document.getElementById('merge-versions-btn'); if (mergeBtn) { mergeBtn.addEventListener('click', function() { const checkboxes = document.querySelectorAll('.version-checkbox:checked'); const timestamps = Array.from(checkboxes).map(cb => parseInt(cb.value)); if (timestamps.length < 2) { alert('Please select at least 2 versions to merge'); return; } if (confirm(`Merge ${timestamps.length} versions? This will create a new CSS file with all unique icons.`)) { const originalText = this.innerHTML; this.disabled = true; this.innerHTML = 'Merging...'; const source = this.getAttribute('data-source') || currentSource; makeAdminRequest('admin-icons', { action: 'merge-icon-versions', source: source, timestamps: timestamps }) .then(data => { handleActionResponse(data, this, originalText); }) .catch(error => { handleActionError(error, this, originalText); }); } }); } // Restore version buttons document.querySelectorAll('[data-icon-action="restore-icon-version"]').forEach(btn => { btn.addEventListener('click', function() { const timestamp = parseInt(this.getAttribute('data-timestamp')); const source = this.getAttribute('data-source') || currentSource; if (confirm('Restore this icon version? This will reload the page.')) { const originalText = this.innerHTML; this.disabled = true; this.innerHTML = 'Restoring...'; makeAdminRequest('admin-icons', { action: 'restore-icon-version', source: source, timestamp: timestamp }) .then(data => { handleActionResponse(data, this, originalText); }) .catch(error => { handleActionError(error, this, originalText); }); } }); }); } /** * Update merge button state based on selected checkboxes */ function updateMergeButtonState() { const checkedCount = document.querySelectorAll('.version-checkbox:checked').length; const mergeBtn = document.getElementById('merge-versions-btn'); if (mergeBtn) { mergeBtn.disabled = checkedCount < 2; } } /** * Make an admin API request * @param {string} endpoint - The API endpoint (without 'jvb/v1/') * @param {object} data - The data to send * @returns {Promise} */ function makeAdminRequest(endpoint, data = {}) { if (typeof jvbSettings === 'undefined') { console.error('jvbSettings is not defined'); return Promise.reject(new Error('jvbSettings is not defined. Scripts may not be loaded correctly.')); } console.log('Making request to:', jvbSettings.api + endpoint, 'with data:', data); return fetch(jvbSettings.api + endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': jvbSettings.nonce, 'X-Action-Nonce': jvbSettings.action }, body: JSON.stringify(data) }) .then(response => { console.log('Response status:', response.status); if (!response.ok) { return response.json().then(err => { throw new Error(err.message || 'Network response was not ok'); }); } return response.json(); }) .then(data => { console.log('Response data:', data); return data; }); } /** * Handle successful action response */ function handleActionResponse(data, button = null, originalText = null) { if (!data.success) { throw new Error(data.message || 'Unknown error'); } if (button && originalText) { button.innerHTML = '✓ Success!'; setTimeout(() => { button.disabled = false; button.innerHTML = originalText; }, 1500); } } /** * Handle action error */ function handleActionError(error, button = null, originalText = null) { console.error('Error:', error); if (button && originalText) { button.innerHTML = '✗ ' + (error.message || 'Error'); setTimeout(() => { button.disabled = false; button.innerHTML = originalText; }, 2000); } }