| | |
| | | document.addEventListener("DOMContentLoaded", function(e) { |
| | | console.log('working'); |
| | | // Tabs functionality for settings pages |
| | | let tabs = document.querySelectorAll('.jvb-settings-tab'); |
| | | // 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); |
| | | }); |
| | | }); |
| | | 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(); |
| | | } |
| | | // 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; |
| | | } |
| | | }); |
| | | } |
| | | 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; |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // Admin action buttons |
| | | 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; |
| | | |
| | | fetch(jvbSettings.api, { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Content-Type': 'application/json', |
| | | 'X-WP-Nonce': jvbSettings.nonce, |
| | | 'action_nonce': jvbSettings.action |
| | | }, |
| | | body: JSON.stringify({ |
| | | action: a |
| | | }) |
| | | }) |
| | | .then(response => { |
| | | if (!response.ok) { |
| | | throw new Error('Network response was not ok'); |
| | | } |
| | | return response.json(); |
| | | }) |
| | | .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'); |
| | | // You might want to add an error state class here |
| | | }); |
| | | }); |
| | | }); |
| | | // 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; |
| | | } |
| | | }); |
| | | 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 id = tab.dataset.tab; |
| | | if (!id) return; |
| | | |
| | | let section = document.querySelector('#' + id); |
| | | if (!section) return; |
| | | let section = document.querySelector('#' + id); |
| | | if (!section) return; |
| | | |
| | | if (set) { |
| | | section.classList.add('active'); |
| | | } else { |
| | | section.classList.remove('active'); |
| | | } |
| | | 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); |
| | | } |
| | | } |