/** * Hi-School Slide Manager Dashboard JavaScript * * Handles AJAX interactions, form management, and dynamic UI updates * * @package Hi_School_Slide_Manager * @since 1.0.0 */ (function($) { 'use strict'; // Dashboard object const HSSMDashboard = { formCounter: 0, maxForms: 5, currentTab: 'create-slides', // Manage slides state currentPage: 1, perPage: 25, totalSlides: 0, hasMore: false, filters: { status: '', site: '', client: '' }, // Edit mode state isEditMode: false, editingSlideId: null, currentSlides: null, // Initialize the dashboard init: function() { this.bindEvents(); this.initializeTabs(); this.addInitialSlideForm(); this.loadExistingSlides(); // Initialize site data window.hssmSites = window.hssmSites || []; }, // Bind event handlers bindEvents: function() { // Tab navigation - use direct binding for reliability setTimeout(() => { $('.hssm-nav-tabs a').off('click.hssm').on('click.hssm', this.handleTabClick.bind(this)); }, 100); // Form management $(document).on('click', '#add-slide-form', this.addSlideForm.bind(this)); $(document).on('click', '.hssm-remove-form', this.removeSlideForm.bind(this)); $(document).on('click', '#clear-all-forms', this.clearAllForms.bind(this)); // Image upload $(document).on('click', '.hssm-upload-btn', this.triggerImageUpload.bind(this)); $(document).on('click', '.hssm-image-preview-small', this.triggerImageUpload.bind(this)); $(document).on('click', '.hssm-remove-image', this.removeImage.bind(this)); // Button management $(document).on('click', '.hssm-add-button', this.addButtonRow.bind(this)); $(document).on('click', '.hssm-remove-button', this.removeButtonRow.bind(this)); // Slide actions $(document).on('click', '.hssm-save-slide', this.saveSlide.bind(this)); $(document).on('click', '#save-all-slides', this.saveAllSlides.bind(this)); $(document).on('click', '.hssm-preview-slide', this.previewSlide.bind(this)); $(document).on('click', '.hssm-schedule-slide', this.scheduleSlide.bind(this)); $(document).on('click', '.hssm-publish-slide', this.publishSlide.bind(this)); // Clear field errors when user starts typing/selecting $(document).on('input change', '.hssm-input, .hssm-textarea, .hssm-select', function() { const $field = $(this); const $fieldContainer = $field.closest('.hssm-field'); $fieldContainer.find('.hssm-field-error').remove(); $field.removeClass('hssm-field-has-error'); $fieldContainer.find('.hssm-checkboxes-compact').removeClass('hssm-field-has-error'); }); // Clear target sites error when a checkbox is checked $(document).on('change', 'input[name="target_sites[]"], input[name*="target_sites[]"]', function() { const $form = $(this).closest('.hssm-slide-form'); const $targetSitesField = $form.find('.hssm-field:has(.hssm-checkboxes-compact)').first(); $targetSitesField.find('.hssm-field-error').remove(); $targetSitesField.find('.hssm-checkboxes-compact').removeClass('hssm-field-has-error'); }); // Filtering and management (slide row edit/delete bound in bindSlideActions after list load) $(document).on('click', '#apply-filters', this.applyFilters.bind(this)); // Edit form actions — register once; do not re-bind in populateEditForm (prevents duplicate toasts) $(document).on('click.hssmDashboard', '.hssm-cancel-edit, .hssm-cancel-edit-btn', (e) => { e.preventDefault(); this.cancelEdit(e); }); $(document).on('click.hssmDashboard', '.hssm-update-slide', this.updateSlide.bind(this)); $(document).on('click.hssmDashboard', '.hssm-schedule-updated-slide', this.scheduleUpdatedSlide.bind(this)); // Analytics functionality $(document).on('click', '#generate-report', this.generateAnalyticsReport.bind(this)); // Additional functionality $(document).on('click', '#import-slides', this.importSlides.bind(this)); $(document).on('click', '#export-slides', this.exportSlides.bind(this)); $(document).on('click', '#save-draft-all', this.saveAllAsDrafts.bind(this)); // Notification Settings $(document).on('submit', '#notification-settings-form', this.saveNotificationSettings.bind(this)); }, // Initialize tab functionality initializeTabs: function() { // Check for saved tab in sessionStorage const savedTab = sessionStorage.getItem('hssm_active_tab'); if (savedTab && $(`[data-tab="${savedTab}"]`).length > 0) { // Restore saved tab $('.hssm-nav-tabs li').removeClass('active'); $('.hssm-tab-content').removeClass('active'); $(`[data-tab="${savedTab}"]`).parent().addClass('active'); $(`#${savedTab}`).addClass('active'); this.currentTab = savedTab; // Load tab-specific data for restored tab if (savedTab === 'manage-slides') { this.loadExistingSlides(); } else if (savedTab === 'analytics') { this.loadAnalyticsData(); } else if (savedTab === 'notifications') { this.loadNotificationSettings(); } } else { // Default to first tab $('.hssm-nav-tabs a').first().parent().addClass('active'); $('.hssm-tab-content').first().addClass('active'); this.currentTab = $('.hssm-nav-tabs a').first().data('tab') || 'create-slides'; } }, // Handle tab switching handleTabClick: function(e) { e.preventDefault(); const $tab = $(e.currentTarget); const targetTab = $tab.data('tab'); // Update active states for navigation tabs $('.hssm-nav-tabs li').removeClass('active'); $tab.parent().addClass('active'); // Update active states for tab content $('.hssm-tab-content').removeClass('active'); $('#' + targetTab).addClass('active'); // Set currentTab BEFORE calling functions this.currentTab = targetTab; // Save active tab to sessionStorage sessionStorage.setItem('hssm_active_tab', targetTab); // Load tab-specific data if (targetTab === 'manage-slides') { this.loadExistingSlides(); } else if (targetTab === 'analytics') { this.loadAnalyticsData(); } else if (targetTab === 'notifications') { this.loadNotificationSettings(); } }, // Add initial slide form addInitialSlideForm: function() { if ($('#slide-forms-container .hssm-slide-form').length === 0) { this.addSlideForm(); } }, // Add a new slide form addSlideForm: function(e) { if (e) e.preventDefault(); if ($('.hssm-slide-form').length >= this.maxForms) { this.showMessage(hssmDashboard.strings.max_forms, 'warning'); return; } this.formCounter++; // Get available sites for checkboxes const sitesHtml = window.hssmSites ? window.hssmSites.map(site => ` `).join('') : '

No sites available

'; const formHtml = `

Slide ${this.formCounter}

× Remove

Basic Information

Site Targeting

${sitesHtml}

Image

Click to upload image

Call-to-Action Buttons

`; $('#slide-forms-container').append(formHtml); this.initializeFormElements(this.formCounter); }, // Initialize form elements for a specific form initializeFormElements: function(formId) { // Set default target site to first available site const $form = $(`.hssm-slide-form[data-form-id="${formId}"]`); $form.find('input[name="target_sites[]"], input[name*="target_sites[]"]').first().prop('checked', true); }, // Remove a slide form removeSlideForm: function(e) { e.preventDefault(); const $form = $(e.currentTarget).closest('.hssm-slide-form'); if ($('.hssm-slide-form').length <= 1) { this.showMessage('At least one form must remain.', 'warning'); return; } $form.fadeOut(300, function() { $(this).remove(); }); }, // Clear all forms clearAllForms: function(e) { if (e) e.preventDefault(); if (confirm('Are you sure you want to clear all forms? This action cannot be undone.')) { $('#slide-forms-container').empty(); this.formCounter = 0; this.addSlideForm(); } }, // Trigger image upload // Handle image upload triggerImageUpload: function(e) { e.preventDefault(); const formId = $(e.currentTarget).data('target') || $(e.currentTarget).closest('.hssm-slide-form').data('form-id'); if (!formId) { console.error('Could not determine form ID for image upload'); return; } console.log('Opening WordPress media uploader for form:', formId); // Use WordPress media uploader const mediaUploader = wp.media({ title: 'Select Slide Image', button: { text: 'Use This Image' }, multiple: false, library: { type: 'image' } }); mediaUploader.on('select', function() { const attachment = mediaUploader.state().get('selection').first().toJSON(); const $preview = $(`#image_preview_${formId}`); console.log('Image selected:', attachment); // Update preview $preview.css('background-image', `url(${attachment.url})`); $preview.addClass('has-image'); $preview.html(''); // Remove the "Click to upload" text // Store image ID $(`#image_id_${formId}`).val(attachment.id); // Show remove button $(`.hssm-remove-image[data-target="${formId}"]`).show(); this.showMessage('Image selected successfully!', 'success'); }.bind(this)); mediaUploader.open(); }, // Remove uploaded image removeImage: function(e) { e.preventDefault(); const formId = $(e.currentTarget).data('target'); const $preview = $(`#image_preview_${formId}`); $preview.css('background-image', ''); $preview.removeClass('has-image'); $preview.html('Click to upload image'); // Restore the placeholder text $(`#image_id_${formId}`).val(''); $(e.currentTarget).hide(); }, // Add button row addButtonRow: function(e) { e.preventDefault(); const formId = $(e.currentTarget).data('form'); const $container = $(`#buttons_${formId}`); const buttonIndex = $container.find('.hssm-button-row-compact').length; if (buttonIndex >= 5) { this.showMessage('Maximum 5 buttons allowed per slide.', 'warning'); return; } const buttonHtml = `
`; $container.append(buttonHtml); }, // Remove button row removeButtonRow: function(e) { e.preventDefault(); const $container = $(e.currentTarget).closest('.hssm-buttons-container-compact'); if ($container.find('.hssm-button-row-compact').length <= 1) { this.showMessage('At least one button is required.', 'warning'); return; } $(e.currentTarget).closest('.hssm-button-row-compact').fadeOut(300, function() { $(this).remove(); }); }, // Save individual slide saveSlide: function(e) { e.preventDefault(); const formId = $(e.currentTarget).data('form'); const $form = $(`.hssm-slide-form[data-form-id="${formId}"]`); this.submitSlideForm($form); }, // Save all slides saveAllSlides: function(e) { if (e) e.preventDefault(); const $forms = $('.hssm-slide-form'); let savedCount = 0; let errorCount = 0; $forms.each((index, form) => { this.submitSlideForm($(form), () => { savedCount++; this.checkAllSaved(savedCount, errorCount, $forms.length); }, () => { errorCount++; this.checkAllSaved(savedCount, errorCount, $forms.length); }); }); }, // Check if all forms have been processed checkAllSaved: function(savedCount, errorCount, totalCount) { if (savedCount + errorCount === totalCount) { if (errorCount === 0) { this.showMessage(`All ${savedCount} slides saved successfully!`, 'success'); } else { this.showMessage(`${savedCount} slides saved, ${errorCount} failed.`, 'warning'); } } }, // Submit individual slide form submitSlideForm: function($form, successCallback, errorCallback) { if (!this.validateForm($form)) { if (errorCallback) errorCallback(); return; } const formData = this.collectFormData($form); $form.addClass('hssm-loading'); formData.append('nonce', hssmDashboard.nonce); $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: formData, processData: false, contentType: false, success: (response) => { $form.removeClass('hssm-loading'); if (response.success) { this.showMessage(response.data.message, 'success'); this.clearForm($form); if (successCallback) successCallback(); } else { this.showMessage(response.data.message || 'Save failed', 'error'); if (errorCallback) errorCallback(); } }, error: () => { $form.removeClass('hssm-loading'); this.showMessage('Save failed. Please try again.', 'error'); if (errorCallback) errorCallback(); } }); }, // Clear all field errors in a form clearFieldErrors: function($form) { $form.find('.hssm-field-error').remove(); $form.find('.hssm-input, .hssm-textarea, .hssm-checkboxes-compact').removeClass('hssm-field-has-error'); }, // Show error for a specific field showFieldError: function($field, message) { // Remove any existing error for this field const $fieldContainer = $field.closest('.hssm-field'); $fieldContainer.find('.hssm-field-error').remove(); // Add error class to field $field.addClass('hssm-field-has-error'); // Create error message element const $error = $('
').text(message); // Insert error above the field (after label, before input) const $label = $fieldContainer.find('label').first(); if ($label.length) { $error.insertAfter($label); } else { // If no label, insert at the beginning of the field container $error.prependTo($fieldContainer); } }, // Validate form data validateForm: function($form) { // Clear previous errors this.clearFieldErrors($form); const title = $form.find('input[name*="[title]"]').val().trim(); const startDate = $form.find('input[name*="[start_date]"]').val(); const endDate = $form.find('input[name*="[end_date]"]').val(); // Find target sites checkboxes - handle all possible name formats // Matches: name="target_sites[]", name="slides[X][target_sites][]", etc. const $targetSiteCheckboxes = $form.find('input[type="checkbox"][name*="target_sites"]'); const targetSitesCount = $targetSiteCheckboxes.filter(':checked').length; let hasErrors = false; console.log('Validating form data:'); console.log('Title:', title); console.log('Start Date:', startDate); console.log('End Date:', endDate); console.log('Target Sites Checkboxes Found:', $targetSiteCheckboxes.length); console.log('Target Sites Selected:', targetSitesCount); console.log('Target Sites Checkbox Names:', $targetSiteCheckboxes.map(function() { return $(this).attr('name'); }).get()); // Validate title if (!title) { const $titleField = $form.find('input[name*="[title]"]'); this.showFieldError($titleField, 'Title is required'); hasErrors = true; } // Validate target sites - check all checkbox formats if (targetSitesCount === 0) { const $targetSitesContainer = $form.find('.hssm-checkboxes-compact').first(); $targetSitesContainer.addClass('hssm-field-has-error'); const $targetSitesField = $form.find('.hssm-field:has(.hssm-checkboxes-compact)').first(); const $error = $('
').text('At least one target site must be selected'); $targetSitesField.find('label').first().after($error); hasErrors = true; } // Validate date logic if (startDate && endDate && new Date(startDate) > new Date(endDate)) { const $endDateField = $form.find('input[name*="[end_date]"]'); this.showFieldError($endDateField, 'End Date must be after Start Date'); hasErrors = true; } if (hasErrors) { console.log('Validation errors found'); // Scroll to first error const $firstError = $form.find('.hssm-field-error').first(); if ($firstError.length) { $('html, body').animate({ scrollTop: $firstError.offset().top - 100 }, 500); } return false; } console.log('Form validation passed'); return true; }, // Collect form data collectFormData: function($form) { const formData = new FormData(); const formId = $form.data('form-id'); formData.append('nonce', hssmDashboard.nonce); // Basic fields - using the new compact form structure formData.append('title', $form.find('input[name*="[title]"]').val() || ''); formData.append('subtitle', $form.find('input[name*="[subtitle]"]').val() || ''); formData.append('content', $form.find('textarea[name*="[content]"]').val() || ''); formData.append('start_date', $form.find('input[name*="[start_date]"]').val() || ''); formData.append('end_date', $form.find('input[name*="[end_date]"]').val() || ''); formData.append('featured_image_id', $form.find('.hssm-image-id').val() || ''); // Target sites - using the new compact form structure // Handle both name="target_sites[]" and name="slides[X][target_sites][]" formats const targetSitesCollected = []; $form.find('input[type="checkbox"][name*="target_sites"]').filter(':checked').each(function() { const siteValue = $(this).val(); formData.append('target_sites[]', siteValue); targetSitesCollected.push(siteValue); }); console.log('Collected target sites:', targetSitesCollected); // Hide all text option const hideAllText = $form.find('input[name*="[hide_all_text]"]:checked').length > 0; formData.append('hide_all_text', hideAllText ? '1' : '0'); // Buttons - using the new compact form structure const buttons = []; $form.find('.hssm-button-row-compact').each(function() { const text = $(this).find('input[name*="[text]"]').val(); const url = $(this).find('input[name*="[url]"]').val(); if (text || url) { buttons.push({ text: text || 'Learn More', url: url || '' }); } }); formData.append('buttons', JSON.stringify(buttons)); return formData; }, // Schedule slide for approval scheduleSlide: function(e) { e.preventDefault(); const formId = $(e.currentTarget).data('form'); const $form = $(`.hssm-slide-form[data-form-id="${formId}"]`); console.log('Schedule slide clicked for form:', formId); console.log('Form found:', $form.length); if (!this.validateForm($form)) { return; } const formData = this.collectFormData($form); formData.append('action', 'hssm_schedule_slide'); formData.append('publication_action', 'schedule'); console.log('Sending AJAX request...'); console.log('Form data:', Array.from(formData.entries())); $form.addClass('hssm-loading'); $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: formData, processData: false, contentType: false, success: (response) => { console.log('AJAX success response:', response); $form.removeClass('hssm-loading'); if (response.success) { this.showMessage('Slide scheduled for approval. Email notifications have been sent.', 'success'); this.clearForm($form); } else { this.showMessage(response.data.message || 'Schedule failed', 'error'); } }, error: (xhr, status, error) => { console.log('AJAX error:', xhr, status, error); $form.removeClass('hssm-loading'); this.showMessage('Schedule failed. Please try again.', 'error'); } }); }, // Publish slide immediately publishSlide: function(e) { e.preventDefault(); const formId = $(e.currentTarget).data('form'); const $form = $(`.hssm-slide-form[data-form-id="${formId}"]`); if (!this.validateForm($form)) { return; } const formData = this.collectFormData($form); formData.append('action', 'hssm_publish_slide'); formData.append('publication_action', 'publish'); $form.addClass('hssm-loading'); $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: formData, processData: false, contentType: false, success: (response) => { $form.removeClass('hssm-loading'); if (response.success) { this.showMessage('Slide published and approval notifications sent.', 'success'); this.clearForm($form); } else { this.showMessage(response.data.message || 'Publish failed', 'error'); } }, error: () => { $form.removeClass('hssm-loading'); this.showMessage('Publish failed. Please try again.', 'error'); } }); }, // Clear form after successful save clearForm: function($form) { const formId = $form.data('form-id'); $form.find('input[type="text"], input[type="url"], input[type="number"], input[type="date"], textarea').val(''); $form.find('input[type="checkbox"]').prop('checked', false); // Reset target sites to first site by default $form.find('input[name="target_sites[]"], input[name*="target_sites[]"]').first().prop('checked', true); // Clear image const $imagePreview = $form.find('.hssm-image-preview-small'); $imagePreview.css('background-image', ''); $imagePreview.removeClass('has-image'); $imagePreview.html('Click to upload image'); $form.find('.hssm-image-id').val(''); $form.find('.hssm-remove-image').hide(); // Reset buttons to one row const $buttonsContainer = $form.find('.hssm-buttons-container-compact'); $buttonsContainer.html(`
`); }, // Load existing slides loadExistingSlides: function() { const $slidesList = $('#slides-list'); if ($slidesList.length === 0) { console.error('slides-list element not found!'); return; } $slidesList.html('
Loading slides...
'); $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: { action: 'hssm_get_slides', nonce: hssmDashboard.nonce }, beforeSend: function(xhr, settings) { // Optional: Add loading indicators }, success: (response) => { if (response.success && response.data && response.data.slides) { this.renderSlidesList(response.data.slides); } else { console.error('Failed to get slides:', response); $slidesList.html('

Failed to load slides. Response format unexpected.

'); } }, error: (xhr, status, error) => { console.error('AJAX error getting slides:', xhr.responseText, status, error); console.error('Status code:', xhr.status); console.error('Status text:', xhr.statusText); $slidesList.html('

Failed to load slides.

'); } }); }, // Render slides list renderSlidesList: function(slides) { const $slidesList = $('#slides-list'); // Store slides for editing functionality this.currentSlides = slides; if (!slides || slides.length === 0) { $slidesList.html(`

No slides found

Create your first slide to get started!

`); $(document).off('click.hssmSlideActions'); return; } let html = `
Image
Title
Status
Schedule
Target Sites
Actions
`; slides.forEach(slide => { const imageUrl = slide.featured_image_url || ''; const statusClass = this.getStatusClass(slide.status); const sitesText = this.formatSitesList(slide.sites || slide.target_sites); const scheduleText = this.formatScheduleText(slide); html += `
${!imageUrl ? '' : ''}
${slide.title}
${slide.subtitle || ''}
${slide.status}
${scheduleText}
${sitesText}
`; }); html += `
`; $slidesList.html(html); this.bindSlideActions(); }, // Helper function to get status CSS class getStatusClass: function(status) { const statusMap = { 'publish': 'published', 'draft': 'draft', 'future': 'scheduled', 'private': 'private' }; return statusMap[status] || 'unknown'; }, // Helper function to format sites list formatSitesList: function(sites) { if (!sites || sites.length === 0) return 'No sites'; if (sites.length === 1) return sites[0]; if (sites.length <= 3) return sites.join(', '); return `${sites.slice(0, 2).join(', ')} +${sites.length - 2} more`; }, // Helper function to format schedule text formatScheduleText: function(slide) { if (!slide.start_date && !slide.end_date) return 'No schedule'; const start = slide.start_date ? new Date(slide.start_date).toLocaleDateString() : ''; const end = slide.end_date ? new Date(slide.end_date).toLocaleDateString() : ''; if (start && end) return `${start} - ${end}`; if (start) return `From ${start}`; if (end) return `Until ${end}`; return 'No schedule'; }, // Bind slide action events bindSlideActions: function() { // Namespaced so repeated list renders replace handlers instead of stacking $(document).off('click.hssmSlideActions', '.hssm-edit-slide').on('click.hssmSlideActions', '.hssm-edit-slide', (e) => { e.preventDefault(); const slideId = $(e.currentTarget).data('slide-id'); this.editSlide(slideId); }); $(document).off('click.hssmSlideActions', '.hssm-delete-slide').on('click.hssmSlideActions', '.hssm-delete-slide', (e) => { e.preventDefault(); const slideId = $(e.currentTarget).data('slide-id'); this.deleteSlide(slideId); }); $(document).off('click.hssmSlideActions', '.hssm-duplicate-slide').on('click.hssmSlideActions', '.hssm-duplicate-slide', (e) => { e.preventDefault(); const slideId = $(e.currentTarget).data('slide-id'); this.duplicateSlide(slideId); }); $(document).off('click.hssmSlideActions', '.hssm-toggle-status').on('click.hssmSlideActions', '.hssm-toggle-status', (e) => { e.preventDefault(); const slideId = $(e.currentTarget).data('slide-id'); this.toggleSlideStatus(slideId); }); }, // Edit slide function editSlide: function(slideId) { // Switch to create tab and populate with slide data $('.hssm-nav-tabs a[data-tab="create-slides"]').click(); this.loadSlideForEditing(slideId); }, // Load slide data for editing loadSlideForEditing: function(slideId) { // Show loading state $('#slide-forms-container').html('
Loading slide for editing...
'); // First, get the slide data from our existing slides list const slideData = this.findSlideById(slideId); if (slideData) { this.populateEditForm(slideData); } else { // Fallback: fetch slide data via AJAX if not found in current list $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: { action: 'hssm_get_slide_for_edit', nonce: hssmDashboard.nonce, slide_id: slideId }, success: (response) => { if (response.success && response.data.slide) { this.populateEditForm(response.data.slide); } else { this.showMessage('Failed to load slide for editing', 'error'); this.addInitialSlideForm(); // Fallback to empty form } }, error: () => { this.showMessage('Failed to load slide for editing', 'error'); this.addInitialSlideForm(); // Fallback to empty form } }); } }, // Find slide by ID in current slides list findSlideById: function(slideId) { // Check if we have slides loaded in memory if (!this.currentSlides) { return null; } return this.currentSlides.find(slide => slide.id == slideId); }, // Populate form with slide data for editing populateEditForm: function(slideData) { // Clear existing forms $('#slide-forms-container').empty(); // Reset form counter and add edit form this.formCounter = 1; this.isEditMode = true; this.editingSlideId = slideData.id; // Get available sites for checkboxes const sitesHtml = window.hssmSites ? window.hssmSites.map(site => { const isSelected = slideData.sites && slideData.sites.includes(site.name); return ` `; }).join('') : '

No sites available

'; const formHtml = `

Editing: ${slideData.title} EDIT MODE

× Cancel Edit

Basic Information

Site Targeting

${sitesHtml}

Image

${!slideData.featured_image_url ? 'Click to upload image' : ''}

Call-to-Action Buttons

${this.generateButtonsHtml(slideData.buttons || [], this.formCounter)}
`; $('#slide-forms-container').html(formHtml); this.showMessage('Slide loaded for editing', 'success'); }, // Generate buttons HTML for editing generateButtonsHtml: function(buttons, formId) { if (!buttons || buttons.length === 0) { return `
`; } return buttons.map((button, index) => `
`).join(''); }, // Cancel edit mode (silent: true skips toast — used after successful update so we do not double-message) cancelEdit: function(e, silent) { if (e && e.preventDefault) { e.preventDefault(); } this.isEditMode = false; this.editingSlideId = null; $('#slide-forms-container').empty(); this.formCounter = 0; this.addInitialSlideForm(); if (!silent) { this.showMessage('Edit cancelled', 'info'); } }, // Update slide function updateSlide: function(e) { e.preventDefault(); const formId = $(e.currentTarget).data('form'); const slideId = $(e.currentTarget).data('slide-id'); const $form = $(`.hssm-slide-form[data-form-id="${formId}"]`); if (!this.validateForm($form)) { return; } const formData = this.collectFormData($form); formData.append('action', 'hssm_update_slide'); formData.append('slide_id', slideId); formData.append('post_status', 'draft'); // Explicitly set as draft $form.addClass('hssm-loading'); $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: formData, processData: false, contentType: false, success: (response) => { $form.removeClass('hssm-loading'); if (response.success) { this.showMessage('Slide updated successfully as draft!', 'success'); this.cancelEdit(null, true); if ($('#manage-slides').length > 0) { $('.hssm-nav-tabs a[data-tab="manage-slides"]').click(); } } else { this.showMessage(response.data?.message || 'Update failed', 'error'); } }, error: () => { $form.removeClass('hssm-loading'); this.showMessage('Update failed. Please try again.', 'error'); } }); }, // Schedule updated slide for approval scheduleUpdatedSlide: function(e) { e.preventDefault(); const formId = $(e.currentTarget).data('form'); const slideId = $(e.currentTarget).data('slide-id'); const $form = $(`.hssm-slide-form[data-form-id="${formId}"]`); if (!this.validateForm($form)) { return; } const formData = this.collectFormData($form); formData.append('action', 'hssm_update_slide'); formData.append('slide_id', slideId); formData.append('post_status', 'pending'); // Set to pending for approval $form.addClass('hssm-loading'); $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: formData, processData: false, contentType: false, success: (response) => { $form.removeClass('hssm-loading'); if (response.success) { this.showMessage('Slide updated and scheduled for approval!', 'success'); this.cancelEdit(null, true); if ($('#manage-slides').length > 0) { $('.hssm-nav-tabs a[data-tab="manage-slides"]').click(); } } else { this.showMessage(response.data?.message || 'Schedule failed', 'error'); } }, error: () => { $form.removeClass('hssm-loading'); this.showMessage('Schedule failed. Please try again.', 'error'); } }); }, // Escape HTML for safe insertion escapeHtml: function(text) { if (!text) return ''; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; }, // Delete slide function deleteSlide: function(slideId) { if (!confirm('Are you sure you want to delete this slide? This action cannot be undone.')) { return; } $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: { action: 'hssm_delete_slide', nonce: hssmDashboard.nonce, slide_id: slideId }, success: (response) => { if (response.success) { this.showMessage('Slide deleted successfully!', 'success'); this.loadExistingSlides(); // Refresh the list } else { this.showMessage('Failed to delete slide: ' + (response.data?.message || 'Unknown error'), 'error'); } }, error: () => { this.showMessage('Failed to delete slide. Please try again.', 'error'); } }); }, // Duplicate slide function duplicateSlide: function(slideId) { $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: { action: 'hssm_duplicate_slide', nonce: hssmDashboard.nonce, slide_id: slideId }, success: (response) => { if (response.success) { this.showMessage('Slide duplicated successfully!', 'success'); this.loadExistingSlides(); // Refresh the list } else { this.showMessage('Failed to duplicate slide: ' + (response.data?.message || 'Unknown error'), 'error'); } }, error: () => { this.showMessage('Failed to duplicate slide. Please try again.', 'error'); } }); }, // Toggle slide status toggleSlideStatus: function(slideId) { $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: { action: 'hssm_toggle_slide_status', nonce: hssmDashboard.nonce, slide_id: slideId }, success: (response) => { if (response.success) { this.showMessage('Slide status updated!', 'success'); this.loadExistingSlides(); // Refresh the list } else { this.showMessage('Failed to update slide status: ' + (response.data?.message || 'Unknown error'), 'error'); } }, error: () => { this.showMessage('Failed to update slide status. Please try again.', 'error'); } }); }, // Show message to user showMessage: function(message, type = 'info') { const $messages = $('#hssm-messages'); if (!$messages.length) { return; } const $msg = $('
').addClass(type).text(message); $messages.append($msg); const dismissMs = 5000; window.setTimeout(() => { $msg.stop(true, true).fadeOut(300, function() { $(this).remove(); }); }, dismissMs); }, // Placeholder methods for future implementation previewSlide: function(e) { e.preventDefault(); this.showMessage('Preview functionality coming soon!', 'info'); }, applyFilters: function(e) { e.preventDefault(); this.showMessage('Filter functionality coming soon!', 'info'); }, // Load analytics data loadAnalyticsData: function() { if (this.currentTab !== 'analytics') return; // Simulate analytics data loading setTimeout(() => { $('.hssm-analytics-number').each(function(index) { const values = ['24', '3', '7']; $(this).text(values[index] || '0'); }); }, 500); }, // Generate analytics report generateAnalyticsReport: function(e) { e.preventDefault(); this.showMessage('Analytics report generation coming soon!', 'info'); }, // Import slides importSlides: function(e) { e.preventDefault(); this.showMessage('Slide import functionality coming soon!', 'info'); }, // Export slides exportSlides: function(e) { e.preventDefault(); this.showMessage('Slide export functionality coming soon!', 'info'); }, // Save all slides as drafts saveAllAsDrafts: function(e) { e.preventDefault(); const $forms = $('.hssm-slide-form'); let savedCount = 0; let errorCount = 0; $forms.each((index, form) => { const $form = $(form); // Override status to draft const formData = this.collectFormData($form); formData.append('post_status', 'draft'); this.submitSlideForm($form, () => { savedCount++; this.checkAllSaved(savedCount, errorCount, $forms.length); }, () => { errorCount++; this.checkAllSaved(savedCount, errorCount, $forms.length); }); }); }, // Load notification settings loadNotificationSettings: function() { $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: { action: 'hssm_get_notification_settings', nonce: hssmDashboard.nonce }, success: (response) => { if (response.success && response.data) { $('#editor_emails').val(response.data.editor_emails || ''); $('#itc_emails').val(response.data.itc_emails || ''); } } }); }, // Save notification settings saveNotificationSettings: function(e) { e.preventDefault(); const $form = $(e.currentTarget); $.ajax({ url: hssmDashboard.ajaxurl, type: 'POST', data: { action: 'hssm_save_notification_settings', nonce: hssmDashboard.nonce, editor_emails: $('#editor_emails').val(), itc_emails: $('#itc_emails').val() }, success: (response) => { if (response.success) { this.showMessage('Notification settings saved successfully!', 'success'); } else { this.showMessage('Failed to save settings.', 'error'); } }, error: () => { this.showMessage('Failed to save settings. Please try again.', 'error'); } }); } }; // Initialize when document is ready $(document).ready(function() { HSSMDashboard.init(); }); })(jQuery);