9bb2171b92
add 'no dates' logic
1479 lines
66 KiB
JavaScript
1479 lines
66 KiB
JavaScript
/**
|
||
* 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
|
||
$(document).on('click', '#apply-filters', this.applyFilters.bind(this));
|
||
$(document).on('click', '.hssm-edit-slide', this.editSlide.bind(this));
|
||
$(document).on('click', '.hssm-delete-slide', function(e) {
|
||
e.preventDefault();
|
||
const slideId = $(e.currentTarget).data('slide-id');
|
||
HSSMDashboard.deleteSlide(slideId);
|
||
});
|
||
|
||
// 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 => `
|
||
<label class="hssm-checkbox-compact">
|
||
<input type="checkbox" name="slides[${this.formCounter}][target_sites][]" value="${site.id}">
|
||
${site.name}
|
||
</label>
|
||
`).join('') : '<p>No sites available</p>';
|
||
|
||
const formHtml = `
|
||
<div class="hssm-slide-form" data-form-id="${this.formCounter}">
|
||
<div class="hssm-form-header">
|
||
<h3>Slide ${this.formCounter}</h3>
|
||
<span class="hssm-remove-form">× Remove</span>
|
||
</div>
|
||
<div class="hssm-form-grid">
|
||
<!-- Left Column: Basic Information + Site Targeting -->
|
||
<div class="hssm-form-section">
|
||
<h4>Basic Information</h4>
|
||
<div class="hssm-field">
|
||
<label>Title</label>
|
||
<input type="text" name="slides[${this.formCounter}][title]" class="hssm-input" required>
|
||
</div>
|
||
<div class="hssm-field">
|
||
<label>Subtitle</label>
|
||
<input type="text" name="slides[${this.formCounter}][subtitle]" class="hssm-input">
|
||
</div>
|
||
<div class="hssm-field">
|
||
<label>Content</label>
|
||
<textarea name="slides[${this.formCounter}][content]" class="hssm-textarea" rows="3"></textarea>
|
||
</div>
|
||
<div class="hssm-field-row">
|
||
<div class="hssm-field">
|
||
<label>Start Date</label>
|
||
<input type="date" name="slides[${this.formCounter}][start_date]" id="start_date_${this.formCounter}" class="hssm-input">
|
||
</div>
|
||
<div class="hssm-field">
|
||
<label>End Date</label>
|
||
<input type="date" name="slides[${this.formCounter}][end_date]" id="end_date_${this.formCounter}" class="hssm-input">
|
||
</div>
|
||
</div>
|
||
|
||
<h4 style="margin-top: 20px;">Site Targeting</h4>
|
||
<div class="hssm-field">
|
||
<label>Target Sites</label>
|
||
<div class="hssm-checkboxes-compact">
|
||
${sitesHtml}
|
||
</div>
|
||
</div>
|
||
<div class="hssm-field" style="margin-top: 15px;">
|
||
<label class="hssm-checkbox-compact hssm-hide-text-option">
|
||
<input type="checkbox" name="slides[${this.formCounter}][hide_all_text]" value="1">
|
||
Hide All Text (Image Only)
|
||
<small style="display: block; color: #666; margin-top: 5px;">Check this to display only the image without any overlay text</small>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Right Column: Image & CTA Buttons -->
|
||
<div class="hssm-form-section">
|
||
<h4>Image</h4>
|
||
<div class="hssm-field">
|
||
<div class="hssm-image-upload-compact">
|
||
<div class="hssm-image-preview-small" id="image_preview_${this.formCounter}" data-target="${this.formCounter}">
|
||
<span>Click to upload image</span>
|
||
</div>
|
||
<div class="hssm-image-controls">
|
||
<button type="button" class="hssm-btn hssm-btn-sm hssm-upload-btn" data-target="${this.formCounter}">Upload</button>
|
||
<button type="button" class="hssm-btn hssm-btn-danger hssm-btn-sm hssm-remove-image" data-target="${this.formCounter}" style="display: none;">Remove</button>
|
||
<input type="hidden" name="slides[${this.formCounter}][featured_image]" id="image_id_${this.formCounter}" class="hssm-image-id">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<h4 style="margin-top: 20px;">Call-to-Action Buttons</h4>
|
||
<div class="hssm-field">
|
||
<div class="hssm-buttons-container-compact" id="buttons_${this.formCounter}" data-form="${this.formCounter}">
|
||
<div class="hssm-button-row-compact">
|
||
<input type="text" name="slides[${this.formCounter}][buttons][0][text]" placeholder="Button text" class="hssm-input hssm-input-small">
|
||
<input type="url" name="slides[${this.formCounter}][buttons][0][url]" placeholder="Button URL" class="hssm-input hssm-input-small">
|
||
<button type="button" class="hssm-btn hssm-btn-danger hssm-btn-tiny hssm-remove-button">×</button>
|
||
</div>
|
||
</div>
|
||
<button type="button" class="hssm-btn hssm-btn-sm hssm-add-button" data-form="${this.formCounter}">+ Add Button</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="hssm-form-actions">
|
||
<button type="button" class="hssm-btn hssm-schedule-slide" data-form="${this.formCounter}">Schedule for Approval</button>
|
||
<button type="button" class="hssm-btn hssm-publish-slide" data-form="${this.formCounter}">Publish Immediately</button>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
$('#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('<span>Click to upload image</span>'); // 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 = `
|
||
<div class="hssm-button-row-compact">
|
||
<input type="text" name="slides[${formId}][buttons][${buttonIndex}][text]" placeholder="Button text" class="hssm-input hssm-input-small">
|
||
<input type="url" name="slides[${formId}][buttons][${buttonIndex}][url]" placeholder="Button URL" class="hssm-input hssm-input-small">
|
||
<button type="button" class="hssm-btn hssm-btn-danger hssm-btn-tiny hssm-remove-button">×</button>
|
||
</div>
|
||
`;
|
||
|
||
$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 = $('<div class="hssm-field-error"></div>').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 = $('<div class="hssm-field-error"></div>').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('<span>Click to upload image</span>');
|
||
$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(`
|
||
<div class="hssm-button-row-compact">
|
||
<input type="text" name="slides[${formId}][buttons][0][text]" placeholder="Button text" class="hssm-input hssm-input-small">
|
||
<input type="url" name="slides[${formId}][buttons][0][url]" placeholder="Button URL" class="hssm-input hssm-input-small">
|
||
<button type="button" class="hssm-btn hssm-btn-danger hssm-btn-tiny hssm-remove-button">×</button>
|
||
</div>
|
||
`);
|
||
},
|
||
|
||
// Load existing slides
|
||
loadExistingSlides: function() {
|
||
const $slidesList = $('#slides-list');
|
||
if ($slidesList.length === 0) {
|
||
console.error('slides-list element not found!');
|
||
return;
|
||
}
|
||
|
||
$slidesList.html('<div class="hssm-loading">Loading slides...</div>');
|
||
|
||
$.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('<p>Failed to load slides. Response format unexpected.</p>');
|
||
}
|
||
},
|
||
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('<p>Failed to load slides.</p>');
|
||
}
|
||
});
|
||
},
|
||
|
||
// 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(`
|
||
<div class="hssm-empty-state">
|
||
<div class="hssm-empty-icon">
|
||
<span class="dashicons dashicons-slides"></span>
|
||
</div>
|
||
<h3>No slides found</h3>
|
||
<p>Create your first slide to get started!</p>
|
||
<button class="hssm-btn hssm-btn-primary" onclick="$('.hssm-nav-tabs a[data-tab=create-slides]').click()">
|
||
<span class="dashicons dashicons-plus-alt"></span> Create First Slide
|
||
</button>
|
||
</div>
|
||
`);
|
||
return;
|
||
}
|
||
|
||
let html = `
|
||
<div class="hssm-slides-table">
|
||
<div class="hssm-table-header">
|
||
<div class="hssm-col-image">Image</div>
|
||
<div class="hssm-col-title">Title</div>
|
||
<div class="hssm-col-status">Status</div>
|
||
<div class="hssm-col-dates">Schedule</div>
|
||
<div class="hssm-col-sites">Target Sites</div>
|
||
<div class="hssm-col-actions">Actions</div>
|
||
</div>
|
||
<div class="hssm-table-body">
|
||
`;
|
||
|
||
slides.forEach(slide => {
|
||
const imageUrl = slide.featured_image_url || '';
|
||
const statusClass = this.getStatusClass(slide.status);
|
||
const sitesText = this.formatSitesList(slide.target_sites);
|
||
const scheduleText = this.formatScheduleText(slide);
|
||
|
||
html += `
|
||
<div class="hssm-slide-row" data-slide-id="${slide.id}">
|
||
<div class="hssm-col-image">
|
||
<div class="hssm-slide-thumbnail" style="background-image: url('${imageUrl}');">
|
||
${!imageUrl ? '<span class="dashicons dashicons-format-image"></span>' : ''}
|
||
</div>
|
||
</div>
|
||
<div class="hssm-col-title">
|
||
<div class="hssm-slide-title">${slide.title}</div>
|
||
<div class="hssm-slide-subtitle">${slide.subtitle || ''}</div>
|
||
</div>
|
||
<div class="hssm-col-status">
|
||
<span class="hssm-status-badge hssm-status-${statusClass}">${slide.status}</span>
|
||
</div>
|
||
<div class="hssm-col-dates">
|
||
<div class="hssm-schedule-info">${scheduleText}</div>
|
||
</div>
|
||
<div class="hssm-col-sites">
|
||
<div class="hssm-sites-info">${sitesText}</div>
|
||
</div>
|
||
<div class="hssm-col-actions">
|
||
<div class="hssm-slide-actions">
|
||
<button class="hssm-btn hssm-btn-sm hssm-btn-secondary hssm-edit-slide" data-slide-id="${slide.id}" title="Edit">
|
||
<span class="dashicons dashicons-edit"></span>
|
||
</button>
|
||
<button class="hssm-btn hssm-btn-sm hssm-btn-secondary hssm-duplicate-slide" data-slide-id="${slide.id}" title="Duplicate">
|
||
<span class="dashicons dashicons-admin-page"></span>
|
||
</button>
|
||
<button class="hssm-btn hssm-btn-sm hssm-btn-success hssm-toggle-status" data-slide-id="${slide.id}" title="Toggle Status">
|
||
<span class="dashicons dashicons-${slide.status === 'publish' ? 'pause' : 'controls-play'}"></span>
|
||
</button>
|
||
<button class="hssm-btn hssm-btn-sm hssm-btn-danger hssm-delete-slide" data-slide-id="${slide.id}" title="Delete">
|
||
<span class="dashicons dashicons-trash"></span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
html += `
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
$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() {
|
||
// Edit slide
|
||
$(document).off('click', '.hssm-edit-slide').on('click', '.hssm-edit-slide', (e) => {
|
||
e.preventDefault();
|
||
const slideId = $(e.currentTarget).data('slide-id');
|
||
this.editSlide(slideId);
|
||
});
|
||
|
||
// Delete slide
|
||
$(document).off('click', '.hssm-delete-slide').on('click', '.hssm-delete-slide', (e) => {
|
||
e.preventDefault();
|
||
const slideId = $(e.currentTarget).data('slide-id');
|
||
this.deleteSlide(slideId);
|
||
});
|
||
|
||
// Duplicate slide
|
||
$(document).off('click', '.hssm-duplicate-slide').on('click', '.hssm-duplicate-slide', (e) => {
|
||
e.preventDefault();
|
||
const slideId = $(e.currentTarget).data('slide-id');
|
||
this.duplicateSlide(slideId);
|
||
});
|
||
|
||
// Toggle status
|
||
$(document).off('click', '.hssm-toggle-status').on('click', '.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('<div class="hssm-loading">Loading slide for editing...</div>');
|
||
|
||
// 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 `
|
||
<label class="hssm-checkbox-compact">
|
||
<input type="checkbox" name="slides[${this.formCounter}][target_sites][]" value="${site.id}" ${isSelected ? 'checked' : ''}>
|
||
${site.name}
|
||
</label>
|
||
`;
|
||
}).join('') : '<p>No sites available</p>';
|
||
|
||
const formHtml = `
|
||
<div class="hssm-slide-form" data-form-id="${this.formCounter}" data-editing-slide-id="${slideData.id}">
|
||
<div class="hssm-form-header">
|
||
<h3>Editing: ${slideData.title} <span class="hssm-edit-badge">EDIT MODE</span></h3>
|
||
<span class="hssm-cancel-edit">× Cancel Edit</span>
|
||
</div>
|
||
<div class="hssm-form-grid">
|
||
<!-- Left Column: Basic Information + Site Targeting -->
|
||
<div class="hssm-form-section">
|
||
<h4>Basic Information</h4>
|
||
<div class="hssm-field">
|
||
<label>Title</label>
|
||
<input type="text" name="slides[${this.formCounter}][title]" class="hssm-input" value="${this.escapeHtml(slideData.title)}" required>
|
||
</div>
|
||
<div class="hssm-field">
|
||
<label>Subtitle</label>
|
||
<input type="text" name="slides[${this.formCounter}][subtitle]" class="hssm-input" value="${this.escapeHtml(slideData.subtitle || '')}">
|
||
</div>
|
||
<div class="hssm-field">
|
||
<label>Content</label>
|
||
<textarea name="slides[${this.formCounter}][content]" class="hssm-textarea" rows="3">${this.escapeHtml(slideData.content || '')}</textarea>
|
||
</div>
|
||
<div class="hssm-field-row">
|
||
<div class="hssm-field">
|
||
<label>Start Date</label>
|
||
<input type="date" name="slides[${this.formCounter}][start_date]" id="start_date_${this.formCounter}" class="hssm-input" value="${slideData.start_date || ''}">
|
||
</div>
|
||
<div class="hssm-field">
|
||
<label>End Date</label>
|
||
<input type="date" name="slides[${this.formCounter}][end_date]" id="end_date_${this.formCounter}" class="hssm-input" value="${slideData.end_date || ''}">
|
||
</div>
|
||
</div>
|
||
|
||
<h4 style="margin-top: 20px;">Site Targeting</h4>
|
||
<div class="hssm-field">
|
||
<label>Target Sites</label>
|
||
<div class="hssm-checkboxes-compact">
|
||
${sitesHtml}
|
||
</div>
|
||
</div>
|
||
<div class="hssm-field" style="margin-top: 15px;">
|
||
<label class="hssm-checkbox-compact hssm-hide-text-option">
|
||
<input type="checkbox" name="slides[${this.formCounter}][hide_all_text]" value="1" ${slideData.hide_all_text ? 'checked' : ''}>
|
||
Hide All Text (Image Only)
|
||
<small style="display: block; color: #666; margin-top: 5px;">Check this to display only the image without any overlay text</small>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Right Column: Image & CTA Buttons -->
|
||
<div class="hssm-form-section">
|
||
<h4>Image</h4>
|
||
<div class="hssm-field">
|
||
<div class="hssm-image-upload-compact">
|
||
<div class="hssm-image-preview-small ${slideData.featured_image_url ? 'has-image' : ''}"
|
||
id="image_preview_${this.formCounter}"
|
||
data-target="${this.formCounter}"
|
||
style="${slideData.featured_image_url ? `background-image: url('${slideData.featured_image_url}')` : ''}">
|
||
${!slideData.featured_image_url ? '<span>Click to upload image</span>' : ''}
|
||
</div>
|
||
<div class="hssm-image-controls">
|
||
<button type="button" class="hssm-btn hssm-btn-sm hssm-upload-btn" data-target="${this.formCounter}">Upload</button>
|
||
<button type="button" class="hssm-btn hssm-btn-danger hssm-btn-sm hssm-remove-image" data-target="${this.formCounter}" style="${slideData.featured_image_url ? '' : 'display: none;'}">Remove</button>
|
||
<input type="hidden" name="slides[${this.formCounter}][featured_image]" id="image_id_${this.formCounter}" class="hssm-image-id" value="">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<h4 style="margin-top: 20px;">Call-to-Action Buttons</h4>
|
||
<div class="hssm-field">
|
||
<div class="hssm-buttons-container-compact" id="buttons_${this.formCounter}" data-form="${this.formCounter}">
|
||
${this.generateButtonsHtml(slideData.buttons || [], this.formCounter)}
|
||
</div>
|
||
<button type="button" class="hssm-btn hssm-btn-sm hssm-add-button" data-form="${this.formCounter}">+ Add Button</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="hssm-form-actions">
|
||
<button type="button" class="hssm-btn hssm-btn-secondary hssm-schedule-updated-slide" data-form="${this.formCounter}" data-slide-id="${slideData.id}">
|
||
<span class="dashicons dashicons-calendar-alt"></span> Schedule for Approval
|
||
</button>
|
||
<button type="button" class="hssm-btn hssm-update-slide" data-form="${this.formCounter}" data-slide-id="${slideData.id}">Update as Draft</button>
|
||
<button type="button" class="hssm-btn hssm-btn-outline hssm-cancel-edit-btn" data-form="${this.formCounter}">Cancel Edit</button>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
$('#slide-forms-container').html(formHtml);
|
||
|
||
// Bind cancel edit events
|
||
$(document).on('click', '.hssm-cancel-edit, .hssm-cancel-edit-btn', this.cancelEdit.bind(this));
|
||
$(document).on('click', '.hssm-update-slide', this.updateSlide.bind(this));
|
||
$(document).on('click', '.hssm-schedule-updated-slide', this.scheduleUpdatedSlide.bind(this));
|
||
|
||
this.showMessage('Slide loaded for editing', 'success');
|
||
},
|
||
|
||
// Generate buttons HTML for editing
|
||
generateButtonsHtml: function(buttons, formId) {
|
||
if (!buttons || buttons.length === 0) {
|
||
return `
|
||
<div class="hssm-button-row-compact">
|
||
<input type="text" name="slides[${formId}][buttons][0][text]" placeholder="Button text" class="hssm-input hssm-input-small">
|
||
<input type="url" name="slides[${formId}][buttons][0][url]" placeholder="Button URL" class="hssm-input hssm-input-small">
|
||
<button type="button" class="hssm-btn hssm-btn-danger hssm-btn-tiny hssm-remove-button">×</button>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
return buttons.map((button, index) => `
|
||
<div class="hssm-button-row-compact">
|
||
<input type="text" name="slides[${formId}][buttons][${index}][text]" placeholder="Button text" class="hssm-input hssm-input-small" value="${this.escapeHtml(button.text || '')}">
|
||
<input type="url" name="slides[${formId}][buttons][${index}][url]" placeholder="Button URL" class="hssm-input hssm-input-small" value="${this.escapeHtml(button.url || '')}">
|
||
<button type="button" class="hssm-btn hssm-btn-danger hssm-btn-tiny hssm-remove-button">×</button>
|
||
</div>
|
||
`).join('');
|
||
},
|
||
|
||
// Cancel edit mode
|
||
cancelEdit: function(e) {
|
||
if (e) e.preventDefault();
|
||
|
||
this.isEditMode = false;
|
||
this.editingSlideId = null;
|
||
|
||
// Return to normal create form
|
||
$('#slide-forms-container').empty();
|
||
this.formCounter = 0;
|
||
this.addInitialSlideForm();
|
||
|
||
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');
|
||
|
||
// Exit edit mode and refresh manage slides if that tab is available
|
||
this.cancelEdit();
|
||
|
||
// If manage slides tab exists, refresh it
|
||
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');
|
||
|
||
// Exit edit mode and refresh manage slides if that tab is available
|
||
this.cancelEdit();
|
||
|
||
// If manage slides tab exists, refresh it
|
||
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');
|
||
const messageHtml = `
|
||
<div class="hssm-message ${type}">
|
||
${message}
|
||
</div>
|
||
`;
|
||
|
||
$messages.append(messageHtml);
|
||
|
||
// Auto-remove after 5 seconds
|
||
setTimeout(() => {
|
||
$messages.find('.hssm-message').last().fadeOut(300, function() {
|
||
$(this).remove();
|
||
});
|
||
}, 5000);
|
||
|
||
// Scroll to messages
|
||
$('html, body').animate({
|
||
scrollTop: $messages.offset().top - 20
|
||
}, 300);
|
||
},
|
||
|
||
// 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); |