Jake Vanderwerf
9 days ago 47e77f9fac1155c536b2b87fec552c7fcce66fa6
assets/js/admin.js
@@ -1,102 +1,320 @@
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);
   }
}